Mysql MVCC 原理 low_limit_id ReadView

  • 参考:感觉好多地方写的都不对。。还是看源码吧
    • http://www.iskm.org/mysql56/read0read_8cc_source.html
    • https://www.cnblogs.com/songwenjie/p/8644646.html
  • MVCC Multi-version Concurrency Control
    • 怎么个MultiVersion法?
      • 每个开启的事务,会有一个tx_id,是不断自增长的,后面开的事务比前面开的事务大
      • 在默认的隔离级别:RepeatableRead,可重复读,需要做成,在事务中,看不到别人的修改,怎么做到呢?
        • 先引入一个概念:ReadView。ReadView里包含:
          • 当前活跃的事务id列表
          • 创建者的事务id
          • up_limit_id , low_limit_id 上下限,小于up_limit_id 可见, 大于low_limit_id 不可见。
            • 那么这个两个值是怎么赋值的呢。
            • low_limit_id 是系统最大的事务id值。up_limit_id是活跃事务列表的最小事务id
              • /* No future transactions should be visible in the view */
              • 349  view->low_limit_no = trx_sys->max_trx_id;
              • 350  view->low_limit_id = view->low_limit_no;
              • /* The last active transaction has the smallest id: */
              • view->up_limit_id = view->trx_ids[view->n_trx_ids - 1];
          • 这样理解Read View :保存了不应该让这个事务看到的其他的事务 ID 列表
        • 再引入关于可见性的规则
          • 读某一行数据的时候,如果发现他的事务id < up_limit_id (活跃id列表最小值),可见。
          • 如果发现数据的事务id>low_limit_id(ReadView时系统中最大的事务id) ,不可见。
          • 如果发现数据的事务id在列表范围内
            • 如果是id集合中的,不可见
            • 如果不在id集合中,可见
        • 根据上面的规则,以RepeatableRead举个例子吧,要求读一个值,一直读都是同一个值。
          • 这种隔离级别下,开启事务的时候开启一个ReadView,在整个事务过程中都用这个ReadView。
          • 我开启是事务是10,ReadView是 (4,8, 10),【我自己也活跃】,up_limit_id=11,low_limit_id=4
          • 如果我读到一个数据的事务id是1,小于活跃列表的最小值,可见。
            • 为什么?事务开启的时候生成的ReadView,除了4,8,10,其他都已经提交了,所以其实版本<4,以及5、6、7、9,都是肯定在我开启的时候已经提交了。这些版本的的数据,再怎么读都不会变。放心读吧。
          • 如果我读到一个数据的事务id是12,说明他在我创建ReadView之后提交的,我不应该看见这个值,应该去undolog里找这个数据的前面的版本,如果找到<4,或者5、6、7、9都是安全的,可以读。
          • 如果我读到一个数据事务id在活跃列表的范围内
            • 如果就是活跃的事务之一,比如说是8,说明这个数据在我开启事务之后提交了,这个我不能看见,应该去undo log中找上一个版本来读,假设说是7。
            • 7也是在这个活跃范围里,但是并不是活跃事务之一,这个版本是在开启事务之前提交的,这个我可见。
        • 再举个读已提交的例子。
          • 这个隔离级别是每次读都采用新的ReadView。
          • 开启的事务是10。
          • 读一个数据,事务id是9,ReadView活跃id是(4,8,10),按照规则,可见。
          • 过一会再读这个数据,发现事务id变成了11,活跃的id还是(4,8,10),但是因为开启了新的ReadView,当前系统最大事务id>11(因为我们已经读到11了嘛),判断规则是:不在活跃id列表,所以可见。这回就读到了这个数据的新版本了

你可能感兴趣的:(数据库)