大部分数据库系统(如Oracle)都将都将读提交(Read-Commited)作为默认隔离级别,而MySQL却选择可重复读(Repeatable-Read)作为其默认隔离级别。这篇文章我们就分析下MySQL为何会选取不可重复读隔离级别作为默认隔离机制以及是如何解决不可重复读隔离级别的幻读问题。
隔离级别
展开分析之前,我们先来认识下隔离级别的概念。
隔离级别总共有四种:
- 读未提交(Read-Uncommited)
- 读提交(Read-Commited)
- 可重复读(Repeatable-Read)
- 串行化(Serializable)
其中,读未提交和串行化隔离级别一般不会使用到,因为读未提交会导致脏读,不可重复读,幻读等一系列问题。而串行化是将所有的事务强制串行执行,严重影响并发性能。
这里我们简单介绍下脏读,不可重复读和幻读的概念:
- 脏读:事务A读取到了事务B修改但未提交且最后要回滚的数据。
如上图所示,t3时刻,事务A读取到了事务B还累加但是还未提交的a值,且在t3时刻,事务B回滚了,那么事务A基于t3时刻的查询所做的操作就会出现问题。
- 不可重复读:事务A前后读取到的数据不一致。
如上图所示,事务A在t2时刻读取到a的值,和t4时刻读取到的a的值不一致,因为事务B在t3时刻对a值进行了更新并提交。
- 幻读:事务A前后读取的结果条数不一致。