MVCC

        为了实现操作可串行化,同时避免锁机制存在的各种问题,我们可以采用基于多版本并发控制(Multiversion concurrency control,MVCC)思想的无锁并发机制。人们一般把基于锁的并发控制机称成为悲观机制,而把MVCC等机制称为乐观机制。这是因为锁机制是一种预防性的,读会阻塞写,写也会阻塞读,当锁定粒度较大,时间较长是并发性能就不会太好;而MVCC是一种后验性的,读不阻塞写,写也不阻塞读,等到提交的时候才检验是否有冲突,由于没有锁,所以读写不会相互阻塞,从而大大提升了并发性能。

        MVCC的一种简单实现是基于CAS(Compare-and-swap)思想的有条件更新(Conditional Update)。普通的update参数只包含了一个keyValueSet,Conditional Update在此基础上加上了一组更新条件conditionSet { ... data[keyx]=valuex, ... },即只有在D满足更新条件的情况下才将数据更新为keyValueSet;否则,返回错误信息。因此,对于单个更新操作可能会失败,这需要重试以提高成功率。

        如果一组更新条件conditionSet的数据量比较大,会导致网络传输量大而影响性能,可考虑版本号来代替一组更新条件来降低网络传输,例如memcache的cas操作。

### MVCC 的原理及实现 #### 什么是 MVCCMVCC(Multi-Version Concurrency Control,多版本并发控制)是数据库管理系统中用于提升并发性能的一种机制。它通过保存数据的历史版本来减少读写之间的冲突,从而允许多个事务在同一时间访问同一份数据的不同版本而不互相干扰。 在 MySQL InnoDB 存储引擎中,MVCC 是通过隐藏列 `DB_TRX_ID` 和 `DB_ROLL_PTR` 来实现的[^1]。这些隐藏列分别存储了最后修改该记录的事务 ID 和指向历史版本的回滚指针。 --- #### MVCC 的核心组件 以下是 MVCC 实现的核心组成部分: 1. **两个隐式字段** - `DB_TRX_ID`: 记录最后一次修改该行数据的事务 ID。 - `DB_ROLL_PTR`: 指向 Undo Log 中该行数据的上一个版本地址,形成一条版本链表[^3]。 2. **Undo Log (回滚日志)** 当某条记录被更新时,旧版本的数据会被保存到 Undo Log 中,并通过 `DB_ROLL_PTR` 进行链接。这样就形成了一个版本链,使得不同事务能够看到不同的数据版本[^3]。 3. **Read View (一致性视图)** Read View 是由事务启动时生成的一组信息,主要包括以下几个部分: - 所有已提交事务的最大事务 ID (`max_trx_id`)。 - 非活跃事务列表。 - 活跃事务列表及其对应的事务 ID[^1]。 使用 Read View 可以判断某一版本的数据是否对当前事务可见。具体来说,如果某个版本的 `DB_TRX_ID` 小于等于 `max_trx_id` 并且不在活跃事务列表中,则该版本对当前事务可见[^3]。 --- #### 快照读与当前读的区别 - **快照读**: 不加锁的 SELECT 查询属于快照读,它是基于 MVCC 实现的非阻塞读操作。快照读不会直接读取最新的数据版本,而是根据 Read View 判断哪些版本对该事务可见并返回相应版本的数据[^2]。 - **当前读**: 加锁的 SELECT 查询或者涉及索引范围扫描的操作称为当前读。当前读总是读取最新的数据版本,并会对所读取的数据施加共享锁或排他锁,因此它不属于 MVCC 的范畴[^2]。 --- #### 如何解决隔离级别的问题 MVCC 主要应用于 RC(Read Committed)和 RR(Repeatable Read)两种隔离级别,在这两种模式下可以通过一致性的快照读避免以下问题: 1. **脏读**: 如果事务 A 修改了一条记录但尚未提交,其他事务无法读取未提交的状态,因为它们只会查看已经提交的版本[^1]。 2. **不可重复读**: 在 RR 隔离级别下,同一个事务多次读取同一条记录的结果是一致的,这是因为每次查询都会使用相同的 Read View[^1]。 3. **幻读**: 对于快照读而言,由于 MVCC 提供的是逻辑上的快照而非物理锁定,所以可以有效防止幻读现象的发生。然而需要注意的是,对于当前读场景下的幻读问题仍然需要借助间隙锁等手段加以处理。 --- #### 性能优化特点 相比传统的悲观锁策略,MVCC 显著提高了系统的吞吐量和响应速度。其主要原因在于大多数只读型工作负载无需等待写入完成即可继续运行,减少了因资源竞争而导致的延迟[^2]。 ```sql -- 示例代码展示如何触发快照读 vs 当前读 SELECT * FROM table WHERE id = 1; -- 快照读 SELECT * FROM table WHERE id = 1 FOR UPDATE; -- 当前读 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值