什么是不可重复读?
参考回答
不可重复读是指在一个事务中多次读取同一条记录时,结果不一致,通常是因为在两次读取之间,另一事务修改了该记录的数据(包括更新或删除操作)。不可重复读是事务隔离性问题之一。
详细讲解与拓展
1. 不可重复读的定义
不可重复读的关键在于,事务中读取到的数据在操作期间被其他事务修改了,导致数据前后不一致。
– 主要表现:
– 第一次读取获得的结果和第二次读取的结果不同。
– 修改可以是更新现有数据或删除数据。
2. 不可重复读的例子
假设有一个用户余额表 Users
:
事务 1:
事务 2(并发执行):
事务 1(继续执行):
- 事务 1 第一次读取时余额是 1000.00,第二次读取时余额变成了 2000.00,发生了不可重复读。
3. 不可重复读的影响
- 数据一致性问题:事务依赖于读取的数据,如果读取的结果在事务执行期间发生变化,可能导致错误的决策。
- 业务逻辑错误:如在基于余额判断的场景中,数据前后不一致可能导致业务异常。
4. 如何解决不可重复读?
不可重复读可以通过提高事务隔离级别来避免。在 MySQL 中,REPEATABLE READ
及更高的隔离级别可以解决不可重复读问题。
1) 使用 REPEATABLE READ 隔离级别
MySQL 默认的 REPEATABLE READ
隔离级别通过 MVCC(多版本并发控制) 来解决不可重复读问题:
– 每个事务在开始时生成一个数据快照(Snapshot)。
– 后续查询都基于该快照进行读取,不会受其他事务修改影响。
示例:
2) 使用 SERIALIZABLE 隔离级别
SERIALIZABLE
是 MySQL 的最高隔离级别,通过对读操作加共享锁,确保其他事务无法修改当前读取的数据,从而防止不可重复读。
示例:
5. 不可重复读与幻读的区别
问题 | 描述 | 例子 |
---|---|---|
不可重复读 | 同一事务中多次读取同一行数据,结果不同,通常是因为另一事务修改了数据(更新或删除)。 | 事务 1 第一次读取 balance = 1000 ,事务 2 更新为 balance = 2000 ,事务 1 第二次读取发现结果不同。 |
幻读 | 同一事务中多次范围查询结果的行数不同,通常是因为另一事务插入或删除了数据。 | 事务 1 查询 price < 300 ,事务 2 插入一条 price = 250 的记录,事务 1 再次查询多了一行。 |
6. 不可重复读的实际应用场景
1) 银行账户查询
– 在转账过程中,查询账户余额,若读取的结果前后不一致,可能导致错误转账或资金丢失。
– 解决方法:使用 REPEATABLE READ
隔离级别,确保读取的余额始终一致。
2) 库存管理
– 查询商品库存后扣减库存时,如果库存数量在事务期间被其他事务修改,可能导致超卖问题。
– 解决方法:使用 REPEATABLE READ
或加锁操作防止修改。
总结
不可重复读是指同一事务中多次读取同一行数据时,结果不同的问题,通常由其他事务修改了数据导致。在 MySQL 中,通过使用 REPEATABLE READ
隔离级别(默认值)即可有效避免不可重复读,同时更高的隔离级别(SERIALIZABLE
)则提供了更强的一致性保证。开发者需要根据业务场景选择合适的隔离级别,避免此类问题对系统造成影响。
人机验证(防爬虫)
