Details
Description
As explained in upstream bug reports (that has all the details on the test case):
http://bugs.mysql.com/bug.php?id=82127
https://bugs.launchpad.net/percona-server/+bug/1598822
there is a deadlock scenario with 3 concurrent DELETEs by UNIQUE key that can not be explained by the manual:
CREATE TABLE `tu`(`id` int(11), `a` int(11) DEFAULT NULL, `b` varchar(10) DEFAULT NULL, `c` varchar(10) DEFAULT NULL, PRIMARY KEY(`id`), UNIQUE KEY `u`(`a`,`b`)) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=0;
|
|
insert into tu values(1,1,'a','a'),(2,9999,'xxxx','x'),(3,10000,'b','b'),(4,4,'c','c');
|
|
mysqlslap -uroot --concurrency=3 --create-schema=test --no-drop --number-of-queries=1000 --query="delete from tu where a = 9999 and b = 'xxxx'"
|
mysqlslap: Cannot run query delete from tu where a = 9999 and b = 'xxxx' ERROR : Deadlock found when trying to get lock; try restarting transaction
|
Deadlock happens both with triggers mentioned in that bug reports and without them (just less often).
The problem was originally noted by customer on MariaDB 5.5.24, but affects all released versions up to those based on InnoDB from 5.7.x for sure.
As there is no visible progress on upstream bugs, I create this bug report for MariaDB to decide if there is anything to fix here or to document clearly in the knowledge base.
Attachments
Issue Links
- is blocked by
-
MDEV-27025 insert-intention lock conflicts with waiting ORDINARY lock
-
- Closed
-
- relates to
-
MDEV-14589 InnoDB should not lock a delete-marked record
-
- Closed
-
-
MDEV-16232 Use fewer mini-transactions
-
- Stalled
-
-
MDEV-16402 Support Index Condition Pushdown for clustered PK scans
-
- Confirmed
-
-
MDEV-16406 Refactor the InnoDB record locks
-
- Open
-
-
MDEV-18706 ER_LOCK_DEADLOCK on concurrent read and insert into already locked gap
-
- In Review
-
-
MDEV-31833 replication breaks when using optimistic replication and replica is a galera node
-
- Closed
-
-
MDEV-20605 Awaken transaction can miss inserted by other transaction records due to wrong persistent cursor restoration
-
- Closed
-
-
MDEV-22698 Deadlock on concurrent acquisition from multiple indexes
-
- Open
-
-
MDEV-23560 Deadlock detected on SELECT when only one record being processed
-
- Open
-
-
MDEV-28800 SIGABRT due to running out of memory for InnoDB locks
-
- Closed
-
- links to
- mentioned in
-
Page Loading...
Activity
Field | Original Value | New Value |
---|---|---|
Affects Version/s | 5.5 [ 15800 ] | |
Affects Version/s | 10.0 [ 16000 ] | |
Affects Version/s | 10.1 [ 16100 ] |
Remote Link | This issue links to "Bug #82127 Deadlock with 3 concurrent DELETEs by UNIQUE key (Web Link)" [ 27622 ] |
Remote Link | This issue links to "lp:1598822 Deadlock with 3 concurrent DELETEs by unique key and triggers reading the same row (Web Link)" [ 27623 ] |
Assignee | Jan Lindström [ jplindst ] |
Fix Version/s | 5.5 [ 15800 ] | |
Fix Version/s | 10.0 [ 16000 ] |
Fix Version/s | 10.1 [ 16100 ] |
Priority | Major [ 3 ] | Critical [ 2 ] |
Fix Version/s | N/A [ 14700 ] | |
Fix Version/s | 5.5 [ 15800 ] | |
Fix Version/s | 10.0 [ 16000 ] | |
Fix Version/s | 10.1 [ 16100 ] | |
Resolution | Not a Bug [ 6 ] | |
Status | Open [ 1 ] | Closed [ 6 ] |
Link | This issue relates to MDEV-16232 [ MDEV-16232 ] |
Link |
This issue relates to |
Link | This issue relates to MDEV-16402 [ MDEV-16402 ] |
Assignee | Jan Lindström [ jplindst ] | Marko Mäkelä [ marko ] |
Resolution | Not a Bug [ 6 ] | |
Status | Closed [ 6 ] | Stalled [ 10000 ] |
Link | This issue relates to MDEV-16406 [ MDEV-16406 ] |
Affects Version/s | 10.2 [ 14601 ] | |
Affects Version/s | 10.3 [ 22126 ] |
Fix Version/s | 10.4 [ 22408 ] | |
Fix Version/s | N/A [ 14700 ] |
Fix Version/s | 10.4 [ 22408 ] | |
NRE Projects | RM_long_term | |
Affects Version/s | 10.4 [ 22408 ] | |
Priority | Critical [ 2 ] | Major [ 3 ] |
Fix Version/s | 10.4 [ 22408 ] |
Link | This issue relates to MDEV-18706 [ MDEV-18706 ] |
Link |
This issue relates to |
Assignee | Marko Mäkelä [ marko ] | Aleksey Midenkov [ midenok ] |
Status | Stalled [ 10000 ] | In Progress [ 3 ] |
Link | This issue relates to MDEV-22698 [ MDEV-22698 ] |
Assignee | Aleksey Midenkov [ midenok ] | Marko Mäkelä [ marko ] |
Status | In Progress [ 3 ] | In Review [ 10002 ] |
Assignee | Marko Mäkelä [ marko ] | Aleksey Midenkov [ midenok ] |
Status | In Review [ 10002 ] | Stalled [ 10000 ] |
Link | This issue relates to MDEV-23560 [ MDEV-23560 ] |
Assignee | Aleksey Midenkov [ midenok ] | Marko Mäkelä [ marko ] |
Status | Stalled [ 10000 ] | In Review [ 10002 ] |
Assignee | Marko Mäkelä [ marko ] | Aleksey Midenkov [ midenok ] |
Status | In Review [ 10002 ] | Stalled [ 10000 ] |
Status | Stalled [ 10000 ] | In Progress [ 3 ] |
Status | In Progress [ 3 ] | Stalled [ 10000 ] |
Workflow | MariaDB v3 [ 77682 ] | MariaDB v4 [ 143490 ] |
Link |
This issue is blocked by |
Assignee | Aleksey Midenkov [ midenok ] | Marko Mäkelä [ marko ] |
Assignee | Marko Mäkelä [ marko ] | Vladislav Lesin [ vlad.lesin ] |
Priority | Major [ 3 ] | Critical [ 2 ] |
Status | Stalled [ 10000 ] | In Progress [ 3 ] |
Assignee | Vladislav Lesin [ vlad.lesin ] | Marko Mäkelä [ marko ] |
Status | In Progress [ 3 ] | In Review [ 10002 ] |
Link |
This issue relates to |
Assignee | Marko Mäkelä [ marko ] | Vladislav Lesin [ vlad.lesin ] |
Status | In Review [ 10002 ] | Stalled [ 10000 ] |
Fix Version/s | 10.4.31 [ 29010 ] | |
Fix Version/s | 10.5.22 [ 29011 ] | |
Fix Version/s | 10.6.15 [ 29013 ] | |
Fix Version/s | 10.9.8 [ 29015 ] | |
Fix Version/s | 10.10.6 [ 29017 ] | |
Fix Version/s | 10.11.5 [ 29019 ] | |
Fix Version/s | 11.0.3 [ 28920 ] | |
Fix Version/s | 11.1.2 [ 28921 ] | |
Fix Version/s | 11.2.1 [ 29034 ] | |
Fix Version/s | 10.4 [ 22408 ] | |
Resolution | Fixed [ 1 ] | |
Status | Stalled [ 10000 ] | Closed [ 6 ] |
Remote Link | This issue links to "Page (MariaDB Confluence)" [ 35637 ] |
Zendesk Related Tickets | 201658 | |
Zendesk active tickets | 201658 |
I will firstly comment on case where we do not have any triggers, just tree concurrent transactions. For deadlock we need only two and I will mark then as trx(1) and trx(2) to identify them. Thus, trx (1) is doing delete t where a = 9999 and b = 'xxxx' and takes X-lock for record where a = 9999 and b = 'xxxx' , trx(2) does delete t where a = 9999 and b = 'xxxx' and tries to obtain X-lock for the same record, it can't have it so it needs to wait, trx(1) continues finds a delete marked row, continues to next record that is end of search range and tries to obtain X-lock with GAP, this can't be granted as we already have waiting lock request for the same record done by trx(1) in lock wait queue. Thus, we have trx(1) -> trx(2) -> trx(1) where -> means waiting and this is naturally a deadlock as it means that trx(1) -> trx(1). Why trx(1) takes a GAP-lock? When trx(1) searches matching rows it firstly finds the matching row and naturally places X-lock for that row to protect it. Then trx(1) tries to find more matching rows and finds a delete-marked row that is naturally skipped. Finally, trx(1) find a index-entry that does not match, in this case it takes GAP-lock. This is end of range like GAP-lock protecting the fact that any concurrent transactions can't INSERT or UPDATE a key here. Now question is this really necessary ? For non-unique secondary indexes, absolutely yes if isolation level is REPEATABLE READ or higher. For unique-index if only a part of the multi-key index is used or any of the key part condition is not exact query, absolutely yes if isolation level is REPEATABLE READ or higher, in above case that would mean query like delete from tu where a = 9999 or delete from tu where a = 9999 and b > 'XXX'. Lets consider INSERT ... VALUES(9999, 'xxxx' ) i.e. value that would cause duplicate key if delete is rolled back. Insert does not take row locks, it takes insert intention gap-lock to index record to avoid concurrent INSERTs to same index gap. Then, for unique-indexes this insert would need to find any duplicate index entries and for that it needs to take S-locks, thus insert would wait. Similarly for UPDATE that would change unique-index entry, it would need to do duplicate check using at least S-locks forcing it to wait for delete. DELETE as we already have seen would try to take X-lock to index entry forcing it to wait for first delete. Honestly, I do not see why exact query using all key parts on unique index would take gap-lock even in case when there is delete marked index entry. However, this is not a bug, this is current implementation so it works as designed.