沫言|解读数据库:深入分析MySQL中事务以及MVCC的实现原理( 四 )
LBCC方案中 , 如果我们的业务系统是读多写少的话 , 这种方案就会极大影响了效率 , 所以我们就有了另一种解决方案:MVCC 。
MVCCMVCC,多版本的并发控制 , 英文全称:Multi Version Concurrency Control 。 就是当我们在修改数据的时候 , 可以为这条数据创建一个快照 , 后面就可以直接读取这个快照 。
那么MVCC具体到底是如何实现的呢?
为了实现MVCC机制 , InnoDB内部为每一行添加了两个隐藏列:DB_TRX_ID和DB_ROLL_PTR(MySQL另外还有一个隐藏列DB_ROW_ID , 这是在InnoDB表没有主键的时候会用来作为主键 , 想详细了解可以点击这里) 。
DB_TRX_ID长度为6字节 , 存储了插入或更新语句的最后一个事务的事务ID 。
DB_ROLL_PTR长度为7字节 , 称之为:回滚指针 。 回滚指针指向写入回滚段的undo log记录 , 读取记录的时候会根据指针去读取undo log中的记录 。
正因为MySQL中undo log中会维护一个历史数据记录 , 所以我们应该养成定期提交事务的习惯 , 否则回滚段会越来越大 , 甚至占满了表空间 。
快照读快照读是针对上文的当前读而言 , 指的是在RR隔离级别下 , 在不加锁的情况下MySQL会根据回滚指针选择从undo log记录中获取快照数据 , 而不总是获取最新的数据 , 这也就是为什么另一个事务提交了数据 , 在当前事务中看到的依然是另一个事务提交之前的数据 。
MySQL什么时候开始读取快照我们先看看MySQL默认隔离级别RR下的一个例子(注意 , test和test2两张表一开始都是空表 , 均只有id和name两个字段) 。
- 场景1(事务1操作数据之后再进行第一次查询):
- 场景2(事务1不进行任何操作 , 事务2先开始第一次查询)
通过上面两个场景中我们可以得出结论:RR隔离级别快照并不是在BEGIN就开始产生了 , 而是要等到事务当中的第一次查询之后才会产生快照 , 之后的查询就只读取这个快照数据
- 场景3(事务2先进行一次t1表查询之后 , 事务1再去操作其他表t2)
从场景3我们可以得出结论:RR隔离级别快照并不只是针对当前所查询的数据 , 而是针对当前MySQL中的所有数据(跨库也一样 , 只要在同一个MySQL)
MVCC查询机制MVCC机制到底如何查询的呢?假设由很多个事务同时进行 , 那么就会产生很多快照 , 查询的时候又到底是怎么做的呢?
接下来我们把抽象的概念具体化 , 假定DB_TRX_ID和DB_ROLL_PTR均为整型 , 接下来我们进行查询演示:
1、清空原先的test表 , 事务A插入两条数据 , 此时DB_TRX_ID(事务id)为1,DB_ROLL_PTR(回滚指针为null)
2、这时候事务B进行了一次查询 , 会得到上面的结果 , 事务2还没提交的时候又来了事务C , 事务C插入了id=3的数据 , 此时表中的数据如下:
注意 , 这时候第3条数据的事务id为3 , 因为事务2也会产生一个事务id3、这时候事务B再次进行查询 , 根据上面了解的 , 我们知道 , 这时候应该是查询不出王五的 , 所以实际上二次查询可能是这么查的:
- 中国青年报客户端|【青声视语】数据解读:中国经济加快复苏引外媒点赞
- 人民网-环保频道|专家科普解读之二:“限塑”之后,我可以用什么?
- 律师解读公司扔员工证:属公然侮辱他人,情节严重可给予拘留
- 【青声视语】数据解读:中国经济加快复苏引外媒点赞
- 李霄鹏|盘点鲁能冠军主帅,分析李霄鹏差在哪里,解读鲁能绝无可能换帅
- 专家科普解读之二:“限塑”之后,我可以用什么?
- 新华社|门诊共济是自己的"钱"给别人用了吗?权威解读来了
- 医保|医保门诊改革是拿个人的“钱”补统筹基金的窟窿吗?权威解读来了
- 上汽|上汽集团“老大难”| 半年报解读
- 央视新闻客户端|门诊共济改革是“补窟窿”吗?为啥要动个人账户的“钱”?专家解读来了