数据库的脏读、不可重复读和幻读,分别是什么?

你好,我是猿java。

在数据库管理系统(DBMS)中,多用户并发访问可能导致数据一致性问题。为了理解这些问题,通常会讨论以下三种现象:脏读(Dirty Read)不可重复读(Non-Repeatable Read)幻读(Phantom Read)。它们主要与事务的隔离级别相关。下面分别介绍这三种现象:

1. 脏读(Dirty Read)

定义: 脏读发生在一个事务读取了另一个事务尚未提交的修改数据。如果后续该修改被回滚,那么读取到的数据就是“脏的”。

示例:

  • 事务A 开始并更新某条记录,将其值从100改为200,但还未提交。
  • 事务B 在事务A未提交的情况下读取了这条记录,得到的值是200
  • 如果事务A随后回滚,那么事务B读取到的数据200就是无效的,即“脏读”。

2. 不可重复读(Non-Repeatable Read)

定义: 不可重复读指的是在同一个事务中,因其他事务的提交修改,导致同一查询在不同时间获取到不同的数据结果。

示例:

  • 事务A 开始并读取某条记录,值为100
  • 事务B 修改该记录的值为200并提交。
  • 事务A 再次读取同一条记录,发现值已变为200,与第一次读取的100不同。

这种情况说明在事务A的整个执行过程中,数据发生了变化,导致读取结果不一致。

3. 幻读(Phantom Read)

定义: 幻读指的是一个事务在执行两次相同的查询时,由于其他事务的插入或删除操作,导致两个查询结果的行数不同,即“出现了幻影行”。

示例:

  • 事务A 开始并执行一个查询,查找满足某条件的所有记录,如SELECT * FROM orders WHERE amount > 100,结果返回10条记录。
  • 事务B 插入了一条新的记录,满足amount > 100,并提交。
  • 事务A 再次执行相同的查询,发现有11条记录,多出了一条“幻影”记录。

这种情况表明在事务A的执行过程中,数据集合发生了变化,影响了查询结果的行数。

事务隔离级别与这些问题

为了防止上述问题,数据库系统提供了不同的事务隔离级别:

  1. 读未提交(Read Uncommitted):
  • 允许脏读、不可重复读和幻读。
  1. 读已提交(Read Committed):
  • 防止脏读,但仍可能发生不可重复读和幻读。
  1. 可重复读(Repeatable Read):
  • 防止脏读和不可重复读,但可能发生幻读。
  1. 串行化(Serializable):
  • 提供最高的隔离级别,防止脏读、不可重复读和幻读。

通过选择适当的隔离级别,可以在性能和数据一致性之间取得平衡。例如,较高的隔离级别(如串行化)虽然提高了数据一致性,但可能降低并发性能;而较低的隔离级别(如读已提交)则在提高并发性能的同时,可能允许一些数据一致性问题。

4. 学习交流

如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。

drawing