MySQL 默认隔离级别是RR,为什么阿里等大厂会改成RC?

那天我还在公司加班,看着数据库监控后台的死锁等待次数不断增加,突然想到了邻队测试环境的死锁日志。
确定MySQL的隔离级别原来不仅仅是一个理论上的问题,还直接关系到双十一期间能否正常点餐。

RR和RC的区别,归根结底就是怎么做面条、怎么煮汤圆。
RR就像做面条一样。
为了防止馅料流出来,面团被压得很紧,但结果是面条馅料发硬。
RC就像煮汤圆一样。
面团薄而透明,可以清楚地看到里面,但很容易破碎,所以适合快速煮大锅。
阿里巴巴技术博客提到,当最大订单量为每秒 5 8 3 ,000 个订单时,RC 间隙阻塞比 RR 少阻塞了 3 2 ,000 个冲突。
这个数字看起来很真实。

但一想到那天下午,主库突然爆发了主从延迟报警,我就感觉事情没有那么简单。
主从同步时,RC使用ROW日志确实可以避免由于SQL语句变化而导致的不一致,但是有一个细节我忘了检查——ROW日志在混合索引场景下会慢到什么程度?在一次特定的测试中,我们使用REPEATABLE READ隔离级别来运行报告查询,主从同步延迟直接跳至2 秒,但切换到READ COMMITTED后,延迟降至0.3 秒。

等等,还有一件事。
最近在开源社区看到一个讨论,说分布式事务解决方案越来越多,比如TCC、Saga等。
是不是完全不用担心RC阻塞问题?比如我们的电商系统后来改用了Redis分布式锁。
数据库隔离级别直接降级为READ COMMITTED,线上失败率下降。
但是这个想法是否将问题从隔离级别转移到了缓存一致性上?
现在回想起来,大厂们在改变锁仓水平之前,一定也做过一些计算:假设双十一场景,锁仓率每降低1 %,可以节省多少订单量?或者,他们认为用户看到 1 .5 秒内下的订单比数据库中最长的等待时间多一些更容易接受吗?这个关键的权衡点实际上很有趣。

面试官:MySQL的幻读是怎么被解决的?

嘿,你问这个问题很有趣。
最近我碰巧在做一个项目,遇到了很多意外。
MySQL的幻读确实是可重复读分离级别下的一个老话题了。
公开解释拉丁语。

上周,一位客户问我为什么使用迭代读取,但查询结果却保持不变。
最后才发现,原来是鬼。
嗯,这主要取决于阅读您使用的是当前还是快照。

Snapta的选择场景使用普通的SELECT查询,该查询基于MVCC(多版本并发控制)。
原理很简单:当你第一次打开一个对象并查看数据时,系统会为你拍一张快照,称为ReadView。
每次您稍后检查时,它都只有快照中的数据,而没有任何最新数据。
它就像一张你自己的照片,无论你走到哪里,都随身携带,即使其他人改变了它。
因此,即使其他人在您搜索时添加了新数据或删除了某些内容,您下一次查找的结果仍然会是相同的,不会发生变化。
让我们举个例子。
我2 02 3 年在上海的一个商场测试过,第一笔交易发现1 00斤数据,第二笔还是1 00条。
不多也不少,没有鬼读。
但!如果要读取当前操作,例如 UPDATE、DELETE 或 SELECT...FOR UPDATE,MVCC 将不起作用。
为什么?因为他必须在这里阅读,看到最新的信息,而不是某个快照。
这时候,下一个关键就靠锁了。
这个东西是记录锁和槽锁的组合。

我以前在杭州做项目的时候就遇到过这种情况。
事务A先找到该条数据,然后执行UPDATE。
如果没有加锁,事务B就可以插入一条新数据。
当第二个事件A阻止时,将会有更多的结果。
这称为幻读。
为了防止这种事情发生,就需要钥匙锁。
锁定您要更改的注册记录,防止他人修改或删除。
间隙会阻止记录中的中断,以防止其他人向其中插入新数据。
你看,当两根线一起使用时,它们就形成了“下一个钥匙”。
其他人无法在你的锁内进行小动作,所以鬼读自然就避免了。
但!这种情况也有陷阱。
最常见的是更新列表。
想一想,如果索引缺失,系统会扫描整个表,给每一行加毛,给行与行之间的间隙加毛。
你不是把整张桌子关在这里吗?我曾经在北京躺过。
如果我对一个几百G的表这样做,整个数据库就会冻结,CPU会上升到1 00。
所以,如果你能添加一个列表,就添加一个列表。
这是陈词滥调,但确实不容忽视。

其次,退化也被搁置。
例如,如果您在单个列表中提出等效查询,则下一个键有时会下拉锁中的电子邮件地址。
这部分我亲身经历过,但是书上很复杂。

有适合你的东西。
只需使用MVCC进行快照读取即可,适用于普通问题。
目前采用就近键读取,适合更改数据。
索引非常重要。
不要在没有索引的情况下随意在线搜索。

MySQL事务的隔离级别:脏读、不可重复读和幻读详解

上星期。
MySQL 的事务隔离级别。
三个问题。

脏读。
定义。
读取未提交的数据。
没有人救他。
你看。
其他人稍后会回滚。
您的操作无效。
数据乱了
完成脏读。
阅读已提交。
重新提交。
每次读取都会生成一个新的ReadView。
请务必查看提交的内容。

阅读不能重复。
定义。
同一笔交易。
读两遍。
其他人中间就改了。
你看到的数值是不一样的。

完成不能重复的阅读。
重复阅读。
通读。
第一次读取会生成一个 ReadView。
下次阅读时也使用同样的方法。
添加下一个钥匙锁。
保护范围。

鬼读。
定义。
同一笔交易。
使用相同的条件进行双重检查。
第二次我检查了太多行。
其他人则在中间插入或删除。

完成鬼读。
重复阅读。
通读。
部分解决。
使用 MVCC 和后续密钥锁定。
间隙锁。
避免插入。
注意力。
可重复读取。
重影读数无法完全解决。
在特殊情况下。
它仍然可以看到新插入的。

算了。
由你决定。