I’m having deadlock issues with a MariaDB (10.0.27)if it’s under pressure. The database schema is basically a hierarchy and the leaf node causes this:
------------------------ LATEST DETECTED DEADLOCK ------------------------ 2020-11-11 15:34:46 0x7fccf00e5700 *** (1) TRANSACTION: TRANSACTION 2780, ACTIVE 27 sec inserting mysql tables in use 1, locked 1 LOCK WAIT 211 lock struct(s), heap size 24784, 1373 row lock(s), undo log entries 1389 MySQL thread id 383, OS thread handle 140518385858304, query id 614348 172.26.0.1 mydatabase Update insert into BARCODE (BARCODE_REC_ID, CODE, COLOR_VARIANT_ID, CREATED, EXTERNAL_RECEIPT_NUM, MODIFIED, SEASON_CODE, SEASON_CODE_EB, SEASON_DESCRIPTION, SEASON_YEAR_EB, TYPE, ID) values (5645669455, '021745228', '9404b25d87630677f68d88417ed3efc7', '2018-05-16 16:53:14', '17', '2018-05-16 16:53:14', 'HW18', null, 'Herbst/Winter 2018', 2018, 'VARIANT_RECEIPT_NUM', '5ff302d48259d09c2030e8bdc21749b8') *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 41 page no 15 n bits 416 index UNI_BARCODE of table `mydatabase`.`BARCODE` trx id 2780 lock mode S waiting Record lock, heap no 340 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 8; hex 8000000150825f21; asc P _!;; 1: len 1; hex 05; asc ;; 2: len 30; hex 623939386139366133316265616632376164396539613463363966643831; asc b998a96a31beaf27ad9e9a4c69fd81; (total 32 bytes); *** (2) TRANSACTION: TRANSACTION 2775, ACTIVE 24 sec inserting mysql tables in use 1, locked 1 247 lock struct(s), heap size 41168, 1915 row lock(s), undo log entries 3256 MySQL thread id 391, OS thread handle 140518177527552, query id 617936 172.26.0.1 mydatabase Update insert into BARCODE (BARCODE_REC_ID, CODE, COLOR_VARIANT_ID, CREATED, EXTERNAL_RECEIPT_NUM, MODIFIED, SEASON_CODE, SEASON_CODE_EB, SEASON_DESCRIPTION, SEASON_YEAR_EB, TYPE, ID) values (5647403803, '021631613', '053ba855feea779a8e7cbbdaa63e681b', '2019-08-08 10:07:25', '51', '2019-08-08 10:07:25', 'HW19', null, 'Herbst/Winter 2019', 2019, 'VARIANT_RECEIPT_NUM', 'dc3ce352fb06609dc9b4a1ab87d872d1') *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 41 page no 15 n bits 416 index UNI_BARCODE of table `mydatabase`.`BARCODE` trx id 2775 lock_mode X locks rec but not gap Record lock, heap no 340 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 8; hex 8000000150825f21; asc P _!;; 1: len 1; hex 05; asc ;; 2: len 30; hex 623939386139366133316265616632376164396539613463363966643831; asc b998a96a31beaf27ad9e9a4c69fd81; (total 32 bytes); *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 41 page no 36 n bits 416 index UNI_BARCODE of table `mydatabase`.`BARCODE` trx id 2775 lock mode S waiting Record lock, heap no 208 PHYSICAL RECORD: n_fields 3; compact format; info bits 32 0: len 8; hex 80000001509d484a; asc P HJ;; 1: len 1; hex 05; asc ;; 2: len 30; hex 343638653564396161373030333537623666376531356666623732613735; asc 468e5d9aa700357b6f7e15ffb72a75; (total 32 bytes); *** WE ROLL BACK TRANSACTION (1)
This is how my leaf table looks like:
CREATE TABLE BARCODE ( ID CHAR(32) NOT NULL, COLOR_VARIANT_ID CHAR(32) NOT NULL, BARCODE_REC_ID BIGINT NOT NULL, TYPE ENUM('UPCA', 'UPCE', 'EAN13', 'EAN8', 'VARIANT_RECEIPT_NUM') NOT NULL, CODE VARCHAR(17) NOT NULL, CREATED TIMESTAMP NOT NULL, MODIFIED TIMESTAMP NOT NULL, EXTERNAL_RECEIPT_NUM INT NOT NULL, SEASON_CODE VARCHAR(10) NULL, SEASON_DESCRIPTION VARCHAR(60) NULL, SEASON_CODE_EB ENUM('CODE_1', 'CODE_5', 'CODE_0') NULL, SEASON_YEAR_EB INT NULL, PRIMARY KEY PRI_BARCODE (ID), INDEX COLOR_VAR_ID (COLOR_VARIANT_ID), UNIQUE KEY UNI_BARCODE (BARCODE_REC_ID, TYPE) )
I’m able to reproduce the deadlock with an input set that puts the system under pressure. With this, I’ve been playing around and once I remove the unique index UNI_BARCODE
there are no deadlocks. In addition, my data does not intersect somehow, as we are using consumer groups from ActiveMQ to enforce in-order update processing for same products. So apparently, the unique index is the only overlapping thing that causes issues.
I’ve spent some time on this trying to fix this but couldn’t do it 🙁 I would highly appreciate any ideas on this 🙂 Thanks in advance!
Advertisement
Answer
Yes, I’ve noticed this a lot at my place of work.
An InnoDB table with both a PRIMARY KEY
and a secondary UNIQUE KEY
has a large chance of causing a deadlock. Example of such a case is described clearly in this bug report: https://bugs.mysql.com/bug.php?id=86812
There seems to be a race condition in InnoDB row-level locking. I guess the locks on the unique index and the locks on the clustered index (primary key) are not acquired atomically.
This affects both MySQL and MariaDB, since they both use InnoDB. It affects many versions of InnoDB, so upgrading will not help. It affects both READ-COMMITTED and REPEATABLE-READ transaction isolation levels, so it won’t help to change that.
What I advised the developers at my place of work is that you have three alternatives:
Retry the transaction that was rolled back as a result of the deadlock. This is the usual recommendation for other types of deadlocks.
Pessimistic locking. Use
LOCK TABLES BARCODE WRITE;
before attempting the insert. And of courseUNLOCK TABLES;
immediately afterwards, to allow concurrent sessions to get their turn.Redesign the table so it doesn’t have both a primary key and unique key. For example, drop the
id
column so the unique key on(BARCODE_REC_ID, TYPE )
becomes the clustered index.