mysql隔离性与MVCC

一、隔离性的定义

隔离性指多个事务间具有隔离,同时进行互不影响。 -- 在解决并发读写的问题

二、并发读写数据库存在的问题

1、脏读:A事务读到了B事务没有提交的数据(这条数据可能被回滚,导致A事务跟着出错)。

2、不可重复读:A事务第一次读取某条数据后,B事务对该数据做了修改,A事务再去读这条数据的时候发现跟上次读取的结果不一样。

3、幻读:A事务读取某范围内的数据并做了修改,此时B事务在这个范围内增加了新数据,A事务再去读取该范围内数据时发现某些数据没有被修改(好像出现幻觉,需要通过间隙锁去解决)。

三、前置知识点

undolog : 事务支持回滚操作,那么必须有回滚机制。mysql基于版本链做回滚,具体实现方法如下。

1、在每条记录中包含一个回滚指针指向上一个版本在undolog中的地址,包含创建这条记录的事务id。

2、每次对数据做操作的时候,都会生成一条反向的sql语句(执行后数据会回到操作前的版本)存入undolog中,新创建的数据的回滚指针会指向对应undolog的地址。

3、在需要回滚时,通过回滚指针找到对应的回滚sql语句去指向。

四、ReadView和可见性算法

ReadView 中包含的信息为 :
m_ids:生成ReadView的这一刻系统中活跃的事务的事务id列表。  --》事务2、4、5
min_trx_id:m_ids中的最小值。 --》 事务2
max_trx_id:当前系统应该分配给下一个事务的id(不是m_ids中最大的)。        --》 事务7
creator_trx_id:生成该ReadView的事务id。        --》 事务6
可见性算法如下:

1、先比较当前记录中的事务id是否小于ReadView中的最小事务id,如果小于则说明当前事务能看到这条记录。 --》 比如说事务1

2、再判断记录中的id是否大于等于尚未分配的事务id,如果大于等于,则说明这条记录是ReadView创建之后的事务生成的,那么当前事务肯定不可见。 --》 比如说事务7、8

3、再判断记录中的事务id是否在ReadView活跃的事务列表中,如果在则说明我生成ReadView的时候这条数据被其他事务创建了但是还没被提交,当前事务不可见。 --》 比如说事务2、4、5

4、如果不在,则说明这条记录在ReadView生成前就提交了,当前事务可见。 --》 比如说事务3

总结起来就是以ReadView为分界线,只有产生ReadView前提交的事务做出的修改可以被当前事务看见。事务在读一条数据的时候,最开始读到的都是数据库中的记录, 里面包含修改他的事务的id(DB_TRX_ID)和回滚指针(DB_ROLL_PTR )。事务通过自己的ReadView和可见性算法来判断当前读到的这条数据是否可见, 如果不可见再通过归滚指针去找上一个版本。如果还是不可见则继续找上一个版本,找到最新的一条符合条件的记录或者nill。
 

五、四大隔离级别

读未提交:一个事务直接读取其他事务未提交的数据(直接读数据库中最新的版本,不需要经过undolog)。  -- 存在脏读、不可重复读、幻读

读已提交:一个事务【每次select】的时候都会【生成新的ReadView】,根据可见性算法读其他事务已提交的数据。        -- 存在不可重复读(每次ReadView都要重新生成)、幻读

可重复读:一个事务在【第一次select】数据的时候【才生成ReadView】,后面每次select都是根据这个ReadView去执行可见性算法读其他事务已提交的数据。        -- 存在幻读

串行化: 一个事务中的所有sql语句是一个不间断的整体,一次性执行完这个事务中所有sql语句后才开始执行下一个事务中的sql语句(用锁避免并发,效率低)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值