除在事务内外,不会发生读取或写入。如果一个数据库尚未生效,那么任何访问数据库的命令(基本上是任何SQL命令,除了几个PRAGMA语句除外)都将自动启动一个事务。最后一条SQL语句完成时,将提交自动启动的事务。
可以使用BEGIN命令手动启动事务。这样的事务通常会持续到下一个COMMIT或ROLLBACK命令为止。但是,如果数据库关闭或发生错误并且指定了ROLLBACK冲突解决算法,则事务也将回滚。有关 ROLLBACK冲突解决算法的更多信息,请参见ON CONFLICT子句的文档。
END TRANSACTION是COMMIT的别名。
使用BEGIN ... COMMIT创建的事务不会嵌套。对于嵌套事务,请使用SAVEPOINT和RELEASE命令。上面的语法图中显示的ROLLBACK命令的“ TO SAVEPOINT名称”子句仅适用于SAVEPOINT 事务。无论事务是由SAVEPOINT启动还是由先前的BEGIN启动,尝试在事务内调用BEGIN命令都将失败并显示错误。不带TO子句的COMMIT命令和ROLLBACK命令在SAVEPOINT事务上的作用与对BEGIN启动的事务的作用相同。
SQLite支持来自单独的数据库连接的多个同时读取事务,这些事务可能在单独的线程或进程中进行,但仅一个同时写入事务。
读事务仅用于读取。写入事务允许读取和写入。读事务由SELECT语句启动,写事务由CREATE,DELETE,DROP,INSERT或UPDATE之类的语句(统称为“写语句”)启动。如果在读事务处于活动状态时发生写语句,则在可能的情况下将读事务升级为写事务。如果某些其他数据库连接已经修改了数据库或正在修改数据库,则无法升级到写事务,并且SQLITE_BUSY会导致写语句失败。
当读取事务处于活动状态时,启动读取事务的数据库连接将看不到由单独的数据库连接实现的对数据库的任何更改。如果数据库连接X持有读取的事务,则其他一些数据库连接Y可能会在X的事务仍处于打开状态时更改数据库的内容,但是X直到事务结束后才能看到这些更改。当读取事务处于活动状态时,X将继续查看数据库的历史快照,然后再进行Y进行的更改。
事务可以是DEFERRED,IMMEDIATE或EXCLUSIVE。默认事务行为是DEFERRED。
DEFERRED表示直到第一次访问数据库后,事务才真正开始。在内部,BEGIN DEFERRED语句仅在数据库连接上设置一个标志,该标志将关闭通常在最后一条语句完成时发生的自动提交。这将导致自动开始的事务持续存在,直到显式COMMIT或ROLLBACK或由于错误或ON CONFLICT ROLLBACK子句引起回滚为止。如果BEGIN DEFERRED之后的第一个语句是SELECT,则将启动读取事务。如果可能,随后的写语句会将事务升级为写事务,或者返回SQLITE_BUSY。如果BEGIN DEFERRED之后的第一个语句是写语句,则将启动写事务。
IMMEDIATE使数据库连接立即开始新的写操作,而无需等待写语句。如果另一个写连接在另一个数据库连接上已经处于活动状态,则BEGIN IMMEDIATE可能会失败并显示SQLITE_BUSY。
EXCLUSIVE与IMMEDIATE相似,因为立即开始写事务。EXCLUSIVE和IMMEDIATE在WAL模式下是相同的,但是在其他日记记录模式下,EXCLUSIVE可以防止其他数据库连接在事务进行过程中读取数据库。
当最后一个活动语句完成时,将自动提交隐式事务(自动启动的事务,而不是由BEGIN启动的事务)。一条语句在其最后一个游标关闭时完成,这肯定会在重置或 结束已准备好的语句时发生。某些语句可能在重置或完成之前出于事务控制的目的而“完成”,但不能保证这一点。确保语句“完成”的唯一方法是在该语句上调用sqlite3_reset()或 sqlite3_finalize()。用于增量BLOB I / O的打开的sqlite3_blob也视为未完成的语句。该sqlite3_blob关闭时完成。
即使有未决的SELECT语句,显式COMMIT命令也会立即运行。但是,如果有挂起的写操作,则COMMIT命令将失败,并显示错误代码SQLITE_BUSY。
如果另一个线程或进程具有打开的读取连接,则 尝试执行COMMIT可能还会导致SQLITE_BUSY返回代码。当COMMIT以这种方式失败时,事务将保持活动状态,并且在读者有机会清除之后,可以稍后重试COMMIT。
在非常旧的SQLite版本(版本3.7.11-2012-03-20之前)中,如果有任何待处理的查询,则ROLLBACK将失败,并显示错误代码 SQLITE_BUSY。在较新版本的SQLite中,ROLLBACK将继续执行,并且挂起的语句通常会中止,从而导致它们返回SQLITE_ABORT或 SQLITE_ABORT_ROLLBACK错误。在SQLite版本3.8.8(2015-01-16)及更高版本中,只要ROLLBACK不修改数据库架构,待处理的读取将在ROLLBACK之后继续起作用。
如果PRAGMA journal_mode设置为OFF(从而禁用回滚日志文件),则ROLLBACK命令的行为是不确定的。
如果事务中发生某些类型的错误,则该事务可能会自动回滚,也可能不会自动回滚。可能导致自动回滚的错误包括:
对于所有这些错误,SQLite尝试仅撤消正在处理的一个语句,并保留同一事务中先前语句的更改不变,然后继续进行事务。但是,根据要评估的语句和发生错误的时间点,SQLite可能有必要回滚并取消整个事务。应用程序可以通过使用sqlite3_get_autocommit() C语言接口来判断SQLite采取了哪种行动 。
建议应用程序通过显式发出ROLLBACK命令来响应上面列出的错误。如果事务已由错误响应自动回滚,则ROLLBACK命令将失败并显示错误,但不会因此而受到损害。
SQLite的未来版本可能会扩展可能导致自动事务回滚的错误列表。未来版本的SQLite可能会更改错误响应。特别是,我们可能选择通过导致上述错误强制执行无条件回滚来简化SQLite未来版本中的接口。