尧图精选

MySQL数据库中事务并发问题以及隔离级别

🕒 发布时间:2026/10/2 20:51:31 📁 来源:尧图网络
1.脏读定义一个事务读到了另一个事务尚未提交的数据。- 场景T2 更新数据但未提交T1 读取到 T2 未提交的修改若 T2 回滚T1 读到的数据无效- 本质读取到临时、可能回滚的无效数据- 隔离级别Read Uncommitted读未提交会出现RC、RR、Serializable 可以解决脏读2.不可重复读定义同一个事务内前后两次读取同一行记录中间别的事务对这一行做了 update 并且提交导致这个事务两次读到的值不一样。- 场景T1先读一行T2更新这一行、提交T1再读同一行数据变了- 本质行还在字段内容被修改- 隔离级别RC读已提交会出现RR可重复读可以解决不可重复读2. 幻读定义事务查询一个范围的数据另一个事务在这个范围 insert 插入新行并提交原事务再次执行相同范围查询多出来一条记录像幻觉。- 场景T1查询 where id10 得到3条T2插入一条id12并提交T1再次查询查到4条- 本质查询范围内行数增加/减少新增或删除行- MySQL InnoDBRR的快照读看不到新增行不会幻读但当前读select ... for update会读到新插入的数据存在幻读SERIALIZABLE串行化才能彻底杜绝幻读。3. 4个隔离级别从低到高右边截图1. READ UNCOMMITTED 读未提交能读到别的事务没提交的数据。脏读、不可重复读、幻读全都存在。2. READ COMMITTED 读已提交RC只能读到已经提交的数据。解决脏读不可重复读、幻读仍然存在。3. REPEATABLE READ 可重复读RRMySQL默认同一个事务多次读同一个字段结果不变。解决脏读、不可重复读不能完全避免幻读。为什么可重复读可以避免不可重复读不能完全避免幻读事务开始时生成一个事务快照。后续本事务所有普通select快照读只读取这个快照版本的数据不会读取其他事务已经提交的最新版本。别的事务修改已有行哪怕提交了当前事务快照读看不到所以不会发生不可重复读。幻读是插入新的纪录MVCC快照只解决快照读场景但油两个关键点快照读普通select不会看到其他事务新插入的数据快照读层面没有幻读。当前读select ... for update/update/delete/insert是读取最新数据会加锁InnDB的RP用记录锁间隙锁防止别的事务插入但是间隙锁不能覆盖所有场景存在漏洞。举经典例子面试最常考表 tid 主键现有数据(1),(5)事务 ARRbegin; select * from t where id1 and id5 for update; -- 当前读加锁 -- 锁定区间 (1,5)这个间隙阻止其他事务插入id2、3、4间隙锁锁住索引间隙不让别的事务在间隙里 insert防止幻读。 但是间隙锁只锁已经存在索引之间的空隙有例外场景。漏洞场景查询的范围超过已有最大索引表只有 (1,5) 事务 Abegin; select * from t where id10 for update;现在表里没有任何 id10 的数据没有索引间隙可以加间隙锁。 事务 B 就可以执行insert t values(12); commit;事务 A 再执行这条select ... for update就能读到 id12 这条新数据 →幻读出现间隙锁只能锁住现有索引之间的空隙如果查询区间在所有记录之外没有间隙可以锁其他事务依然可以插入新数据产生幻读。4. SERIALIZABLE 串行化最高级别所有读写加锁事务串行执行。脏读、不可重复读、幻读全部解决但是性能最差。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →