我有一个for循环,该循环使用我编写的sqlite管理器类对数据库进行了许多更改,但是我不确定我必须提交的频率…
for i in list: c.execute('UPDATE table x=y WHERE foo=bar') conn.commit() c.execute('UPDATE table x=z+y WHERE foo=bar') conn.commit()
基本上,我的问题是我是否必须在此处调用两次commit,或者在进行两项更改后是否只能调用一次?
conn.commit()在每个数据库更改之后,是否在过程结束时调用一次取决于几个因素。
conn.commit()
这是每个人乍一看的想法:提交对数据库的更改后,该更改对于其他连接变为可见。除非提交,否则更改仅在本地可见。由于的有限并发功能sqlite,只能在打开事务时读取数据库。
sqlite
您可以通过运行以下脚本并调查其输出来调查发生的情况:
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)] $
因此,这取决于您是否可以忍受这样的情况:同一个读者(无论是在同一脚本中还是在另一个程序中)有时会减少两个。
当要进行大量更改时,其他两个方面进入了场景:
数据库更改的性能在很大程度上取决于您执行更改的方式。它已经作为常见问题解答指出:
实际上,在普通的台式计算机上,SQLite每秒可以轻松地执行50,000个或更多的INSERT语句。但是它每秒只能进行几十笔交易。[…]
在这里了解详细信息绝对有帮助,因此请不要犹豫,点击链接并深入研究。另请参见此令人敬畏的分析。它是用C编写的,但结果将是相似的,而在Python中也是如此。
注意:虽然两个资源都引用INSERT,但是UPDATE对于相同的参数,情况将非常相似。
INSERT
UPDATE
如上所述,一个打开的(未提交的)事务将阻止并发连接的更改。因此,通过执行更改并联合提交全部更改,将对数据库的许多更改捆绑到单个事务中是很有意义的。
不幸的是,有时计算更改可能需要一些时间。当并发访问成为问题时,您将不需要锁定数据库那么长时间。因为它可以成为相当棘手收集挂起UPDATE和INSERT语句不知何故,这通常会留给你的性能和独特的锁定之间的权衡。