Tri*_*ids 5 mysql innodb deadlock
Mysql/innodb 8.0.16,读取已提交的事务,事务中的几个语句在删除非拦截行时引发死锁。试图了解正在发生的事情:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2019-05-14 21:57:44 0x7fe9546c6700
*** (1) TRANSACTION:
TRANSACTION 2852, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 8 lock struct(s), heap size 1136, 14 row lock(s), undo log entries 25
MySQL thread id 146, OS thread handle 140640122267392, query id 1586 localhost 127.0.0.1 oc5z updating
DELETE FROM deal_product_rows_tmp WHERE batch_no=7533
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 11 page no 4 n bits 88 index PRIMARY of table `db1`.`deal_product_rows_tmp` trx id 2852 lock_mode X locks rec but not gap waiting
Record lock, heap no 14 PHYSICAL RECORD: n_fields 11; compact format; info bits 0
0: len 4; hex 8000650e; asc e ;;
1: len 6; hex 000000000b25; asc %;;
2: len 7; hex 81000001340110; asc 4 ;;
3: len 4; hex 80001d6e; asc n;;
4: len 4; hex 8010a626; asc &;;
5: len 4; hex 8000253a; asc %:;;
6: len 4; hex 8000986e; asc n;;
7: len 4; hex 80000002; asc ;;
8: len 30; hex 415254455820d184d0bed180d0bcd18b20d0bfd180d18fd0bcd0bed183d0; asc WRX ; (total 81 bytes);
9: len 8; hex 0000000000208c40; asc @;;
10: len 1; hex 4d; asc M;;
*** (2) TRANSACTION:
TRANSACTION 2853, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
8 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 12
MySQL thread id 147, OS thread handle 140640120497920, query id 1594 localhost 127.0.0.1 oc5z updating
DELETE FROM deal_product_rows_tmp WHERE batch_no=7534
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 11 page no 4 n bits 88 index PRIMARY of table `db1`.`deal_product_rows_tmp` trx id 2853 lock_mode X locks rec but not gap
Record lock, heap no 14 PHYSICAL RECORD: n_fields 11; compact format; info bits 0
0: len 4; hex 8000650e; asc e ;;
1: len 6; hex 000000000b25; asc %;;
2: len 7; hex 81000001340110; asc 4 ;;
3: len 4; hex 80001d6e; asc n;;
4: len 4; hex 8010a626; asc &;;
5: len 4; hex 8000253a; asc %:;;
6: len 4; hex 8000986e; asc n;;
7: len 4; hex 80000002; asc ;;
8: len 30; hex 415254455820d184d0bed180d0bcd18b20d0bfd180d18fd0bcd0bed183d0; asc WRX ; (total 81 bytes);
9: len 8; hex 0000000000208c40; asc @;;
10: len 1; hex 4d; asc M;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 11 page no 4 n bits 96 index PRIMARY of table `db1`.`deal_product_rows_tmp` trx id 2853 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 11; compact format; info bits 32
0: len 4; hex 80006502; asc e ;;
1: len 6; hex 000000000b24; asc $;;
2: len 7; hex 0200000128012d; asc ( -;;
3: len 4; hex 80001d6d; asc m;;
4: len 4; hex 80109d40; asc @;;
5: len 4; hex 800023ba; asc # ;;
6: len 4; hex 800098e6; asc ;;
7: len 4; hex 80000007; asc ;;
8: len 9; hex 466f696c20676c7565; asc Foil glue;;
9: len 8; hex 0000000000005940; asc Y@;;
10: len 1; hex 4d; asc M;;
*** WE ROLL BACK TRANSACTION (2)
Run Code Online (Sandbox Code Playgroud)
表结构:
CREATE TABLE `deal_product_rows_tmp` (
`batch_no` int(11) NOT NULL,
`bitrix_id` int(11) NOT NULL,
`deal_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`quantity` int(11) NOT NULL,
`product_name` varchar(1000) NOT NULL,
`price` double DEFAULT NULL,
`status` varchar(50) NOT NULL,
`tmp_id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`tmp_id`),
KEY `idx_deal_row_tmp_deal` (`deal_id`),
KEY `idx_deal_row_tmp_batchno` (`batch_no`)
) ENGINE=InnoDB AUTO_INCREMENT=7500 DEFAULT CHARSET=utf8
Run Code Online (Sandbox Code Playgroud)
1)查询删除分隔行,如何在同一行上记录锁定?
2) 即使事务在同一行上加锁,为什么会死锁?为什么第一个事务不能等到第二个释放锁?
UPDATE1:应用程序逻辑 - Spring Boot 应用程序接收来自 crm 系统的休息调用,获取客户订单(交易)产品行并尝试在 micro dwh 中同步数据。RC事务中有多个语句,本应用中只实现了一种事务。第一条语句 REPLACE INTO deal table,这应该可以防止并行处理相同 deal_id 上的批次(目前未使用 FK 密钥)。接下来,在“tmp”表中插入接收到的产品行并在目标“dwh”表上进行比较的事务。插入丢失的交易产品,更新“已删除”产品行的状态。下一步从 deal_product_rows_tmp(死锁点)和最后一步中删除“tmp”数据 - 将批次标记为已完成(更新批次集状态=.. 表,其中 batch_no=? )
通常人们对间隙锁定和额外锁定感到困惑,因为整个表上的索引错误或记录比预期的多,但这不是你的情况:
idx_deal_row_tmp_batchno
索引,否则我无法重现该问题根据有限的信息,我能猜到的是:
batch_no=7533
记录,而事务 2 能够锁定batch_no=7534
,但是他们还想在单独的查询(但相同的事务)上更新其他记录他们不能只是等待,否则将是无限等待(因为它们相互依赖)。如果不是循环,第二个事务确实会等待innodb_lock_wait_timeout
几秒钟。
您可以采取多种策略:
SKIP LOCKED
并NOWAIT
忽略立即锁定的行,特别是批处理:https : //mysqlserverteam.com/mysql-8-0-1-using-skip-locked-and-nowait-to-handle-hot-行/ 归档时间: |
|
查看次数: |
5302 次 |
最近记录: |