记一次线上MySQL数据库死锁问题
2018-06-26 23:55
344 查看
最近线上项目报了一个MySQL死锁(DealLock)错误,虽说对业务上是没有什么影响的,由于自己对数据库锁这块了解不是很多,之前也没怎么的在线上碰到过。这次刚好遇到了,便在此记录一下。
-
出现死锁问题背景
CREATE TABLE `test` ( `id` bigint(11) NOT NULL , `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `type` tinyint(4) NULL DEFAULT NULL , `uid` int(11) NULL DEFAULT NULL , PRIMARY KEY (`id`), UNIQUE INDEX `uniq_type_name` (`type`, `name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=COMPACT ;
出现死锁的情况是批量下单的接口,外部重复请求了两次,两次相隔10毫秒。 两次请求执行的sql(一次请求会执行三条insert)除了主键id不一样,其他都是一样的:如下
insert into test(id, name, type, uid) values(1, "DT590", 3, 1001); insert into test(id, name, type, uid) values(2, "DT589", 3, 1001); insert into test(id, name, type, uid) values(3, "DT588", 3, 1001);
报错的死锁日志:
------------------------ LATEST DETECTED DEADLOCK ------------------------ 2018-06-21 10:51:03 2b16deb03700 *** (1) TRANSACTION: TRANSACTION 1905650677, ACTIVE 0.001 sec inserting mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s), undo log entries 1 LOCK BLOCKING MySQL thread id: 16983306 block 34208692 MySQL thread id 34208692, OS thread handle 0x2b2203b0b700, query id 9093982364 172.24.18.106 app_redcliffc update INSERT INTO `test` (id, name, type, uid) VALUES (4, 'DT590', 3, 1001) *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 138 page no 16492 n bits 408 index `uniq_type_name` of table `db`.`test` trx id 1905650677 lock mode S waiting Record lock, heap no 341 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 4; hex 80000048; asc H;; 1: len 10; hex 44543631393230363835; asc DT61920685;; 2: len 8; hex 0461116807c09a00; asc a h ;; *** (2) TRANSACTION: TRANSACTION 1905650675, ACTIVE 0.004 sec inserting mysql tables in use 1, locked 1 3 lock struct(s), heap size 1184, 2 row lock(s), undo log entries 2 MySQL thread id 16983306, OS thread handle 0x2b16deb03700, query id 9093982366 172.24.18.105 app_redcliffc update INSERT INTO `test` (id, name, type, uid) VALUES (2, 'DT589', 3, 1001) *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 138 page no 16492 n bits 408 index `uniq_type_name` of table `db`.`test` trx id 1905650675 lock_mode X locks rec but not gap Record lock, heap no 341 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 4; hex 80000048; asc H;; 1: len 10; hex 44543631393230363835; asc DT61920685;; 2: len 8; hex 0461116807c09a00; asc a h ;; *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 138 page no 16492 n bits 408 index `uniq_type_name` of table `db`.`test` trx id 1905650675 lock_mode X locks gap before rec insert intention waiting Record lock, heap no 341 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 4; hex 80000048; asc H;; 1: len 10; hex 44543631393230363835; asc DT61920685;; 2: len 8; hex 0461116807c09a00; asc a h ;; *** WE ROLL BACK TRANSACTION (1)
-
问题分析
session1 | session2 | |
insert into test(id, name, type, uid) values(1, "DT590", 3, 1001); | 事务一先到,先插入第一条记录DT590,成功 | |
insert into test(id, name, type, uid) values(2, "DT589", 3, 1001); | 事务一继续插入第二天DT589记录,这个时候事务二请求到了,开始 插入第一条记录DT590,然后就报出死锁,事务二回滚,事务一成功执行 | insert into test(id, name, type, uid) values(1, "DT590", 3, 1001); |
session1 | 持锁 | session2 | 持锁 |
insert into test(id, name, type, uid) values(1, "DT590", 3, 1001); | 插入一条数据库中没有的记录,对DT590这条记录加了一个x锁 | ||
insert into test(id, name, type, uid) values(2, "DT589", 3, 1001); | 这时事务一插入DT589时候,发现这条记录已经有了一个gap lock(DT589这条记录刚好被事务二插DT590时候申请的gap lock包含了),会先申请一个insert intention waiting插入意向锁,这个锁和事务二持有gap lock互斥,发生死锁。 事务一在等事务二释放这条记录gap lock, 事务二在等事务一释放DT590 X锁 | insert into test(id, name, type, uid) values(1, "DT590", 3, 1001); | 事务二插入有唯一索引DT590这条记录,发现这条记录上已经有了x锁,所以会申请一个该条记录的s锁和gap lock |
-
相关一些锁知识
-
总结
相关文章推荐
- 一次线上多线程程序问题排查
- 分享一次解决线上java应用导致JVM内存溢出(OOM)的问题
- 记一次:c3p0连接池死锁的问题
- 分享一次解决线上java应用导致JVM内存溢出(OOM)的问题
- 记录一次排查极光推送SDK死锁问题
- 一次Mysql数据库服务器磁盘空间满引发的写入和同步问题
- 分享一次解决线上java应用导致JVM内存溢出(OOM)的问题
- 记录一次定位死锁的问题
- 记一次线上Mysql数据库 宕机
- [ Mariadb ] 记录一次MySQL数据库时区的问题
- [OOM]记一次线上OOM的问题
- 一次线上机器load负载过高报警问题排查及其后续处理
- 一次程序死锁问题的解决
- 分享一次解决线上java应用导致JVM内存溢出(OOM)的问题
- 一次线上的GC问题排查
- 记一次线上服务器load高问题定位和解决
- 一个Web报表项目的性能分析和优化实践(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例
- 一次线上问题排查所引发的思考
- 一次线上redis实例cpu占用率过高问题优化
- 记录一次Elasticsearch线上部署后出现:org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: []的问题解决