Python MySQLdb 空查询虽然手动执行查询能返回结果

7 投票
2 回答
3195 浏览
提问于 2025-04-17 04:14

我写了一个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 个回答

2

MySQLdb.cursor 对象可能不支持提交操作,具体可以参考 MySQLDB 手册。而连接对象是支持的。

因为你是通过数据库类来处理所有事情的,所以我想提交的代码可以放在那个地方。

为了给Simon说的内容提供一个代码示例

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

的循环中做一些事情,而不是调用新定义的函数。

10

你可能在查询一个InnoDB表,而这个表的同时还有其他进程在插入新数据。如果是这样,MySQL服务器会自动为你的连接开启一个新的事务。因为你没有在任何地方调用 dbConnection.commit().rollback(),所以你就一直停留在这个事务中。InnoDB的默认设置确保你在一个事务中查询数据时,看到的结果始终是一样的。因此,其他进程插入到表中的数据对你的连接是不可见的。

解决方法很简单:不要调用 db.disconnect(),而是调用 dbConnection.commit(),这样就可以结束当前的事务并开始一个新的事务。

撰写回答