数据库脏读、不可重复读、幻读以及对应的隔离级别

本文详细阐述了数据库并发读取数据时可能出现的脏读、幻读和不可重复读问题,以及如何通过设置不同的事务隔离级别来解决这些问题。读未提交级别允许脏读,读已提交级别防止脏读但可能导致不可重复读,可重复读级别消除脏读和不可重复读但仍有幻读风险,而可串行化级别则完全避免这些问题但牺牲了效率。在实际应用中,数据库如Oracle和MySQL会选择不同的默认隔离级别以平衡安全性与性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

并发读取数据出现的问题

脏读:一个事务读取另一个事务未提交的数据

幻读:一个事务内进行了多次读取,数据总量不一致

不可重复读:一个事务对同一数据进行读取,前后数据内容不一致

区别:

隔离级别

读未提交:所有读问题都有可能发生,一般不会采取这种隔离级别

读已提交:只能避免脏读发生,Oracle默认的隔离级别

可重复读:能够避免脏读、不可重复读,MySQL中Innodb引擎默认的隔离级别

可串行化:可以解决所有读问题,但是由于是串行执行,效能效率比较低

并发事务下发生的问题与解决方式


并发读取数据出现的问题

脏读:一个事务读取另一个事务未提交的数据

        A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这个时候A事务立即读取了这个脏数据,但事务B良心发现,又用回滚把数据恢复成原来干净、纯粹的样子,而事务A却什么都不知道,最终结果就是事务A读取了此次的脏数据,称为脏读。

幻读:一个事务内进行了多次读取,数据总量不一致

        事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,成为幻读。

不可重复读:一个事务对同一数据进行读取,前后数据内容不一致

       事务A在执行读取操作,由整个事务A比较大,前后读取同一条数据需要经历很长的时间 。而在事务A第一次读取数据,比如此时读取了小明的年龄为20岁,事务B执行更改操作,将小明的年龄更改为30岁,此时事务A第二次读取到小明的年龄时,发现其年龄是30岁,和之前的数据不一样了,也就是数据不重复了,系统不可以读取到重复的数据,成为不可重复读。
可以理解为根据同一个Id查询,前后结果不一致

区别:

1.脏读指的是一个事务读到了其他事务未提交的数据。

2.不可重复读指的是一个事务中多次读到同一条数据发生了变化,重点在于表中已经存在的数据被其他事务修改了。

3.幻读指的是一个事务被其他事务插入或者删除的数据有影响,重点在于事务开始后,其他事务插入或删除了数据。


脏读、幻读、不可重复读是在并发事务的情况下才发生的,为了解决这些问题,数据库引入了隔离级别,并且不同的隔离级别可以解决不同的问题。

隔离级别

读未提交:所有读问题都有可能发生,一般不会采取这种隔离级别

     在这种隔离级别下,所有事务能够读取其他事务未提交的数据。读取其他事务未提交的数据,会造成脏读。因此在该种隔离级别下,不能解决脏读、不可重复读和幻读。

读已提交:只能避免脏读发生,Oracle默认的隔离级别

       在这种隔离级别下,所有事务只能读取其他事务已经提交的内容。能够彻底解决脏读的现象。但在这种隔离级别下,会出现一个事务的前后多次的查询中却返回了不同内容的数据的现象,也就是出现了不可重复读。

可重复读:能够避免脏读、不可重复读,MySQL中Innodb引擎默认的隔离级别

       在这种隔离级别下,所有事务前后多次的读取到的数据内容是不变的。也就是某个事务在执行的过程中,不允许其他事务进行update操作,但允许其他事务进行add操作,造成某个事务前后多次读取到的数据总量不一致的现象,从而产生幻读。

可串行化:可以解决所有读问题,但是由于是串行执行,效能效率比较低

      在这种隔离级别下,所有的事务顺序执行,所以他们之间不存在冲突,从而能有效地解决脏读、不可重复读和幻读的现象。但是安全和效率不能兼得,这样事务隔离级别,会导致大量的操作超时和锁竞争,从而大大降低数据库的性能,一般不使用这样事务隔离级别。

并发事务下发生的问题与解决方式

隔离级别脏读    不可重复读幻读
读未提交可能(出现)可能可能
度已提交不可能(出现)可能可能
可重复读不可能不可能可能
可串行化不可能不可能不可能

 如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏

<think>嗯,用户让我介绍一下不可重复,这三个都是数据库事务隔离中的问题。我需要先回忆一下每个术语的具体定义,然后确保用中文解释清楚。用户可能是在学习数据库或者准备面试,需要这些概念的区别和应用场景。 首先,,应该是指一个事务取了另一个未提交事务的数据。比如事务A修改了数据但还没提交,事务B就到了这个修改,如果A回滚了,B到的就是错误的数据。这个需要例子说明,比如银行转账中途取了中间状态。 然后是不可重复,指的是同一事务内多次取同一数据,结果不同。这可能是因为在两次取之间,另一个事务修改并提交了数据。比如用户两次查询账户余额,中间有其他事务扣款,导致结果不一致。和的区别在于这里取的是已提交的数据,而是未提交的。 则是在范围查询时,同一个事务多次查询,结果集的行数不同。比如事务A查询年龄大于18的用户,第一次得到10条,这时事务B插入了一条符合条件的记录并提交,事务A再次查询得到11条,这就是侧重于新增或删除数据导致的结果集变化,而不可重复侧重同一数据内容的修改。 接下来要区分这三个问题的隔离级别。通常,未提交会导致已提交解决,但可能有不可重复可重复解决不可重复,但可能有;序列化则解决所有。不过不同数据库实现不同,比如MySQL的InnoDB在可重复级别通过间隙锁解决了。 用户可能需要知道这些问题的解决办法,或者如何在实际中避免。比如设置合适的事务隔离级别,或者使用锁机制。这时候需要简要提到隔离级别的关系,以及每个问题对应的解决方案。 还要注意用户可能混淆这些概念,特别是不可重复的区别。不可重复是同一行数据的修改,是范围数据的变化。所以例子要明确这一点,比如修改vs新增。 总结结构的话,先分别介绍每个问题,定义、例子、解决办法,然后对比它们的区别和适用的隔离级别。可能需要用简单的中文词汇,避免过于技术化的术语,但又要准确。比如“事务”、“提交”、“回滚”这些术语可能需要保留,但解释清楚。 检查有没有错误的地方,比如是否一定是取未提交的数据,是的。不可重复是否在同一个事务内多次取同一数据,是的。是否涉及插入或删除,是的。确认隔离级别是否正确对应每个问题。 最后,可能需要给出如何选择隔离级别的建议,或者常见数据库如何处理这些问题,比如MySQL的例子。但用户可能只需要基本概念,所以保持简洁,但足够清晰。</think>**不可重复** 是数据库事务隔离级别中常见的并发问题,用于描述多个事务并发操作时可能引发的不一致现象。以下是它们的定义和区别: --- ### 1. **(Dirty Read)** - **定义**:一个事务取了另一个**未提交事务**修改的数据。如果后者回滚(Rollback),前者到的数据就是“的”(无效的)。 - **例子**: - 事务 A 修改了某行数据(未提交),事务 B 取了修改后的值。 - 若事务 A 最终回滚,事务 B 的取结果就是错误的。 - **隔离级别**:通过 `已提交(Read Committed)` 及以上级别解决。 --- ### 2. **不可重复(Non-Repeatable Read)** - **定义**:同一事务内多次取同一数据,结果不一致(因为其他事务**修改并提交**了该数据)。 - **例子**: - 事务 A 第一次取某行数据为 100。 - 事务 B 修改该数据为 200 并提交。 - 事务 A 再次取时发现值变为 200。 - **与的区别**:不可重复针对的是其他事务**已提交的修改**。 - **隔离级别**:通过 `可重复(Repeatable Read)` 及以上级别解决。 --- ### 3. **(Phantom Read)** - **定义**:同一事务内多次按相同条件查询,结果集的行数不同(因为其他事务**插入或删除**了符合条件的数据并提交)。 - **例子**: - 事务 A 查询年龄 >18 的用户,返回 10 条记录。 - 事务 B 插入一条年龄为 20 的记录并提交。 - 事务 A 再次查询时返回 11 条记录。 - **与不可重复的区别**:关注的是数据**行数的变化**(插入/删除),不可重复关注的是数据的**内容变化**(更新)。 - **隔离级别**:通常需要 `序列化(Serializable)` 解决,但某些数据库(如 MySQL InnoDB)在 `可重复` 级别通过间隙锁(Gap Lock)也支持避免。 --- ### 总结对比 | **问题** | **触发原因** | **关注点** | **解决隔离级别**
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小张自由—>张有博

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值