### 13.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}
```

这些语句提供对使用的控制[交易](glossary.html#glos_transaction)：

-   `开始交易`要么`开始`开始新的交易。

-   `犯罪`提交当前事务，使其更改永久化。

-   `回滚`回滚当前事务，取消其更改。

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

    默认情况下，MySQL 运行[自动提交](glossary.html#glos_autocommit)模式启用。这意味着，当不在事务中时，每个语句都是原子的，就好像它被包围`开始交易`和`犯罪`.你不能使用`回滚`撤消效果；但是，如果在语句执行期间发生错误，则该语句将回滚。

    要为单个语句系列隐式禁用自动提交模式，请使用`开始交易`陈述：


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

和`开始交易`, 自动提交保持禁用状态，直到您使用以下命令结束事务`犯罪`要么`回滚`.然后自动提交模式恢复到之前的状态。

`开始交易`允许控制事务特征的几个修饰符。要指定多个修饰符，请用逗号分隔它们。

-   这`具有一致的快照`修饰符开始一个[一致读](glossary.html#glos_consistent_read)对于能够做到这一点的存储引擎。这仅适用于`InnoDB`.效果和发出一个一样`开始交易`其次是[`选择`](select.html)从任何`InnoDB`桌子。看[第 15.7.2.3 节，“一致的非锁定读取”](innodb-consistent-read.html).这`具有一致的快照`修饰符不改变当前事务[隔离级别](glossary.html#glos_isolation_level)，因此仅当当前隔离级别是允许一致读取的隔离级别时，它才提供一致的快照。唯一允许一致读取的隔离级别是[`可重复阅读`](innodb-transaction-isolation-levels.html#isolevel_repeatable-read).对于所有其他隔离级别，`具有一致的快照`子句被忽略。时会生成警告`具有一致的快照`子句被忽略。

-   这`读写`和`只读`修饰符设置事务访问模式。它们允许或禁止对事务中使用的表进行更改。这`只读`限制防止事务修改或锁定对其他事务可见的事务和非事务表；该事务仍然可以修改或锁定临时表。

    MySQL 为以下查询启用了额外的优化`InnoDB`已知事务为只读时的表。指定`只读`确保在无法自动确定只读状态的情况下应用这些优化。看[第 8.5.3 节，“优化 InnoDB 只读事务”](innodb-performance-ro-txn.html)了解更多信息。

    如果未指定访问模式，则应用默认模式。除非更改了默认值，否则它是读/写的。不允许同时指定`读写`和`只读`在同一个声明中。

    在只读模式下，仍然可以更改使用`暂时的`使用 DML 语句的关键字。与永久表一样，不允许使用 DDL 语句进行更改。

    有关事务访问模式的更多信息，包括更改默认模式的方法，请参阅[第 13.3.7 节，“SET TRANSACTION 语句”](set-transaction.html).

    如果[`只读`](server-system-variables.html#sysvar_read_only)启用系统变量，显式启动事务`开始交易 读写`需要[`CONNECTION_ADMIN`](privileges-provided.html#priv_connection-admin)特权（或已弃用的[`极好的`](privileges-provided.html#priv_super)特权）。

重要的

许多用于编写 MySQL 客户端应用程序（例如 JDBC）的 API 提供了自己的方法来启动可以（有时应该）使用的事务，而不是发送`开始交易`来自客户的声明。看[第 29 章，*连接器和 API*](connectors-apis.html)，或您的 API 的文档，以获取更多信息。

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

```
SET autocommit=0;
```

通过设置禁用自动提交模式后[`自动提交`](server-system-variables.html#sysvar_autocommit)变量为零，更改事务安全表（例如[`InnoDB`](innodb-storage-engine.html)要么[`新开发银行`](mysql-cluster.html)) 不会立即永久化。你必须使用[`犯罪`](commit.html)将更改存储到磁盘或`回滚`忽略更改。

[`自动提交`](server-system-variables.html#sysvar_autocommit)是一个会话变量，必须为每个会话设置。要为每个新连接禁用自动提交模式，请参阅[`自动提交`](server-system-variables.html#sysvar_autocommit)系统变量在[第 5.1.8 节，“服务器系统变量”](server-system-variables.html).

`开始`和`开始工作`支持作为别名`开始交易`用于发起交易。`开始交易`是标准 SQL 语法，是启动 ad-hoc 事务的推荐方式，并允许修饰符`开始`才不是。

这`开始`声明不同于使用`开始`开头的关键字[`开始...结束`](begin-end.html)复合语句。后者不开始交易。看[第 13.6.1 节，“BEGIN ... END 复合语句”](begin-end.html).

笔记

在所有存储程序（存储过程和函数、触发器和事件）中，解析器将`开始[工作]`作为一个开始[`开始...结束`](begin-end.html)堵塞。在这种情况下开始交易[`开始交易`](commit.html)反而。

可选的`工作`支持关键字`犯罪`和`回滚`, 和`链`和`发布`条款。`链`和`发布`可用于对事务完成进行额外控制。的价值[`完成类型`](server-system-variables.html#sysvar_completion_type)系统变量确定默认的完成行为。看[第 5.1.8 节，“服务器系统变量”](server-system-variables.html).

这`和链`子句使新事务在当前事务结束后立即开始，并且新事务与刚刚终止的事务具有相同的隔离级别。新事务也使用相同的访问模式（`读写`要么`只读`) 作为刚刚终止的交易。这`发布`子句使服务器在终止当前事务后断开当前客户端会话。包括`不`关键字抑制`链`要么`发布`完成，如果[`完成类型`](server-system-variables.html#sysvar_completion_type)系统变量默认设置为导致链接或释放完成。

开始事务会导致提交任何待处理的事务。看[第 13.3.3 节，“导致隐式提交的语句”](implicit-commit.html)， 了解更多信息。

开始事务也会导致获取表锁[`锁定表`](lock-tables.html)被释放，好像你已经被处决了[`解锁桌子`](lock-tables.html).开始一个事务不会释放一个全局读锁[`带读锁的刷新表`](flush.html#flush-tables-with-read-lock).

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

-   如果您使用来自多个事务安全存储引擎的表（例如`InnoDB`)，并且事务隔离级别不是[`可序列化`](innodb-transaction-isolation-levels.html#isolevel_serializable)，当一个事务提交时，另一个使用相同表的正在进行的事务可能只看到第一个事务所做的一些更改。也就是说，混合引擎无法保证事务的原子性，并可能导致不一致。（如果混合引擎事务不频繁，您可以使用[`设置事务隔离级别`](set-transaction.html)将隔离级别设置为[`可序列化`](innodb-transaction-isolation-levels.html#isolevel_serializable)必要时以每笔交易为基础。）

-   如果您在事务中使用非事务安全的表，则对这些表的更改会立即存储，而不管自动提交模式的状态如何。

-   如果您发出一个[`回滚`](commit.html)更新事务中的非事务表后的语句，[`ER_WARNING_NOT_COMPLETE_ROLLBACK`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_warning_not_complete_rollback)出现警告。回滚对事务安全表的更改，但不会回滚对非事务安全表的更改。

    每个事务都以一个块的形式存储在二进制日志中，在[`犯罪`](commit.html).不记录回滚的事务。(**例外**: 对非事务表的修改不能回滚。如果回滚的事务包括对非事务性表的修改，则整个事务将使用[`回滚`](commit.html)最后声明以确保复制对非事务性表的修改。）请参阅[第 5.4.4 节，“二进制日志”](binary-log.html).

    您可以更改事务的隔离级别或访问模式[`设置交易`](set-transaction.html)陈述。看[第 13.3.7 节，“SET TRANSACTION 语句”](set-transaction.html).

    回滚可能是一个缓慢的操作，可能会在用户没有明确要求的情况下隐式发生（例如，发生错误时）。因为这，[`显示进程列表`](show-processlist.html)显示`滚回来`在里面`状态`会话列，不仅用于显式回滚[`回滚`](commit.html)声明，但也适用于隐式回滚。

笔记

在 MySQL 8.0 中，`开始`,`犯罪`， 和`回滚`不受影响[`--replicate-do-db`](replication-options-replica.html#option_mysqld_replicate-do-db)要么[`--replicate-ignore-db`](replication-options-replica.html#option_mysqld_replicate-ignore-db)规则。

什么时候`InnoDB`执行一个事务的完整回滚，该事务设置的所有锁都被释放。如果事务中的单个 SQL 语句由于错误（例如重复键错误）而回滚，则在事务保持活动状态时保留由语句设置的锁。发生这种情况是因为`InnoDB`以一种格式存储行锁，这样它就无法知道哪个锁是由哪个语句设置的。

如果一个[`选择`](select.html)事务中的语句调用存储函数，并且存储函数中的语句失败，则该语句回滚。如果[`回滚`](commit.html)随后为事务执行，整个事务回滚。
