mysql事务隔离实现原理MVCC

问题一:在多线程情况下,多个线程访问同一个变量,需要保证数据安全问题;在mysql数据库中同样存在多线程访问同一条数据导致的数据问题;很多人第一时间想到加锁,但是对数据库来说,加锁相对比较消耗性能,并发量很难上去;

MVCC是如何解决并发场景下,不加锁,解决多个事务访问同一条数据产生的数据安全的三种问题(脏读、不可重复读、幻读)?

1、什么是MVCC?

Multi-Version-Concurrenty-Control:多版本并发控制,多版本指什么?

2、三个基础概念:

(1)undo log:当执行任何一条insert、update、delete语句时,mysql会记录每条sql的回滚日志;

a、undo log回滚日志的字段包含:

    row_id:     就是数据库的隐藏字段row_id;

    db_trx_id:当前事务的ID;

    db_roll_ptr:  roll_pointer,回滚指针,每条数据的回滚日志中的回滚指针都会指向上一条回滚日志;

b、作用:
      回滚日志用来实现事务的回滚操作
      事务的原子性,也是基于undo log实现的
当然,mysql还有其他日志,redo log和bing log,后面在学习;

(2)版本链:

一条数据的多个回滚日志,通过回滚指针链接在一起,形成了这条数据的版本链;

所有的针对该条数据的查找,都是基于一定规则在这条数据对应的版本链中进行判断并查找;

MVCC中多版本并发控制中的多版本应该就是指某条数据在undo log形成的版本链中有多条记录

(3)ReadView:查询视图,mysql在执行select的时候,都会生成ReadView查询视图,通过查询视图的关键字段去判断,该从版本链的哪些记录提取数据,并返回结果;

a、ReadView的几个关键字段:

m_ids:表示在生成ReadView视图的时候,活跃的事务ID集合,所谓活跃,就是开启了事务,没提交的那些事务的id集合,一条数据,可以被多个会话开启多个事务,就会有多个ReadView;

m_min_trx_id:在m_ids集合中最小的值;

m_max_trx_id:  m_max_trx_id并不是m_ids中的最大值,而是在m_ids的最大值再递增一位,

比如某条数据有3个事务同时对它进行修改,事务A的id是1,事务B的id是2,事务3的id是4,则m_ids=[1,2,3],而m_max_trx_id则等于4;

creator_trx_id:  当前事务的id;

b、根据ReadView这几个关键字段,判断数据是否可被访问,主要遵循以下几点原则:

db_trx_id ==   creator_trx_id:当前事务就是查询的ReadView事务中的数据,那么这条数据肯定是可以被查询的;

db_trx_id   <  m_min_id:说明要查询的事务是m_min_id之前提交的那些事务,因此数据也是可以被查看的;

db_trx_id > m_max_id:说明当前事务要查询的数据在最大的活跃事务后,是不能被访问的;

m_min_id  <  db_trx_id < m_ids:这里分为2种情况:

3、mysql怎样通过undo log、版本链、ReadView去进行数据筛选,从而达到不加锁,也能实现事务的隔离级别所达到的那个隔离效果的?

(1)READ UNCOMMITTED和SERIALIZABLE,

a、由于READ UNCOMMITTED隔离级别低,每次读取时只需要从版本链中读取最新版本的数据返回即可,

b、SERIALIZABLE是通过串行的方式执行,直接从最近不活跃的版本链中进行数据提取即可,因此值得讨论的只有READ COMMITTED和REPEATABLE READ 这两个隔离级别;

(2)READ COMMITTED的执行流程:

每个select新建一个ReadView视图,

(3)REPEATABLE READ的执行流程:

在一个事务中,里面都沿用同一个ReadView

(4)总结二者的区别:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值