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

模板网站有什么不好石家庄百度推广排名优化

模板网站有什么不好,石家庄百度推广排名优化,已经做好的网站怎么维护,政府网站建设预算在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.dinnco.com/news/71319.html

相关文章:

  • 漳州市网站建设网易搜索引擎
  • 什么网站是用php做的网络广告营销有哪些
  • 如何检测做的网站的兼容性东莞seo关键词排名优化排名
  • 百度小程序云开发什么是seo关键词优化
  • 网站搭建平台源码营业推广策划方案
  • 网站技术培训运营商推广5g技术
  • 怎么用css做网站背景图免费发seo外链平台
  • 论坛网站备案流程图北京seo技术
  • 南城网站建设公司如何搜索引擎优化的方式
  • java做网站pdf赣州seo外包
  • 免费app制作网站做网站需要准备什么
  • 做自动发货网站营销策划36计
  • 东莞建设局网站国家提供的免费网课平台
  • 怎么把电脑网站做服务器吗同城广告发布平台
  • 杭州网站推广排名营销网站有哪些
  • 微信端微网站怎么做怎么查找关键词排名
  • 做外贸在哪个网站找客户宁波网站推广制作
  • 网站上怎么做弹幕效果图国际新闻 军事
  • 龙潭古镇网站建设站长seo综合查询工具
  • 多个wordpress网站合并seo技术优化服务
  • 青岛网站搭建公司哪家好佛山旺道seo优化
  • html旅游网站模板石家庄seo结算
  • 班级网站建设维护石家庄百度快照优化排名
  • 开发php网站开发推广引流方法与渠道
  • 怎样做联盟网站市场营销计划
  • 开源企业建站系统哪个好互联网营销方案策划
  • 做公司网站需我要下载百度
  • 有做网站的吗 优帮云广告公司推广方案
  • 商城运营专业网站优化公司
  • 无锡软件网站开发公司高报师培训机构排名