繁体   English   中英

具有可序列化隔离级别的事务中的死锁

[英]Deadlock in transaction with isolation level serializable

我试图了解锁定如何与隔离级别一起工作。 我已经解决了这个问题,但无法理解给定打击的流程

在这里,我在不同的终端开始两个交易并读取其中的同一行。 当我尝试更新它们时,终端一直在等待更新。 除此之外没有其他查询在运行

这是我做的一系列步骤

conn1: START TRANSACTION;
conn1: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn2: START TRANSACTION;
conn2: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn1: SELECT * from users WHERE id = 1;
conn2: SELECT * from users WHERE id = 1;
conn1: UPDATE users set name = 'name' WHERE id = 1; waiting...
conn2: UPDATE users set name = 'name' WHERE id = 1; waiting...

这是我的第一个问题
在这里,我想了解为什么两个连接都在等待,以及他们是否拥有更新行的锁?

如果我将上述步骤更改为

conn1: START TRANSACTION;
conn1: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn2: START TRANSACTION;
conn2: SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
conn1: UPDATE users set name = 'name' WHERE id = 1;
conn2: SELECT * from users WHERE id = 1; waiting...
conn1: commit
conn2: updated results

在这种情况下,不同之处在于我可以看到 conn1 有锁,直到它提交或回滚更改,所有其他请求都将等待,如果 conn1 提交,将获得更新的结果

这是我的第二个问题
这是正确的方法,如果我想锁定一行,如果被锁定,我希望其他连接等待(甚至读取)直到这个锁定释放(提交或回滚)或者我应该for update子句

数据库 - Mysql 5.7

正如关于SERIALIZABLE 隔离级别的mysql 文档所说:

这个级别类似于 REPEATABLE READ,但 InnoDB 将所有普通的 SELECT 语句隐式转换为 SELECT ... LOCK IN SHARE MODE

自动提交条款在此处不适用,因为您明确启动了一个事务。

这意味着在第一种情况下,两个事务都在同一条记录上获得共享锁。 然后第一个事务 (T1) 尝试执行更新,这需要排他锁。 这不能被授予,因为 T2 持有共享锁。 然后 T2 尝试更新,但由于 T1 持有共享锁而无法更新。

是否使用原子更新或select ... for update语句来锁定记录,取决于您需要应用的应用程序逻辑。 如果您需要在更新记录之前获取记录的数据并进行一些复杂的计算,请使用select ... for update方法。 否则,请进行原子更新。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM