MySQL是如何实现可重复读的?

坦白讲,在谈论数据库隔离级别时,迭代读是不可避免的。
当我第一次开始这个项目时,我对这些概念感到摸不着头脑。
现在我就为大家总结一下。
也许有点罗嗦,但绝对脚踏实地。
想象一个场景:您正在超市购物,想给朋友带一瓶水。
你到柜台一看,A店的矿泉水一瓶要1 0元。
你拍了张照片,发到朋友圈:“A店的水1 0块钱!”刚说完,旁边B店的老板就着急了,把价格改为8 元,开始促销。
当你的朋友过来问你:“我拍一张照片花了1 0块钱!”这是可重复的读取——事务开始时看到的快照在整个事务中是一致的。

InoDB 是如何工作的?需要明确的是,它向每个交易发送一个称为交易 ID (trx_id) 的“识别号”,并按顺序递增。
例如1 00、1 01 、1 02 每次更新数据时,Undolog中都会记录这个ID,相当于给数据打了时间戳。

关键是:可重复读取比整个数据库的快照更聪明。
当您的交易开始时创建“活动交易列表”。
什么是活跃的?这些交易已启动但尚未完成。
例如,当事务A启动时,只会处理ID为9 9 的事务,因此会记录9 9 当另一个事务B启动时,列表将是9 9 和1 00。
这个列表将有高水位和低水位。
最小水位是列表中最低的ID,最大水位是生成的最高ID加1
现在事务B读取数据。
某行数据已被事务C(ID 1 02 )修改,但1 02 尚未提交。
您将看到重复读数,表明 1 02 在 B 启动之前处于“活动”状态。
如果是这样,B 将在启动时继续使用该数据。
无论如何,1 02 还没有“完成”。
这就是为什么你检查交易两次并且结果是相同的 - 因为它看起来像相同的“快照”。

让我告诉你我遇到的一个陷阱:在一个测试事务中更新数据并读取事务。
然后B回滚。
如果没有锁,事务C再次更新,结果会很混乱可以但是InnoDB会自动给该行数据加行锁,直到A提交或返回时锁才会释放。
这就消除了脏读(读取尚未处理的数据)、非重复读(在同一事务中读取时结果发生变化)和读取(读取时添加了新数据)。
有趣的是,这种方法并非没有成本。
例如,当您的事务 A 开始时,有一个活动事务 9 9 尚未输入。
你的业务B在9 9 年去阅读并改进了。
但是当你的交易B结束时,9 9 可能已经完成了。
此时,当你再次读取事务B时,你会发现数据已经变回了9 9 更新之前的状态。
这称为“非重复读取”变体。
这就是为什么InnoDB后来实现了更高级的“序列化”——性能较差但绝对安全。

那一年我尝试的时候,如果两个事务同时更新同一行,那么就过期了,没有加锁。
但是加了行锁之后,虽然慢了一些,但是数据肯定是一致的。
这实际上是可重复的阅读。

可重复读归根结底就是在事务开始时利用trx_id和undolog进行“动态快照”,保证整个事务过程中数据保持不变。
它不是简单地复制数据库,而是智能地跟踪活动事务。
当您的交易发起时,系统将为您提供所有已发起但未完成的交易ID的列表。
这是你的“安全区”。
在这些交易发生之前,你看到的将永远是原始状态。

我没有亲自运行过这个分布式事务代码,但我记得信息是关于X的,但我建议你检查最新版本。
总之,勤读书是好事,但也要知道限度。

数据库隔离级别

隔离级别是为了控制事务重叠的程度。
说白了,级别越高,越安全,但速度也越慢。

未提交的阅读:最不安全。
请随意查看未提交的数据。
它容易受到脏读、非重复读和幽灵读的影响。
最佳表现。

提交读:安全脏读。
不过,不重复阅读和幻读仍然是可能的。
这是默认设置。

重复读取:多次读取数据结果不变。
但幻读仍有可能发生。
MySQL 默认使用它。

顺序:最安全。
完全孤立。
但这是效率最低的。
就像排队办事一样。

如何选择?取决于企业想要什么。
数据的准确性和速度哪个更重要?

mysql为什么使用可重复读(repeatableread)为默认隔离级

嘿,我们来谈谈数据库,特别是未提交的读取、已提交的读取和可重复的 MySQL 读取。
这些是隔离级别的宝藏。
之前优化数据库的时候,我对这五个级别非常了解。

首先我们来谈谈无义务阅读。
这允许一个事务查看另一事务未发送的数据。
这在平时可能没什么大不了的,但是如果出现脏读、不可重复读、鬼读,那就让人头疼了。
例如,如果您看到帐户余额,但您看到的数据在其他人发送转账之前发生了变化,这不是脏读吗?
然后读取commit,这样就好多了。
确保只能查看已确认的交易数据。
但问题又回来了。
虽然避免了脏读数,但不可重复读数和重影读数仍然可能发生。
就像看电影预告片一样。
电影结束后,预告片再次发生变化。
这是不可重复的读取。

我们来谈谈可重复阅读。
创建事务的一致性视图,保证事务内多次读取相同数据时的一致性。
这样就不怕脏读和不可重复读,但是鬼读的问题依然存在。
就像您在线购买一本书一样,您多次更新同一链接并找到其他书籍。
这是幻读。

序列化,这个东西是让事务串行执行,避免一切问题,但是这样会降低并发性能。
就像排队买票一样,很好,但是效率很低。

我们来谈谈默认的可重复阅读。
这样的设置是为了保证最大的数据一致性,同时又不会过度牺牲并发性能。
这在需要数据一致性的金融系统和订单处理中特别有用。

但说实话,可重复读取有时会影响并发性能,因为数据需要锁定。
因此,在设计系统时,您需要根据您的具体需求评估性能和一致性。

说到事务,这是数据库操作的灵魂,保证数据的一致性和完整性。
例如银行转账就是一个典型的需要交易的场景。
您需要保证转账操作能够成功或者失败,并且不能半途而废。

当时我不明白为什么数据库有这么多隔离级别。
后来想想,就像开车一样,需要知道如何根据不同的路况调整速度和距离,以确保安全。
数据库也是如此。
您需要根据实际情况选择合适的隔离级别。

最易懂的数据库事务的四种隔离级别知识

隔离级别:未提交读 真实故事:老板付错了工资(3 9 000/月),程序员看到了脏数据(未提供)。
问题:脏读。
这是一个陷阱,不要相信。

隔离级别:已提交读 真实的故事:老婆转了钱(没有交付),程序员付账的时候发现卡里没钱了。
问题:不可重复读取。
不要这样做。
隔离级别:Repeatable(可重复读取) 真实故事:不允许更新操作(妻子不能转账),但允许读取(插入新数据)。
问题:幻读。
小心使用。
隔离级别:序列化 真实故事:交易是连续执行的(效率低)。
问题:没有相关问题,但性能较差。
谨慎使用。

设置隔离级别:MySQL SQL: SET tx_isolation='读取完成';
温馨提示:使用RC来提高兼容性,聚焦重点。