Mysql 死锁 - 事务是否正在等待它持有的锁?

标签 mysql deadlock database-deadlocks database-locking

我无法解释 MySql(5.7,InnoDB)的死锁输出。我知道死锁最终会通过更改应用程序级别代码来解决,并且您无法从这段代码中找到根本原因。然而,希望有人能够告诉我为什么我对这个 MySql 诊断的解释是不正确的。

------------------------
LATEST DETECTED DEADLOCK
------------------------
2018-04-09 19:41:39 0x2b7323ef1700
*** (1) TRANSACTION:
TRANSACTION 33312589, ACTIVE 16 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 150744, OS thread handle 47781157312256, query id 53141856 ec2-34-250-106-67.eu-west-1.compute.amazonaws.com 34.250.106.67 sc_appuser3 statistics
/* requestId: 11e8-3c2d-fb145a10-b404-0242ac110003 */ SELECT locator FROM policy WHERE locator = 'df0d7ef5-2e14-4664-90b2-2bfb3f35cce2' AND tenant_locator = '8df5d824-6de9-4e21-8135-b19303aec800' FOR UPDATE
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 464385 page no 21 n bits 232 index policy_locator_idx of table `main_1523299445`.`policy` trx id 33312589 lock_mode X locks rec but not gap waiting
Record lock, heap no 41 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 30; hex 64663064376566352d326531342d343636342d393062322d326266623366; asc df0d7ef5-2e14-4664-90b2-2bfb3f; (total 36 bytes);
 1: len 30; hex 38646635643832342d366465392d346532312d383133352d623139333033; asc 8df5d824-6de9-4e21-8135-b19303; (total 36 bytes);
 2: len 8; hex 000000000000004e; asc N;;

*** (2) TRANSACTION:
TRANSACTION 33312511, ACTIVE 31 sec starting index read
mysql tables in use 2, locked 2
37 lock struct(s), heap size 3520, 21 row lock(s), undo log entries 10
MySQL thread id 150683, OS thread handle 47773524104960, query id 53142921 ec2-34-250-106-67.eu-west-1.compute.amazonaws.com 34.250.106.67 sc_appuser3 Sending data
/* requestId: 11e8-3c2d-cc07ac92-93f6-0242ac110002 */ UPDATE invoice_schedule iss JOIN policy p on iss.policy_id = p.id SET iss.deleted = TRUE WHERE iss.deleted = FALSE AND iss.scheduled_invoice_locator IS NULL AND (null IS NULL OR iss.start_timestamp >= null) AND p.locator = 'df0d7ef5-2e14-4664-90b2-2bfb3f35cce2' AND iss.tenant_locator = '8df5d824-6de9-4e21-8135-b19303aec800'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 464385 page no 21 n bits 232 index policy_locator_idx of table `main_1523299445`.`policy` trx id 33312511 lock_mode X locks rec but not gap
Record lock, heap no 41 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 30; hex 64663064376566352d326531342d343636342d393062322d326266623366; asc df0d7ef5-2e14-4664-90b2-2bfb3f; (total 36 bytes);
 1: len 30; hex 38646635643832342d366465392d346532312d383133352d623139333033; asc 8df5d824-6de9-4e21-8135-b19303; (total 36 bytes);
 2: len 8; hex 000000000000004e; asc N;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 464385 page no 21 n bits 232 index policy_locator_idx of table `main_1523299445`.`policy` trx id 33312511 lock mode S waiting
Record lock, heap no 41 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 30; hex 64663064376566352d326531342d343636342d393062322d326266623366; asc df0d7ef5-2e14-4664-90b2-2bfb3f; (total 36 bytes);
 1: len 30; hex 38646635643832342d366465392d346532312d383133352d623139333033; asc 8df5d824-6de9-4e21-8135-b19303; (total 36 bytes);
 2: len 8; hex 000000000000004e; asc N;;

*** WE ROLL BACK TRANSACTION (1)

对我来说,这个死锁似乎涉及两个事务。事务 2 持有此锁,而事务 1 等待它:

RECORD LOCKS space id 464385 page no 21 n bits 232 index policy_locator_idx of table `main_1523299445`.`policy` trx id 33312589 lock_mode X locks rec but not gap waiting
Record lock, heap no 41 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 30; hex 64663064376566352d326531342d343636342d393062322d326266623366; asc df0d7ef5-2e14-4664-90b2-2bfb3f; (total 36 bytes);
 1: len 30; hex 38646635643832342d366465392d346532312d383133352d623139333033; asc 8df5d824-6de9-4e21-8135-b19303; (total 36 bytes);
 2: len 8; hex 000000000000004e; asc N;;

现在,这是我不明白的部分。事务 2 似乎也在 S(共享)模式下等待同一锁。但是,事务 2 已经在 X 模式下获取了该锁,因此我不明白为什么它需要等待才能获取锁。

  1. 我对这个诊断输出的解释一定有问题。谁能指出这里到底发生了什么?
  2. MySql 是否有其他可用的诊断信息可以帮助我了解这里发生的情况?

最佳答案

我认为问题在于,如果另一个事务正在等待对该锁的独占授予,则 MySql 无法授予该共享记录锁,即使同一事务已经对该锁具有独占授予。

我还没有找到任何直接支持 MySql 的文档,但我想不出任何其他可能导致此问题的原因。

关于Mysql 死锁 - 事务是否正在等待它持有的锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49744025/

相关文章:

Java 7 传递方法作为通用 SQL 死锁检查的参数

usb - Windows下如何解决USB设备重连问题

两个相同查询(不同参数)的MySQL InnoDB死锁问题

php - 如何连接两个表然后选择两个不同的列?

php - SQL 查询在 PHP 中返回 null,但在 MySQL 中返回正确结果

multithreading - 自同步 Goroutines 以死锁告终

c - 专用加载和存储 ARM 指令会引发死锁吗?

sql - SQL死锁问题

mysql - sequel pro 只在 mycli 中检查 "connect using ssl"相当于什么?

php - 如何使用 YEAR 函数从数据库读取数组