Sql MariaDb InnoDB在执行许多插入时发生死锁

Sql MariaDb InnoDB在执行许多插入时发生死锁,sql,mariadb,innodb,deadlock,Sql,Mariadb,Innodb,Deadlock,如果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

如果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_条码,就没有死锁了。此外,我的数据并没有以某种方式相交,因为我们正在使用ActiveMQ中的消费者组来强制执行相同产品的订单更新处理。所以很明显,唯一的索引是导致问题的唯一重叠部分


我已经花了一些时间试图解决这个问题,但无法做到:我非常感谢任何关于这个问题的想法:提前谢谢

是的,我在工作场所经常注意到这一点

同时具有主键和次唯一键的InnoDB表很有可能导致死锁。此错误报告中清楚地描述了此类情况的示例:

InnoDB行级锁定中似乎存在竞争条件。我猜唯一索引上的锁和聚集索引主键上的锁不是原子式获取的

这会影响MySQL和MariaDB,因为它们都使用InnoDB。它会影响许多版本的InnoDB,因此升级将无济于事。它同时影响读提交和可重复读事务隔离级别,因此改变这一点没有帮助

我建议我工作地点的开发者有三种选择:

重试由于死锁而回滚的事务。对于其他类型的死锁,这是通常的建议

悲观锁定。使用锁表写入条码;在尝试插入之前。当然,打开桌子;紧接着,允许并发会话轮到它们

重新设计表,使其不同时具有主键和唯一键。例如,删除id列,以便BARCODE_REC_id,TYPE上的唯一键成为聚集索引


是的,在我工作的地方我经常注意到这一点

同时具有主键和次唯一键的InnoDB表很有可能导致死锁。此错误报告中清楚地描述了此类情况的示例:

InnoDB行级锁定中似乎存在竞争条件。我猜唯一索引上的锁和聚集索引主键上的锁不是原子式获取的

这会影响MySQL和MariaDB,因为它们都使用InnoDB。它会影响许多版本的InnoDB,因此升级将无济于事。它同时影响读提交和可重复读事务隔离级别,因此改变这一点没有帮助

我建议我工作地点的开发者有三种选择:

重试由于死锁而回滚的事务。对于其他类型的死锁,这是通常的建议

悲观锁定。使用锁表写入条码;在尝试插入之前。当然,打开桌子;紧接着,允许并发会话轮到它们

重新设计表,使其不同时具有主键和唯一键。例如,删除id列,以便BARCODE_REC_id,TYPE上的唯一键成为聚集索引


那些是CHAR32 MD5吗?如果是这样的话,请注意,它们会导致大型表格由于频繁跳转而效率低下。是的,这是md5。我想我已经被使用了,因为长度是恒定的。你能解释一下,你经常跳来跳去是什么意思吗使用自动递增,插入的下一行将获得下一个更高的数字。如果这是主键,则表示下一行将插入上一行的旁边。相反,如果PK是MD5,则它与以前的MD5不同,因此它会插入表中的其他位置。然后……如果您从一个小时的时间跨度中提取行,auto_inc会将它们放在彼此相邻的位置,从而使数据缓存工作得很好。但是对于MD5,每一行都不太可能靠近您正在获取的任何其他行,因此在数据中跳跃。这会降低缓存的效率。因此,使用自动递增值作为PK并将md5保留在单独的列中基本上是一个好主意。谢谢你提供的信息:那些是CHAR32 MD5吗?如果是这样的话,请注意,它们会导致大型表格由于频繁跳转而效率低下。是的,这是md5。我想我已经被使用了,因为长度是恒定的。你能解释一下,你经常跳来跳去是什么意思吗使用自动递增,插入的下一行将获得下一个更高的数字。如果这是主键,则表示下一行将插入上一行的旁边。相反,如果PK是MD5,则它与以前的MD5不同,因此它会插入表中的其他位置。然后……如果你从一个小时的时间跨度中提取行,auto_inc会将它们放在彼此相邻的位置,从而使
对数据的缓存进行优化可以很好地工作。但是对于MD5,每一行都不太可能靠近您正在获取的任何其他行,因此在数据中跳跃。这会降低缓存的效率。因此,使用自动递增值作为PK并将md5保留在单独的列中基本上是一个好主意。感谢您提供的信息: