2020年10月14日 / 77次阅读 / Last Modified 2020年11月9日
SQLite
python标准库自带sqlite3接口,在编译安装的时候,sqlite3也会一起编译。sqlite3是一个轻量自包含的文件数据库,没有独立的管理进程,因此,在基于此数据库编写应用系统的时候,并发访问就成了一个需要自己处理的问题。
因为sqlite3是文件,一个进程在写入的时候,另一个进程就无法写入!而进程间的同步,需要我们自己处理。多线程也一样,python sqlite3模块默认不允许在线程间共享 connect 对象。
多线程序列化访问比较好处理,多进程可能就需要代码自己处理 database is locked 这个异常了!
下面这段测试代码,能够跑出 database is locked 异常,以此证明本文主题的存在:
$ cat test_sqlite3.py
import multiprocessing as mp
import sqlite3
def write():
conn = sqlite3.connect('tdb')
conn.isolation_level = None
c = conn.cursor()
for i in range(1000):
c.execute("INSERT INTO mod2 VALUES (1,2,3)")
phlist = [mp.Process(target=write, args=(), daemon=True) for i in range(3)]
for ph in phlist:
ph.start()
for ph in phlist:
ph.join()
print('done')
运行时,有两个process会抛出异常:
$ python3 test_sqlite3.py
Process Process-2:
Traceback (most recent call last):
File "/usr/local/python3.8.6/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/local/python3.8.6/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "test_sqlite3.py", line 16, in write
c.execute("INSERT INTO mod2 VALUES (1,2,3)")
sqlite3.OperationalError: database is locked
Process Process-3:
Traceback (most recent call last):
File "/usr/local/python3.8.6/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/local/python3.8.6/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "test_sqlite3.py", line 16, in write
c.execute("INSERT INTO mod2 VALUES (1,2,3)")
sqlite3.OperationalError: database is locked
当看到此异常时,在sqlite3的shell中做select,也是一样的异常:
sqlite> select count(*) from mod2;
Error: database is locked
sqlite> select count(*) from mod2;
Error: database is locked
有一行代码很有趣:
conn.isolation_level = None
默认情况下,都需要调用commit函数才能真正写入数据库,而 isolation_level=None 后,对应的就是 sqlite3 的autocommit模式,也就不需要再调用commit函数了。
autocommit 顾名思义,就是每一次修改都有效,都默认支持了一次commit操作。因此 autocommit 模式下 insert 速度特别地慢!!一般别这样用。
-- EOF --
本文链接:https://www.pynote.net/archives/2570
《sqlite3.OperationalError: database is locked》有1条留言
Ctrl+D 收藏本页
©Copyright 麦新杰 Since 2019 Python笔记
符合python DB-API2.0 (PEP 249)的sqlite3模块,其成员threadsafety显示:
含义为:Threads may share the module, but not connections. [ ]