在线文档教程

BEGIN TRANSACTION

SQL As Understood By SQLite

[Top]

BEGIN TRANSACTION

begin-stmt: hide

commit-stmt: hide

rollback-stmt: hide

除了在事务内部之外,不能对数据库进行更改。任何改变数据库的命令(基本上,除了 SELECT 之外的任何 SQL 命令)都会自动启动一个事务,如果这个事务还没有生效。自动启动的事务在最后一次查询完成时提交。

事务可以使用 BEGIN 命令手动启动。这种事务通常会持续到下一个 COMMIT 或 ROLLBACK 命令。但是,如果数据库关闭或发生错误并且指定了 ROLLBACK 冲突解决算法,则事务也将 ROLLBACK 。有关 ROLLBACK 冲突解决算法的其他信息,请参阅 ON CONFLICT 子句上的文档。

END TRANSACTION 是 COMMIT 的别名。

使用 BEGIN ... COMMIT 创建的事务不会嵌套。对于嵌套事务,使用 SAVEPOINT 和 RELEASE 命令。上述语法图中显示的 ROLLBACK 命令的“TO SAVEPOINT name”子句仅适用于 SAVEPOINT 事务。尝试在事务中调用 BEGIN 命令将失败,并出现错误,无论事务是由 SAVEPOINT 还是先前的 BEGIN 启动。没有 TO 子句的 COMMIT 命令和 ROLLBACK 命令在 SAVEPOINT 事务上的作用与 BEGIN 开始的事务作用相同。

交易可以延期,立即或排他。默认的事务行为是延迟的。延迟意味着在数据库第一次访问之前,数据库上不会获取锁。因此,对于延迟事务,BEGIN 语句本身对文件系统没有任何影响。在第一次读取或写入操作之前不会获取锁。对数据库的第一次读取操作会创建 SHARED 锁,并且第一次写操作会创建一个 RESERVED 锁。由于锁的获取被推迟到需要时,另一个线程或进程可能会创建一个单独的事务并在当前线程上的 BEGIN 执行后写入数据库。如果事务是立即执行的,则在执行 BEGIN 命令后立即在所有数据库上获取 RESERVED 锁,而不用等待数据库被使用。在 BEGIN IMMEDIATE 之后,没有其他数据库连接将能够写入数据库或执行 BEGIN IMMEDIATE 或 BEGIN EXCLUSIVE 。但是,其他进程可以继续从数据库读取。独占事务会导致在所有数据库上获取 EXCLUSIVE 锁。在 BEGIN EXCLUSIVE 之后,除 read_uncommitted 连接之外,没有其他数据库连接将能够读取数据库,并且在事务完成之前没有其他连接无例外地能够写入数据库。独占事务会导致在所有数据库上获取 EXCLUSIVE 锁。在 BEGIN EXCLUSIVE 之后,除 read_uncommitted 连接之外,没有其他数据库连接将能够读取数据库,并且在事务完成之前没有其他连接无例外地能够写入数据库。独占事务会导致在所有数据库上获取 EXCLUSIVE 锁。在 BEGIN EXCLUSIVE 之后,除 read_uncommitted 连接之外,没有其他数据库连接将能够读取数据库,并且在事务完成之前没有其他连接无例外地能够写入数据库。

隐式事务(自动启动的事务,而不是 BEGIN 启动的事务)在最后一个活动语句结束时自动提交。当其准备好的陈述被重置或最终确定时,陈述即告结束。用于增量 BLOB I/O 的开放 sqlite3_blob 计为未完成的语句。sqlite3_blob 在关闭时结束。

明确的 COMMIT 命令立即运行,即使有未决的 SELECT 语句。但是,如果存在未完成的写入操作,则 COMMIT 命令将失败并显示错误代码 SQLITE_BUSY 。

如果另一个线程或进程对数据库有一个共享锁,导致 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_FULL:数据库或磁盘已满

  • SQLITE_IOERR: disk I/O error

  • SQLITE_BUSY:另一个进程正在使用的数据库

  • SQLITE_NOMEM: out or memory

对于所有这些错误,SQLite 试图撤消它正在处理的一条语句,并且保持同一事务中先前语句的更改不变,并继续执行事务。但是,根据要评估的语句和错误发生点,SQLite 可能需要回滚并取消整个事务。应用程序可以通过使用sqlite3_get_autocommit() C 语言接口来确定 SQLite 采取了哪些操作。

建议应用程序通过显式发出 ROLLBACK 命令来响应上面列出的错误。如果事务已由错误响应自动回滚,则 ROLLBACK 命令将失败并出现错误,但不会造成此损害。

未来版本的 SQLite 可能会扩展可能导致自动事务回滚的错误列表。未来版本的 SQLite 可能会改变错误响应。特别是,我们可能会选择通过导致上述错误强制无条件回滚来简化 SQLite 未来版本中的接口。