文档章节

mysql事务死锁案例分析(GAP锁篇)

陈卓明
 陈卓明
发布于 2017/05/14 23:22
字数 829
阅读 227
收藏 0

gap lock(间隙锁),主要用在mysql中解决RR级别事务隔离的幻读问题

下面是mysql对gap lock给出的官方解释:

A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record。

在官方详细解析中有提到一个要点,也是导致本次事务死锁的根本原因

Gap locks in InnoDB are “purely inhibitive”, which means they only stop other transactions from inserting to the gap. They do not prevent different transactions from taking gap locks on the same gap. Thus, a gap X-lock has the same effect as a gap S-lock.

大致意思是:X-lock的gap和S-lock的效果是一样的,都是可以被多个事务获取到。

详见:https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html#innodb-gap-locks

下面开始先分析gap lock 在唯一索引中的表现

表结构:

建表sql

DROP TABLE IF EXISTS `staff_role_biz_role_id`;

CREATE TABLE `staff_role_biz_role_id` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kdt_id` int(11) unsigned NOT NULL COMMENT 'kdtId',
  `admin_id` int(11) unsigned NOT NULL COMMENT '有赞id',
  `biz` varchar(20) NOT NULL DEFAULT '1' COMMENT '角色类型',
  `role_id` int(11) unsigned NOT NULL COMMENT '角色id',
  `shop_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'shopId,多门店使用',
  `operator` varchar(20) NOT NULL DEFAULT '0' COMMENT '操作人',
  `operator_id` int(11) NOT NULL DEFAULT '0' COMMENT '操作人id',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_kdtId_adminId_biz_roleId` (`kdt_id`,`admin_id`,`role_id`,`biz`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

LOCK TABLES `staff_role_biz_role_id` WRITE;
INSERT INTO `staff_role_biz_role_id` (`id`, `kdt_id`, `admin_id`, `biz`, `role_id`, `shop_id`, `operator`, `operator_id`, `create_time`, `update_time`)
VALUES
	(1,10,1,'retail',1,0,'0',0,'2017-05-09 15:55:26','2017-05-09 15:55:26'),
	(2,20,1,'retail',1,0,'0',0,'2017-05-09 15:55:40','2017-05-09 15:55:40'),
	(3,30,1,'retail',1,0,'0',0,'2017-05-09 15:55:55','2017-05-09 15:55:55'),
	(4,40,1,'retail',1,0,'0',0,'2017-05-09 15:56:06','2017-05-09 15:56:06'),
	(5,50,1,'retail',1,0,'0',0,'2017-05-09 15:56:16','2017-05-09 15:56:16');
UNLOCK TABLES;

 

执行sql(多个session模拟并发,请按照sql前的序号来执行相应的sql)

场景一:唯一索引,delete条件无任何命中,然后执行insert

session A:

begin;

1.

delete from staff_role_biz_role_id where kdt_id = 15 and admin_id = 1 and biz = 'retail' and role_id = '1';

4.

INSERT INTO `staff_role_biz_role_id` (`kdt_id`, `admin_id`, `biz`, `role_id`, `shop_id`, `operator`, `operator_id`, `create_time`, `update_time`) VALUES ('15', '1', 'retail', '2', '0', '0', '0', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

 

session B:

begin;

2.

delete from staff_role_biz_role_id where kdt_id = 18 and admin_id = 2 and biz = 'retail' and role_id = '1';

 

3.

INSERT INTO `staff_role_biz_role_id` (`kdt_id`, `admin_id`, `biz`, `role_id`, `shop_id`, `operator`, `operator_id`, `create_time`, `update_time`) VALUES ('18', '2', 'retail', '2', '0', '0', '0', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

当执行完第4步时,会出现如下的死锁提示

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

相关事务锁信息

INNODB_LOCKS

INNODB_TRX

INNODB_LOCK_WAITS

gap锁简单模型如图:

场景二:唯一索引,delete条件部分命中,然后执行insert

session A

delete from staff_role_biz_role_id where kdt_id = 20 and admin_id = 1 and biz = 'retail' and role_id = '1';

session B

delete from staff_role_biz_role_id where kdt_id = 20 and admin_id = 1 and biz = 'retail' and role_id = '1';

 

由于where条件命中,所以直接在索引上给记录(kdt_id = 20 and admin_id = 1 and biz = 'retail' and role_id = '1')上面加上了X锁,session B的事务就需要等待session A事务释放了X锁后才能执行事务,此情况下不会出现死锁

相关事务锁信息

 

以上为mysql中,innodb下,建立唯一索引,在执行sql中存在索引不命中时使用了gap锁导致的死锁场景分析,主要原因还是在于gap锁可以被多个事务获取到,谢谢拍砖^_^

 

© 著作权归作者所有

陈卓明
粉丝 0
博文 3
码字总数 1939
作品 0
深圳
程序员
私信 提问
mysql 锁机制 详解二 (死锁)

1 死锁问题背景 1 1.1 一个不可思议的死锁 1 1.1.1 初步分析 3 1.2 如何阅读死锁日志 3 2 死锁原因深入剖析 4 2.1 Delete操作的加锁逻辑 4 2.2 死锁预防策略 5 2.3 剖析死锁的成因 6 3 总结 ...

LYQ1990
2016/05/19
55
0
mysql并发insert死锁问题——gap、插入意向锁冲突

问题描述 线上出现MySQL死锁报警,通过show engine innodb status命令查看死锁日志,结合异常代码,还原发生死锁的事务场景如下: 环境: mysql5.7,事务隔离级别REPEATABLE-READ 表结构 并发...

hebaodan
2018/06/26
0
1
Mysql并发时经典常见的死锁原因及解决方法

Mysql并发时经典常见的死锁原因及解决方法 1. mysql都有什么锁 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最...

rshare
2017/12/06
0
0
mysql死锁问题分析

mysql死锁问题分析 源贴:https://www.cnblogs.com/LBSer/p/5183300.html 线上某服务时不时报出如下异常(大约一天二十多次):“Deadlock found when trying to get lock;”。 Oh, My God! ...

rshare
2017/12/06
0
0
从一次诡异的MySQL死锁故障看数据库锁机制真相

前几天,线上发生了一次数据库死锁问题,这一问题前前后后排查了比较久的时间,这个过程中自己也对数据库的锁机制有了更深的理解。本文总结了这次死锁排查的全过程,并分析了导致死锁的原因及...

DBAplus社群
05/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Angular 英雄编辑器

应用程序现在有了基本的标题。 接下来你要创建一个新的组件来显示英雄信息并且把这个组件放到应用程序的外壳里去。 创建英雄组件 使用 Angular CLI 创建一个名为 heroes 的新组件。 ng gener...

honeymoose
今天
5
0
Kernel DMA

为什么会有DMA(直接内存访问)?我们知道通常情况下,内存数据跟外设之间的通信是通过cpu来传递的。cpu运行io指令将数据从内存拷贝到外设的io端口,或者从外设的io端口拷贝到内存。由于外设...

yepanl
今天
6
0
hive

一、hive的定义: Hive是一个SQL解析引擎,将SQL语句转译成MR Job,然后再在Hadoop平台上运行,达到快速开发的目的 Hive中的表是纯逻辑表,就只是表的定义,即表的元数据。本质就是Hadoop的目...

霉男纸
今天
5
0
二、Spring Cloud—Eureka(Greenwich.SR1)

注:本系列文章所用工具及版本如下:开发工具(IDEA 2018.3.5),Spring Boot(2.1.3.RELEASE),Spring Cloud(Greenwich.SR1),Maven(3.6.0),JDK(1.8) Eureka: Eureka是Netflix开发...

倪伟伟
昨天
15
0
eclipse常用插件

amaterasUML https://takezoe.github.io/amateras-update-site/ https://github.com/takezoe/amateras-modeler modelGoon https://www.cnblogs.com/aademeng/articles/6890266.html......

大头鬼_yc
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部