龙空技术网

一次吃透MVCC原理,让MySQL并发性能飙升

程序员宝妹儿 603

前言:

现在你们对“mysql并发能力”大致比较珍视,咱们都需要分析一些“mysql并发能力”的相关文章。那么小编在网上网罗了一些有关“mysql并发能力””的相关资讯,希望看官们能喜欢,兄弟们快快来了解一下吧!

在 MySQL 中,MVCC (多版本并发控制)主要解决并发访问数据库带来的一系列问题。

例如,读写之间阻塞的问题、减少死锁的发生、解决一致性读(快照读)的问题。

MVCC 可以在尽量减少锁使用的情况下,用更高效、更好的方式去处理读写冲突,极大提高了数据库并发性能。

本篇主要深入理解 MVCC(多版本并发控制)原理。

PS.

刚结束的 Binlog 系列,宝子们的反馈还不错,例如:例如:binlog从基础到精通系列图解bin log、redo log及undo log区别等,宝妹儿已将内容更新到《MySQL 大厂高频面试题大全》PDF了,方便系统学习、面试通关。

《MySQL 大厂高频面试题大全》PDF,已收录100+道真题,一共78页,近30000字,文末自取。

吃透它,足以应付MySQL面试。

01

什么是 MVCC

MVCC ,即多版本并发控制,全拼 Version Concurrency Control 。

MVCC 为每个事务创建多个数据版本,每个版本对应一个特定时间点的数据库状态,不同事务可以基于各自的时间点来进行读取和写入操作,而不会相互干扰。

02

什么是当前读、快照读?

在深入MVCC 前,有必要先了解下 MySQL InnoDB 的当前读和快照读。

当前读和快照读是 MVCC 机制下的两种不同读取数据的方式,分别适用于不同的应用场景。

当前读(Current Read)

当前读是指事务在读取数据时,要读取最新提交的数据版本。当前读可以读取其他事务已经提交的数据,如果当前事务有未提交的修改,也会读取自己所做的修改,可能读取到未提交的数据。当前读适用于需要读取最新数据状态的场景,例如,对账户余额的实时查询。需要注意的是,在并发环境下,当前读可能会引发一致性问题。

快照读(Snapshot Read)

快照读,又称为一致性读,是指事务在读取数据时,会读取一个事务开始时的数据版本,即创建事务时的快照。快照读只会读取已提交的数据版本,不会读取其他事务未提交的数据。快照读适用于需要事务隔离和数据一致性的场景。例如,在事务内部进行多次读取操作。快照读能够提供事务开始时的数据一致性视图,避免了并发冲突和未提交数据的影响,但可能不够实时。

主要根据事务隔离级别和应用需求的不同,来选择适合的读取方式。

03

MVCC 的作用

数据库的三种并发场景是读 - 读、读 - 写、写 - 写。

读 - 读:不存在任何问题,也不需要并发控制;读 - 写:有线程安全问题,事务可能出现隔离性问题,例如脏读、幻读、不可重复读;写 - 写:有线程安全问题,可能存在更新丢失问题。

在 MySQL InnoDB 中,MVCC 主要解决并发访问数据库带来的一系列问题:

读写之间阻塞的问题;减少死锁的发生;解决一致性读(快照读)的问题。

MVCC 支持数据库的不同事务隔离级别,例如读未提交、读已提交、可重复读和串行化。

在多个事务同时读取和修改数据库时,MVCC 可以在尽量减少锁使用的情况下,用更高效、更好的方式去处理读写冲突,即便出现了读写冲突,也可以做到不加锁、非阻塞并发读,极大提高了数据库并发性能。

PS. 脏写最为严重,四种隔离级别都不允许出现脏写,因此没有脏写。

04

MVCC 的实现原理

在 InnoDB 存储引擎为每行数据添加了三个隐藏字段:trx_id、roll_pointer、row_id。

MVCC 的实现主要依赖于这三个隐藏字段、Undo log 及 ReadView。

版本链在每次进行 update 或者 delete 操作时,会将每次的操作详细记录在 undo log 中。

每条 undo log 中,都记录了 rol_pointer 信息,通过 roll_pointer 进行关联,可以构成数据的版本链。

一个记录会被一堆事务进行修改,一个记录中就会存在很多 Undo log。

那对某个事务来说,这么多 Undo log,到底应该选择哪些 Undo log 执行回滚呢?

即,哪个版本可以被事务看到呢?

ReadView 机制 就是用来为事务做可见性判断的,它可以判断版本链中的哪个版本是当前事务可见的。

05

ReadView 机制

5.1 什么是 ReadView

ReadView(读视图)是多版本并发控制(MVCC)中的一个重要概念。

ReadView 用于控制事务读取数据的逻辑视图,确保事务在整个过程中看到一致的数据状态。

它是如何判断的呢?

ReadView 最重要的 4 个部分:

5.2 ReadView 读取规则

用 ReadView 判断哪个版本的数据可读,主要遵循可见性算法。

将要被修改的数据的最新记录中的 DB_TRX_ID(即当前事务 ID)取出来,与系统当前其他活跃事务的 ID 去对比(由Read View维护)。

当被访问版本的 trx_id 属性值:

如果 trx_id = creator_trx_ id ,当前事务在访问自己修改过的记录,则该版本可以被当前事务访问。如果 trx_id < min trx_id,表明生成该版本的事务在当前事务生成 ReadView 前已经提交,故该版本可以被当前事务访问。如果 trx_id > = max _trx_id,表明生成该版本的事务在当前事务生成 ReadView 后才开启,故该版本不可以被当前事务访问。如果min_trx_id <= trx _id<= max_trx_id ,那就需要判断一下 trx_id 属性值是不是在 m_ids 列表中,如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。5.3 ReadView 生成规则

但是,读取已提交 和 可重复读 这两种隔离级别所产生的 ReadViem 是不同的。

在读已提交(READ COMMITTED)的隔离级别下:事务中每次对数据进行 SELECT ,都会生成一个 ReadView。在可重复读( REPEATABLE READ)的隔离级别下:在一个事务中对一行数据第一次进行 SELECT 查询,会生成一个 ReadView,之后事务都将使用该 ReadView 进行数据的读取。

06

总结

通过本文,我们了解并掌握了MVCC 的概念、作用、工作原理等。

MVCC 为每个事务创建多个数据版本,每个版本对应一个特定时间点的数据库状态,不同事务可以基于各自的时间点来进行读取和写入操作,而不会相互干扰,极大提高了数据库并发性能。

MVCC 依赖于InnoDB 下的三个隐藏字段、Undo log 及 ReadView 来实现,在一定程度上实现了 读写并发。

建议收藏备用,划走就找不到啦。

果觉得有用,请顺手【关注+点赞】支持下宝妹儿,拜谢

PS.

本文已收录于宝妹儿精编的 2023版《MySQL 大厂高频面试题大全》PDF。

《MySQL 大厂高频面试题大全》一共78页,34000字,图文并茂,长期持续更新。

吃透它,足以应对 MySQL 面试。

标签: #mysql并发能力