mysql MVVC理解

mysql中,每一行数据,除了本身的数据,还维护着其他信息,其中包括:
1. 一个隐藏id
2. 事务id
3. 回滚指针。
其中隐藏id的选择规则如下:
– 如果有主键id, 则是主键id
– 如果有唯一键,则是唯一键
– 如果都没有,则mysql生成一个隐藏id

事务id是顺序递增的,每新增一个事务,事务id就加1;同时,将(update|insert)操作的sql语句记录在undolog中,而回滚指针则指向上一个事务的地址。便于当前事务失败的时候,结合undolog日志,回滚到之前的状态。
但是,当并发的时候,当前事务之前的事务都是历史版本;当存在多个历史版本的时候,我们读的时候要读哪个历史版本呢?这就会设计到一个可见性算法,来计算当前事务读取的是哪一个版本的历史数据。这个可见性算法就是read view:读视图。

read view

当进行快照读的时候会生成一个事务id的列表,来保存不同的信息,这个列表就是readview;通过这些信息来做可见性的判断。这些信息包括:
list:生成readview的时候活跃的id
up_limit_id:当前活跃id的最小值
low_limit_id:尚未分配的下一个事务id

readview在不同的隔离级别下,生成的时机也不同:
– 在RC(读已提交隔离级别)下:每次快照读的时候生成新的readview
– 在RR(可重复读隔离级别)下:readview第一次执行快照读的时候会生成,之后都是这个版本的。

其判断规则为:
– 判断被访问版本的 trx_id 属性值是否小于 up_limit_id,如果小于,表明生成该版本的事务在生成 ReadView 前已经提交,所以该版本可以被当前事务访问。
– 判断被访问版本的 trx_id 属性值是否大于 lower_limit_id ,如果大于,表明生成该版本的事务在生成 ReadView 后才生成,所以该版本不可以被当前事务访问。
– 判断被访问版本的 trx_id 属性值是否在list 列表中,如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。

例如下方事务列表:

事务1 事务2 事务3 事务4
begin begin begin begin
nothing todo nothing todo nothing todo update; commint;
select(读视图) -

当前情况下:
undolog中保存的历史版本只有一个,就是事务4.
list: 1,2,3 (当前获取的事务列表)
up_limit_id:1 (当前活跃的最小事务id)
low_limit_id:5(下一个分配的事务id)

于是可以得出当前行的事务ID(也就是trx_id)是4,根据上方的条件判断:RC隔离级别是可以堵到事务4提交的数据,而RR隔离级别是读取不到的。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇