ps:当前索引不是普通索引 , 而且是唯一索引等其他情况,请参考下面资料
MySQL 加锁处理分析
回到我自己的案例中,重新屡一下事务1的执行过程:
因为普通索引
KEY hotel_date_idx ( hotel_id , rate_date )
的关系 这段sql会获取一个gap lock,范围(2,11111]
这段sql会获取一个insert intention lock (waiting)
再看事务2的执行过程
因为普通索引
KEY hotel_date_idx ( hotel_id , rate_date )
的关系 这段sql也会获取一个gap lock , 范围也是(2,11111](根据前面的知识 , gap lock之间会互相兼容,可以一起持有锁的)
这段sql也会获取一个insert intention lock (waiting)
看到这里,基本也就破案了 。因为普通索引的关系,事务1和事务2的gap lock的覆盖范围太广,导致其他事务无法插入数据 。
重新梳理一下:
所以从结果来看,一堆事务被回滚 , 只有10007数据被更新成功
gap lock 导致了并发处理的死锁
在mysql默认的事务隔离级别(repeatable read)下,无法避免这种情况 。只能把并发处理改成同步处理 。或者从业务层面做处理 。
共享锁、排他锁、意向共享、意向排他
record lock、gap lock、next key lock、insert intention lock
show engine innodb status
mysql解决死锁问题官方定义如下:两个事务都持有对方需要的锁 , 并且在等待对方释放,并且双方都不会释放自己的锁 。
这个就好比你有一个人质,对方有一个人质,你们俩去谈判说换人 。你让对面放人,对面让你放人 。
看到这里,也许你会有这样的疑问,事务和谈判不一样,为什么事务不能使用完锁之后立马释放呢?居然还要操作完了之后一直持有锁?这就涉及到 MySQL 的并发控制了 。
MySQL的并发控制有两种方式 , 一个是 MVCC , 一个是两阶段锁协议 。那么为什么要并发控制呢?是因为多个用户同时操作 MySQL 的时候,为了提高并发性能并且要求如同多个用户的请求过来之后如同串行执行的一样( 可串行化调度 ) 。具体的并发控制这里不再展开 。咱们继续深入讨论两阶段锁协议 。
官方定义:
对应到 MySQL 上分为两个阶段:
就是说呢,只有遵循两段锁协议,才能实现可串行化调度。
但是两阶段锁协议不要求事务必须一次将所有需要使用的数据加锁 , 并且在加锁阶段没有顺序要求,所以这种并发控制方式会形成死锁 。
MySQL有两种死锁处理方式:
由于性能原因,一般都是使用死锁检测来进行处理死锁 。
死锁检测的原理是构建一个以事务为顶点、锁为边的有向图,判断有向图是否存在环 , 存在即有死锁 。
检测到死锁之后,选择插入更新或者删除的行数最少的事务回滚 , 基于 INFORMATION_SCHEMA.INNODB_TRX 表中的 trx_weight 字段来判断 。
MySQL如何处理死锁
关于mysql表死锁怎么办和mysql解决死锁的三种方法的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。
推荐阅读
- 姜云升直播的手机壁纸,姜云升直播里出现的书
- sap刷新,SAP刷新快捷键
- 电脑p3p4线什么意思,电脑p3线插在哪里图解
- 星空游戏模拟经营,星空模拟器下载手机
- go语言注释是什么意思 go语言chan
- redisc语言api,redis编程语言
- 包含asp.netmvcnvelocity的词条
- 抖音和公众号粉丝哪个值钱,抖音和公众号各自适合做什么内容
- java代码上线操作记录 java项目上线常见问题