Python MySQLdb пустой запрос выбора, хотя выполнение запроса вручную дает результаты - PullRequest
7 голосов
/ 13 октября 2011

Я написал демона python, который непрерывно опрашивает базу данных mysql.Он работает нормально, когда я непрерывно подключаюсь к базе данных и повторно подключаюсь к ней между запросами следующим образом:

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

Но когда я пытаюсь сохранить соединение с базой данных открытым (как показано ниже), я получаю пустой запрос, хотя, хотяон работает, я могу запросить базу данных вручную, дать ему тот же запрос и получить ожидаемый результат.

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

Я попробовал все, чтобы понять, почему он это сделает:

  • отключил кеш запросов и добавил случайный x = x к запросу в случае, если кеширование mysql было перепутано аналогичными запросами
  • включил ведение журнала запросов mysql: запрос проходит, но все еще возвращает пустой набор
  • переместил cursor.connect в database.connect и обратно в getData (), без разницы

Мне бы хотелось понять, что я не понимаю.

Ответы [ 2 ]

9 голосов
/ 13 октября 2011

Вы, вероятно, запрашиваете таблицу InnoDB, где другой процесс тем временем вставляет новые данные. В этом случае сервер MySQL автоматически запускает новую транзакцию для вашего соединения, и, поскольку вы нигде не вызываете dbConnection.commit() или .rollback(), вы навсегда застряли в этой транзакции. Настройки InnoDB по умолчанию гарантируют, что при каждом запросе данных вы всегда будете видеть один и тот же результат в одной транзакции. Поэтому все, что какой-либо другой процесс вставляет в таблицу, скрыто от соединения вашего демона.

Решение простое: вместо вызова db.disconnect(), вызовите dbConnection.commit(), который завершает текущую и начинает новую транзакцию.

2 голосов
/ 13 октября 2011

Объект MySQLdb.cursor, вероятно, не поддерживает коммит, как указано в Руководство MySQLDB Объекты соединения, с другой стороны, делают.

Так как вы обрабатываете все через класс Database, я думаю, что код коммита может пойти туда.

Просто чтобы дать код для того, что сказал Саймон

    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()

Я не уверен, но, вероятно, вы также можете сделать что-то вроде

db.connection.commit()

в цикле while вместо вызова новой определенной функции

...