当前位置: 首页 > news >正文

模板网站有什么不好重庆seo网站

模板网站有什么不好,重庆seo网站,wordpress下载页,做ps的素材哪个网站在MySQL的默认事务隔离级别——读已提交(Read Committed, RC)中,开发者普遍认为不会出现间隙锁(Gap Lock)。这一认知源于RC级别的设计原则:仅通过行锁确保已提交数据的可见性,而将幻读问题交由应…

在MySQL的默认事务隔离级别——读已提交(Read Committed, RC)中,开发者普遍认为不会出现间隙锁(Gap Lock)。这一认知源于RC级别的设计原则:仅通过行锁确保已提交数据的可见性,而将幻读问题交由应用层处理。然而,近期多个生产环境却报告了反常现象——RC级别下竟触发了Gap Lock!这不仅导致事务意外阻塞,更动摇了我们对隔离级别底层行为的理解。

问题来源

“mysql RC 隔离级别也会出现gap 锁吗?我们生产环境是RC 隔离级别,出现了gap 锁导致死锁咯 ”? 上一周同事突如其来的问题彻底把我问懵了。

其实一直以来我也是认为只有RR隔离级别才会出现的,甚至我找到曾有人就这个问题给mysql 团队提了个bug ,并且mysql 团队也认为是个bug。那为啥现在RC 也会出现,甚至RU 级别也会出现呢。。我来盘下到底是怎么回事

问题背景

事情经过是这样子的,上周我们生产环境报了个死锁的问题,是并发执行insert into ... on duplicate key update 的时候报的一个死锁。死锁的日志是这样子的

trx id 679250 lock_mode X locks gap before rec insert intention waiting

gap lock 阻塞了各自的的insert intention lock 。一眼看去这个是老生常谈的死锁现象了。慢着,我们生产环境是RC 隔离级别,一连串的疑问冒出来:RC 隔离级别怎么会出现gap lock 呢?gap lock 不是在RR隔离级别下为了解决幻读而存在的吗?直接颠覆了我的认知,不死心查几次生产环境的事务隔离级别确认都是RC 隔离级别。

难道我记错了吗?登录mysql官网,下面是官网的描述:

image.png

虽然说gap lock 可以通过改变为RC 进行禁用,但是依然在外键和唯一键的时候会用到gap lock。 um um 确实是官方说是会产生的,但是依然不明白为啥会用gap lock 呢?

网上找到一个网友跟我一样,因为这个问题曾经给mysql 提了一个bug bug73170

神奇的是mysql 当时还当成bug 修复了,但是导致二级索引的唯一键失效,又revert 掉这个fix bug 68021

似乎看起来,mysql 团队也曾经认为这是一个bug ,只是由于实现难度解决不了还是继续使用了gap lock

Anway 先重现死锁,再一步一步分析为啥唯一键的检查需要用到gap lock,为什么mysql 团队没有去掉它

问题重现

根据我同事提供的重现sql.

第一步:

CREATE TABLE `test2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` int(11) NOT NULL, `other` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `code` (`code`) ) ENGINE=InnoDB ; TRUNCATE table test2; insert ignore into test2 (id,code, other) values(1,1,1),(3,3,3),(5,5,5);

现在数据库的数据是这样子的

idcodeother
111
333
555

第二步session1 

begin; insert into test2(code, other) values (3, 4) on duplicate key update other = VALUES(other); 数据库已经存在一个3的值,所以这里会冲突并且执行更新(这里的冲突很重要,是重现问题的关键)

第三步session2:

begin; insert into test2(code, other) values (5, 6) on duplicate key update other = VALUES(other); 数据库已经存在一个5的值,所以这里会冲突并且执行更新(这里的冲突很重要,是重现问题的关键)

以上正常执行,但是问题来了,当我在session2 继续插入(2,2)的时候,被锁阻塞住了,why? 数据库中有没有这条记录和我冲突,为啥要给我锁住,而且我是RC 隔离级别,可以允许幻读的存在,为啥给我加个gap lock?

session2: insert into test2(code, other) values (2, 2) on duplicate key update other = VALUES(other); 这个时候这个语句被阻塞了

第四步session1:

insert into test2(code, other) values (4, 4) on duplicate key update other = VALUES(other)

这个时候死锁产生了,是不是觉得很奇怪,不管是session 2 插入的(2,2)还是session1 插入的(4,4)他们在数据库中都不存在,理论上都应该可以正常执行,但实际上却阻塞了,这不是导致并发性能下降了吗?锁粒度过大了呢?

执行show engine innodb status; 看下死锁日志

image.png

从死锁日志可以看到插入意向锁是被对方的gap lock 阻塞住导致的死锁

问题分析

二级唯一索引的

俗话说的好,你要解决一个问题,你得先去了解它,我们看看二级索引的唯一键是怎么实现的

find the B-tree page in the secondary index you want to insert the value to assert the B-tree page is latched equal-range = the range of records in the secondary index which conflict with your value if(equal-range is not empty){ release the latches on the B-tree and start a new mini-transaction for each record in equal-range lock gap before it, and the record itself (this is what LOCK_S does) also lock the gap after the last(equal-range) also (before Bug #32617942 was fixed) lock the record after last(equal-range) once you are done with all of the above, find the B-tree page again and latch it again } insert the record into the page and release the latch on the B-tree page.

可以看到在二级唯一索引插入record 的时候, 分成了两个阶段

  1. 判断当前的物理记录上是否有冲突的record(delete mark 为不冲突)
  2. 如果没有冲突, 那么可以执行插入操作

这里在第一步 和 第二步 之间必须有锁来保证, 否则第一步 判断没有冲突可以插入的时候, 但是在第一步和第二步 之间另外一个事务插入了一个冲突的record, 那么第二步 再插入的时候其实是冲突了.

所以当前的实现如果gap 上存在至少一个相同的record(包括删除但是还没被回收的记录,因为删除只是做了个删除的墓碑标识,后面再回收), 那么需要给整个range 都加上gap X lock, 加了gap X lock 以后就可以禁止其他事务在这个gap 区间插入数据, 也就是通过lock 来保证第一步和第二步的原子性.

假设在code 这个唯一索引的数据是这样子的,总共有两个数据页,page1通过point 指针指向下一个数据页page2。红色带有delete mark 是代表这个数据已经被删除了,由于还没有给purge线程回收,因此还是在page 上,只是做了个删除的墓碑标识。绿色代表是正常的数据

image.png

现在我们有两个线程分别执行以下语句

sesson1: insert into test2(id,code, other) values (4,3, 4) on duplicate key update other = VALUES(other);

sesson2: insert into test2(id,code, other) values (12,3, 12) on duplicate key update other = VALUES(other);

session 1 执行第一个步判断code 唯一索引上找到有相同value 的记录 <3,3 delete mark>,<3,10 delete mark>,<3,11 delete mark>,<3,18 delete mark>,然后分别给他们加上next-key 锁。

最后还得再<5,5> 上增加gap 锁(假如这个5,5变成很大,那么意味着锁的gap 会非常大,影响并发性能),以防止<3,19>之后的数据被插入。到这一步是没有冲突的,因为这些值都是已经被删除的,插进去后不会违背唯一索引

如果在session 1 在第一阶段和第二阶段中间,session2 并发执行,那么第一阶段也会跟session 1 一样执行,都加上gap lock。因此后面他们两个人的插入都会失败,成功避免他们都成功来导致最终的数据不一致的问题。当然也就引入了死锁的

这个时候,你可能会说,如果我只是加数据上加锁S的行锁不是更好吗?这样就可以避免锁的范围太大,导致并发低下的问题。

session 1 执行第一个步判断code 唯一索引上找到有相同value 的记录 <3,3 delete mark>,<3,10 delete mark>,<3,11 delete mark>,<3,18 delete mark>,然后分别给他们加上s锁。

session 2 并发执行,也分别给他们加上s 锁,这个时候是不冲突的。他们两个都认为数据库没有这个记录,最后他们都插入成功。最终就违反了数据库的唯一键规则,这也就是mysql 团队修复了之前说bug 后带来的问题,因此有立马revert 了,直到今天都一直保留这个RC 隔离级别依然出现gap lock 的方式来保证唯一的正确性

image.png

http://www.fp688.cn/news/160948.html

相关文章:

  • 在网站开发中进行用户管理站点搜索
  • 青岛出版集团网站珠海网站设计
  • 淘宝客网站源码html做网页用什么软件好
  • 福州网站建设 联系yanktcn 04娃哈哈软文推广
  • 兰州网站建设方案百度竞价广告的位置
  • 工商局网站怎么做身份确认网络营销的定义
  • 网站关键词策略温州网站建设优化
  • 偃师网站制作最彻底的手机优化软件
  • 网站品牌建设功能爱站长工具
  • 受欢迎的广州网站设计seo搜索引擎优化工程师招聘
  • 网站建设图片像素是多大的百度友情链接
  • 亚马逊插件WordPress网络推广的优化服务
  • 有哪些可以做1元夺宝的网站100个关键词
  • 网站开发接口深圳市前十的互联网推广公司
  • 分类网站怎么做项目河北seo诊断培训
  • 官方网站投诉平台独立站seo是什么
  • asp动态网站被攻击网站快速刷排名工具
  • 网站建设策划书ppt网站建设黄页视频
  • 如何做招聘网站的方案google国际版入口
  • 服装网站建设发展状况学历提升哪个教育机构好一些
  • 培训学校网站建设方案重庆森林电影简介
  • 高端网站建设青岛世界十大网站排名
  • 简单网站开发项目实例市场推广seo职位描述
  • 建站费用参考电话营销系统
  • 网站研发进度表下载帮别人推广app赚钱
  • 网站快速排名怎么做百度知道官网首页登录入口
  • 有几个网站打不开最简短的培训心得
  • 网站建设主动型电话销售话术整站优化方案
  • 新中建设公司招聘网站提交百度一下
  • 春播网站是谁做的google play