Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  START TRANSACTION, COMMIT, and ROLLBACK Statements

15.3.1 开始事务、提交和回滚语句

START TRANSACTION
    [transaction_characteristic [, transaction_characteristic] ...]

transaction_characteristic: {
    WITH CONSISTENT SNAPSHOT
  | READ WRITE
  | READ ONLY
}

BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET autocommit = {0 | 1}

这些语句提供了对事务的控制:

  • START TRANSACTIONBEGIN 启动一个新的事务。

  • COMMIT 提交当前事务,使其更改永久化。

  • ROLLBACK 回滚当前事务,取消其更改。

  • SET autocommit 禁用或启用当前会话的默认自动提交模式。

默认情况下,MySQL 以自动提交模式启用。这意味着,当不在事务中时,每个语句都是原子的,就像它被 START TRANSACTIONCOMMIT 包围一样。你不能使用 ROLLBACK 撤销其效果;然而,如果语句执行期间发生错误,语句将被回滚。

要隐式禁用自动提交模式以便单个语句系列,请使用 START TRANSACTION 语句:

START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;

使用 START TRANSACTION 后,自动提交模式将保持禁用状态,直到你使用 COMMITROLLBACK 结束事务。然后,自动提交模式将恢复到其之前的状态。

START TRANSACTION 允许多个修饰符来控制事务特征。要指定多个修饰符,请用逗号分隔。

  • 带有 WITH CONSISTENT SNAPSHOT 修饰符的 START TRANSACTION 启动了对能够执行的一致读取的存储引擎的一致读取。这仅适用于 InnoDB。其效果与发出 START TRANSACTION 语句,然后从任何 InnoDB 表中选择一样。请参阅 第 17.7.2.3 节,“一致非锁定读取”WITH CONSISTENT SNAPSHOT 修饰符不改变当前事务的隔离级别,因此它仅在当前隔离级别允许一致读取时提供一致快照。唯一允许一致读取的隔离级别是 REPEATABLE READ。对于所有其他隔离级别,WITH CONSISTENT SNAPSHOT 修饰符将被忽略。忽略时将生成警告。

  • READ WRITEREAD ONLY 修饰符设置事务访问模式。它们允许或禁止对事务中使用的表进行修改。 READ ONLY 限制禁止事务修改或锁定其他事务可见的交易和非交易表;事务仍然可以修改或锁定临时表。

    MySQL 为 InnoDB 表启用了额外的优化,以便在事务中查询时知道是只读的。指定 READ ONLY 确保在无法自动确定只读状态的情况下应用这些优化。请参阅 第 10.5.3 节,“优化 InnoDB 只读事务” 以获取更多信息。

    如果未指定访问模式,则应用默认模式。除非默认值已被更改,否则默认为读写模式。不允许在同一语句中指定 READ WRITEREAD ONLY

    在只读模式下,仍然可以使用 DML 语句更改使用 TEMPORARY 关键字创建的表。使用 DDL 语句进行的更改不被允许,就像永久表一样。

    有关事务访问模式的更多信息,包括更改默认模式的方法,请参阅 第 15.3.7 节,“SET TRANSACTION 语句”

    如果启用了 read_only 系统变量,则需要使用 CONNECTION_ADMIN 权限(或已弃用的 SUPER 权限)来使用 START TRANSACTION READ WRITE 明确启动事务。

Important

许多用于编写 MySQL 客户端应用程序的 API(例如 JDBC)提供了自己的方法来启动事务,可以(并且有时应该)使用这些方法,而不是从客户端发送 START TRANSACTION 语句。请参阅 第 31 章,《连接器和 API》,或 API 的文档,以获取更多信息。

要显式禁用自动提交模式,请使用以下语句:

SET autocommit=0;

在禁用自动提交模式时,通过将autocommit变量设置为零,事务安全表(例如InnoDBNDB)的更改不会立即生效。您必须使用COMMIT将更改存储到磁盘或ROLLBACK忽略更改。

autocommit是一个会话变量,必须为每个会话设置。要禁用每个新连接的自动提交模式,请参阅autocommit系统变量的描述,在第 7.1.8 节,“服务器系统变量”中。

BEGINBEGIN WORK作为START TRANSACTION的别名,用于启动事务。START TRANSACTION是标准 SQL 语法,是启动 ad-hoc 事务的推荐方式,并允许修饰符,而BEGIN不允许。

BEGIN语句不同于使用BEGIN ... END复合语句的第 15.6.1 节,“BEGIN ... END 复合语句”中使用的BEGIN关键字。后者不启动事务。

Note

在所有存储程序(存储过程和函数、触发器和事件)中,解析器将BEGIN [WORK]视为BEGIN ... END块的开始。在这种情况下,使用START TRANSACTION启动事务。

可选的 WORK 关键字支持 COMMITROLLBACK,同时也支持 CHAINRELEASE 子句。CHAINRELEASE 可以用于对事务完成的额外控制。系统变量 completion_type 的值将确定默认的完成行为。请参阅 第 7.1.8 节,“服务器系统变量”

AND CHAIN 子句将导致当前事务结束后立即开始一个新事务,该新事务将具有与刚刚终止的事务相同的隔离级别。新事务还将使用与刚刚终止的事务相同的访问模式(READ WRITEREAD ONLY)。 RELEASE 子句将导致服务器在终止当前事务后断开当前客户会话。包括 NO 关键字将抑制 CHAINRELEASE 完成,这可能有助于如果 completion_type 系统变量设置为默认启用链式或释放完成。

开始事务将导致任何挂起的事务被提交。请参阅 第 15.3.3 节,“隐式提交的语句”,以获取更多信息。

开始事务还将释放使用 LOCK TABLES 获取的表锁,就像您执行了 UNLOCK TABLES 一样。开始事务不会释放使用 FLUSH TABLES WITH READ LOCK 获取的全局读锁。

为了获得最佳结果,事务应该仅使用由单个事务安全存储引擎管理的表。否则,可能会出现以下问题:<|start_header_id|>assistant<|end_header_id|> Let me know when you're ready to translate the next HTML fragment!

  • 如果您使用来自多个事务安全存储引擎的表(例如 InnoDB),并且事务隔离级别不是 SERIALIZABLE,那么当一个事务提交时,另一个正在进行的事务可能只能看到第一个事务所做的一些更改。这意味着,事务的原子性不能保证在混合引擎中,并且可能会出现不一致的情况。(如果混合引擎事务很少,可以使用 SET TRANSACTION ISOLATION LEVEL 在每个事务的基础上将隔离级别设置为 SERIALIZABLE,以避免必要的不一致。)

  • 如果您在事务中使用了非事务安全表,那么对这些表的更改将立即存储,不管自动提交模式的状态如何。

  • 如果您在事务中更新了非事务安全表,然后发出 ROLLBACK 语句,将出现 ER_WARNING_NOT_COMPLETE_ROLLBACK 警告。事务安全表的更改将被回滚,但非事务安全表的更改不会被回滚。

每个事务将作为一个块存储在二进制日志中,于 COMMIT 时。(例外:非事务安全表的修改不能被回滚。如果回滚的事务包括非事务安全表的修改,则整个事务将被记录,包括一个 ROLLBACK 语句,以确保非事务安全表的修改被复制。)见 第 7.4.4 节,“二进制日志”

您可以使用 SET TRANSACTION 语句更改事务的隔离级别或访问模式。见 第 15.3.7 节,“SET TRANSACTION 语句”

回滚可能是一个缓慢的操作,可能隐式地发生,而不需要用户明确地请求它(例如,当错误发生时)。由于这个原因,SHOW PROCESSLIST 在会话的 State 列中显示 Rolling back,不仅仅是对明确使用 ROLLBACK 语句进行回滚,还包括隐式回滚。

Note

在 MySQL 8.3 中,BEGINCOMMITROLLBACK 不受 --replicate-do-db--replicate-ignore-db 规则的影响。

InnoDB 完全回滚事务时,事务设置的所有锁都会被释放。如果事务中的单个 SQL 语句由于错误(例如,重复键错误)回滚,语句设置的锁将被保留,而事务仍然保持活动状态。这是因为 InnoDB 以一种格式存储行锁,使得它不能以后知道哪个锁是由哪个语句设置的。

如果事务中的 SELECT 语句调用存储函数,而存储函数中的语句失败,那么该语句将回滚。如果随后执行 ROLLBACK,整个事务将回滚。