【通俗易懂】彻底搞清Mysql事务的四种隔离级别

这篇博客通过通俗易懂的方式介绍了MySQL事务的四种隔离级别:读未提交、不可重复读、可重复读和串行化,分别用银行取钱的例子展示了脏读、不可重复读的现象,并分析了不同隔离级别对数据一致性的影响以及性能成本。

前言

上网找资料学习,过多的专业术语让人看得头大难以专注持久阅读,本人想总结一篇博客让自己永远记住这些概念,废话不多说,通俗易懂图文并茂来彻底理解四种事务隔离级别

摆名词

读未提交(read-uncommitted)

不可重复读(read-committed)

可重复读(repeatable-read)

串行化(serializable)

脏读

不可重复读

幻读

看不懂?没关系,反正第一次看名词解释也没几个能理解的,我就连基本解释也省了直接看下面。

以经典的银行取钱为代入

剧本一.READ-UNCOMMITTED 字面意思 允许读取(另一个事务)未提交的数据

SQL :

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;

看图,剧本是这样的

时间线T1:事务2——>查询余额是 1000 元,买了900元东西

时间线T2:事务1——>在用户2扣款,但还未提交,用户1查询余额只有100

用户1本来想买200元的东西,查询余额只有100只好作罢 

剧本结局:事务2在事务1查询之后意外回滚了,金额变回了1000元,这次事故导致用户1本来可以买(或有机会可以买)到东西的,结果变成了余额不足

此乃事故1——脏读:隔离级别不够时,在事务过程中,读到另一事务中修改但未提交的数据

 

——————————————————————隔离线————————————————————

时间原因,故事不好找(很难找到不可重复读带来影响的例子),快速翻译几个名词,借助上面的故事各位自行理解下

不可重复读(read-committed):这个隔离级别应该翻译为 :可以读到自身事务内非自身事务内已经修改提交的数据 

例子:

时间1. 事务1读取到1000元

时间2:事务2扣了100元未提交

时间3:事务1读取到1000元

时间4:事务2提交,事务1读取到900元

所以叫可读已提交的数据。为什么叫不可重复读,大概是这个隔离级别有可能导致两次读取数据不一致

可重复读(repeatable-read):可以读到自身事务内已经修改提交的数据 

例子:

时间1:事务1读取到1000元

时间2:事务2扣了100元提交了

时间3:事务1读取到1000元

时间4:事务2提交,事务1读取到1000元

串行化(serializable):事务与事务之间排队执行,比如都对表1操作的两个事务,事务1和事务2,事务1执行时直接锁表,事务1执行完后,才会执行事务2——效率最低非常少使用

 

快速总结

隔离级别从小到大:

读未提交(read-uncommitted)——>不可重复读(read-committed)——>可重复读(repeatable-read)

——>串行化(serializable)

造成的毛病易解决程度:

脏读——>不可重复读——>幻读

读未提交(read-uncommitted)造成的毛病:脏读——>不可重复读——>幻读

不可重复读(read-committed)造成的毛病:不可重复读——>幻读     解决的毛病:脏读

可重复读(repeatable-read)造成的毛病:(mysql中) 无   解决的毛病:所有

  串行化(serializable):造成的毛病:无    解决的毛病:所有

 

最后:隔离级别越大事务中数据的一致性越好,但会更加影响性能

 

<think>好的,用户之前让我解释过脏读、不可重复读和幻读,现在他们想了解MySQL事务隔离级别。我需要确保这次回答与之前的内容衔接,同时保持通俗易懂。用户可能是刚开始学习数据库,或者需要在实际应用中处理事务问题,所以应该用生活化的例子来解释每个隔离级别,并关联到之前的问题。 首先,我需要回忆MySQL的四个隔离级别:读未提交、读已提交、可重复读、串行化。然后,针对每个级别,用简单的场景说明它们如何解决脏读、不可重复读和幻读的问题。同时,需要指出每个级别的优缺点,比如性能差异。可能用户想知道如何选择隔离级别,所以最后可以给出选择建议。 要注意之前用户的问题回复中用了存钱罐、账户余额、班级身高的例子,这次可以继续类似的场景,保持一致性。比如,用银行转账、统计人数等例子。另外,用户可能对默认隔离级别感兴趣,所以需要提到MySQL默认是可重复读,而其他数据库如Oracle可能不同。 需要确保解释清晰,避免技术术语过多,但也要准确。例如,可重复读如何避免幻读,而实际上在MySQL中通过Next-Key Locking实现,但用户可能不需要深入细节,只要知道结果即可。最后用表格对比总结,帮助用户记忆。</think>用银行存取款的例子,轻松理解MySQL四种事务隔离级别: --- ### **1. 读未提交(Read Uncommitted)** **场景**:ATM机显示你的余额是500元,这时别人正在给你转账(操作未完成),ATM直接显示转账中途的余额(比如转账中的1000元),但对方突然取消转账,你看到的钱其实是假的。 **特点**: - 性能最好,但可能看到**脏数据**(别人未提交的操作) - 相当于没有隔离,容易引发脏读、不可重复读、幻读 **代码设置**: ```sql SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; ``` --- ### **2. 读已提交(Read Committed)** **场景**:ATM机只显示已完成的转账金额。第一次查余额是500元,期间别人成功转给你200元,你再查就看到700元。 **特点**: - 解决脏读,但**同一事务中两次查询结果可能不同**(不可重复读) - 多数数据库的默认级别(如Oracle) **代码设置**: ```sql SET TRANSACTION ISOLATION LEVEL READ COMMITTED; ``` --- ### **3. 可重复读(Repeatable Read)** **场景**:你开启事务查看余额是500元,之后即使别人转账成功,你在这个事务中每次查都是500元(像事务开始时拍了快照)。 **特点**: - **解决脏读和不可重复读** - **可能仍有幻读**(但MySQL通过Next-Key Locks解决了幻读) - MySQL的默认隔离级别 **代码设置**: ```sql SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; ``` --- ### **4. 串行化(Serializable)** **场景**:ATM机被锁住,一次只允许一个人操作,其他人必须排队等待。 **特点**: - 通过锁表实现完全隔离,**解决所有并发问题** - **性能最差**,实际很少使用 **代码设置**: ```sql SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; ``` --- ### **隔离级别对照表** | **隔离级别** | 脏读 | 不可重复读 | 幻读 | 性能 | |--------------------|------|------------|------|-------| | 读未提交(Read Uncommitted) | ❌可能 | ❌可能 | ❌可能 | ⚡最快 | | 读已提交(Read Committed) | ✅避免 | ❌可能 | ❌可能 | ⚡快 | | 可重复读(Repeatable Read) | ✅避免 | ✅避免 | ✅避免* | 🐢中等 | | 串行化(Serializable) | ✅避免 | ✅避免 | ✅避免 | 🐢最慢 | > *注:MySQL的"可重复读"通过MVCC+间隙锁实际解决了幻读 --- ### **如何选择?** 1. **默认选可重复读**(MySQL优化较好,兼顾性能和安全) 2. **对数据一致性要求极高**(如金融系统)→ 串行化 3. **只追求速度,允许暂时数据错误**(如实时性高的统计)→ 读未提交 4. **平衡选择**(多数OLTP系统)→ 读已提交 **通俗记忆**: - 读未提交 → **裸奔模式** - 读已提交 → **穿件外套** - 可重复读 → **开美颜相机** - 串行化 → **进保险箱**
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值