Mysql 隔离级别及实现(MVCC)

Mysql 隔离级别及实现
脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
在这里插入图片描述

未提交读:只有写的时候的行级锁。
读已提交:MVCC每次读都进行一次快照,行级锁。
可重复读:MVCC事务中的第一次读会对事务进行快照,行级锁间隙锁。
可串行化:表锁。

[锁机制](set tx_isolation=“REPEATABLE-READ”)

死锁
在两个事务中,第一个事务为某行上锁(update、delete等)之后,另外一个事务对另外一行数据也上锁后,当这两个事务分别要请求对方上锁的数据时会发生死锁。测试时发现,发生死锁时被请求的那个事务会抛出异常:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

通过 show engine innodb status;可以找到发生的死锁信息。

MVCC (Multi-Version Concurrency Control)

MVCC下读是不需要加锁的,也就是读写可以并发进行。

数据
MVCC会给表中每一行数据加两个字段:

创建该记录的事务编号:mysql对每一个执行的事务(begin后的第一个实际执行的命令),分配一个严格递增的事务Id。记为trx_id
回滚指针:将老的数据放到undo(回滚)日志,并在新纪录中的回滚指针中指向上一条数据的地址。记为roll_pointer
快照
MVCC对事务中的读操作会进行 整个库 的 快照,并且会生成一致性(同一个事务一致性,保证可重复读)的视图read-view。

所有未提交事务id的数组(包括最小的id即min_id)。
已创建的最大的事务id(max_id,可能是已提交事务也可能是未提交事务)。
在这里插入图片描述

快照比对规则
1如果undo日志中的数据的事务id(trx_id)< min_id,表示这个版本是已提交的事务生成的,数据可见。
2如果undo日志中的trx_id > max_id,表实这个版本是由将来启动的事务生成的是不可见的。也就是该事务生成快照之后创建的事务。
3如果事务id在两个之间:min_id <= trx_id <= max_id
1)如果trx_id在快照中的未提交事务的id数组中,表实还没有提交的事务生成的,只对查询事务也是该事务可见,否则不可见。
2)如果不在数组中,则是已提交的事务,可见。
在事务进行查询时会生成相应快照,根据事务当前的id和undo的存储规则(新的在前面),则可以优先找到最新的且不是之后的对于该事务的可见id。

过程
开始某个事物(事务号:10)插入一条数据。
在这里插入图片描述

事务11,更新该条数据(上行级锁,事务结束或回滚后取消),将name设置为了“Snack”

事务12(一定是事务)查询这条信息,则会生成整个库(当然也包含该条数据)的快照,此时read_view包含的数据为:

未提交事务的数组:[11]
max_id=11,min_id=11

按照比对规则我们可以知道结果是:
在这里插入图片描述

事务11,再次更新该条数据,将name设置为了“张伟”,并且进行回滚。

在这里插入图片描述

事务12再次查询这条信息,此时比对的仍然是开始时生成的read_view(在读已提交中每次读都会生成新的),也就是说此时事务12仍然认为事务11是未完成状态。读取的事务仍然是:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值