事务隔离级别
1. 事务隔离级别的类型
隔离级别 | 解决问题 | 性能 | 描述 |
---|---|---|---|
READ UNCOMMITTED | 无 | 最高 | 允许读取未提交的数据,可能会发生脏读。 |
READ COMMITTED | 脏读 | 较高 | 只能读取已提交的数据,避免了脏读,但可能发生不可重复读。 |
REPEATABLE READ | 脏读、不可重复读 | 中 | 保证同一事务中多次读取数据一致,但可能出现幻读(数据行数可能变化)。 |
SERIALIZABLE | 脏读、不可重复读、幻读 | 最低 | 通过加锁来确保事务的串行执行,避免所有的并发问题,确保数据一致性,但性能最低。 |
2. 每个隔离级别的实际场景分析
(1) READ UNCOMMITTED(读未提交)
场景:
假设你有一个系统用来记录用户余额,而另一个系统正在更新余额,但尚未提交。
-
事务A:查询账户余额。
-
事务B:将余额从 $100 修改为 $50,未提交。
过程:
-
事务A读取到余额 $50,虽然事务B并未提交。
-
事务B发生错误,余额恢复为 $100。
问题:
事务A读取到了事务B未提交的数据,导致了脏读。
(2) READ COMMITTED(读已提交)
场景:
假设你正在查询某个商品的库存数量,而另一个系统正在修改库存数量。
-
事务A:查询库存数量。
-
事务B:在事务A查询之后但未提交之前修改库存数量。
过程:
-
事务A第一次读取库存,得到数量10。
-
事务B修改库存并提交,数量变为12。
-
事务A再次查询,得到数量12。
问题:
事务A在同一事务中查询了不同的数据,发生了不可重复读。
(3) REPEATABLE READ(可重复读)
场景:
假设你正在进行一个查询操作,并且想要确保查询结果在同一个事务中始终保持一致。
-
事务A:查询库存中价格大于 $100 的商品数量。
-
事务B:在事务A的查询和再次查询之间,插入了一条新的商品数据。
过程:
-
事务A第一次查询得到数量为10。
-
事务B插入新商品并提交,数量变为11。
-
事务A再次查询,得到数量依然为10。
问题:
事务A在同一事务中多次查询时得到了不同的结果,出现了幻读现象。
(4) SERIALIZABLE(串行化)
场景:
假设你有一个高并发系统,两个事务同时修改同一个商品的价格,使用串行化隔离级别确保事务按顺序执行。
-
事务A:查询商品总价。
-
事务B:修改商品的价格并提交。
过程:
-
事务A开始,读取商品总价 $100。
-
事务B修改商品价格并提交。
-
事务A再次读取商品总价,仍然是 $100。
问题:
由于串行化事务执行,事务A始终看到一个一致的数据视图,避免了脏读、不可重复读和幻读。