1-2 【包子mysql系列】, 对mysql的innoDB加锁分析
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加锁分析的更多相关文章
- MySQL中一条SQL的加锁分析
MySQL中一条SQL的加锁分析 id主键 + RC id唯一索引 + RC id非唯一索引 + RC id无索引 + RC id主键 + RR id唯一索引 + RR id非唯一索引 + RR id ...
- 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 ...
- 【MySql系列】MySql踩坑系列
问题一:远程登录报错Host '192.168.181.201' is not allowed to connect to this MySQL server 解决: 问题二:MySql access ...
- Mysql系列二:Mysql 开发标准规范
原文链接:http://www.cnblogs.com/liulei-LL/p/7729983.html 一.表设计 1. 库名.表名.字段名使用小写字母,“_”分割. 2. 库名.表名.字段名不超过 ...
- MySQL系列(二)--MySQL存储引擎
影响数据库性能的因素: 1.硬件环境:CPU.内存.存盘IO.网卡流量等 2.存储引擎的选择 3.数据库参数配置(影响最大) 4.数据库结构设计和SQL语句 MySQL采用插件式存储引擎,可以自行选择 ...
- MySQL系列:MySQL的基本使用
数据库的基本操作 在MySQL数据库中,对于一个MySQL示例,是可以包含多个数据库的. 在连接MySQL后,我们可以通过 show databases; 来进行查看有那么数据库.这里已经存在一些库了 ...
- MySQL 系列(四)主从复制、备份恢复方案生产环境实战
第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...
- MySQL 系列(三)你不知道的 视图、触发器、存储过程、函数、事务、索引、语句
第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...
- MySQL 系列(二) 你不知道的数据库操作
第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 本章内容: 查看\创建\使用\删除 数据库 用户管理及授权实战 局域网 ...
- MySQL 系列(五) 多实例、高可用生产环境实战
MySQL 系列(五) 多实例.高可用生产环境实战 第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 史上最屌.你不知道的数据库操作 第三 ...
随机推荐
- iview weapp输入组件input事件顺序
做小程序,使用ivew weapp组件框架,同时用到了i-input和i-modal,更具体说,就是在modal里面放置了input,填写数据后点击确定,实现提交数据. 出现点小问题,发现是事件顺序导 ...
- Vue3路由进阶实战:深度解析参数传递与导航守卫核心技术
一.路由参数传递的进阶应用技巧 1.1 路由配置与参数验证 // router/index.js { path: '/user/:userId(\\d+)', // 使用正则表达式限制只匹配数字 na ...
- 分布式锁—4.Redisson的联锁和红锁
大纲 1.Redisson联锁MultiLock概述 2.Redisson联锁MultiLock的加锁与释放锁 3.Redisson红锁RedLock的算法原理 4.Redisson红锁RedLock ...
- 【由技及道】在wsl容器中进行远程java开发【人工智障AI2077的开发日志003】
指令接收:「需要万能开发环境」 系统警报:检测到主人即将陷入"环境配置地狱" 启动救赎协议:构建量子化开发容器 终极目标:让"在我机器上能跑"成为历史文物 需求 ...
- PPT图片搭配
- 阻尼、模态应变能法与FRP的关系
阻尼的概念 系统损耗振动能或声能的能力称为阻尼 阻尼越大,输人系统的能量便能在较短时间内损耗完毕.系统从受激振动到重新静止所经历的时间就越短; 阻尼也可理解为系统受激后迅速恢复到受激前状态的一种能力 ...
- 写一个简单的SQL生成工具
知识点: MyBatis 语法概览 MyBatis 是一个强大的数据持久化框架,它提供了一种半自动化的 ORM 实现方式.通过 MyBatis,开发者可以通过简单的 XML 或注解来配置和映射原生信息 ...
- 一款torrent文件格式分析工具(绿色纯天然)
点击下载 1.主界面 2.文件分析(显示文件所在分片的位置) 3.获取指定分片所在的peers服务器列表 一只会铲史的猫
- CENTOS 7 使用Docker安装oracle 11g
1.docker第一次安装失败,下一次会提示同名的容器已经存在,解决办法: docker container ls -a 根据上面执行的接口,选择一个containerid,然后带入到下面的命令 do ...
- BUUCTF---old flashion
1.题目 2.知识 3.解题 很奇怪,一段英文字母,看起来像维吉尼亚,但需要key,不知道什么是Key,我们丢到q爆破中试试 直接得出来了flag:flag{n1_2hen-d3_hu1-mi-ma_ ...