【问题标题】:Commit behavior and atomicity in python sqlite3 modulepython sqlite3模块中的提交行为和原子性
【发布时间】:2012-11-18 12:58:03
【问题描述】:

如果我想创建一个表并在另一个表中插入一个新条目,可以这样吗? 在 sqlite 模块中成为原子的?

参考http://docs.python.org/2/library/sqlite3.html的文档:

默认情况下,sqlite3 模块在 数据修改语言 (DML) 语句(即 INSERT/UPDATE/DELETE/REPLACE),并隐式提交事务 在非 DML、非查询语句之前(即除 SELECT 或上述)。

因此,如果您在事务中并发出 CREATE 之类的命令 TABLE ...,VACUUM,PRAGMA,sqlite3 模块将隐式提交 在执行该命令之前。这样做有两个原因。 首先是其中一些命令在其中不起作用 交易。另一个原因是 sqlite3 需要跟踪 事务状态(事务是否处于活动状态)。

我不确定这第二段是否适用于自动启动 交易或手动和自动交易。

Sqlite 文档http://www.sqlite.org/lang_transaction.html 告诉我们手动交易 在明确的 COMMIT 之前不会提交:

可以使用 BEGIN 命令手动启动事务。这样的 事务通常持续到下一次 COMMIT 或 ROLLBACK 命令。

所以假设我们有这样的东西:

con = sqlite3.connect(fdb) 
cur = con.cursor()

sql = 'begin transaciton'
cur.execute(sql)    

sql = 'CREATE TABLE some-table ...
cur.execute(sql)

# *** is there an implicit commit at this point ?! ***

sql = 'INSERT INTO  another-table ...
cur.execute(sql)

con.commit()

这是原子的,还是 python sqlite 在create table 语句之后提交? 有没有办法让它原子化?

【问题讨论】:

    标签: python sqlite commit atomic


    【解决方案1】:

    Python SQLite3 库即使在不需要的地方也会插入自动提交。

    要使您的整个事务原子化,请使用任何其他 Python SQLite 包装器,例如 APSW

    【讨论】:

    • 我正在通过打开两个单独的 sqlite3 shell 并在一个中运行事务并在另一个中检查结果来进行测试。是的,你是对的。
    • 如果 sqlite3 像这样取消原子性,他们至少应该在文档中突出显示这样的问题。
    • 目前有一个关于这个问题的open bug,但从 cmets 的外观来看,对于 Python 2.x(由于向后兼容性问题)和 Python 3.x 不太可能发生任何事情......好吧,已经好几年了,似乎没有太大的动静。还值得注意的是(来自那个 bug 的 cmets),仅在 DML 语句之前插入 cmets 会导致使用 sqlite3 模块进行隐式提交(换句话说,它基本上被破坏了)。
    【解决方案2】:

    您不能以原子方式执行此操作。每当您执行 CREATE TABLE .. 语句时,Python SQLite 库都会隐式发出 COMMIT,因为 SQLite 不支持在事务处于活动状态时执行 CREATE TABLE .. 语句。

    您可以通过在 python 解释器和sqlite3 命令行工具中打开数据库来测试这一点。发出CREATE TABLE .. 语句后,您可以在sqlite3 命令行工具中运行.schema 命令并查看该语句的结果。

    请注意,这意味着您在事务中CREATE TABLE .. 语句之前所做的任何事情也将被提交。换一种方式来看,CREATE TABLE .. 语句首先提交,然后开始一个完全事务。

    【讨论】:

    • 谢谢 - 订单重要吗?!如果我们先插入然后创建表,那么我们可以获得这种特定情况的原子性吗?
    • 不,您仍然会得到两个单独的交易。表创建可能会失败,并且您的插入仍在提交中。自己试试;进行插入(不提交),然后再次创建 same table。您将收到操作错误(表已存在),但插入将已提交。
    • 只是 Python 库进行了提交;当您处于显式事务中时,SQLite 本身永远不会自动提交。
    • @CL.:你是对的,我误读了引用的文档。更新了我的答案。
    • SQLite 支持事务中的任何 DML 和 DDL 语句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 2015-10-16
    • 2014-08-31
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多