MySQL返回带有插入行的死锁,FK被锁定'用于更新'

use*_*814 7 mysql deadlock

我的mysql事务中出现死锁错误.

我的情况的简单例子:

Thread1 > BEGIN;
Query OK, 0 rows affected (0.00 sec)

Thread1 > SELECT * FROM A WHERE ID=1000 FOR UPDATE;
1 row in set (0.00 sec)

Thread2 > BEGIN;
Query OK, 0 rows affected (0.00 sec)

Thread2 > INSERT INTO B (AID, NAME) VALUES (1000, 'Hello world');
[Hangs]

Thread1 > INSERT INTO B (AID, NAME) VALUES (1000, 'Hello world2');
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Thread2 >
Query OK, 1 row affected (10.00 sec)
Run Code Online (Sandbox Code Playgroud)

B.AID是指代A.ID的外键

我看到三个解决方案:

  1. 捕获代码中的死锁错误并重试查询.
  2. 在my.cnf中使用innodb_locks_unsafe_for_binlog
  3. 在插入之前,在Thread2中锁定(用于更新)表A.

还有其他解决方案吗?

Ken*_*ins 1

我不知道这个示例周围有什么代码,但它可能值得用于LOCK IN SHARE MODE​​两个线程,因为您实际上并没有更新行本身。如果您必须使用LOCK FOR UPDATE,我认为锁定另一个线程将是唯一的逻辑路径。

另外,如果您愿意放弃 MySQL,我发现 PostgreSQL 可以更好地解决死锁问题。在某些情况下,我发现每次在 >1 个线程上运行相同的脚本时 MySQL 都会死锁。PostgreSQL 中的相同脚本可以很好地处理任意数量的并行线程。