你真的明白数据一致性吗—— max(id) 破坏 Mysql 事务一致性

场景

业务中有一个日志表,插入数据与同步数据查询强依赖于主键的有序性

数据同步时携带上次同步更新的主键,查询到Max(id)之间的数据,只同步增量部分

意味数据只有一次同步机会

表结构如下
表.png

问题

Mysql 数据隔离级别是RR

讲道理,两个不同的事务来读取数据后一个事务 B 是无法读取的到先一个事务 A 数据的数据

但是我们这里有个逻辑很特殊Max(id)

这里有两个场景:

A先读,B后写

假设目前数据最后一条记录是3

A事务携带上次同步主键2来请求,Max(id) = 3

这时B事务前来写数据

A事务先于B事务,根据 Mysql MVCC 视图,查询到了id=2,id=3的数据

同时B事务,写入数据id=4,id=5

下次数据同步携带id=3,继续走,业务无误

图示:

先读后写.png

AC先写,B后读

假设目前数据最后一条记录是3

A事务开始写入4

C事务开始写入5

事务还没有结束时,B携带2来读

期望同步2~3之间的数据,实际上却读到了2~5,但是实际上可读的数据还是1 2 3

这是为什么呢?

这就牵扯到了InnoDB 主键自增的规则了

InnoDB 的每个表的自增主键都,保存在内存中

偏移量:auto_increment_offset

步长:auto_increment_increment

默认双1

插入数据时获取该值,+后写入1

因为事务A耗时长,事务C耗时短

导致事务 C 先于事务 A提交

就种情况就是对业务有损了!!

4 数据就被永远的丢失了,阿西吧!!!

天知道我查了多久啊!!!

图示:
先写后读png.png

解决方案

1.间隙锁

在数据同步查询前加上select max(1) from table for update;增加间隙锁

阻塞读写,但是会有性能瓶颈

注意:间隙锁的范围要控制好

BadCase

1.select * from table limit 1 for update;

本意是只想锁住(max-1,max](max,sumpernum],减少锁间隙

但是忘记主键索引默认正向有序,这样其实是锁住了(-supernum,1](1,2]

正确的写法是:select * from table order by desc limit 1 for update;

2.select max(1) from table for update;

这种写法虽然满足了锁住表的要求,但是锁的是主键索引,也就是全表

当时考虑1会增加一次 Mysql 运算,希望节省性能,但是这样并发就下去了

2.分布式读写锁

以上的问题经过分析后都不是最好的方案,最后修改为分布式读写锁,具体方案见下一篇文章


7 声望
3 粉丝
0 条评论
推荐阅读
Liquibase 数据库版本管理工具:3. changeSet 变更集详解
上篇文章中详细了介绍了一下changelog 文件的使用,本篇文章将详细说一下 changeSet 变更集 中的细节,以及通常的使用方式 1.变更集分类 changeSet 分为 6类: add create drop rename sql other 官方文档:[链接...

哒哒队长1阅读 4k评论 1

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 5.9k评论 16

从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7.1k评论 6

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木32阅读 6k评论 9

从零搭建 Node.js 企业级 Web 服务器(五):数据库访问
回顾 从零搭建 Node.js 企业级 Web 服务器(一):接口与分层,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,控制层与服务层实现了业务处理过程,模型层定义了业务实体并以 对象-关系...

乌柏木32阅读 4.5k评论 9

从零搭建 Node.js 企业级 Web 服务器(十三):断点调试与性能分析
Node.js 官方提供了断点调试机制,出于安全性考虑默认为关闭状态,可以通过 node 参数 --inspect 或 --inspect-brk 开启,配合 IDE 能够非常方便地调试代码,本章就上一章已完成的项目 licg9999/nodejs-server-ex...

乌柏木29阅读 3.8k评论 9

从零搭建 Node.js 企业级 Web 服务器(八):网络安全
计算机网络依据 TCP/IP 协议栈分为了物理层、网络层、传输层、应用层,通常基础设施供应商会解决好前三层的网络安全问题,需要开发者自行解决应用层的网络安全问题,本章将着重表述应用层常见的网络安全问题及处...

乌柏木31阅读 5.7k评论 1

7 声望
3 粉丝
宣传栏