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

q35jwt9p  于 2023-05-28  发布在  Mysql
关注(0)|答案(4)|浏览(221)

我的Python程序查询MySQL DB中的一组表,休眠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不会受到影响?)
1.如果我在Python程序中显式执行SET SESSION query_cache_type = OFF,问题仍然会发生。
为每个查询创建一个新的数据库连接是我解决这个问题的唯一方法。
我如何从Python中获取查询,以查看我知道的新结果?

pdsfdshx

pdsfdshx1#

This website和本网站包含有关同一问题的信息。为了使表保持最新,必须提交事务。使用db.commit()来执行此操作。
正如我下面的帖子所提到的,你可以通过启用自动提交来消除这种需要。这可以通过运行db.autocommit(True)来完成
另外,在交互式shell中启用了自动提交,所以这解释了为什么在那里没有问题。

5gfr0r5j

5gfr0r5j2#

您可能需要检查数据库的事务隔离级别。如果将其设置为REPEATABLE-READ,您所描述的行为就是您所期望的。您可能希望将其更改为READ-COMMITTED。
由于问题的最初发布者提到他只是在查询数据库,所以它不可能是一个被遗忘的提交。插入一个提交似乎是一个解决办法,因为它会导致一个新的事务开始;并且可能需要建立新的快照。不过,在每次选择之前都必须插入一个提交,这对我来说听起来并不像是一个好的编程实践。
这里没有Python代码,因为解决方案在于正确配置数据库。

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

可重复读取
这是InnoDB的默认隔离级别。对于一致读取,与READ COMMITTED隔离级别有一个重要的区别:同一事务中的所有一致读取都读取第一次读取所建立的快照。这个约定意味着,如果在同一个事务中发出几个普通(非锁定)SELECT语句,这些SELECT语句彼此之间也是一致的。参见www.example.com部分14.3.9.2“一致非锁定读取”。
阅读已提交
对于一致(非锁定)读取,有点类似于Oracle的隔离级别:即使在同一事务中,每次一致读取也会设置和读取自己的新快照。参见www.example.com部分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>

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

xe55xuns

xe55xuns3#

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

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

这为您提供了与在交互式shell中使用的相同的行为。

798qvoo8

798qvoo84#

我不能确切地说为什么这个问题会发生,但我已经测试了3个解决方案,解决了这个问题
1.在运行每个查询之前创建一个新的MySQL连接(和一个新的游标)

cnx = mysql.connector.connect(**config2)
csr = cnx.cursor(named_tuple=True, buffered=True)

我不确定这是推荐的做法,但它解决了问题
1.提交-通过将autocommit设置为true或在每次查询后手动提交
1.要知道,这个问题只会发生在事务存储引擎上,因此如果使用transactional并不重要,您可以将正在查询的表设置为非事务类型,如MyISAM -这可能是最简单的选择
我没有添加将事务隔离级别设置为READ COMMITED,因为我还没有尝试过,而且其他人声称这对他不起作用

相关问题