在Python中使用MySQLdb的慢性陈旧结果

时间:2011-05-09 22:56:14

标签: python mysql caching

我的Python程序查询MySQL数据库中的一组表,睡眠30秒,然后再次查询等等。有问题的表由第三方不断更新,(显然)我希望看到每隔30秒就有一次新结果。

假设我的查询如下:

"select * from A where A.key > %d" % maxValueOfKeyFromLastQuery

定期我会看到我的程序在一次或两次迭代后停止查找新结果,即使表中存在新行 。我知道表中存在新行,因为当我从交互式mysql(即不是Python)发出相同的查询时,我可以看到它们。

如果我在每次查询后终止与数据库的连接,然后为下一个查询建立一个新的连接,我发现Python中的问题就消失了。

我想也许这可能是服务器端缓存问题,如下所述:Explicit disable MySQL query cache in some parts of program

然而:

  1. 当我检查交互式mysql shell时,它表示已启用缓存。 (所以,如果这是一个缓存问题,交互式shell怎么会不受它的影响?)

  2. 如果我在Python程序中显式执行SET SESSION query_cache_type = OFF,问题仍然存在。

  3. 为每个查询创建一个新的数据库连接是我能够解决问题的唯一方法。

    如何从Python获取查询以查看我知道的新结果?

3 个答案:

答案 0 :(得分:23)

This websitethis website包含有关同一问题的信息。为了使您的表保持最新,您必须提交您的交易。使用db.commit()执行此操作。

如我下面的帖子所述,您可以通过启用自动提交来消除此需求。这可以通过运行db.autocommit(True)

来完成

此外,在交互式shell中启用了自动提交,因此这解释了为什么你没有遇到问题。

答案 1 :(得分:13)

您可能想要检查数据库的事务隔离级别。如果设置为REPEATABLE-READ,您描述的行为就是您可能期望的行为。您可能希望将其更改为READ-COMMITTED。

由于问题的原始海报提到他只是在查询数据库,所以它不能被遗忘。插入提交似乎是一种解决方法,因为它会导致新事务开始;并且可能需要建立新的快照。不过,在每次选择之前必须插入一个提交对我来说听起来不是很好的编程实践。

没有要显示的python代码,因为解决方案在于正确配置数据库。

DO 检查http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html处的MySQL文档。

  

可重复阅读   这是InnoDB的默认隔离级别。对于一致性读取,与READ COMMITTED隔离级别存在重要差异:同一事务中的所有一致性读取读取第一次读取建立的快照。此约定意味着如果在同一事务中发出多个普通(非锁定)SELECT语句,则这些SELECT语句也相互一致。请参见第14.3.9.2节“一致的非锁定读取”。

     

READ COMMITTED
  关于一致(非锁定)读取的类似Oracle的隔离级别:即使在同一事务中,每个一致读取也会设置和读取自己的新快照。请参见第14.3.9.2节“一致的非锁定读取”。

检查配置的隔离级别:

>mysql > SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
+-----------------------+-----------------+
| @@GLOBAL.tx_isolation | @@tx_isolation  |
+-----------------------+-----------------+
| REPEATABLE-READ       | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.01 sec)

将事务隔离级别设置为READ-COMMITTED

mysql> SET GLOBAL tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
+-----------------------+----------------+
| @@GLOBAL.tx_isolation | @@tx_isolation |
+-----------------------+----------------+
| READ-COMMITTED        | READ-COMMITTED |
+-----------------------+----------------+
1 row in set (0.01 sec)

mysql>

再次运行应用程序......

答案 2 :(得分:9)

可以在MySQLdb中自动启用自动提交!请尝试以下方法:

conn = MySQLdb.Connect("host", "user", "password")
conn.autocommit(True)

这为您提供了在交互式shell中习惯的相同行为。