简述mysql的事务隔离实现原理-mvcc

2021/9/20 19:27:05

本文主要是介绍简述mysql的事务隔离实现原理-mvcc,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 个人公众号,欢迎关注下:小蜗牛会飞

简述mysql的事务隔离实现原理-mvccicon-default.png?t=L892https://mp.weixin.qq.com/s/09YZ2soZZxH7ZTza8fYxYw

上篇文章我们分析了mysql的explain的关键字,这次我们来聊聊mysql的事务实现原理,这个是非常热门的一个面试题,我本人也在面试过程中被问到,所以就记录下,话不多说,直接开干

(如有错误,请留言 告知纠正)

1> 事务是什么?

        个人认为事务就是一些列的数据库操作,都放在一个单元里面进行执行,这些操作都是            不能分割的,要么全部都操作成功,要不都不操作,它们是不可分割的工作单元

2> 首先我们先来说说事务的四大特性:ACID 

     (1)A(原子性):一个事务是不可分割的单元,单元里面的所有的数据库操作要么都执                行,要不都不执行,是个整体的操作过程。

     (2)C(一致性):事务必须是使数据库的一个一致性状态变到另外一个一致性状态,比              如经典的转账场景,用A向用户B转账100,那么对于用户A的账号就减一百,用户B的              账号增加100,这样子就是一致性。

     (3)I(隔离性):即一个事务不会被另外一个事务干扰,就是事务之间是互补干扰的,                个事务之间的操作不会对另外一个事务的操作有影响。

     (4)D(持久性):一旦事务被提交,那么数据库数据的改变就是永久性的,其他的操作或者故障不应该对其有影响。

3> mysql的隔离级别:

      (1)读取未提交:出现脏读,幻读,不可重复度

      (2)读取已提交:这个是在同一个事务中(当前事务是未提交的),可                                      以读取别人已经提交事务的数据,会出现不可重复读和幻读

      (3)可重复度:这个是在同一个事务中(当前事务是未提交的),多次读 取都是相                    同 的数据,别人已经提交的事务的数据是读取不到的,所以 就是每次都都是读取                   一个快照,只有自己提交了事务,你再去读取的时候才会读取到别人已经提交的事                  务数据,此时就会出现幻读(MySQL默认)

      (4)可串行话:读写串行执行,解决了幻读,脏读,不可重读

4> 接下来我们来看看mysql的事务的实现原理-MVCC(多版本并发控制),是数据库控制并发访问的一种手段。

    特别注意:mvcc只有在读已提交可重复读这种事务隔离级别才生效,它是数据库引擎层面的实现,用来处理读写冲突的手段(不用加锁),提高访问性能

5> 对于mvcc多版本控制的了解,我们首先要知道mysql对于每条数据的的结构是怎样的:

       对于mysql的innodb存储引擎的表来说,他的聚簇索引记录会包含三个隐藏字段:

       a.trx_id:存储修改此条数据的事务id,对数据记录进行增删改操作的时候,会分配一个

               事务id,这个事务id是递增的

       b.roll_pointer:指针,指向上一次修改的记录,这个是在undo.log的日志文件记录里,                         该字段值指向上一次被修改的trx_id

       c.row_id:这个是隐藏的聚簇索引,当表没有设置主键索引,已经不存在唯一索引的话,

          mysql就会设置这个字段作为唯一索引,因为mysql的innodb的存储引擎必须                        要有唯一索引

如下图所示:

图片

6> 接下来,我们再聊聊mvcc的关键实现:一致性视图(readView)

      需要判断版本链中的哪个版本是是当前事务可见的,因此有了一致性视图的概念。其中            有四个属性比较重要:

      1.m_ids: 在生成ReadView时,当前活跃的读写事务的事务id列表

      2.min_trx_id: m_ids的最小值

      3.max_trx_id: m_ids的最大值+1

      4.creator_trx_id: 生成该事务的事务id,单纯开启事务是没有事务id的,默认为0,                     creator_trx_id是0。

7> 版本链中的当前版本是否可以被当前事务可见的要根据这四个属性按照以下几种情况来判断:

      a.当 trx_id = creator_trx_id 时:当前事务可以看见自己所修改的数据, 可见,

      b.当 trx_id < min_trx_id 时 : 生成此数据的事务已经在生成readView前提交了, 可见

      c.当 trx_id >= max_trx_id 时 :表明生成该数据的事务是在生成ReadView后才开启 的,          不可见

      d.当 min_trx_id <= trx_id < max_trx_id 时

        trx_id 在 m_ids 列表里面 :生成ReadView时,活跃事务还未提交,不可见

        trx_id 不在 m_ids 列表里面 :事务在生成readView前已经提交了,可见

图片

       如果某个版本数据对当前事务不可见,那么则要顺着版本链继续向前寻找下个版本,              继续这样判断,以此类推。



这篇关于简述mysql的事务隔离实现原理-mvcc的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程