一、MySQL有哪几种事务隔离级别?
1.读未提交
读的都是最新版本的数据,会出现脏读
2.读已提交
读的都是已提交的数据,会出现不可重复读
3.可重复读
解决了不可重读的问题,InnoDB解决了幻读问题
4.串行化
用加锁的方式实现串行化
二、事务的隔离级别是怎么实现的?
每行数据其实在数据库都是多个版本的,可能同一时间有很多事务在更新一条数据,事务在开始的时候会申请一个id,这个id是严格随着时间递增的,先开始的事务id总是小的,数据库的版本就是事务id的版本。
1.读未提交
每次读的都是最新版本,这样速度是最快的,使用中的业务场景基本上没有
2.读已提交
如果当前数据版本的号(最新事务对这条数据的操作)比事务的id大,就会根据版本的id查看事务是否提交了,如果提交了,就会承认这条数据,如果查到这个事务还没有提交,就会查看上个版本,直到找到已提交的版本,获取那个版本的数据,那有没有读到的版本是已提交的,上个版本还没提交呢,当然是不会的,更新的时候会加上一个行锁,上个事务如果没有提交,这个事务是不可能提交的
3.可重复读
可重读读在事务启动的时候获取一个数组,记录未提交的事务,可重复读取数据的时候多了一个验证,如果事务提交了但是数据的版本号(操作这个数据事务的id)比当前事务高,说明这个事务是在当前事务启动后启动并且提交的,这条数据是不会被承认的,如果当数据的版本号比当前事务id低的话,说明操作是在当前事务开启之前就开启了,这条数据是被当前事务承认的。
可以发现InoDB引擎是通过MVCC解决了幻读的问题。
4.串行化
用加锁的方式来避免并行访问
5.视图
读已提交和可重复读都有视图概念的,读已提交获取的是最新提交的视图,可重复读在事务启动的时候就开启,保证事务内读到的数据是一样的,比如一个事务 执行了两次 select city from tb_user where id = 100 ,中间有一个新的事务执行了修改操作,对于可重复读,两次查询结果都是一样的,对于读已提交,两次结果就不一样了。