⾏状态变更⽰意图
图中虚线框⾥是同⼀⾏数据的 4 个版本,当前最新版本是 V4,k 的值是 22,它是被 transaction id 为 25 的事务更新的,因此它的 row trx_id 也是 25。
你可能会问,前⾯的⽂章不是说,语句更新会⽣成 undo log(回滚⽇志)吗?那么,undo log 在哪呢?教程摄影
实际上,图中的三个虚线箭头,就是 undo log;⽽ V1、V2、V3 并不是物理上真实存在的,⽽是每次需要的时候根据当前版本和 undo log 计算出来的。⽐如,需要 V2 的时候,就是通过 V4 依次执⾏ U3、U2 算出来。
明⽩了多版本和 row trx_id 的概念后,我们再来想⼀下,InnoDB 是怎么定义那个“100G”的快照的。
按照可重复读的定义,⼀个事务启动的时候,能够看到所有已经提交的事务结果。但是之后,这个事务执⾏期间,其他事务的更新对它不可
数据版本可见性⽰意图
这样,对于当前事务的启动瞬间来说,⼀个数据版本的 row trx_id,有以下⼏种可能:
如果落在绿⾊部分,表⽰这个版本是已提交的事务或者是当前事务⾃⼰⽣成的,这个数据是可见的;
如果落在红⾊部分,表⽰这个版本是由将来启动的事务⽣成的,是肯定不可见的;
如果落在黄⾊部分,那就包括两种情况
a. 若 row trx_id 在数组中,表⽰这个版本是由还没提交的事务⽣成的,不可见;
b. 若 row trx_id 不在数组中,表⽰这个版本是已经提交了的事务⽣成的,可见。
⽐如,对于图中的数据来说,如果有⼀个事务,它的低⽔位是 18,那么当它访问这⼀⾏数据时,就会从 V4 通过 U3 计算出 V3,所以在它看来,这⼀⾏的值是 11。
你看,有了这个声明后,系统⾥⾯随后发⽣的更新,是不是就跟这个事务看到的内容⽆关了呢?因为之后的更新,⽣成的版本⼀定属于上⾯的2 或者 3(a) 的情况,⽽对它来说,这些新的数据版本是不存在的,所以这个事务的快照,就是“静态”的了。
事务A查询结果⽰意图
外键约束怎么写>borderlands歌曲从图中可以看到,第⼀个有效更新是事务 C,把数据从 (1,1) 改成了 (1,2)。这时候,这个数据的最新版本的 row trx_id 是 102,⽽ 90 这个版本已经成为了历史版本。
在电脑中table是什么意思第⼆个有效更新是事务 B,把数据从 (1,2) 改成了 (1,3)。这时候,这个数据的最新版本(即 row trx_id)是 101,⽽ 102 ⼜成为了历史版
你可能注意到了,在事务 A 查询的时候,其实事务 B 还没有提交,但是它⽣成的 (1,3) 这个版本已经变成当前版本了。但这个版本对事务 A 必须是不可见的,否则就变成脏读了。
好,现在事务 A 要来读数据了,它的视图数组是[99,100]。当然了,读数据都是从当前版本读起的。所以,事务 A 查询语句的读数据流程是
到 (1,3) 的时候,判断出 row trx_id=101,⽐⾼⽔位⼤,处于红⾊区域,不可见;
接着,到上⼀个历史版本,⼀看 row trx_id=102,⽐⾼⽔位⼤,处于红⾊区域,不可见;
再往前,终于到了(1,1),它的 row trx_id=90,⽐低⽔位⼩,处于绿⾊区域,可见。
事务B更新逻辑图
是的,如果事务 B 在更新之前查询⼀次数据,这个查询返回的 k 的值确实是 1。
但是,当它要去更新数据的时候,就不能再在历史版本上更新了,否则事务 C 的更新就丢失了。因此,事务 B 此时的 set k=k+1 是在(1,2)的基础上进⾏的操作。
mysql中文下载所以,这⾥就⽤到了这样⼀条规则:更新数据都是先读后写的,⽽这个读,只能读当前的值,称为“当前读”(current read)。
因此,在更新的时候,当前读拿到的数据是 (1,2),更新后⽣成了新版本的数据 (1,3),这个新版本的 row trx_id 是 101。
mysql怎么读英语所以,在执⾏事务 B 查询语句的时候,⼀看⾃⼰的版本号是 101,最新数据的版本号也是 101,是⾃⼰的更新,可以直接使⽤,所以查询得到的 k 的值是 3。
这⾥我们提到了⼀个概念,叫作当前读。其实,除了 update 语句外,select 语句如果加锁,也是当前读。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论