前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL里的MVCC

MySQL里的MVCC

作者头像
jeanron100
发布2019-05-08 18:26:30
1.6K0
发布2019-05-08 18:26:30
举报
文章被收录于专栏:杨建荣的学习笔记

这是学习笔记的第 1934 篇文章

对于MVCC想必大家也看到了不少源码层的解读,最大特点就是分析的是比较深入了,但是却不大好理解,最后有种不明觉厉的感觉,以至于在面试中经常翻船。

我们换个角度来解读一下, 在表设计中,我们有一种策略,那就是尽可能保留数据变化的历史,比如在数据发生变化时我们不会直接删除数据,而是把它转换为两类操作。

比如修改一个账户的余额,这是敏感信息,属于状态型数据,在更新时需要保留完整的数据变化历史,那么把余额从100变化为200的过程,会转化为1条update语句,1条insert语句。

如下的操作是我们预期的结果:

可以把这个过程改造为:

有的同学说,这个和MVCC有什么关系呢,其实MVCC的实现原理也是类似的方式,我们就以这种方式作为例子来解释,在这种情况下,第1行update语句对应的数据可以理解为是之前的数据镜像,而第2行则是数据处理后的结果。

如果存在大量的并发读写,我们可以把读的压力分担出来,即数据的查询可以指向镜像,而数据的修改指向当前的变化数据,这样两者是一个互补的关系。

这种情况类似下面的方式,比如T1,T2,T3三个顺序时间里发生了三次请求,分别是一次写请求和两次读请求.

那么在MySQL中会先在T1时间生成一个快照,比如数据标识是90,然后在这个基础上进行数据修改,数据标识为100,但是事务未提交。

在T1写数据的事务内,T2时间的读请求会读取T1时间生成的快照数据,读取的数据标识依旧是90,T3时间的读请求也是类似。

所以MVCC本身还是比较接地气的,只是我们理解的方式有些高大上,消化不了了。

我们小结一下:

1.表设计中数据生命周期的管理是一种体系化的管理方式,原理和思路是通用的。

2.数据生命周期管理有两个重要的标识,一个是标识数据变化的,一个是标识数据可用状态的。

明白了这些,理解InnoDB的MVCC就很简单了,我们使用类似的思路来做下解读,假设在每行记录后面保存两个隐藏的列来实现的,这两个列,分别保存了这个行的创建时间,一个保存的是行的删除时间。这里存储的是系统版本号,会自动递增,我们按照DML的几个维度进行阐述。

1)、首先是Insert操作, 事务id 假设是1

id

name

create version

delete version

1

test

1

2)、Update操作,会先把当前记录标识为已删除,然后新增一列数据,写入相应的版本号,在这里就是2,和上一条的delete_version是一致的,比如把字段name修改为new_test

id

name

create version

delete version

1

test

1

2

1

new_test

2

3)delete操作,就是把当前记录标识为已删除

id

name

create version

delete version

1

new_value

2

3

此外需要考虑的是上面的实现方式中,如果事务发生回滚该如何处理,这个是我们需要重点考虑的,也是对数据周期管理流程的一个补充,这里我们就要引出InnoDB层的实现undo.

我们来设想一个问题,原有的镜像数据在表中存放显然是难以维护的,而且从存储上也是一笔不小的开销,所以从性价比考虑,这部分的内容应该是独立存放的,这个存放的地方就是undo日志里面,一旦出现了事务回滚,我们可以把已有的数据状态通过逆向应用保证事务的ACID特性。

要实现这个细粒度的操作,在InnoDB的设计中,实际上所有行数据会增加三个内部属性列:

(1)DB_TRX_ID,6字节,记录每一行最近一次修改它的事务ID;

(2)DB_ROLL_PTR,7字节,记录指向回滚段undo日志的指针;

(3)DELETE BIT,标识该记录是否被删除,不是真正的删除数据;

把这三个列组合起来,就可以标记数据的周期性,并定位到相应的事务,在需要的时候进行回滚。

比如一张表test (id,name)主键为id列

l insert的数据在redo中顺序记录insert操作,同时生成undo记录,为逆操作delete

l delete的数据在redo中顺序记录delete操作,同时生成undo记录,为逆操作insert

l update的数据在redo中顺序记录update操作,同时生成undo记录,为逆操作update,原来是从id=1 变成 id=3,则逆操作为id =3,变成id=1

对于InnoDB来说,无论是更新,删除,都只是设置行记录上的deleted version标记位,而不是真正的删除记录,后续这些记录的清理,是通过Purge后台进程实现的。

此外,需要说明的是只有在隔离级别read-committed和 repeatable-read 才能使用MVCC,read-uncommited由于是读到未提交的,所以不存在版本的问题,而serializable 则会对所有读取的行加锁。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档