您是否在每次数据库更改后的过程结束时调用conn.commit() 取决于几个因素。
并发读者看到什么
这是每个人第一眼看到的:当对数据库的更改被提交时,它对其他连接变得可见。除非它被提交,否则它只会在本地对进行更改的连接保持可见。由于sqlite 的并发特性有限,只能在事务打开时读取数据库。
您可以通过运行following script 并调查其输出来调查发生了什么:
import os
import sqlite3
_DBPATH = "./q6996603.sqlite"
def fresh_db():
if os.path.isfile(_DBPATH):
os.remove(_DBPATH)
with sqlite3.connect(_DBPATH) as conn:
cur = conn.cursor().executescript("""
CREATE TABLE "mytable" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT, -- rowid
"data" INTEGER
);
""")
print "created %s" % _DBPATH
# functions are syntactic sugar only and use global conn, cur, rowid
def select():
sql = 'select * from "mytable"'
rows = cur.execute(sql).fetchall()
print " same connection sees", rows
# simulate another script accessing tha database concurrently
with sqlite3.connect(_DBPATH) as conn2:
rows = conn2.cursor().execute(sql).fetchall()
print " other connection sees", rows
def count():
print "counting up"
cur.execute('update "mytable" set data = data + 1 where "id" = ?', (rowid,))
def commit():
print "commit"
conn.commit()
# now the script
fresh_db()
with sqlite3.connect(_DBPATH) as conn:
print "--- prepare test case"
sql = 'insert into "mytable"(data) values(17)'
print sql
cur = conn.cursor().execute(sql)
rowid = cur.lastrowid
print "rowid =", rowid
commit()
select()
print "--- two consecutive w/o commit"
count()
select()
count()
select()
commit()
select()
print "--- two consecutive with commit"
count()
select()
commit()
select()
count()
select()
commit()
select()
输出:
$ python try.py
created ./q6996603.sqlite
--- prepare test case
insert into "mytable"(data) values(17)
rowid = 1
commit
same connection sees [(1, 17)]
other connection sees [(1, 17)]
--- two consecutive w/o commit
counting up
same connection sees [(1, 18)]
other connection sees [(1, 17)]
counting up
same connection sees [(1, 19)]
other connection sees [(1, 17)]
commit
same connection sees [(1, 19)]
other connection sees [(1, 19)]
--- two consecutive with commit
counting up
same connection sees [(1, 20)]
other connection sees [(1, 19)]
commit
same connection sees [(1, 20)]
other connection sees [(1, 20)]
counting up
same connection sees [(1, 21)]
other connection sees [(1, 20)]
commit
same connection sees [(1, 21)]
other connection sees [(1, 21)]
$
因此,这取决于您是否可以忍受当前阅读器(无论是在同一个脚本中还是在另一个程序中)有时会落后两个的情况。
当要进行大量更改时,另外两个方面进入场景:
性能
数据库更改的性能很大程度上取决于您如何进行更改。它已经被标注为FAQ:
实际上,SQLite 在普通台式计算机上每秒可以轻松执行 50,000 或更多的 INSERT 语句。但它每秒只会进行几十次交易。 [...]
了解此处的详细信息绝对有帮助,因此请随时关注link 并深入了解。另请参阅此awsome analysis。它是用 C 语言编写的,但结果与 Python 中的结果相似。
注意:虽然这两个资源都引用了 INSERT,但对于相同的参数,UPDATE 的情况将非常相似。
独占锁定数据库
正如上面已经提到的,一个打开的(未提交的)事务将阻止来自并发连接的更改。因此,通过执行它们并共同提交所有这些更改,将数据库的许多更改捆绑到单个事务中是有意义的。
不幸的是,有时计算更改可能需要一些时间。当并发访问是一个问题时,您不会希望将数据库锁定那么长时间。因为以某种方式收集待处理的 UPDATE 和 INSERT 语句会变得相当棘手,这通常会让您在性能和排他锁定之间进行权衡。