事物隔离级别
主要用来处理多个处理在并发的情况下对同一条数据进行读写操作所产生的不安全问题
- 脏读
- 事物1对数据进行修改未提交被事物二读到未提交的
- 不可重复度(1条数据)
- 事物1查到数据,事务二对数据进行修改并提交,事物1再次查询查询到的数据不一致
- 幻读(整张表,某几条数据)
- 事物1针对整个表统计一次后,事物2插入并提交了一条数据,事物1再次统计数据不一致。
读未提交read uncommited
读已提交 read commited :解决脏读问题
可重复度: 解决不可重复读,两次读到的数据一致
串行化: 在事物1读的时候加个表锁,其他事物要修改或删除则需要等待。
Mysql默认隔离级别为重复读,orcal是读已提交。
MVCC
读已提交,无锁实现原理:
读不到未提交的数据,不是行锁,加了行锁等于串行化执行降低了并发。
MVCC三个隐藏列重要字段:隐藏id,当前事物id, 上一个事物id
当发生更新后,版本链怎加一条。新事物id记录上一个事物id,如果需要回滚找到上一个事物历史事物,然后找到undolog,进行回滚。
当这条数据发生并发读写时,
-
事物1读到 原数据 1,当前事物id10 ,上一条事物id在undog版本中为9,最大事物id30 未提交。
-
- 再此过程中并发有一个线程进来,当前事务id为9,所有正在并发未提交的事物列表为【10,-----30】未开始的事物为21.
- 再此过程中并发有一个线程进来,当前事务id为22,所有正在并发未提交的事物列表为【10,-----32】未开始的事物为32.
- 再此过程中并发有一个线程进来,当前事务id为18,所有正在并发未提交的事物列表为【10,-----32】未开始的事物为30.
-
拿到当前事物8与最小的10进行比较,如果等于则说明是当前事物内可以读取。
-
如果小于,说明读到了历史已提交数据也可以读取。
-
如果大于,则拿当前事物id与最大事物id进行比较,如果大于,则说明是在开启事物后读取到的则不能读取。
-
如果大于最小事物id<最大事物id,则说明是并发读取到的,按照读已提交原理,则不能读取,需要拿当前事物对应版本链的上一条事物id去再跑一遍,如果满足,则读取。
-
如果在这个区间内,但是没有找到,说说明已经提交,可以读取到。
重复读,每个事物多次查询只会创建一个readView,前后读到的数据一致