mysql 事务的隔离机制

前置

 读未提交读已提交可重复读串行
脏读:读到了未提交的数据vxxx
重复读:同一个事务内对某个特定数据查询的结果不一致(针对update操作)vvxx
幻读:同一个事务内对某些数据查询的结果集不一致(针对insert操作)vvx(如果不更新的话是不会幻读的)x

名词解释

MVCC多版本并发控制
活跃事务集合已开始但是没有提交的事务
traceId事务id 递增
版本号每条数据都会有对应的一个版本号其实就是更新这条数据的事务id
快照读mysql 默认的读取方式 select,会产生一个活跃事务的快照
当前读select ... for update 通过该方式获取的数据是最新的数据不存在数据的隔离,并且该方式会对查询范围内数据加上一个间隙锁,其他事务无法修改插入删除
间隙锁当显示使用for update 查询时会对查询的记录行添加范围锁使用唯一索引时会转化为行锁,不使用索引则添加表锁

INNODB 事务隔离的实现

假设目前存在2个事务 A和B

A事务开启后 开始查询今天的订单表数据,此时的查询=快照读,会获取当前的的活跃事务id集合(快照)

此时B事务开启并且插入了一条数据到订单表后提交

A事务再次查询今天的订单数据,此时会获取每条订单数据对应的版本号 有以下判断

如果改数据的版本号小于活跃事务id集合里面的最小id 那么该版本已提交,该数据对于当前事务是可见的;

如果该数据的版本号大于活跃事务id集合里面的最大id 那么该版本是一个新开启的事务,对当前事务是不可见的;

如果该数据的版本号大于最小id 小于最大id 那么再判断该版本是否存在于集合中,如果存在说明该版本在当前事务开启时是处于未提交状态,所以是不可见的;如果不存在则说明该版本在产生快照的时刻是已经提交的,所以是可见的

当数据的版本对于当前事务是不可见的时候,会去从undolog 中获取更早的版本号再次比对直到该数据可见或者没有更早的版本号

最终 的结果是 A事务无法查询到刚刚B事务插入的数据

但是此时A事务进行一次批量的更新

如把今天的订单统一改为异常订单状态

此时B事务插入的数据同样会被修改

A事务再次查询今日订单数据则可以查到B事务刚刚插入的数据

原因是:

事务中的update delete 操作都是先读后操作 该读指的是当前读 也就读取最新的数据然后更新 更新完后该数据的版本号就变成了当前的事务id,该数据在当前事务中是可见的.

为了避免先读后改在并发时会出现数据的覆盖,所以在每次更新或者和删除时事务需要获取到该数据的行锁,等待事务结束后释放

如果该更新或者删除操作没有加索引那么会获取表锁,所以事务中的任何更新操作都要记得加上索引

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值