外观
幻读、脏读和不可重复读是什么
脏读(Dirty Read
)
- 定义:一个事务读取到了另一个未提交事务修改的数据。也就是说,当一个事务对数据进行了修改但还未提交时,另一个事务就读取了这个被修改但未确定的数据。如果第一个事务后来进行了回滚操作,那么第二个事务读取到的数据就是无效的、“脏” 的数据。
- 示例
- 事务 A 开始执行,将账户余额从 1000 元修改为 2000 元,但还未提交。
- 事务 B 在此时读取账户余额,得到的是 2000 元。
- 事务 A 由于某些原因进行了回滚,账户余额恢复到 1000 元。
- 此时事务 B 读取到的 2000 元就是脏数据。
不可重复读(Non - Repeatable Read
)
- 定义:在一个事务内,多次读取同一数据时得到了不同的结果。通常是因为在两次读取之间,有其他事务对该数据进行了修改并提交,导致原事务再次读取时数据已经发生了变化。不可重复读主要针对的是数据的更新操作。
- 示例
- 事务 A 开始执行,第一次读取账户余额为 1000 元。
- 事务 B 在事务 A 执行期间将账户余额修改为 1500 元并提交。
- 事务 A 再次读取账户余额,得到的是 1500 元,与第一次读取的结果不同。
幻读(Phantom Read
)
- 定义:一个事务在执行过程中,按照某个条件进行多次查询时,前后两次查询得到的结果集行数不同。这通常是因为在两次查询之间,有其他事务插入或删除了符合查询条件的数据,就好像出现了 “幻影” 一样的行。幻读主要针对的是数据的插入和删除操作。
- 示例
- 事务 A 开始执行,查询年龄大于 20 岁的用户,得到 10 条记录。
- 事务 B 在事务 A 执行期间插入了 5 条年龄大于 20 岁的用户记录并提交。
- 事务 A 再次查询年龄大于 20 岁的用户,得到 15 条记录,结果集行数发生了变化。
解决方案
- 脏读:通过设置隔离级别为
READ COMMITTED
或更高,确保一个事务只能读取到其他事务已提交的数据。 - 不可重复读:通过设置隔离级别为
REPEATABLE READ
,保证同一事务内多次读取同一数据时,读取的结果一致。 - 幻读:通过设置隔离级别为
SERIALIZABLE
,强制事务串行执行,确保查询结果集在整个事务内不发生变化。