如果有遗漏,评论区告诉我进行补充
面试官: 什么是脏读、不可重复读和幻读?
我回答:
在数据库事务的并发控制中,脏读(Dirty Read)、不可重复读(Non-repeatable Read)和幻读(Phantom Read)是三种常见的并发问题,它们主要涉及到事务的隔离级别和一致性。了解这些问题有助于我们设计更健壮的数据库系统。
1. 脏读(Dirty Read)
- 定义: 脏读是指一个事务读取到了另一个事务尚未提交的数据。
- 影响: 如果一个事务读取了另一个未提交事务的数据,然后该事务被回滚,那么第一个事务读取的数据实际上是无效的。这种情况会导致数据的不一致性和不可预测性。脏读违反了数据库的“隔离性”原则。
示例:
- 事务A修改了某行数据,但尚未提交。
- 事务B读取了事务A修改后的数据。
- 事务A由于某种原因回滚,撤销了之前的修改。
- 此时,事务B读取的数据就是“脏”的,因为它读取了从未真正存在的数据。
2. 不可重复读(Non-repeatable Read)
- 定义: 不可重复读是指一个事务在执行过程中多次读取同一数据时,由于其他事务的并发执行,导致读取结果不一致的现象。
- 影响: 在同一个事务内,两次或多次查询相同的数据返回了不同的结果。这是因为其他事务在这段时间内对数据进行了修改并提交了这些修改。这通常是因为其他事务修改了数据,但并非所有数据库系统都认为这是问题(取决于其隔离级别)。
示例:
- 事务A两次读取同一数据集合。
- 在两次读取之间,事务B修改了集合中的某些数据并提交。
- 因此,事务A的两次读取结果不一致。
3. 幻读(Phantom Read)
- 定义: 幻读是指一个事务在执行过程中多次读取同一数据集合时,由于其他事务的并发执行,导致数据集合发生变化的现象。
- 影响: 在同一个事务内,两次或多次查询相同的数据集合返回了不同的结果。这是因为其他事务在这段时间内插入或删除了一些记录。
示例:
- 事务A执行了一个范围查询(如
SELECT * FROM table WHERE id > 10
)。 - 在事务A再次执行相同查询之前,事务B插入了新的行(如
id = 12
)并提交。 - 当事务A再次执行相同的范围查询时,会发现新的行(
id = 12
),即出现了“幻读”。
4. 隔离级别
为了解决这些问题,数据库提供了不同的隔离级别,从低到高依次为:
- 读未提交(Read Uncommitted):允许脏读、不可重复读和幻读。
- 读已提交(Read Committed):禁止脏读,但允许不可重复读和幻读。
- 可重复读(Repeatable Read):禁止脏读和不可重复读,但某些数据库(如MySQL的InnoDB引擎)的默认设置可能仍允许幻读。
- 串行化(Serializable):最高的隔离级别,禁止脏读、不可重复读和幻读。它通过强制事务串行执行来实现,但会影响性能。
理解这些概念对于设计和实现高性能且一致的数据库应用至关重要。在实际开发中,应根据业务需求和性能要求选择合适的事务隔离级别。