文档首页
MySQL 8.4 参考手册
相关文档 下载此手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  START TRANSACTION、COMMIT 和 ROLLBACK 语句

15.3.1 START TRANSACTION、COMMIT 和 ROLLBACK 语句

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 修饰符用于启动对支持它的存储引擎的一致性读取。这仅适用于 InnoDB。其效果等同于发出 START TRANSACTION,然后从任何 InnoDB 表中执行SELECT。请参见第 17.7.2.3 节,“一致性非锁定读取”WITH CONSISTENT SNAPSHOT 修饰符不会更改当前事务的隔离级别,因此它仅在当前隔离级别允许一致性读取时才提供一致性快照。唯一允许一致性读取的隔离级别是 REPEATABLE READ。对于所有其他隔离级别,WITH CONSISTENT SNAPSHOT 子句将被忽略。当忽略 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 系统变量,则显式使用 START TRANSACTION READ WRITE 启动事务需要 CONNECTION_ADMIN 权限(或已弃用的 SUPER 权限)。

重要

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

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

SET autocommit=0;

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

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

BEGINBEGIN WORK 被支持为 START TRANSACTION 的别名,用于启动事务。START TRANSACTION 是标准 SQL 语法,是启动临时事务的推荐方法,并且允许 BEGIN 不允许的修饰符。

BEGIN 语句不同于用于启动 BEGIN ... END 复合语句的 BEGIN 关键字的用法。后者不会开始事务。请参见第 15.6.1 节,“BEGIN ... END 复合语句”

注意

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

COMMITROLLBACK 支持可选的 WORK 关键字,以及 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 获取的全局读锁。

为了获得最佳效果,事务应该仅使用由单个事务安全存储引擎管理的表执行。否则,可能会出现以下问题

  • 如果使用来自多个事务安全存储引擎(例如 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 PROCESSLISTState 列中为会话显示 Rolling back,不仅针对使用 ROLLBACK 语句显式执行的回滚,也针对隐式回滚。

注意

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

InnoDB 对事务执行完全回滚时,将释放事务设置的所有锁。如果事务中的单个 SQL 语句由于错误(例如重复键错误)而回滚,则该语句设置的锁将保留,而事务将保持活动状态。发生这种情况是因为 InnoDB 以一种格式存储行锁,使其无法事后知道哪个锁是由哪个语句设置的。

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