如何知道交易是否连续持有独占锁?

how to KNOW if a transaction holds exclusive lock in a row?

提问人:theBackendLearner 提问时间:11/16/2023 最后编辑:theBackendLearner 更新时间:11/16/2023 访问量:142

问:

我正在学习交易、锁等,我想知道如何知道交易是否连续持有独占锁

我尝试使用 MySQL 命令行模拟它,但我不确定这是否是了解事务是否在一行中持有独占锁的正确方法,您能确认我的测试是否正确吗?我知道它正在起作用,因为我看到了它,但也许这只是一个巧合

我尝试按以下顺序进行此测试:

在连接 1 中打开事务:

begin;
UPDATE users SET rol = 'Admin' WHERE email LIKE '%example.net%';
Query OK, 182 rows affected (0.03 sec)
Rows matched: 182  Changed: 182  Warnings: 0

现在,在连接 2 中打开另一个事务(这是满足连接 1 条件的行):

begin;
UPDATE users SET rol = 'Admin' WHERE id = 11; // Blocked, it's waiting

现在,我将关闭连接 1 中的事务:

rollback;
Query OK, 0 rows affected (0.02 sec)

立即(自动)连接 2:

Query OK, 1 row affected (18.33 sec) // "Free"
Rows matched: 1  Changed: 1  Warnings: 0
rollback; // I close the another transaction
  1. 如果我上面的例子知道事务是否在某些行上持有独占锁是正确的,那么它是否适用于并且因为它也设置了独占锁?DELETESELECT ... FOR UPDATE

另一方面,文档内容如下:

原子语句

默认情况下,MySQL在启用自动提交模式的情况下运行。这意味着,当不在事务中时,每个语句都是原子的,就好像它被 START TRANSACTION 和 COMMIT 包围一样。不能使用 ROLLBACK 撤消效果;但是,如果在语句执行过程中发生错误,则会回滚该语句。

  1. 每个语句都是原子的”是指单个语句(只有一个)吗?
  2. 即使条件“跨越”多行(例如连接 1)单个语句仍然是原子的吗?UPDATE
SQL MySQL 并发 事务 innodb

评论

0赞 Shadow 11/16/2023
老实说:我不明白你的问题!复制独占锁意味着您希望以不同的方式实现它们。但是,您似乎试图查看独占锁是否有效。确实如此。不太确定您的示例应该展示什么关于排他锁,但是您不会保持交易打开状态,因此任何锁都会保持几分之一秒。
0赞 theBackendLearner 11/16/2023
"但是,您似乎试图查看专用锁是否有效。- 我已经编辑了这个问题,这就是我想知道的问题,想知道交易是否真的在某些行中具有排他性锁?我不知道正确的词,对不起@Shadow
1赞 danblack 11/16/2023
您已经演示了锁定。锁位于索引上,而不是行上。查看第三个连接中的输出。show engine innodb status
0赞 Rick James 11/17/2023
请提供 .另外,id=11 的 rol=Admin 吗?在第一次更新之前?SHOW CREATE TABLE users
0赞 theBackendLearner 11/17/2023
嗨,@Rick詹姆斯,当然,我之前确保 id = 11 满足连接 1 中的 UPDATE 条件

答:

2赞 Bill Karwin 11/16/2023 #1
  1. 如果我上面的例子知道事务是否在某些行上持有独占锁是正确的,那么它是否适用于 DELETE 和 SELECT ...FOR UPDATE,因为它还设置了排他锁?

是的,您可以对其他锁定语句运行类似的测试来证明这一点。

  1. “每个语句都是原子的”是指单个语句(只有一个)吗?

是的,自动提交模式意味着每个语句启动并提交一个事务。

  1. 即使条件“跨越”多行(例如连接 1 的 UPDATE),单个语句仍然是原子的吗?

是的。在默认事务隔离级别中,该语句在它检查的所有行上获取锁这可能比受 UPDATE 影响或由 SELECT 返回的行多,因为查询中的条件可能会筛选行。

例如,在您的示例 UPDATE 中:

UPDATE users SET rol = 'Admin' WHERE email LIKE '%example.net%';

具有通配符模式的条件将检查表中的所有行,即使您已在要搜索的列上定义了索引也是如此。因此,此更新将锁定所有行,即使是那些不满足条件的行。LIKE

该语句以原子方式获取锁。这意味着它要么获取所需的所有锁,要么如果失败(例如,因为某些行已被另一个会话锁定),它必须释放它试图在该语句中获取的其他锁,即使是那些本来会成功的锁。

评论

0赞 theBackendLearner 11/16/2023
文档说:“在InnoDB中,所有用户活动都发生在事务中。如果启用了自动提交模式,则每个 SQL 语句都会自行形成一个事务。- 这是否意味着任何单个语句(只有一个),例如 (没有被“明确”的交易包围)会像 ?@Bill 卡文UPDATE table SET column = 'something' WHERE id > 1;begin; UPDATE table SET column = 'something' WHERE id > 1; commit;
0赞 Bill Karwin 11/16/2023
是的。我想我已经回答了这个问题。
0赞 theBackendLearner 11/16/2023
对不起,只是我是新来的,有时我觉得他们指的是不同的东西。它看起来是幕后包围的,因为“隐式”是以防单个语句失败,对吧?@Bill 卡文commit;rollback;
0赞 Bill Karwin 11/16/2023
如果失败,则该语句无效。这意味着该声明是原子的。它不更新任何行,并且它获取的任何锁都会被释放。在这一点上,它是提交还是回滚事务并不重要,因为无论哪种方式都没有效果。
1赞 theBackendLearner 11/17/2023
伟大!!!感谢您引用文档,最好使用官方引用来支持信息。我仍然没有阅读所有文档,这就是为什么我没有意识到这一点。对不起,由于我的声誉,我不能给你的答案+1,但是当我有一些声誉时,我会停下来留下我的+1。