前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >读已提交隔离级别下竟然有间隙锁

读已提交隔离级别下竟然有间隙锁

作者头像
CBeann
发布2024-03-19 09:21:11
790
发布2024-03-19 09:21:11
举报
文章被收录于专栏:CBeann的博客CBeann的博客
业务背景

广告主痛点的为进行一次全媒体联合投放,若投放10个媒体,需要制作和上传10+个创意、50+张不同尺寸和出血区要求的图片和视频素材、近100个元素,投放成本极高。这也是制约部分用户使用新产品投放的原因。

因此进行升级。以三个创意为例。广告主上传一个创意包,开发通过业务逻辑进行拆分为3个创意。整个过程用户只需要操作一次,体验感极佳。

在上面的图中,我们可以看到在右边一个创意包变为3个创意的时候,也是需要绑定到单元上。 其中创意包的绑定是用户触发。而后台绑定的操作是包绑定的binlog触发

问题

在一个阳光明媚的中午,在没有做任何发布的中午,业务同学找过来因为死锁导致绑定创意失败了,有客诉。那必须要重视一下这个问题了。

代码语言:javascript
复制
Deadlock found when trying to get lock; try restarting transaction More

当用户同时绑定多个创意包有普通创意时(即用户先绑定了一个普通创意后,用户在同时绑定两个创意包),此时会出现死锁的问题。

定位问题
找日志并分析

从应用日志来看,其实你并不知道你和谁冲突,因为死锁触发后会有一方是成功的。 此时只能求助DBA去排查。

其实很庆幸的是db里是有冗余trace的,所以发生死锁后我日志中会trace。 通过trace在加上日志系统是可以判断出并发的源头是下面红线的地方。

理论去证明问题

不过在日志中我发现了一个关键词lock_mode X locks gap,这不是八股文中的间隙锁和临间锁吗??? 这种不应该是在可重复度隔离级别下解决幻读才会出现吗?我还用GPT问了一下

在这里插入图片描述
在这里插入图片描述

其实就在这,理论与实际发生冲突了,无解了。 我请教了一下DBA的同学,DBA同学给了个文档说案例3就是你的情况

案例三用我们的问题去推演

T1

T2

begin

begin

insert into order_tb ( id, biz_number, adgroup_id, creative_id, campaign_id, cust_id, member_id, product_id, ref_type, flow_ratio, online_status, audit_status, audit_time, audit_reason, op_id, task_id, action_id, start_time, end_time, begin_time, stop_time, gmt_create, gmt_modified) values ( 14352655886, 0, 69735327295, 562734517, 69741860133, null, 40730745, 136001001, 0, null, 1, -1, ‘2024-02-29 14:14:05’, null, ‘0b64cf9617091872303006231d2e8c;9.1.1.7.1.6.6’, 0, 0, null, null, null, null, NOW(), NOW()) 此时获得唯一索引的行锁

insert into order_tb ( id, biz_number, adgroup_id, creative_id, campaign_id, cust_id, member_id, product_id, ref_type, flow_ratio, online_status, audit_status, audit_time, audit_reason, op_id, task_id, action_id, start_time, end_time, begin_time, stop_time, gmt_create, gmt_modified) values ( 14352655886, 0, 69735327295, 562734517, 69741860133, null, 40730745, 136001001, 0, null, 1, -1, ‘2024-02-29 14:14:05’, null, ‘0b64cf9617091872303006231d2e8c;9.1.1.7.1.6.6’, 0, 0, null, null, null, null, NOW(), NOW()) 此时因为唯一索引发生冲突且没有拿到行锁,触发间隙锁,锁范围,此时等待T2

insert into order_tb ( id, biz_number, adgroup_id, creative_id, campaign_id, cust_id, member_id, product_id, ref_type, flow_ratio, online_status, audit_status, audit_time, audit_reason, op_id, task_id, action_id, start_time, end_time, begin_time, stop_time, gmt_create, gmt_modified) values ( 14425938786, 0, 69735327295, 562714621, 69741860133, null, 40730745, 136001001, 0, null, 1, -1, ‘2024-02-29 14:14:05’, null, ‘0b64cf9617091872303066232d2e8c;9.1.1.6.1.6.6’, 0, 0, null, null, null, null, NOW(), NOW()) 此时因为插入的位置在间隙锁的范围内,所以此时等待T1

执行成功

触发死锁error释放资源

为什么会出现唯一冲突

业务侧的逻辑为:当收到创意包绑定单元的时间后,有一个全删全增的动作。如果用户同时绑定两个创意包,此时业务侧会收到两个请求,此时都执行全删全增的时候就会有插入的交集,从而触发唯一冲突。又因为主键序列通过区间段实现(不严格有序),所以后面会命中在间隙锁的范围从而出现死锁。

解决方案
  • 逻辑修改 全删全增改为diff操作。这样做有两个好处:1)之前调用两个接口,现在调用1个 2)减少无效的binlog变更,甚至能规避环。
  • 解决并发 当用户同时绑定多个创意包时,发送的binlog转mq的时候进行顺序消费,根据memberId路由到一个线程里。
  • 监控报警 早发现早治疗。
参考

MySQL 并发insert 唯一键冲突导致的死锁

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 业务背景
  • 问题
  • 定位问题
    • 找日志并分析
      • 理论去证明问题
        • 为什么会出现唯一冲突
        • 解决方案
        • 参考
        相关产品与服务
        云数据库 MySQL
        腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档