mysql 原理 ~ 死锁问题
一 锁
1 锁的定义
1 按照宏观角度
共享锁【S锁】
又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
排他锁【X锁】
又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
2 按照微观角度
recrod lock 行锁 锁定相关行
gap lock 间隙锁 锁定相关间隙,目的为了防止幻读的发生,阻止insert操作
Next-Key(record lock+gap lock)
二 死锁
1 死锁的定义
当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,时,就会导致这几个线程都进入无限等待的状态,称之为死锁,死锁会回滚成本较高的事务,执行成本较低的事务
2 死锁检测参数,默认开启
innodb_deadlock_detect=ON
3 死锁记录日志
show engine innodb status
LATEST DETECTED DEADLOCK
事务1
具体的sql语句
WAITING FOR THIS LOCK TO BE GRANTED//等待被授予的锁
包括(table,index,wait for lock,no 923 n bits(类似这种锁定的具体数据页))
事务2
具体的sql语句
HOLDS THE LOCK(S) //拥有的锁
包括(table,index,hold lock,no 923 n bits(类似这种锁定的具体数据页))
WAITING FOR THIS LOCK TO BE GRANTED//等待被授予的锁
包括(table,index,wait for lock)
三 死锁的分析
1 基础分析
死锁问题分为两种,一种是必然会发生的死锁场景,不过在业务研发上很少见 一种是高并发导致的死锁场景,在业务研发上很常见,也是死锁发生的最主要场景
2 基础知识
1 mysql的加锁方式 如果sql语句本身条件是主键,那么会按照主键加行锁 如果sql语句本身是辅助索引,那么会先给辅助索引加锁,再给辅助索引对应的主键加锁,同时还有gap lock范围锁
2 mysql的加锁顺序 如果多个事务内的多个操作同时对同一资源申请加锁,是根据事务内操作申请先后有序申请的,比如事务1申请X锁->事务2申请X锁->事务1又申请X锁
3 获取相关分析
1 是2个事务等待被授予的锁和 具体的sql语句 和表结构
2 是全部的事务操作语句,因为死锁日志记录并不包含全部的事务操作,只会记录发生死锁的最近的两个sql操作
3 sql语句的explain 一定要根据sql语句的explain进行具体分析,不同的索引扫描行数是不同的,而mysql是逐行扫描加锁的
这里说一个update语句的加锁顺序
当Update SQL被发给MySQL后,MySQL Server会根据where条件,读取第一条满足条件的记录,然后InnoDB引擎会将第一条记录返回,并加锁 (current read-> for update)。待MySQL Server收到这条加锁的记录之后,会再发起一个Update请求,更新这条记录(update -> X 锁)。一条记录操作完成,再 读取下一条记录,直至没有满足条件的记录为止。因此,Update操作内部,就包含了一个当前读。同理,Delete操作也一样。
四 死锁的案例
场景 1
1 insert并发导致的死锁
事务1 insert into value(1) 事务1 rollback
事务2 insert into value(1)
事务3 insert into value(1)
2 死锁日志分析
1 insert在进行唯一值检测的时候会加一个唯一性Insert Intention锁,这个其实是(S)锁,对发生冲突的事务X锁,当事务1回滚后 事务2 和3 都申请了S锁,后续需要申请了X锁,但是由于事务2和3都拥有S锁,互相等待不释放,导致了死锁,1个事务回滚释放了S锁,另一个事物申请成功
2 插入意向锁需要加的锁依次为 S NK, X IK, X RK
3 锁等待 两个事务都在等待 insert intention lock 锁,也即是2阶段的IK锁
场景 2
1 update并发导致的死锁
事务 1 update tab_test set state=1064,time=now() where state=1061 and time < date_sub(now(), INTERVAL 30 minute)
事务 2 update tab_test set state=1067,time=now () where id in (9921180)
2 死锁日志分析
1 加锁可能应用在主键或者辅助索引上,此问题场景于高并发下的update导致的死锁,有几率会出现
2 造成死锁的原因是由于 事务1 在执行期间先在辅助索引加锁,再加主键 事务2 先加主键先在主键上加锁,再在辅助索引加锁,最后造成互相持有资源不释放
场景 3
1 混合事务导致的死锁
事务 1 delete from table_1 where id=1 事务2 update table_2 set message='aa' where token='aaa'
update table_2 set message='aa' where token='aaa' delete from table_1 where id=1
2 死锁日志分析
1 mysql锁申请是有序的
2 事务1 delete语句先拿到ID=1的行锁 需要获取token的辅助索引 事务2拥有token的辅助索引需要获取ID=1的行锁 互相等待持有不释放
五 解决死锁问题的通用方法
1 并发insert导致的死锁(单事务)
1 减少唯一值检测
2 降低重复值插入
3 降低插入频率
2 并发update导致的死锁 (单事务)
1 尽量采用主键进行更新
2 降低更新频率
3 混合事务导致的死锁 (混合事务)
1 尽量采用主键进行操作
2 分析事务内加锁顺序,改造程序,调整业务逻辑
3 降低事务操作频率
4 特殊操作导致的死锁
1 insert into select from 在目标表低峰业务期做
2 pt-osc同样可能导致死锁, 在目标表低峰业务期做
六 总结
1 死锁问题经常爆发于高并发场景下,所以业务场景要考虑
2 不建议根据区分度较低的辅助索引值进行事务操作
3 排查死锁问题最好能模拟死锁场景问题
4 请注意 一定要依靠死锁日志打印进行锁的判断,explain出现的rows并不一定代表锁定的行
mysql 原理 ~ 死锁问题的更多相关文章
- MySQL更新死锁问题
作为一个社交类的 App ,我们有很多操作都会同时发生,为了确保数据的一致性,会采用数据库的事物. 比如现在我们有一个点赞操作,点赞成功后,需要更改文章的热度.以下是 SQL 语句: INSERT I ...
- MySQL会发生死锁吗?
SHOW ENGINE INNODB STATUS;来查看死锁日志: SHOW PROCESSLIST;查看进程 MySQL的InnoDB引擎事务有4种隔离级别,主要是为了保证数据的一致性. Inno ...
- [MySQL] 锁/死锁问题一例
MySQL锁/死锁问题 在MySQL中, 不同事务隔离级别下, 锁的情况表现是不同的, 另外表的设计上有无索引也是一个因素. 做一个小的实验测试InnoDB锁表现 -:) 说明 事务隔离级别 READ ...
- MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction
文章导航-readme MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction 1.场景 //t ...
- MySQL的死锁系列- 锁的类型以及加锁原理
疫情期间在家工作时,同事使用了 insert into on duplicate key update 语句进行插入去重,但是在测试过程中发现了死锁现象: ERROR 1213 (40001): De ...
- Mysql 原理以及常见mysql 索引等
## 主键 超键 候选键 外键 (mysql数据库常见面试题) 数据库之互联网常用架构方案 数据库之互联网常用分库分表方案 分布式事务一致性解决方案 MySQL Explain详解 ## 数据库事务的 ...
- MySQL原理
MySQL基础: sql语句的执行过程: 连接器:登录连接sql数据库 分析器:分析解读sql语句,并检查是否符合SQL语法规则 优化器:对实现方式进行优化,比如在查询时决定使用哪个索引. 执行器:执 ...
- mysql数据库死锁的产生原因及解决办法
这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下 数据库和操作系统一样,是一个多用户使用的共享资源.当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同 ...
- Mysql原理与优化
原文:https://mp.weixin.qq.com/s__biz=MzI4NTA1MDEwNg==&mid=2650763421&idx=1&sn=2515421f09c1 ...
随机推荐
- apache2 以及https证书配置
环境Ubuntu12.04 server 配置 1,首先在进入找到/etc/apache2/apache2.conf的配置文件,里面有包含了较多配置文件的路径如:httpd.conf/ports.co ...
- maomao的现在与未来
今晚开始,maomao决定要成为一个和以前不一样的人了. 自从高一开始竞赛生涯以来,我的竞赛就一直处于不是很好,也不是很差的水平,就像我初中一年级到二年级一直处于的状态一样.一直以来,我从来没有对自己 ...
- opencv: 轮廓提取;
一般轮廓提取是通过对图像的梯度进行卷积计算,得到图像边缘(滤波),常用的边缘检测方法有candy.sobel. Laplacian等,再对二值化后的边缘图像进行轮廓计算: 1.Candy算子: cv: ...
- [ZJOI2007]棋盘制作 悬线法dp 求限制下的最大子矩阵
https://www.luogu.org/problemnew/show/P1169 第一次听说到这种dp的名称叫做悬线法,听起来好厉害 题意是求一个矩阵内的最大01交错子矩阵,开始想的是dp[20 ...
- [DUBBO] Unexpected error occur at send statistic, cause: Forbid consumer 192.168.3.151 access servic
[DUBBO] Unexpected error occur at send statistic, cause: Forbid consumer 192.168.3.151 access servic ...
- Elastic Stack之Redis集群使用
Elastic Stack之Redis集群使用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客数据流走向:FileBeat ===>Redis ===>lo ...
- nginx的下载、编译安装和启动
一.nginx简介 nginx(“engine x”)是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器.nginx是由Igor Sysoev为俄罗斯访问量第二的R ...
- ContentType组件
django提供的一个快速连表操作的组件 适用于:一个字段确定不了唯一: 如:pricepolicy表中,course_id和content_type中对应的课程类型id才能确定唯一: model.p ...
- mysql使用navicat和mysqldump导出数据
1.navicat 方式一:选中表,右键转储:(含有表结构和数据) 方式二:选择右上角工具,点击数据传输,在这个页面右侧选择数据库,左侧选择文件. 点击下一步,选择导出的表名和各种函数什么的,然后点击 ...
- ACM-ICPC 2018 焦作赛区网络预赛 I Save the Room(水题)
https://nanti.jisuanke.com/t/31718 题意 问能否用1*1*2的长方体填满a*b*c的长方体. 分析 签到.如果a.b.c都是奇数,一定不能. #include< ...