innoDB的事务,是基于锁来实现的,用到事务不自然就会用到锁,而如果对锁理解的不通透,很容易造成线上问题。

数据库加锁的分析,和事务的引擎,隔离级别,索引,主键索引都有关系,

如果去考虑引擎和各种隔离级别的话,就会很复杂了,所以下面都是基于innoDB和RR的隔离级别进行分析:

表结构:

内容:

1 , 根据主键更新

如果根据主键来行数

事务A

事务B

 

update user set name='ce1' where id='1';

update user set name='ce3' where Id='3';

同时执行,都成功

update user set name='ce1' where id='1';

update user set name='ce3' where userId='10003';

B更新失败,直至:Lock wait timeout

结论,如果根据非主键来更新,会把整个表进行锁定,无法 进行更新操作。

注:只要是根据主键索引来更新,哪怕事务A没命中主键,也不会锁定整个表

2,根据非索引非主键更新

事务A

事务B

 

update user set name='ce1' where userId='10001';

update user set name='ce3' where Id='3';

或者

update user set name='ce3' where userId='10003'

都会失败,如果非索引,直接锁表

3, 如果在userId 列上加入普通唯一索引

修改成

再更新

事务A

事务B

 

update user set name='ce1' where userId='10001';

update user set name='ce3' where Id='3';

或者

update user set name='ce3' where userId='10003'

都会成功,如果有唯一索引,也是能成功行数,互相不影响

4, 如果在userId 列上加入普通非唯一索引 (重点探讨)

把userId改成非唯一索引:

记录内容如下:

+----+--------+------+

| id | userId | name |

+----+--------+------+

| 1 | 10001 | ce1 |

| 2 | 10002 | ce2 |

| 3 | 10001 | ce3 |

| 4 | 10004 | ce4 |

+----+--------+------+

再相同操作

事务A

事务B

 

update user set name='ce1' where userId='10001';

update user set name='ce3' where Id='3';

B失误执行失败,显然id=3的这行也被锁住了

其实最终还是按主键锁住的记录 id=1和id=3的记录

非唯一索引与普通索引,更一步的区别是GAP锁

gap锁是用于解决幻读的存在,演示

把记录修改成,如:

id为pk. userId为Normal key

A事务

B事务

结果

begin;

update user set name='ce22' where userId='100020';

   
 

insert into user (userId,name) values('100021','tttt');

直至事务失败超时

1, 首先GAP锁针对的是insert操作

2, 当更新userId='100020'时,会锁住两边的记录区间,防止幻读的存在。

3, 锁是作用在普通索引上,但由于索引是由B+树存储,那么锁住的是两边的区间,防止insert

GAP锁为什么不是锁住一条记录,而是锁住一个区间呢? 

附上疑问: https://www.oschina.net/question/867417_2289606

其实:

GAP锁是解决幻读存在的,如当 delete时就必须锁住区间了

A事务

B事务

 

begin;

delete from user where userId='888888';

   
 

insert into user (userId,name) values('100021','tttt');

OK, 可以插入

 

insert into user (userId,name) values('100041','tttt');

插入超时

可见,这个GAP锁,锁住的是100040~无穷大 的记录

死锁的产生分析

1, 两条语句产生的死锁

id = pk, userId= key

最简单的。两条语句互相更新等待

begin;

update user set name='ce1' where userId='100010';

begin;

update user set name='ce2' where userId='100020';

update user set name='ce2' where userId='100020';

update user set name='ce1' where userId='100010';

 

最简单的死锁

2, 由于gap锁,删除一台不存在的记录

如,先删除一条记录,然后插入一条记录, 如果记录GAP锁冲突,两个事务容易互为死锁。如:

A事务

B事务

begin;

delete from user where userId='100020';

(Query OK, 1 row affected)

begin;

delete from user where userId='565656';

insert into user (userId,name) values('100041','tttt');

 

insert into user (userId,name) values('100019','tttt');

结果直接抛出:

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

分析:

A事务 delete 加入gap锁【100010,100020】, 第二段【100020,100030】

B事务 delete加入gap 锁【100040,无穷大】

然后A事务插入,获取插入意向锁时B事务的GAP锁被阻塞

B事务插入,获取插入意向锁时时被A事务的GAP锁阻塞

结果死锁

1-2 【包子mysql系列】, 对mysql的innoDB加锁分析的更多相关文章

  1. MySQL中一条SQL的加锁分析

    MySQL中一条SQL的加锁分析 id主键 + RC id唯一索引 + RC id非唯一索引 + RC id无索引 + RC id主键 + RR id唯一索引 + RR id非唯一索引 + RR id ...

  2. mysql InnoDB加锁分析

    文章转载自:http://www.fanyilun.me/2017/04/20/MySQL%E5%8A%A0%E9%94%81%E5%88%86%E6%9E%90/ 以下实验数据基于MySQL 5.7 ...

  3. 【MySql系列】MySql踩坑系列

    问题一:远程登录报错Host '192.168.181.201' is not allowed to connect to this MySQL server 解决: 问题二:MySql access ...

  4. Mysql系列二:Mysql 开发标准规范

    原文链接:http://www.cnblogs.com/liulei-LL/p/7729983.html 一.表设计 1. 库名.表名.字段名使用小写字母,“_”分割. 2. 库名.表名.字段名不超过 ...

  5. MySQL系列(二)--MySQL存储引擎

    影响数据库性能的因素: 1.硬件环境:CPU.内存.存盘IO.网卡流量等 2.存储引擎的选择 3.数据库参数配置(影响最大) 4.数据库结构设计和SQL语句 MySQL采用插件式存储引擎,可以自行选择 ...

  6. MySQL系列:MySQL的基本使用

    数据库的基本操作 在MySQL数据库中,对于一个MySQL示例,是可以包含多个数据库的. 在连接MySQL后,我们可以通过 show databases; 来进行查看有那么数据库.这里已经存在一些库了 ...

  7. MySQL 系列(四)主从复制、备份恢复方案生产环境实战

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...

  8. MySQL 系列(三)你不知道的 视图、触发器、存储过程、函数、事务、索引、语句

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...

  9. MySQL 系列(二) 你不知道的数据库操作

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 本章内容: 查看\创建\使用\删除 数据库 用户管理及授权实战 局域网 ...

  10. MySQL 系列(五) 多实例、高可用生产环境实战

    MySQL 系列(五) 多实例.高可用生产环境实战   第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 史上最屌.你不知道的数据库操作 第三 ...

随机推荐

  1. iview weapp输入组件input事件顺序

    做小程序,使用ivew weapp组件框架,同时用到了i-input和i-modal,更具体说,就是在modal里面放置了input,填写数据后点击确定,实现提交数据. 出现点小问题,发现是事件顺序导 ...

  2. Vue3路由进阶实战:深度解析参数传递与导航守卫核心技术

    一.路由参数传递的进阶应用技巧 1.1 路由配置与参数验证 // router/index.js { path: '/user/:userId(\\d+)', // 使用正则表达式限制只匹配数字 na ...

  3. 分布式锁—4.Redisson的联锁和红锁

    大纲 1.Redisson联锁MultiLock概述 2.Redisson联锁MultiLock的加锁与释放锁 3.Redisson红锁RedLock的算法原理 4.Redisson红锁RedLock ...

  4. 【由技及道】在wsl容器中进行远程java开发【人工智障AI2077的开发日志003】

    指令接收:「需要万能开发环境」 系统警报:检测到主人即将陷入"环境配置地狱" 启动救赎协议:构建量子化开发容器 终极目标:让"在我机器上能跑"成为历史文物 需求 ...

  5. PPT图片搭配

  6. 阻尼、模态应变能法与FRP的关系

    阻尼的概念 系统损耗振动能或声能的能力称为阻尼 阻尼越大,输人系统的能量便能在较短时间内损耗完毕.系统从受激振动到重新静止所经历的时间就越短; 阻尼也可理解为系统受激后迅速恢复到受激前状态的一种能力 ...

  7. 写一个简单的SQL生成工具

    知识点: MyBatis 语法概览 MyBatis 是一个强大的数据持久化框架,它提供了一种半自动化的 ORM 实现方式.通过 MyBatis,开发者可以通过简单的 XML 或注解来配置和映射原生信息 ...

  8. 一款torrent文件格式分析工具(绿色纯天然)

    点击下载 1.主界面 2.文件分析(显示文件所在分片的位置) 3.获取指定分片所在的peers服务器列表 一只会铲史的猫

  9. CENTOS 7 使用Docker安装oracle 11g

    1.docker第一次安装失败,下一次会提示同名的容器已经存在,解决办法: docker container ls -a 根据上面执行的接口,选择一个containerid,然后带入到下面的命令 do ...

  10. BUUCTF---old flashion

    1.题目 2.知识 3.解题 很奇怪,一段英文字母,看起来像维吉尼亚,但需要key,不知道什么是Key,我们丢到q爆破中试试 直接得出来了flag:flag{n1_2hen-d3_hu1-mi-ma_ ...