一.业务背景
我们现在的业务是一款数据产品,有不少实时计算和爬取来的数据都汇总到大数据仓库、数据挖掘平台ODPS上。然后应用在读取这些数据时,这些数据会先导入到并发读能力更强,适合结构查询的mysql上。数据端开发的同学在跑定时任务时, tps比较高,于是出现了一些线上问题:在开发过程中发现对某一包含unique key(联合的唯一索引)的表进行并发插入的时候,出现大量的死锁,使得插入几乎无法进行。于是为了排查问题,请教了DBA以及数据库事业部的同学,最后发现了问题的所在,特此记录下来
二.死锁现场
1.表结构
CREATE TABLE tkn_tb_cinema_show_data (
……
cinema_id bigint(20) DEFAULT NULL COMMENT ‘影院ID’,
show_id bigint(20) DEFAULT NULL COMMENT ‘影片ID’,
now_date varchar(32) DEFAULT NULL COMMENT ‘当日时间’,
……
PRIMARY KEY (id),
UNIQUE KEY uid_cinema_show_date (cinema_id,show_id,now_date),
……
) ENGINE=InnoDB AUTO_INCREMENT=2162973490 DEFAULT CHARSET=utf8 COMMENT=’淘宝电影订单影院影片数据统计’
2.问题状况
可以看到出现死锁的原因是因为批量插入的时候,该事务
持有锁
index uid_cinema_show_date of table tkn.tkn_tb_cinema_show_data trx id 73278630826 lock_mode X
等待锁
index uid_cinema_show_date of table tkn.tkn_tb_cinema_show_data trx id 73278630826 lock_mode X locks gap before rec insert intention waiting
这样一看确实奇怪,怎么批量插入不同行怎么会有死锁,再看看死锁日志
(SHOW ENGINE INNODB STATUS;)
transactions deadlock detected, dumping detailed information.
2017-06-11 08:41:03 2ac742684700
*** (1) TRANSACTION:
TRANSACTION 73278630816, ACTIVE 1 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 622 lock struct(s), heap size 79400, 743 row lock(s), undo log entries 388
MySQL thread id 13824253, OS thread handle 0x2ac195786700, query id 53621728233 11.227
本文介绍了在高并发环境下,对包含唯一索引的表进行并发插入时遇到的大量死锁问题。通过分析死锁现场、死锁日志以及锁的详细机制,揭示了死锁产生的原因,主要是由于插入意向锁(X IK)和Next-Key Lock(S NK)之间的冲突。提出了保持事务简短和使用低隔离级别等预防死锁的策略。
最低0.47元/天 解锁文章

1911

被折叠的 条评论
为什么被折叠?



