事务性语句和锁定语句
START TRANSACTION、COMMIT 和 ROLLBACK
1. START TRANSACTION
2. [transaction_characteristic [, transaction_characteristic] ...]
3.
4. transaction_characteristic: {
5. WITH CONSISTENT SNAPSHOT
6. | READ WRITE
7. | READ ONLY
8. }
9.
10. BEGIN [WORK]
11. COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
12. ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
13. SET autocommit = {0 | 1}
这些语句提供了对事务使用的控制:
● START TRANSACTION 或 BEGIN 启动新事务。
● COMMIT 提交当前事务,使其更改永久化。
● ROLLBACK 回滚当前事务,取消其更改。
● SET autocommit 将禁用或启用当前会话的默认自动提交模式。
默认情况下,MySQL 在自动提交模式下运行。这意味着,如果不是在事务内部,每个语句都是原子的,就好像它被 START TRANSACTION 和 COMMIT 包围一样。不能使用 ROLLBACK 撤消效果;但是,如果在语句执行过程中发生错误,语句将回滚。
要隐式禁用一系列单个语句的自动提交模式,请使用 START TRANSACTION 语句:
1. START TRANSACTION;
2. SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
3. UPDATE table2 SET summary=@A WHERE type=1;
4. COMMIT;
使用 START TRANSACTION,自动提交保持禁用状态,直到使用 COMMIT 或 ROLLBACK 结束事务。然后,自动提交模式将恢复到以前的状态。
START TRANSACTION 允许多个修饰符控制事务特征。要指定多个修饰符,请用逗号分隔它们。
● WITH CONSISTENT SNAPSHOT 修饰符为支持一致性读取的存储引擎启动一致性读取。这只适用于 InnoDB。其效果与发出 START TRANSACTION 指令,然后从任何 InnoDB 表中执行 SELECT 一样。WITH CONSISTENT SNAPSHOT 修饰符不会更改当前事务隔离级别,因此仅当当前隔离级别允许一致读取时,它才提供一致的快照。唯一允许一致读取的隔离级别是 REPEATABLE READ。所有其他隔离级别,将忽略 WITH CONSISTENT SNAPSHOT 子句。忽略 WITH CONSISTENT SNAPSHOT 子句时,将生成警告。
● READ WRITE 和 READ ONLY 修饰符设置事务访问模式。它们允许或禁止对事务中使用的表进行更改。READ ONLY 阻止事务修改或锁定对其他事务可见的事务表和非事务表;事务仍然可以修改或锁定临时表。
当已知事务为只读时,MySQL 支持对 InnoDB 表的查询进行额外优化。指定 READ ONLY 可确保在无法自动确定只读状态的情况下应用这些优化。
如果未指定访问模式,则应用默认模式。除非默认值已更改,否则为读/写。不允许在同一语句中同时指定 READ WRITE 和 READ ONLY。
在只读模式下,仍然可以使用 DML 语句更改用 TEMPORARY 关键字创建的表。但不允许使用 DDL 语句进行更改。
如果启用 read_only 系统变量,则使用 START TRANSACTION READ WRITE 显式启动事务需要 CONNECTION_ADMIN 权限(或不推荐使用的 SUPER 权限)。
重要
许多用于编写 MySQL 客户端应用程序的 API (如JDBC)提供了自己的启动事务的方法,可以使用这些方法(有时也应该),而不是从客户端发送 START TRANSACTION 语句。
要显式禁用自动提交模式,请使用以下语句:
1. SET autocommit=0;
通过将 autocommit 变量设置为零来禁用自动提交模式后,对事务安全表(如 InnoDB 或 NDB 的表)的更改不会立即永久化。必须使用 COMMIT 才能将更改存储到磁盘,或使用 ROLLBACK 放弃更改。
autocommit 是一个会话变量,必须为每个会话单独设置。
BEGIN 和 BEGIN WORK 作为 START TRANSACTION 的别名受到支持,用于启动事务。START TRANSACTION 是标准的 SQL 语法,是启动特定事务的推荐方法,并且允许使用 BEGIN 不支持的修饰符。
BEGIN 语句不同于使用 BEGIN 关键字来启动 BEGIN ... END 的复合语句,后者不启动事务。
注意
在所有存储程序(存储过程和函数、触发器和事件)中,解析器将 BEGIN [WORK] 视为 BEGIN ... END 块的开始。在这个上下文中用 START TRANSACTION 开始事务。
COMMIT 和 ROLLBACK 支持可选的 WORK 关键字,CHAIN 和 RELEASE 子句也是如此。CHAIN 和 RELEASE 可用于对事务结束的额外控制。completion_type 系统变量的值决定默认结束行为。
AND CHAIN 子句使新事务在当前事务结束时立即开始,并且新事务与刚刚终止的事务具有相同的隔离级别。新事务还使用与刚刚终止的事务相同的访问模式(READ WRITE 或 READ ONLY)。RELEASE 子句使服务器在终止当前事务后断开当前客户端的会话。包含 NO 关键字会抑制 CHAIN 或 RELEASE 结束,如果 completion_type 系统变量默认设置为链接或释放结束行为,这将非常有用。
开始一个事务会导致所有挂起的事务被提交。
开始一个事务也会使通过 LOCK TABLES 获取的表锁被释放,就像执行了 UNLOCK TABLES 一样。开始一个事务不会释放通过 FLUSH TABLES WITH READ LOCK 获得的全局读锁。
为了获得最佳结果,应该只使用由单个事务安全存储引擎管理的表来执行事务。否则,可能会出现以下问题:
● 如果使用来自多个事务安全存储引擎(如 InnoDB)的表,并且事务隔离级别不是 SERIALIZABLE,则当一个事务提交时,使用相同表的另一个正在进行的事务可能只看到第一个事务所做的一些更改。也就是说,使用混合引擎不能保证事务的原子性,可能会导致数据不一致。(如果混合引擎事务很少发生,则可以根据需要使用 SET TRANSACTION ISOLATION LEVEL 将每个事务的隔离级别设置为SERIALIZABLE。)
● 如果在事务中使用的表不是事务安全的,则对这些表所做的更改将立即存储,而不管自动提交模式的状态如何。
●如果在事务内更新非事务表后发出 ROLLBACK 语句,则会出现 ER_WARNING_NOT_COMPLETE_ROLLBACK 警告。回滚对事务安全表的更改,但不会回滚对非事务安全表的更改。
提交时,每个事务都存储在二进制日志中的一个块中。不会记录回滚的事务。(例外:无法回滚对非事务表的修改。如果回滚的事务包括对非事务表的修改,则整个事务将在结尾使用 ROLLBACK 语句进行记录,以确保复制对非事务表的修改。)
可以使用 SET TRANSACTION 语句更改事务的隔离级别或访问模式。
回滚可能是一个缓慢的操作,可能在用户没有明确请求的情况下隐式发生(例如,当发生错误时)。因此,SHOW PROCESSLIST 在会话的 State 列中显示 Rolling back,这不仅用于使用 ROLLBACK 语句执行的显式回滚,还包括隐式回滚。
注意
在 MySQL 8.0 中,BEGIN、COMMIT 和 ROLLBACK 不受 --replicate-do-db 或 --replicate-ignore-db 规则的影响。
当 InnoDB 执行事务的完全回滚时,该事务设置的所有锁都会被释放。如果事务中的单个 SQL 语句由于错误(如重复键错误)而回滚,则在事务保持活动状态的同时保留由该语句设置的锁。发生这种情况是因为 InnoDB 以一种格式存储行锁,它无法知道哪一个锁是由哪个语句设置的。
如果事务中的 SELECT 语句调用存储函数,而存储函数中的语句失败,则该语句将回滚。如果随后对事务执行 ROLLBACK,则整个事务回滚。
官方网址:
https://dev.mysql.com/doc/refman/8.0/en/commit.html