
1) 【一句话结论】:核心是数据库事务并发控制导致脏读,需通过调整事务隔离级别(如升级为REPEATABLE READ/SERIALIZABLE)或引入乐观锁机制,确保数据一致性,避免未提交事务的修改被其他事务读取。
2) 【原理/概念讲解】:老师口吻解释事务隔离级别。事务隔离级别用于控制并发事务之间的可见性,防止脏读、不可重复读、幻读。脏读是指事务T2读取了事务T1未提交的修改(T1未提交,T2读取后T1回滚,T2看到错误数据)。类比:比如A在写简历(未提交),B在查询时看到A的更新内容(脏读),后来A取消修改,B看到的是错误信息。隔离级别从低到高:READ UNCOMMITTED(允许脏读)、READ COMMITTED(不脏读,但可能不可重复读)、REPEATABLE READ(解决不可重复读,MySQL InnoDB默认)、SERIALIZABLE(最高,解决所有问题,但性能低)。脏读发生在隔离级别较低时,如READ UNCOMMITTED或READ COMMITTED(若数据库实现不严格)。
3) 【对比与适用场景】:
| 隔离级别 | 定义 | 脏读 | 不可重复读 | 幻读 | 适用场景 |
|---|---|---|---|---|---|
| READ UNCOMMITTED | 事务开始时允许读取未提交的数据 | 是 | 是 | 是 | 极少用,仅测试 |
| READ COMMITTED | 事务开始时只读取已提交的数据 | 否 | 是 | 是 | 通用,如OLTP |
| REPEATABLE READ | 事务期间保持行锁,防止不可重复读 | 否 | 否 | 是 | MySQL InnoDB默认(除幻读) |
| SERIALIZABLE | 全局加锁,事务串行执行 | 否 | 否 | 否 | 需高一致性,低并发 |
4) 【示例】:伪代码示例(假设简历表含version字段,乐观锁机制):
-- 表结构
CREATE TABLE resume (
id INT PRIMARY KEY,
user_id INT,
education VARCHAR(50),
version INT DEFAULT 1
);
-- 事务A(更新,乐观锁)
UPDATE resume
SET education='硕士', version=version+1
WHERE id=1 AND version=1; -- version不匹配则更新失败
-- 事务B(读取)
SELECT * FROM resume WHERE id=1;
并发场景:事务A开始,更新education为“硕士”(未提交),事务B读取,此时事务A未提交,事务B读取到新值(脏读)。解决:将隔离级别升级为REPEATABLE READ后,事务B读取时,事务A的未提交修改不会被读取,避免脏读。
5) 【面试口播版答案】:
面试官您好,这个问题属于数据库并发控制中的脏读问题。首先,脏读是因为多个事务并发执行时,一个事务读取了另一个未提交事务的修改。我定位问题的步骤是:1. 检查数据库事务隔离级别,当前可能设置为READ COMMITTED或更低,导致脏读;2. 通过SQL查询(如SHOW VARIABLES LIKE 'transaction_isolation')确认隔离级别;3. 诊断:模拟并发场景,发现多个用户更新时,查询界面显示旧数据。解决方法:将隔离级别升级为REPEATABLE READ(MySQL InnoDB默认,解决脏读和不可重复读),或者使用乐观锁,比如在简历表中添加version字段,更新时检查版本号是否一致,不一致则拒绝更新。具体操作是修改数据库配置,将transaction_isolation设置为REPEATABLE READ,或者修改业务逻辑,在更新前检查版本号。这样就能避免脏读,保证数据一致性。
6) 【追问清单】:
7) 【常见坑/雷区】: