MySQL 中的语句回滚与事务回滚

Statement rollback vs transaction rollback in MySQL

MySQL docs 我得到以下信息(关于错误代码):

在这个语句中,明确了语句回滚和事务回滚的区别。我的问题是如何回滚一条语句,而其中运行的事务不回滚?更有什者,我在一个事务中得到这样的锁超时,整个事务被回滚。有人可以启发我吗?

与事务类似,语句也是原子的。一旦语句开始执行数据更改,就会保存原始状态(实际上会记录更改)。如果语句由于任何原因(超时、与刚提交的事务冲突)而失败,则更改必须恢复到原始状态。该语句将报告失败,但事务仍处于打开状态,您可以继续执行事务,就像语句从未执行过一样。

这个其实和savepoint有点类似——你可以想象在每条statement的savepoint被记录之前,statement完成之后,savepoint被commit。但是,这对外部事务或保存点没有影响。

接受的答案是完全正确和好的,但我最终进入了同一个文档页面,进行了快速测试设置,并且由于评论太短,如果您愿意测试并查看行为,这里是该设置自己:

1) 初始化tables

CREATE TABLE `x` (
    `id` INT(10) UNSIGNED NOT NULL,
    `xx` INT(11) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
;
INSERT INTO X (id, xx) VALUES (1,NULL),(2,NULL),(3,NULL);

2) 打开客户端连接,启动事务,触发 INSERT 以锁定新创建的行 table

START TRANSACTION;
INSERT INTO X (id, xx) VALUES (1, 5) ON DUPLICATE KEY UPDATE xx = VALUES(xx);

不提交事务

3) 打开一个 second 客户端连接,开始一个事务,然后在非锁定行

上触发另一个 INSERT
START TRANSACTION;
INSERT INTO X (id, xx) VALUES (2, 7) ON DUPLICATE KEY UPDATE xx = VALUES(xx);

再说一次,不要承诺。

到目前为止,如果发出 SELECT * FROM x 则客户端 1 看到“1,5; 2,NULL, 3;NULL”,客户端 2 看到“1,NULL; 2,7; 3,NULL”

4) 在客户端 2 上触发一个锁定的 INSERT 并等待它以 SQL 1025:

结束
INSERT INTO X (id, xx) VALUES (1, 6) ON DUPLICATE KEY UPDATE xx = VALUES(xx);

现在,如果在客户端 2 上发出 SELECT * FROM x,我们仍然会看到“1,NULL; 2,7; 3,NULL”,因此 语句 已滚动背部。如果我们在客户端 1 上发出它,我们仍然会看到“1,5;2,NULL;3,NULL”,因此客户端 2 事务仍然是 运行(假设您的客户端未配置为在每个 SQL错误)。

5) 现在,如果您在两个客户端上发出 ROLLBACK,则 table 将 "restored" 变为所有 NULL 值。如果你 COMMIT 它,那么你会得到“1,5; 2,7, 3,NULL”(“1,6”在回滚时无处可寻,但客户端 2 事务已提交)