问题
I need help solving a deadlock situation I'm facing. Thanks for your help.
I think the deadlock is related to the SELECT subquery of transaction 2, but I don't understand several things:
- 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?
- In any case, why is transaction 1 blocking anything? I would expect it to just need one lock, therefore not get a lock of anything else, and just wait until that lock is available to be processed... Is transaction 1 really holding the lock that 2 is waiting for? It makes no sense to me.
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;
THANKS A LOT!
回答1:
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?
The 2nd query uses a select subquery to create a derived table. Select queries by default create a shared (S) lock only, unless you enable serialisable isolation level. You can explicitly instruct the select to use exclusive lock (well, intention exclusive, IX) by adding for update
clause to the subquery, but I would be careful with that. You need to evaluate if the subquery could lock more records than the update part does and if it is worth locking these extra records.
In any case, why is transaction 1 blocking anything?
The select subquery of the 2nd query places an S lock on the given record. Then comes the 1st query along requesting an X lock on the same record, which cannot be granted immediatelly because of the S lock already there.
Whent the 2nd query tries to upgrade the lock to X, it finds that it is 2nd in the queue to get the X lock behind the first transaction. However, since the 2nd transaction is still running, the 2nd query cannot release the S lock, preventing the 1st transaction from completing.
Pls do not ask why mysql works this way because only a mysql developer can answer this question.
来源:https://stackoverflow.com/questions/63897010/mysql-deadlocks-explanation