概述
sql标准定义了四种隔离级别,而且每一种隔离级别都规定了一个事务所做的修改。较低级别的隔离通常可以执行更高的并发,系统的消耗更加低。(每种存储引擎实现的隔离级别各不相同)
重要概念
1. 脏读
当存在A,B两个事务,A事务可以读到B事务中未提交的内容,B失败回滚,导致A读到B未提交的的记录
2. 不可重复读
在A事务中对同一数据两次查询不一致,可能原因是在A事务提交之前其他事务对该数据进行了修改。
3. 幻读
幻读和不可重复读类似,当某个事务在读取某个范围的记录时,另一个事务又插入了新的记录,当前事务再次读取同样范围的记录会出现幻行。不可重复读更侧重于修改,而幻读更侧重于新增和删除。避免不可重复读需要锁行,而解决幻读则需要锁表。
4. MVCC
mvcc是行级锁的一种变种,但是它在很多情况下避免了加锁的操作,因此开销更低,大都实现了非阻塞读,锁定必要行写的效果。然而不同的引擎实现的mvcc是不同的,典型的分为两种,乐观并发控制和悲观锁并发控制。在innodb的mvcc是通过每行保存了两个隐藏列来实现的,一个保存行创建版本号,一个保存了行的过期(或删除)版本号,而这字段相当于版本号的作用,每开始一个新的事务,版本号就会递增,事务开始的时间的版本号就会作为事务的版本号。
- 查只查小于当前事务系统版本号和删除标识不存在的或删除标识大于当前版本号的(保证了查到事务开始前的所有行)
- 插入为新行保存当前系统版本号作为行版本号
- 删除为删除行保存当前系统版本号作为删除标识
- 更新为插入新行,新行保存当前系统版本号作为行版本,同时为原来行保存当前系统版本号作为删除标识
隔离级别
- read-uncommitted(未提交读)
该级别表示在事务处理中,事务的修改,即时未提交,对于其他事务也是可见的(脏读) - read-committed(提交读)
该级别表示在事务处理中,事务对记录的修改,对于其他事务是不可见的,只能读取到已提交事务的信息。大多数的数据库系统默认级别是可提交读(mysql不是),这也叫做不可重复读,因为执行两次同样的查询,可能得到不一样的效果(即在事务中执行两次查询之间,出现了新的事务提交,导致结果不一)。 - repeatable-read(可重复读)
该级别表示在同一个事务处理中,多次读取同样的记录是一样的。这就解决了脏读的问题,但是无法解决幻读的问题,可重复读是Mysql的默认事务隔离级别,innodb存储引擎采用了MVCC方法解决了幻读的问题。 - serializable(可串行化)
serializable是最高的隔离级别,该级别是通过强制事务串行执行,来避免幻读问题,也就是读取的每一行数据都会加锁。这种隔离级别可能导致超时或者锁争用的问题。实际应用中较少用。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read-uncommitted(未提交读) | Y | Y | Y |
read-committed(提交读) | N | Y | Y |
repeatable-read(可重复读) | N | N | Y |
serializablee(可串行化) | N | N | N |