【发布时间】:2021-02-23 15:13:03
【问题描述】:
如果 MariaDB (10.0.27) 有压力,我会遇到死锁问题。数据库模式基本上是一个层次结构,叶子节点导致了这个:
------------------------
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)
这是我的叶子表的样子:
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)
)
我能够使用使系统承受压力的输入集重现死锁。有了这个,我一直在玩,一旦我删除了唯一索引UNI_BARCODE,就没有死锁了。此外,我的数据不会以某种方式相交,因为我们使用 ActiveMQ 中的消费者组来强制执行相同产品的按顺序更新处理。显然,唯一索引是唯一导致问题的重叠事物。
我花了一些时间试图解决这个问题,但无法做到:(我非常感谢任何关于此的想法 :) 提前致谢!
【问题讨论】:
-
是
CHAR(32)MD5吗?如果是这样,请注意,由于跳动很多,它们会导致大桌子效率低下。 -
是的,它是 md5。我想我已经习惯了,因为长度是恒定的。你能解释一下,你所说的“跳来跳去”是什么意思? :)
-
使用
AUTO_INCREMENT,您插入的“下一个”行将获得下一个更大的数字。如果那是PRIMARY KEY,则意味着下一行将插入到上一行的“下一个”。相反,如果 PK 是一个 MD5,它与之前的 MD5 不同,所以它被插入到表中的其他位置。那么…… -
如果您从一小时的时间跨度中获取行,auto_inc 会将它们彼此“靠近”,从而使数据缓存工作得很好。但是对于 MD5,每一行不太可能“靠近”您正在获取的任何其他行,从而在数据中跳跃。这会降低缓存的效率。
-
因此,使用自动增量值作为 PK 并将 md5 保存在单独的列中基本上是个好主意。感谢您的信息:)
标签: sql mariadb innodb deadlock