数据库隔离级别(MySQL默认隔离级别是可重复读):
1. read uncommitted 读取未提交数据:如果用户A正读取表t1,用户B对表t1作出修改但未提交,当用户A再次读取t1时,可以读到修改的数据。是隔离级别最低的情况,读取到未提交的数据,会造成脏读问题。
2. read committed 读取已提交数据:如果用户A正读取表t1,并对t1作出修改,然后用户B再读取表t1,读取的数据不会改变,接着用户A将修改提交,用户B再次读取将读取出已修改数据。两次读取结果不同,造成不可重复读问题。
3. repeatable read 可重复读:用户B读取表t1,此时用户A在表中添加一行数据,用户B再次读取不会读取到A添加的数据,但是当B尝试添加一条数据会提示数据重复。数据已经发生改变了仍要求保持一致,出现幻读问题。
4. serializable 可串行化:用户B读取表t1数据,此时用户A尝试向t1写入数据,用户A将陷入等待,直到用户B提交修改。隔离级别最高,会对性能造成影响,实际应用时需要根据需要选择合适的。
MySQL默认隔离级别是可重复读,那么可重复读的实现机制是什么?MySQL的可重复读级别如何避免幻读?
(参考@Meiko丶:https://blog.youkuaiyun.com/u010365819/article/details/84026040 )
1. 可重复读底层原理:
MySQL的可重复读是通过InnoDB的MVCC(多版本并发控制)实现的。
首先,可重复读指一个事务在执行过程中可以看到其他事务已经提交的新插入的记录(早于本事务开始且已提交),但是不能看到其他事务对已有记录的更新(晚于本事务开始)。
使用MVCC,InnoDB为每行记录添加一个版本号,每当修改数据时,版本号+1。在事务读取开始时,系统会给事务分配一个当前的版本号,事务会读取版本号<=当前版本号的所有数据,只要是版本号>当前版本号的数据都不会被读取。
2. MySQL可重复读如何避免幻读?
MySQL支持三种行锁定方式:
- 行锁(Record Lock):在索引记录上加锁;
- 间隙锁(Gap Lock):在不存在的空闲空间加锁;
- Next-Key Lock:行锁与间隙锁的组合。
InnoDB默认工作在可重复读级别,以Next-Key Lock的方式对数据进行加锁,具体步骤为:当扫描行记录时,对选中的索引记录上加行锁;对索引记录两边的空隙加上间隙锁(这样其他事务不能在这个间隙中插入数据)。这样便有效避免了幻读现象。