InnoDB---可重复读隔离级别的实现

本文解析了InnoDB存储引擎如何实现可重复读隔离级别。通过构建一致性读视图(快照),确保事务能始终看到一致的数据状态,即使在并发环境中也能避免脏读等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可重复读的实现

    可重复读隔离级别,简称RR,在2.1.1节,我们说过:

    Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录(读已经提交的,其实是读早于本事务开始且已经提交的),但是不能看到其他事务对已有记录的更新(即晚于本事务开始的),并且,该事务不要求与其他事务是“可串行化”的。

    这句话的核心,是“但是不能看到其他事务对已有记录的更新”,那么RR隔离级别是怎么保证这一点的呢?

    如果数据库并发控制引擎是单纯的封锁协议机制,则应该在读取数据的时候,判断数据项是不是其他事务更新过的。可是InnoDB没有这么做,而是通过如下方式,在RR隔离级别下为事务设置了一个“一致性读视图(即快照)”,之后读取数据,就是根据这个快照来获取,这样,就不能看到他晚于本事务的事务对已有记录的更新(更新生成新版本,必然不在旧的快照所限定的范围内)。

static my_bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)

{

    handlerton *hton= plugin_data<handlerton*>(plugin);

    if (hton->state == SHOW_OPTION_YES && hton->start_consistent_snapshot) //隔离级别是RRstart_consistent_snapshot才被赋值

    {

        hton->start_consistent_snapshot(hton, thd); //对于InnoDB,实际执行innobase_start_trx_and_assign_read_view()函数

        *((bool *)arg)= false;

    }

    return FALSE;

}

    如图11-4和下面的代码分析,在事务开始的时候trans_begin()会调用snapshot_handlerton()函数指针即使用innobase_start_trx_and_assign_read_view()函数在可重复读隔离级别下创建一个快照,其他隔离级别则不创建快照。

InnoDB---可重复读隔离级别的实现 - 那海蓝蓝 - 那海蓝蓝的博客
 

11-4 snapshot_handlerton()函数上下文调用关系图

 

innobase_start_trx_and_assign_read_view(  //在可重复读隔离级别下创建一个快照,其他隔离级别则不创建快照

    handlerton*    hton,    /*!< in: InnoDB handlerton */

    THD*           thd)     /*!< in: MySQL thread handle of the user for whom the transaction should be committed */

{...

    if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) { //如果是RR隔离级别,则给read view赋值,即构建一致性视图

        trx_assign_read_view(trx);  //为读一致性视图(快照)赋一个值,注意在store_lock()中应隔离级别小于RR才关闭快照

    } else {

        push_warning_printf(thd, Sql_condition::SL_WARNING,

                    HA_ERR_UNSUPPORTED,

                    "InnoDB: WITH CONSISTENT SNAPSHOT"

                    " was ignored because this phrase"

                    " can only be used with"

                    " REPEATABLE READ isolation level.");

    }

...

}

    之后,在每条SQL语句执行的时候,根据隔离级别判断是不是要使用一个新的快照,如果是可重复读,则不使用新快照,沿用老的快照,这样就能保证所有的读操作看到的是同一个数据状态;同时也确保了读已提交隔离级别下一个事务块内的不同语句的读操作看到的不是同一个数据状态。

ha_innobase::store_lock(...)

{...

    if (lock_type != TL_IGNORE && trx->n_mysql_tables_in_use == 0) {

        trx->isolation_level = innobase_map_isolation_level((enum_tx_isolation) thd_tx_isolation(thd));

        if (trx->isolation_level <= TRX_ISO_READ_COMMITTED  //隔离级别小于等于读已提交,关闭老的快照。可重复读不关闭老快照所以可以沿用

            && MVCC::is_view_active(trx->read_view)) {

            /* At low transaction isolation levels we let each consistent read set its own snapshot */

            mutex_enter(&trx_sys->mutex);

            trx_sys->mvcc->view_close(trx->read_view, true);  //隔离级别小,关闭快照,这样下一条SQL执行时,将获取新快照

            mutex_exit(&trx_sys->mutex);

        }

    }

...

}

    从上面的分析可以看出,InnoDB的可重复读的实现,利用了实现MVCC技术的快照技术。这是MVCC和基于封锁技术这两个并非控制技术的结合之处。
### 可重复隔离级别的含义与作用 可重复(Repeatable Read,简称 RR)是数据库事务的四种隔离级别之一,其主要目的是确保在同一个事务中多次执行相同的查询时,返回的结果集始终一致。这意味着,在事务开启后,即使其他事务对数据进行了修改并提交,当前事务仍然能够看到事务开始时的数据状态[^1]。 在实现上,可重复隔离级别通过生成一个 **Read View** 来保证一致性。当事务首次执行 `SELECT` 操作时,数据库会为该事务创建一个快照(Snapshot),此后在整个事务期间复用这个快照。因此,事务内的所有查询都会基于这个初始快照进行,而不会受到其他事务更新的影响[^1]。 此外,可重复隔离级别还通过锁机制来进一步增强数据的一致性。例如,在 InnoDB 存储引擎中,间隙锁(Gap Lock)和临键锁(Next-Key Lock)被用来解决幻问题。间隙锁锁定的是索引记录之间的间隙,阻止其他事务在这些间隙中插入新数据;而临键锁则是记录锁和间隙锁的组合,用于锁定一个左开右闭的区间,从而有效防止幻的发生[^3]。 ### 锁机制的作用 锁机制是数据库中实现并发控制的重要手段。在可重复隔离级别下,共享锁(Shared Lock)和排他锁(Exclusive Lock)的合理使用可以确保数据的一致性和完整性。共享锁允许多个事务同时取同一资源,而排他锁则确保只有一个事务可以修改特定资源[^2]。 具体到可重复隔离级别,锁机制的作用主要体现在以下几个方面: - **防止不可重复**:通过生成 Read View 和使用共享锁,确保事务内多次查询的结果一致。 - **解决幻问题**:通过间隙锁和临键锁,阻止其他事务在当前事务范围内的间隙中插入新数据[^5]。 ### 示例代码 以下是一个简单的事务示例,展示了如何在 MySQL 中使用可重复隔离级别: ```sql -- 设置事务隔离级别可重复 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- 开始事务 START TRANSACTION; -- 查询数据 SELECT * FROM users WHERE id = 10; -- 在事务中再次查询,结果应保持一致 SELECT * FROM users WHERE id = 10; -- 提交事务 COMMIT; ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值