2011-10-13 9 views
6

Pisałem demona Pythona, który nieustannie sonduje bazy danych MySQL. To działa dobrze, kiedy ciągły łączyć się i ponownie połączyć się z bazą danych między zapytaniami następująco:Python MySQLdb pusty kwerenda wybierająca natomiast ręczne wykonanie kwerendy dostarcza wyniki

def connect(self): 
    self.connection = MySQLdb.connect(...) 
    self.cursor = self.connection.cursor() 
    return self.cursor 

def disconnect(self): ... 
    self.cursor.close() 
    self.connection.close() 

def getData(); .... 
    sqlcmd = """SELECT ....""" 
    self.cursor.execute (sqlcmd % (params)) 
    result = self.cursor.fetchall() 
    return result 

if __name__ == "__main__": 
    db = prepaid_db.Database() 
    while 1: 
     dbConnection = db.connect() 
     data = db.getData() 
     ... do stuff 
     db.disconnect 

Ale gdy próbuję utrzymać połączenie z bazą danych open (jak poniżej) pojawia się pusty zapytanie, chociaż, gdy jest Uruchamianie Mogę wykonać zapytanie do bazy danych ręcznie, podać to samo zapytanie i uzyskać wynik, którego oczekuję.

if __name__ == "__main__": 
    db = prepaid_db.Database() 
    dbConnection = db.connect() 
    while 1: 
     data = db.getData() 
     ... do stuff 
    db.disconnect 

Próbowałem wszystkiego, aby zrozumieć, dlaczego miałby to zrobić:

  • cache zapytań niepełnosprawnych i dodaje losowe X = x do zapytania w sprawie mysql cache był zdezorientowany podobnych zapytań
  • włączone rejestrowanie zapytań mysql: zapytanie przychodzi, ale nadal zwraca pusty zestaw
  • przeniesione cursor.connect do database.connect iz powrotem do getData(), bez różnicy

Chciałbym wskazówkę, czego nie rozumiem.

+0

Średnik w 'def getData();' powinien być dwukropkiem. – unutbu

+0

Czy 'self.cursor.fetchall()' zwraca 'Brak' po raz pierwszy podczas' while-loop' lub po wielu przejściach? – unutbu

+0

- tak na dwukropek, przepraszam, prosta literówka –

Odpowiedz

6

Pewnie zapytań tabelę InnoDB, gdzie inny proces wstawia nowe dane w międzyczasie. Jeśli tak jest, MySQL zerwać automatycznie rozpoczyna nową transakcję połączenia, a ponieważ nie nazywają dbConnection.commit() lub .rollback() wszędzie, jesteś zawsze tkwi w tej transakcji. Domyślne ustawienia InnoDB gwarantują, że za każdym razem, gdy będziesz wyszukiwać dane, zawsze zobaczysz ten sam wynik w ramach jednej transakcji. A więc to, co jakiś inny proces wstawia do tabeli, jest ukryte przed połączeniem demona.

Rozwiązanie jest proste: zamiast dzwonić pod numer db.disconnect(), należy zadzwonić pod numer dbConnection.commit(), który kończy bieżące połączenie i rozpoczyna nową transakcję.

+3

geniuszy tam! –

+0

dzięki Simon, to była jedyna tabela InnoDB w moim DB i nie sądziłem, że będzie to miało wpływ na instrukcję Select. Ale oczywiście tak, dodałem commit() i teraz działa idealnie! dziękuje bardzo! –

+0

maaaaaaaan! to było niesamowite, myślałem, że db.commit() służy tylko do aktualizacji. To uratowało moje życie. – AliBZ

2

MySQLdb.cursor przedmiot prawdopodobnie nie obsługują popełnić jak podano w MySQLDB manual. Z drugiej strony, obiekty połączeń.

Od obsługiwać wszystko przez klasy Database, myślę kod popełnić można tam iść.

Wystarczy podać kod co Simon powiedział

def connect(self): 
     self.connection = MySQLdb.connect(...) 
     self.cursor = self.connection.cursor() 

    def disconnect(self): ... 
     self.cursor.close() 
     self.connection.commit() 
     self.connection.close() 

    def commit(self): 
     self.connection.commit() 

    def getData(self): .... 
     sqlcmd = """SELECT ....""" 
     self.cursor.execute (sqlcmd % (params)) 
     result = self.cursor.fetchall() 
     return result 

if __name__ == "__main__": 
    db = prepaid_db.Database() 
    db.connect() 
    while 1: 
     data = db.getData() 
     ... do stuff 
     db.commit() 
    db.disconnect() 

Nie jestem pewien, ale prawdopodobnie można też zrobić coś podobnego

db.connection.commit() 

w pętli while zamiast dzwonić nowo zdefiniowana funkcja

+0

dzięki RebBaron, tak właśnie to zrobiłem. –

Powiązane problemy