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

读未提交的实现

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

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 are ready to look at a possible new index entry in the result

       set: the cursor is now placed on a user record */

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

...

    } else {  //不需要加锁

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

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

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

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

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

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

                if we have a very high force recovery level set, 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-clustered index, 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. */

...

            }

        }

    }

...}

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