MySQL: 自动提交标志打开但事务仍然可以回滚

MySQL: autocommit flag is on but transaction still can rollback

我使用的是 MariaDB 版本 10.3.13。我上次检查时,autocommit 标志已打开。

MariaDB> SHOW VARIABLES WHERE Variable_name='autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+

正如我在文档中读到的那样,当自动提交开启时,您无法按规定回滚事务 here

By default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk to make it permanent. The change cannot be rolled back.

所以我写了一个小脚本来测试。首先,我开始交易并更新一些数据:

BEGIN;
UPDATE foo SET year = 2019  WHERE id = 1;
Query OK, 1 row affected (0.000 sec)
Rows matched: 1  Changed: 1  Warnings: 0

看来我已经完成了。然后我回滚:

ROLLBACK;
Query OK, 0 rows affected (0.005 sec)

然后我再次查看更新记录,我看到数据没有变化。这很奇怪,因为我认为无论如何数据都会改变,因为 autocommit 标志已打开。

请解释原因。 谢谢

BEGIN 是禁用 autocommit.

效果的显式事务开始

自动提交适用于 SQL 不是明确事务性的。

即使 autocommit 开启,如果您使用 BEGINSTART TRANSACTION,它会暂时中止每个语句的自动提交,直到您完成事务。

您引用了手册页 https://dev.mysql.com/doc/refman/8.0/en/commit.html,其中继续解释:

To disable autocommit mode implicitly for a single series of statements, use the START TRANSACTION statement:

With START TRANSACTION, autocommit remains disabled until you end the transaction with COMMIT or ROLLBACK. The autocommit mode then reverts to its previous state.

(强调我的)

换句话说,您在 BEGINSTART TRANSACTION 之后执行的语句 不会 自动提交。这是预期的。

虽然前面的答案是正确的,但让我指出另一个角度。

如果你运行一个billion-rowUPDATE(这需要几个小时),然后拔掉电脑的插头,UPDATE将部分完成。重新启动计算机(和 MySQL)后,会发生什么?在 MyISAM 中,有些行会被更新,有些不会。但是对于 InnoDB,它将 ROLLBACK 部分完成 UPDATE (并且可能需要更多时间才能完成)。

因此,手册中的引述不仅含糊不清(正如其他答案所指出的),而且 'literally' 不正确。在我的示例中,更改 canwas 回滚。

我喜欢这样表述:

Autocommit=ON, when not otherwise in a transaction, is equivalent to wrapping the statement in BEGIN and COMMIT. That is, the statement is performed atomically.

我提交了 http://bugs.mysql.com/95414 .