英文:
python mysql - is commit() required for SELECT?
问题
我有一个非常简单的Python代码,从MySQL获取一些数据:
version = 1
with conn.cursor() as cur:
query = f'select latest_version from version'
cur.execute(query)
for row in cur:
version = int(row[0])
cur.close()
print(version)
该代码在从AWS Lambda访问我的私有MySQL实例时执行(但在我看来,这些都不重要)。
它一直运行得很好,然后我使用SQL更新了DB中的版本值:
UPDATE version set latest_version=11;
COMMIT;
FLUSH TABLES;
问题是:在运行上述SQL代码后,当我运行我的Python代码时,我从DB中获取的是旧值(10而不是11),就像某种缓存一样...
现在,当我将commit()添加到我的Python代码中,就像这样:
version = 1
with conn.cursor() as cur:
query = f'select latest_version from version'
cur.execute(query)
conn.commit()
for row in cur:
version = int(row[0])
cur.close()
print(version)
一切开始正常工作,我得到了一个新版本。
这个问题对我来说已经发生了多次,涉及不同的SQL表格(不得不使用上述的“解决方法”)。结果始终相同,进行了多次测试。
我有一些其他代码在该DB上运行,对其他表格进行了大量插入操作(但我从未通过Python代码向version表格插入)。此外,我在许多并行线程中非常频繁地运行这些工作程序,它们同时在同一个DB上运行(但没有依赖关系,不应该有任何死锁,所有工作程序都按时完成工作)。
请帮助我理解为什么会发生这种情况?
我的一个猜测是,我没有在其他脚本中正确关闭MySQL连接,但在这种情况下,我想我会耗尽连接/数据库处理程序(工作程序),不再能够连接,而不是获取缓存值...所以我一无所知。有什么建议吗?
谢谢。
英文:
I have a very simple python code getting some data from mysql:
version = 1
with conn.cursor() as cur:
query = f'select latest_version from version'
cur.execute(query)
for row in cur:
version = int(row[0])
cur.close()
print(version)
That code is executed from AWS Lambda accessing my private mysql instance (but none of that should matter imho).
It was working perfectly fine, then i have updated version values in DB using SQL:
UPDATE version set latest_version=11;
COMMIT;
FLUSH TABLES;
The problem: after running above SQL code when i run my python code i was getting the old value from DB (10 instead of 11), like some caching....
Now when i have added to my python code commit() like this:
version = 1
with conn.cursor() as cur:
query = f'select latest_version from version'
cur.execute(query)
conn.commit()
for row in cur:
version = int(row[0])
cur.close()
print(version)
It all started to work fine and i got a new version.
This problem occurred for me several times with different SQL tables (and had to use above "workaround"). Always the same results, tested many times.
I have quite some other code operating on that DB running a lot of inserts on other tables (but i never insert on version table via python code). Also i am quite intensive running those workers in many parallel threads operating on the same DB as the same time (but no dependencies, should not have any deadlocks, all workers finishing work in time).
Could you please help me understand why this is happening ?
One of my guesses was that i did not close connections to mysql correctly in other scripts, but in such case i guess i would run out of connections/db hanlders(workers) and would not be able to connect anymore, not get cached values....So i am clueless here. Any ideas ?
Thanks,
答案1
得分: 2
发生的情况是您的默认事务隔离级别为REPEATABLE-READ,因此在同一事务中重复查询永远不会看到数据库的更新视图。
您应该将事务隔离级别设置为READ-COMMITTED,这样您的SELECT语句始终可以看到当前已提交的数据。在执行第一个查询之前,请执行以下操作:
cur.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")
如果这不起作用,那么在更改隔离级别后进行一次COMMIT操作即可。
在这种情况下,您不需要执行FLUSH TABLES。
英文:
What's happening is that your default transaction isolation is REPEATABLE-READ, so repeated queries in the same transaction never see an updated view of the database.
You should set your transaction isolation to READ-COMMITTED, so your SELECT always sees the current committed data. Do the following before you do your first query:
cur.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")
If that doesn't work, then do one COMMIT after changing the isolation level.
You don't need to do FLUSH TABLES in this case.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论