Python中while循环检查数据库字段改变,为何不重新初始化连接就查不到最新数据?
我是用的 pymysql 这个库,大体的代码逻辑如下:
...
做了一些事情,这些事情会导致数据库某个字段的值会改变
...
a=usermysql() # 自定义类的 __init__方法,pymysql.connect 和创建 cursor
while True:
a.execute()
result = a.fetchone()
if result == ‘WORKING’: # 执行语句,获取需要的字段的值,如果值变成了想要的,就退出循环,做接下来的任务
break
然而运行的时候,发现获取到的字段的值并不会变化,只有在 while 循环里初始化数据库的连接,才能获取到最新的数据库的值
请问这是为什么呢?
Python中while循环检查数据库字段改变,为何不重新初始化连接就查不到最新数据?
数据库配置记录所有的查询,查看数据库 log 看请求有没有被数据库处理。
没有的话,查 execute 的文档,看是不是使用了类似执行过就不执行的机制。
这个问题很典型,是因为数据库连接池或事务隔离级别导致的。
简单说,你第一次执行查询时,连接可能开启了一个事务(取决于数据库驱动和配置,比如MySQL的默认隔离级别是“可重复读”)。在这个事务里,后续的查询看到的都是事务开始时的“快照”数据,即使数据库里实际数据已经变了,你这个连接里也看不到。
所以你的while循环一直在用同一个连接/事务,自然查不到其他会话提交的新数据。
要解决这个问题,最直接的办法就是在每次循环查询前,提交当前事务并开始一个新事务。对于大多数数据库驱动,执行一个SELECT查询也会隐式地开始一个事务。你需要显式地结束它。
这里给你一个使用mysql-connector-python的示例,其他数据库(如psycopg2、sqlite3)原理类似,具体方法可能稍有不同(比如用autocommit模式)。
import mysql.connector
import time
def monitor_database_change():
# 1. 建立连接
conn = mysql.connector.connect(
host="your_host",
user="your_user",
password="your_password",
database="your_db"
)
cursor = conn.cursor()
# 关键点:设置自动提交为True。这样每次查询后都会自动提交事务,
# 下次查询就是一个新事务,能看到最新的提交。
conn.autocommit = True
# 或者,如果你不想用autocommit,可以在循环里手动提交:
# conn.start_transaction(isolation_level='READ COMMITTED') # 也可以设置隔离级别
last_value = None
query = "SELECT your_field FROM your_table WHERE your_condition"
try:
while True:
cursor.execute(query)
current_value = cursor.fetchone()[0] # 假设查询返回单个值
if current_value != last_value:
print(f"数据发生变化: {last_value} -> {current_value}")
last_value = current_value
# 这里可以触发你的业务逻辑
time.sleep(1) # 每秒检查一次
# 如果没用autocommit,就在这里手动提交并开始新事务
# conn.commit()
except KeyboardInterrupt:
print("监控停止")
finally:
cursor.close()
conn.close()
if __name__ == "__main__":
monitor_database_change()
核心就两点:
- 设置
autocommit=True:这是最简单粗暴的方法,让每次查询独立。 - 使用
READ COMMITTED隔离级别:如果你需要保持事务但又能看到最新提交,可以在创建连接或开始事务时指定更宽松的隔离级别(如READ COMMITTED),而不是默认的REPEATABLE READ。
总结: 循环里查不到新数据是因为事务快照,让每次查询都开新事务就能解决。
仅仅从你 po 的这段 snippet 并不能看出问题,上源码链接吧
理论上,同一个语句,不同时候执行,返回的结果应该都是数据库里边最新的数据是吗?
"MVCC"
开启 autocommit,或者每次查完 commit。
能不能详细给讲一下呢?
pymysql 默认的 autocommit 是 false,不 commit 是不能查询到新的数据的,你可以设置为 true 或者每次查询完 commit

