MySQL 中的语句回滚与事务回滚
Statement rollback vs transaction rollback in MySQL
从 MySQL docs 我得到以下信息(关于错误代码):
1205 (ER_LOCK_WAIT_TIMEOUT)
Lock wait timeout expired. The statement that waited too long was
rolled back (not the entire transaction). You can increase the value
of the innodb_lock_wait_timeout configuration option if SQL statements
should wait longer for other transactions to complete, or decrease it
if too many long-running transactions are causing locking problems and
reducing concurrency on a busy system.
在这个语句中,明确了语句回滚和事务回滚的区别。我的问题是如何回滚一条语句,而其中运行的事务不回滚?更有什者,我在一个事务中得到这样的锁超时,整个事务被回滚。有人可以启发我吗?
与事务类似,语句也是原子的。一旦语句开始执行数据更改,就会保存原始状态(实际上会记录更改)。如果语句由于任何原因(超时、与刚提交的事务冲突)而失败,则更改必须恢复到原始状态。该语句将报告失败,但事务仍处于打开状态,您可以继续执行事务,就像语句从未执行过一样。
这个其实和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 事务已提交)
从 MySQL docs 我得到以下信息(关于错误代码):
1205 (ER_LOCK_WAIT_TIMEOUT)
Lock wait timeout expired. The statement that waited too long was rolled back (not the entire transaction). You can increase the value of the innodb_lock_wait_timeout configuration option if SQL statements should wait longer for other transactions to complete, or decrease it if too many long-running transactions are causing locking problems and reducing concurrency on a busy system.
在这个语句中,明确了语句回滚和事务回滚的区别。我的问题是如何回滚一条语句,而其中运行的事务不回滚?更有什者,我在一个事务中得到这样的锁超时,整个事务被回滚。有人可以启发我吗?
与事务类似,语句也是原子的。一旦语句开始执行数据更改,就会保存原始状态(实际上会记录更改)。如果语句由于任何原因(超时、与刚提交的事务冲突)而失败,则更改必须恢复到原始状态。该语句将报告失败,但事务仍处于打开状态,您可以继续执行事务,就像语句从未执行过一样。
这个其实和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 事务已提交)