MySQL 死锁解释
MySQL deadlocks explanation
我需要帮助解决我面临的僵局情况。感谢您的帮助。
我认为死锁与事务 2 的 SELECT 子查询有关,但有几点我不明白:
- 为什么它持有一个S锁然后等待同一个X锁
行...为什么它一开始没有获得 X 锁?
- 无论如何,为什么事务 1 阻塞了任何东西?我希望它只需要一个
锁定,因此不会锁定其他任何东西,只需等到
该锁可用于处理...事务 1 真的是
持有 2 正在等待的锁?这对我来说毫无意义。
LATEST DETECTED DEADLOCK
------------------------
2020-09-09 07:56:01 2b2bf0401700
*** (1) TRANSACTION:
TRANSACTION 28039013420, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 5603884, OS thread handle 0x2b28527c6700, query id 1343987203 admin updating
UPDATE `order` SET `is_in` = 0 WHERE `order`.`id` = 2084725
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 27319884 page no 45175 n bits 4 index `PRIMARY` of table `order` trx id 28039013420 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 55; compact format; info bits 0
*** (2) TRANSACTION:
TRANSACTION 28039013409, ACTIVE 0 sec fetching rows
mysql tables in use 4, locked 4
LOCK WAIT 435 lock struct(s), heap size 376, 39002 row lock(s)
MySQL thread id 5603883, OS thread handle 0x2b23e8e82700, query id 1343987095 admin Creating sort index
UPDATE order
JOIN items ON items.id = order.item_id
JOIN ( select switch_item_id, sum(quantity) total_sent from order
inner join items on items.id = item_id
where scenario_id = 1088
and is_in = 1
group by items.switch_item_id
) q on items.switch_item_id = q.switch_item_id
SET
total_item_quantity = q.total_sent,
WHERE is_in = 1 and scenario_id = 1088
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 27319884 page no 45175 n bits 2 index `PRIMARY` of table `order` trx id 28039013409 lock mode S locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 55; compact format; info bits 0
0: len=8; bufptr=0x2b0c9748008b; hex= 80000000001fcf73; asc s;;
0; asc ;;
54: SQL NULL;
[bitmap0 of 16 bytes in hex: 7c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 27319884 page no 45175 n bits 4 index `PRIMARY` of table `order` trx id 28039013409 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 55; compact format; info bits 0
0: len=8; bufptr=0x2b0c97480302; hex= 80000000001fcf75; asc u;;
54: SQL NULL;
非常感谢!
Why is it holding a S lock and then waiting for a X lock of the same row... why didn't it get an X lock to begin with?
第二个查询使用 select 子查询创建派生的 table。 Select 默认情况下查询仅创建共享 (S) 锁,除非您启用可序列化隔离级别。您可以通过向子查询添加 for update
子句来明确指示 select 使用排他锁(好吧,意向排他,IX),但我会小心处理。您需要评估子查询是否可以锁定比更新部分更多的记录,以及是否值得锁定这些额外的记录。
In any case, why is transaction 1 blocking anything?
第二个查询的 select 子查询在给定记录上放置了一个 S 锁。然后是第一个查询,请求对同一记录的 X 锁,由于 S 锁已经存在,因此无法立即授予。
当第二个查询尝试将锁升级到 X 时,它发现在第一个事务之后获得 X 锁的队列中是第 2 个。但是,由于第二个事务仍然是运行,第二个查询无法释放S锁,导致第一个事务无法完成。
请不要问为什么 mysql 这样工作,因为只有 mysql 开发人员才能回答这个问题。
我需要帮助解决我面临的僵局情况。感谢您的帮助。
我认为死锁与事务 2 的 SELECT 子查询有关,但有几点我不明白:
- 为什么它持有一个S锁然后等待同一个X锁 行...为什么它一开始没有获得 X 锁?
- 无论如何,为什么事务 1 阻塞了任何东西?我希望它只需要一个 锁定,因此不会锁定其他任何东西,只需等到 该锁可用于处理...事务 1 真的是 持有 2 正在等待的锁?这对我来说毫无意义。
LATEST DETECTED DEADLOCK
------------------------
2020-09-09 07:56:01 2b2bf0401700
*** (1) TRANSACTION:
TRANSACTION 28039013420, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 5603884, OS thread handle 0x2b28527c6700, query id 1343987203 admin updating
UPDATE `order` SET `is_in` = 0 WHERE `order`.`id` = 2084725
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 27319884 page no 45175 n bits 4 index `PRIMARY` of table `order` trx id 28039013420 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 55; compact format; info bits 0
*** (2) TRANSACTION:
TRANSACTION 28039013409, ACTIVE 0 sec fetching rows
mysql tables in use 4, locked 4
LOCK WAIT 435 lock struct(s), heap size 376, 39002 row lock(s)
MySQL thread id 5603883, OS thread handle 0x2b23e8e82700, query id 1343987095 admin Creating sort index
UPDATE order
JOIN items ON items.id = order.item_id
JOIN ( select switch_item_id, sum(quantity) total_sent from order
inner join items on items.id = item_id
where scenario_id = 1088
and is_in = 1
group by items.switch_item_id
) q on items.switch_item_id = q.switch_item_id
SET
total_item_quantity = q.total_sent,
WHERE is_in = 1 and scenario_id = 1088
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 27319884 page no 45175 n bits 2 index `PRIMARY` of table `order` trx id 28039013409 lock mode S locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 55; compact format; info bits 0
0: len=8; bufptr=0x2b0c9748008b; hex= 80000000001fcf73; asc s;;
0; asc ;;
54: SQL NULL;
[bitmap0 of 16 bytes in hex: 7c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 27319884 page no 45175 n bits 4 index `PRIMARY` of table `order` trx id 28039013409 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 55; compact format; info bits 0
0: len=8; bufptr=0x2b0c97480302; hex= 80000000001fcf75; asc u;;
54: SQL NULL;
非常感谢!
Why is it holding a S lock and then waiting for a X lock of the same row... why didn't it get an X lock to begin with?
第二个查询使用 select 子查询创建派生的 table。 Select 默认情况下查询仅创建共享 (S) 锁,除非您启用可序列化隔离级别。您可以通过向子查询添加 for update
子句来明确指示 select 使用排他锁(好吧,意向排他,IX),但我会小心处理。您需要评估子查询是否可以锁定比更新部分更多的记录,以及是否值得锁定这些额外的记录。
In any case, why is transaction 1 blocking anything?
第二个查询的 select 子查询在给定记录上放置了一个 S 锁。然后是第一个查询,请求对同一记录的 X 锁,由于 S 锁已经存在,因此无法立即授予。
当第二个查询尝试将锁升级到 X 时,它发现在第一个事务之后获得 X 锁的队列中是第 2 个。但是,由于第二个事务仍然是运行,第二个查询无法释放S锁,导致第一个事务无法完成。
请不要问为什么 mysql 这样工作,因为只有 mysql 开发人员才能回答这个问题。