在Python中使用MySQLdb的长期陈旧结果

2024-04-18 06:33:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我的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,问题仍然会出现。

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

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


Tags: keyfrom程序数据库cache服务器端mysqlshell
3条回答

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

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

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

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

REPEATABLE READ
This is the default isolation level for InnoDB. For consistent reads, there is an important difference from the READ COMMITTED isolation level: All consistent reads within the same transaction read the snapshot established by the first read. This convention means that if you issue several plain (nonlocking) SELECT statements within the same transaction, these SELECT statements are consistent also with respect to each other. See Section 14.3.9.2, “Consistent Nonlocking Reads”.

READ COMMITTED
A somewhat Oracle-like isolation level with respect to consistent (nonlocking) reads: Each consistent read, even within the same transaction, sets and reads its own fresh snapshot. See Section 14.3.9.2, “Consistent Nonlocking Reads”.

检查配置的隔离级别:

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

再次运行应用程序

您可以在MySQLdb中自动启用自动提交!请尝试以下操作:

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

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

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

正如我下面的文章所提到的,您可以通过启用自动提交来消除这种需要。这可以通过运行db.autocommit(True)来完成

另外,在交互式shell中启用了自动提交,所以这解释了为什么在那里没有问题。

相关问题 更多 >