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

举例
脏读
假设有一个银行账户的余额记录,账户 ID 为 1。现在有两个事务,分别为事务 A 和事务 B。
- 事务 A:
BEGIN;
UPDATE account SET balance = balance - 100 WHERE id = 1;
- 开始事务后,将账户余额减少 100 元,但此时还未提交。
- 事务 B:
BEGIN;
SELECT balance FROM account WHERE id = 1;
- 在事务 A 修改后、提交前,事务 B 读取该账户余额。
- 事务 B 读到了事务 A 尚未提交的减少 100 元后的余额,这就是“脏读”。
- 后续情况:
- 如果事务 A 最终回滚,则事务 A 的修改不会被保存,而事务 B 已经读取到一个错误的、未最终确定的数据,导致数据不一致的问题。
不可重复读
还是假设有一个银行账户的余额记录,账户 ID 为 1,初始余额为 1000 元。现在有两个事务,分别为事务 A 和事务 B,说明不可重复读现象:
- 事务 A 开始并首次读取余额
BEGIN;
SELECT balance FROM account WHERE id = 1;
-- 返回结果为:1000
此时事务 A 读取了账户余额为 1000 元。
- 事务 B 修改余额
在事务 A 仍未结束时,事务 B 开始并修改该账户余额,例如存入 500 元:
BEGIN;
UPDATE account SET balance = balance + 500 WHERE id = 1;
COMMIT;
事务 B 修改并提交后,账户余额变为 1500 元。
- 事务 A 再次读取余额
事务 A 在之前读取后仍未提交,再次读取账户余额:
SELECT balance FROM account WHERE id = 1;
-- 返回结果为:1500
此时事务 A 得到了与第一次不同的余额,从 1000 元变为 1500 元,这就是不可重复读的现象。
幻读
假设有一个员工表 Employees,其中有个字段 department 表示员工所在的部门。两个事务 T1 和 T2 同时运行:
- 事务 T1 开始并执行查询:
SELECT * FROM Employees WHERE department = 'Sales';
此时返回满足条件的所有销售部门员工。
- 在 T1 还未提交之前,事务 T2 执行插入操作:
INSERT INTO Employees (name, department) VALUES ('张三', 'Sales');
T2 插入了一条新记录,其部门为 ‘Sales’,并提交了事务。
- 事务 T1 再次执行同样的查询:
SELECT * FROM Employees WHERE department = 'Sales';
这次返回的结果中,除了之前的记录外,还多了一条刚刚插入的新记录,即“张三”。
在这种情况下,由于 T2 在 T1 的事务过程中插入了新数据,导致 T1 第二次查询时看到的数据集(幻影数据)与第一次不一致,这就是幻读现象。
411




被折叠的 条评论
为什么被折叠?



