MySqL事务隔离级别

事务的特性:

原子性:事务要么全部提交成功要么全部失败

一致性:事务操作前和操作后具有完整性约束,数据库保持一致性状态

隔离性:事务执行时相互隔离互不影响,可以防止多个事务并发执行由于交叉执行导致的不一致

持久性:事务操作结束后修改是永久性的,即使关机故障也不会消失

MySQL InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?

  • 持久性是通过 redo log (重做日志)来保证的;
  • 原子性是通过 undo log(回滚日志) 来保证的;
  • 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
  • 一致性则是通过持久性+原子性+隔离性来保证;

事务的隔离级别有哪些?

读未提交

​ 最低的隔离级别, 会导致脏读、幻读或不可重复读。

读已提交

​ 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。这是大多数数据库(如 Oracle, SQL Server)的默认隔离级别。

可重复读

​ 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。并且,InnoDB 在此级别下通过 MVCC(多版本并发控制) 和 Next-Key Locks(间隙锁+行锁) 机制,在很大程度上解决了幻读问题。

RR隔离级别甚至连部分情况的可重复读也没解决:事务A先快照读查到数据a=10,事务B更新a=15并提交,事务A再当前读数据,读出来是a=15,两次前后读取不一样。

当前读一定读取“最新已提交版本(Latest Committed Version)”,而不是事务开始时的快照。

可串行化

​ 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

事务执行可能出现的问题

脏读 :当一个事务读到另一个没有提交事务修改过的数据,此时就发生脏读了。通过读已提交可以避免

不可重复读 : 在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。

幻读 : 在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象。

image-20251224220314987

image-20251224221935836

RR 隔离级别下如果第一次是快照读、第二次是当前读,确实可能读到不同的值;但严格来说,这并不属于不可重复读,因为比较的是两种不同的读语义。不可重复读只讨论同一种读方式。
在 RC 隔离级别下,虽然普通快照读无法避免不可重复读,但如果显式使用当前读并加锁,同样可以通过锁机制避免前后读取不一致。