SQLite并发问题咨询:多进程下第二个进程无法获取数据库更新
解决SQLite多进程读写时查询无法获取更新的问题
首先,你的问题其实是SQLite默认事务隔离级别的特性导致的,我来给你拆解下原因和对应的解决办法:
问题根源
SQLite默认采用SERIALIZABLE隔离级别,当一个连接执行查询操作时,会自动开启一个隐式事务。只要这个事务没有被提交或回滚,该连接就会一直锁定在事务启动时的数据库快照状态——也就是说,其他连接提交的任何更新,这个未结束的事务都看不到。你的script2.py用同一个连接持续循环查询,事务从未终止,所以始终拿到的是第一次查询时的旧数据。
几种简单可行的解决方法
方法1:每次查询后提交/回滚事务
在script2.py的每次查询完成后,调用conn.commit()或者conn.rollback()(因为查询没有修改数据,回滚也能结束当前事务),这样下一次查询会开启新的事务,自然能获取到最新的数据库状态。
修改后的script2.py代码:
import sqlite3, time conn = sqlite3.connect('test.db') c = conn.cursor() while True: c.execute('SELECT value FROM kv WHERE key = ?', (1,)) item = c.fetchone() print(item) conn.commit() # 提交事务,结束当前快照 time.sleep(1)
方法2:修改连接的隔离级别为READ COMMITTED
SQLite支持READ COMMITTED隔离级别,在这个级别下,同一个事务内的后续查询可以看到其他连接已经提交的更新。你只需要在建立连接时指定这个隔离级别即可:
修改后的script2.py代码:
import sqlite3, time # 建立连接时指定隔离级别为READ COMMITTED conn = sqlite3.connect('test.db', isolation_level='READ COMMITTED') c = conn.cursor() while True: c.execute('SELECT value FROM kv WHERE key = ?', (1,)) item = c.fetchone() print(item) time.sleep(1)
这个方法不需要频繁提交事务,更适合需要长期保持连接的场景。
方法3:每次查询重新建立连接(不推荐)
虽然可以每次查询都创建新连接,但频繁的连接创建与销毁会带来性能损耗,除非特殊场景,不建议使用这种方式:
import sqlite3, time while True: with sqlite3.connect('test.db') as conn: c = conn.cursor() c.execute('SELECT value FROM kv WHERE key = ?', (1,)) item = c.fetchone() print(item) time.sleep(1)
验证效果
任选上述一种方法修改后,重新启动script1.py和script2.py,你就能看到script2.py实时打印出script1.py更新的数值了。
内容的提问来源于stack exchange,提问作者Basj
相关产品推荐
相关产品推荐

