四种隔离级别
一、读未提交
一个事务能够读取到其他事务未提交的数据。(发生了脏读)
比如有这么一张表
id | name |
---|---|
1 | a |
例举两个事务
事务1 | 事务2 |
---|---|
开启事务 | 开启事务 |
将id为1的name修改为b | |
查到id为1的name为b | |
将id为1的name修改为c | |
提交事务 | 提交事务 |
二、读已提交
对于其他事务已经提交的数据、可以读取得到、(每一次读取都是已经提交的数据、发生不可重复读)
不可重复读(比如事务a在开启的时候,第一次读取的数据 name=a ,其他事务对这个数据进行修改为 name=b 并且提交、这时候事务a再次读取的时候就是 name=b,读取不到之前 name=a 这个数据,就称为不可以重复读)
事务1 | 事务2 |
---|---|
开启事务 | 开启事务 |
读取id为1的数据此时name为a | |
修改id为1的数据将name为b | |
提交事务 | |
读取id为1的数据此时name为b | |
提交事务 | |
事务 1不能够读取到之前读取到的数据,称为不可重复读 |
三、可重复读
列举:A事务读取到一个数据 (暂且称为数据A) ,然后其他事务对这个数据进行了修改并且也提交成功了 (暂且称为新数据B),然后事务A再次去读取这个数据,读取到的还是之前的数据(数据A),但如果其他事务使用 insert 插入一条数据,这时候 A事务去读取就会显示其他事务插入的这条数据、称为"幻读"。
A事务 | 其他事务 |
---|---|
开启事务 | 开启事务 |
读取id为1的数据此时name为a | |
修改id为1的数据将name为b | |
提交事务 | |
读取id为1的数据此时name为a | |
提交事务 | |
A事务能够读取到之前读取到的数据,称为可重复读 |
针对 可重复读 和 不可重复读 MySQL 通过 MVCC ( Multi-Version Concurrency Control )多版本并发控制
MySQL中的MVCC(多版本并发控制)个人观点仅供交流学习
四、可串行化
一个事务读取数据的时候会用到读锁、其他事务可以读取到这个数据、但修改和删除会发生阻塞。
如果这个事务时修改数据、就会用到写锁、其他事务读取和修改、删除这个数据会发生阻塞。
读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。
读锁和写锁属于表级锁、而InnoDB 是支持表级锁和行级锁的,默认行级锁。
例举有一个user表
读锁:
其他事务; a事务对user表进行加锁后、其他的事务可以读取到user表中的数据、如果要进行修改就会进入阻塞状态、等待a事务把user表的锁释放。
a本事事务;a事务只能对user表进行读取、无法修改user表、也无法操纵其他表。
写锁
a本身事务;a事务可以对user表进行 insert、update、delete 和 query。
其他事务;对user表做任何操作都需要进入阻塞状态、只能等待a事务释放user锁。
总结
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
可串行化 | × | × | × |