为什么从共享锁切换到独占锁会导致死锁并回滚所有其他阻塞的事务?

Why does switching from a shared lock to an exclusive lock cause a deadlock and rolls back all other blocked transactions?

我在 MySQL 5.7.26 上测试了一些查询,发现了一些奇怪的东西(?)。为什么按以下顺序输入以下命令会出现死锁:

会话 1:

start transaction;
SELECT * FROM test_table WHERE id = 1 LOCK IN SHARE MODE;

会话 2:

UPDATE test_table set col_1 = "foobar" WHERE id = 1;
# blocks

会话 1:

SELECT * FROM test_table WHERE id = 1 FOR UPDATE;

会话 2:

# displays ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

我问这个是因为我觉得这与我在我正在开发的网络应用程序中遇到的事情有关,该应用程序处理包含某个父项 table 的外键的子项 table .它会像下面这样,也会导致死锁(希望它足够简单,可以遵循):

会话 1:

start transaction;
INSERT INTO child_table (parent_id, col1) VALUES (1, "a");

会话 2:

UPDATE parent_table SET col2 = "foo" WHERE id = 1;
# blocks, because the insert query in session 1 creates a shared lock on the related parent_table row

会话 1:

UPDATE parent_table SET col2 = "bar" WHERE id = 1;

会话 2:

# displays ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

我想我应该多看看文档。下面的 link 中有一个示例与我的问题

完全相同

https://dev.mysql.com/doc/refman/8.0/en/innodb-deadlock-example.html

基本上:“这里发生死锁是因为客户端A需要一个X锁来更新行。但是,那个锁请求不能被授予,因为客户端B已经有一个X锁的请求,正在等待客户端A释放它的 S 锁。由于 B 先前请求 X 锁,A 持有的 S 锁也不能升级为 X 锁。结果,InnoDB 为其中一个客户端生成错误并释放其锁"= 11=]