InnoDB---读未提交隔离级别的实现

来源:互联网 发布:社会关系网络企业 编辑:程序博客网 时间:2024/06/09 14:15

读未提交的实现

    对于读未提交隔离级别,此级别不会对记录加锁,有如下几种情况:

1 对系统表的数据操作,是数据引擎自己发出的数据查询操作,使用读未提交隔离级别,目的是不与其它事务因锁的存在而冲突。

2 row_search_mvcc()row_sel_get_clust_rec_for_mysql()等获取记录的函数中确保读未提交隔离级别下允许读到最新的记录

   那么,怎么才能读到最新的记录呢?以row_search_mvcc()为例, 我们来看代码实现方式:对于读未提交的隔离级别,代码什么也没有做,默认本函数的“PHASE 4”调用“rec = btr_pcur_get_rec(pcur);”获得的rec就是可用的。如果不是读未提交的隔离级别,才判断rec的可见性,rec不可见时才去找旧版本。所以,InnoDB以此方式,实现了读未提交隔离级别。与此方式类似的处理,还有row_sel_get_clust_rec_for_mysql()函数,读者可以参考阅读。

row_search_mvcc(...)  //获取记录

{...

    /* We areready to look at a possible new index entry in the result

       set: the cursor is now placed on a userrecord */

    if (prebuilt->select_lock_type!= LOCK_NONE) {  //如果需要加锁,则加锁的语义来自上层

...

    } else {  //不需要加锁

        /*This is a non-locking consistent read: if necessary, fetch a previous versionof the record */

        if(trx->isolation_level == TRX_ISO_READ_UNCOMMITTED){ //如果是读未提交,则什么也不做

           /* Do nothing: we let a non-locking SELECT read the latest version ofthe record */

        }else if (index == clust_index) { //否则,才需要检查“rec”是否满足可见性,不满足则找出满足可见性要求的旧版本

            //所以,读未提交什么也不做,就是在说当前的rec是符合的,能被读到的,根本不用到回滚段找出旧版本(所得即所“可见”)

           /*  Fetch a previous version ofthe row if the current one is not visible in the snapshot;

                if we have a very high force recovery levelset, we try to avoid crashes by skipping this lookup */

           if (srv_force_recovery < 5

               && !lock_clust_rec_cons_read_sees(rec,index, offsets, trx_get_read_view(trx))) {

               rec_t*    old_vers;

               /* The following call returns 'offsets' associated with 'old_vers' */

                err = row_sel_build_prev_vers_for_mysql(trx->read_view,clust_index, prebuilt, rec, &offsets, &heap,

                                                         &old_vers,need_vrow ? &vrow : NULL, &mtr);

               if (err != DB_SUCCESS) {

                   goto lock_wait_or_error;

               }

               if (old_vers == NULL) {

                   /* The row did not exist yet in the read view */

                   goto next_rec;

               }

               rec = old_vers;

            }

        }else {

            /* We are looking into a non-clusteredindex, and to get the right version of the record we

               have to look also into the clustered index:this is necessary, because we can only get the undo

               information via the clustered index record.*/

...

            }

        }

    }

...}

0 0