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 TRANSACTION
或BEGIN
开始一个新事务。COMMIT
提交当前事务,使其更改永久生效。ROLLBACK
回滚当前事务,取消其更改。SET autocommit
禁用或启用当前会话的默认自动提交模式。
默认情况下,MySQL 以 自动提交 模式运行。这意味着,当不处于事务中时,每个语句都是原子的,就好像它被 START TRANSACTION
和 COMMIT
包围一样。您不能使用 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
,自动提交将保持禁用状态,直到您使用 COMMIT
或 ROLLBACK
结束事务为止。然后自动提交模式将恢复到其先前状态。
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 WRITE
和READ ONLY
修饰符用于设置事务访问模式。它们允许或禁止对事务中使用的表进行更改。READ ONLY
限制阻止事务修改或锁定对其他事务可见的事务表和非事务表;事务仍然可以修改或锁定临时表。当已知事务为只读时,MySQL 会对
InnoDB
表上的查询启用额外的优化。指定READ ONLY
可确保在无法自动确定只读状态的情况下应用这些优化。请参见第 10.5.3 节,“优化 InnoDB 只读事务”,以获取更多信息。如果没有指定访问模式,则使用默认模式。除非已更改默认值,否则为读/写模式。不允许在同一个语句中同时指定
READ WRITE
和READ 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
变量设置为零来禁用自动提交模式后,对事务安全表(例如 InnoDB
或 NDB
的表)的更改不会立即永久保存。您必须使用 COMMIT
将更改存储到磁盘,或者使用 ROLLBACK
忽略这些更改。
autocommit
是一个会话变量,必须为每个会话设置。要为每个新连接禁用自动提交模式,请参见第 7.1.8 节,“服务器系统变量” 中对 autocommit
系统变量的说明。
BEGIN
和 BEGIN WORK
被支持为 START TRANSACTION
的别名,用于启动事务。START TRANSACTION
是标准 SQL 语法,是启动临时事务的推荐方法,并且允许 BEGIN
不允许的修饰符。
BEGIN
语句不同于用于启动 BEGIN ... END
复合语句的 BEGIN
关键字的用法。后者不会开始事务。请参见第 15.6.1 节,“BEGIN ... END 复合语句”。
在所有存储程序(存储过程和函数、触发器和事件)中,解析器将 BEGIN [WORK]
视为 BEGIN ... END
块的开始。在此上下文中,请使用 START TRANSACTION
代替启动事务。
COMMIT
和 ROLLBACK
支持可选的 WORK
关键字,以及 CHAIN
和 RELEASE
子句。CHAIN
和 RELEASE
可用于对事务完成进行额外的控制。completion_type
系统变量的值决定了默认完成行为。请参见第 7.1.8 节,“服务器系统变量”。
AND CHAIN
子句会导致在当前事务结束时立即开始一个新的事务,并且新事务具有与刚刚终止的事务相同的隔离级别。新事务还使用与刚刚终止的事务相同的访问模式 (READ WRITE
或 READ ONLY
)。RELEASE
子句会导致服务器在终止当前事务后断开当前客户端会话的连接。包括 NO
关键字会抑制 CHAIN
或 RELEASE
完成,如果 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 PROCESSLIST
在 State
列中为会话显示 Rolling back
,不仅针对使用 ROLLBACK
语句显式执行的回滚,也针对隐式回滚。
在 MySQL 8.4 中,BEGIN
、COMMIT
和 ROLLBACK
不受 --replicate-do-db
或 --replicate-ignore-db
规则的影响。
当 InnoDB
对事务执行完全回滚时,将释放事务设置的所有锁。如果事务中的单个 SQL 语句由于错误(例如重复键错误)而回滚,则该语句设置的锁将保留,而事务将保持活动状态。发生这种情况是因为 InnoDB
以一种格式存储行锁,使其无法事后知道哪个锁是由哪个语句设置的。
如果事务中的 SELECT
语句调用存储函数,并且存储函数中的语句失败,则该语句将回滚。如果随后对事务执行 ROLLBACK
,则整个事务将回滚。