MVCC(多版本并发控制)在MySQL中是如何工作的?

狼影
发布: 2025-09-11 13:13:01
原创
448人浏览过
MVCC通过维护数据多版本和读视图机制,在InnoDB中实现非阻塞读,提升并发性能。它利用undo log存储历史版本,结合事务ID和回滚指针判断数据可见性,避免脏读与不可重复读。该机制在READ COMMITTED和REPEATABLE READ隔离级别下发挥作用,减少读写冲突,而在READ UNCOMMITTED中被绕过,SERIALIZABLE中被锁机制替代。

mvcc(多版本并发控制)在mysql中是如何工作的?

MVCC在MySQL中,尤其是在InnoDB存储引擎里,本质上是一种非阻塞的读操作机制。它通过维护同一行数据的多个版本,让读操作可以读取到事务开始时的数据快照,而写操作则可以同时进行,互不干扰。这样一来,就极大地提升了数据库的并发性能,减少了读写之间的锁竞争,让用户体验到更流畅的数据访问。说白了,它让数据库在处理大量并发请求时,能像一个高效的多任务处理者,而不是一个排队等候的单线程程序。

解决方案

要理解MVCC是如何在MySQL中工作的,我们需要深入到InnoDB的一些核心机制。在我看来,这套设计精妙而实用。

当一个事务对某行数据进行修改(UPDATE或DELETE)时,InnoDB并不会直接覆盖或删除原始数据。相反,它会做几件事:

  1. 创建新版本: 它会为被修改的行创建一个新的版本。这个新版本包含了修改后的数据。
  2. 记录事务ID: 每个行版本都会关联一个隐藏的事务ID(
    DB_TRX_ID
    登录后复制
    ),记录了是哪个事务创建或最后修改了它。
  3. 指向旧版本: 另一个隐藏列是回滚指针(
    DB_ROLL_PTR
    登录后复制
    )。这个指针指向了
    undo log
    登录后复制
    中的一个记录,该记录存储了当前行版本修改前的旧数据。通过这个指针,我们可以沿着链条追溯到这行数据的所有历史版本。
  4. Undo Log: 这就是关键了。
    undo log
    登录后复制
    不仅用于事务回滚,更是MVCC实现多版本并发控制的核心。每当数据被修改,旧的数据值就会被写入
    undo log
    登录后复制
    。这样,即使数据被更新了,其他事务仍然可以通过
    undo log
    登录后复制
    找到并读取到它们需要看到的旧版本数据。

当一个

SELECT
登录后复制
语句(在特定的隔离级别下)被执行时,它会获得一个“读视图”(Read View),这可以理解为数据库在那个时间点的一个“快照”。这个读视图包含了当前所有活跃的事务ID列表。然后,InnoDB会根据以下规则来判断哪个行版本对当前的
SELECT
登录后复制
事务是可见的:

  • 如果一个行版本的
    DB_TRX_ID
    登录后复制
    小于读视图中最早的活跃事务ID,这意味着这个版本是在读视图创建之前就已经提交的,所以它是可见的。
  • 如果一个行版本的
    DB_TRX_ID
    登录后复制
    大于读视图中最大的活跃事务ID,那么这个版本是在读视图创建之后才启动的事务修改的,所以它是不可见的。
  • 如果一个行版本的
    DB_TRX_ID
    登录后复制
    在读视图的活跃事务ID列表中,那么这个版本是由一个尚未提交的事务修改的,同样不可见(除非是当前事务自己修改的)。
  • 如果当前版本不可见,InnoDB就会沿着
    DB_ROLL_PTR
    登录后复制
    指向的
    undo log
    登录后复制
    链条,不断回溯,直到找到一个对当前读视图可见的旧版本。

通过这种机制,读事务总能看到一个一致的数据快照,而写事务则可以自由地修改数据,两者之间几乎没有阻塞,极大地提升了数据库的并发处理能力。

MVCC解决了哪些并发问题,与传统锁机制有何不同?

MVCC的引入,在我看来,是数据库并发控制领域的一个里程碑,它巧妙地解决了传统锁机制下的一些痛点。

MVCC解决的并发问题主要包括:

  • 脏读(Dirty Reads)的避免:
    READ COMMITTED
    登录后复制
    REPEATABLE READ
    登录后复制
    隔离级别下,MVCC确保读事务不会看到其他未提交事务的修改。它总是提供已提交的数据版本,或者在
    REPEATABLE READ
    登录后复制
    下提供事务开始时的那个一致快照。
  • 不可重复读(Non-Repeatable Reads)的缓解: 尤其是在MySQL默认的
    REPEATABLE READ
    登录后复制
    隔离级别下,MVCC通过固定事务的读视图,保证了在一个事务的生命周期内,多次读取同一行数据会得到相同的结果,即便这期间有其他事务修改并提交了该行数据。
  • 读写冲突的减少: 这是MVCC最显著的优势之一。传统的锁机制下,读操作(共享锁)和写操作(排他锁)会互相阻塞。而MVCC允许读事务在不加锁的情况下读取数据的旧版本,写事务则只对当前写入的行加排他锁。这样,读写操作可以并行进行,极大地提高了并发度。
  • 幻读(Phantom Reads)的间接处理: 虽然MVCC本身并不能完全阻止幻读(因为幻读涉及的是行的增删,而非修改),但在
    REPEATABLE READ
    登录后复制
    级别下,MySQL结合了间隙锁(Gap Locks)和Next-Key Locks来进一步解决幻读问题。不过,单就MVCC而言,它主要关注的是已有行的版本一致性。

与传统锁机制的不同:

  • 阻塞性: 传统锁机制是“悲观锁”的典型代表,读写操作都会因为锁而互相阻塞,导致并发性能下降。MVCC则是一种“乐观”的并发控制策略,它允许读操作非阻塞地进行,只有在写操作时才需要对具体行加锁。
  • 数据可见性: 锁机制下,读事务只能看到当前已提交的最新数据(如果未被其他事务锁定)。MVCC则能让读事务看到其事务开始时的数据快照,即使之后有新的提交,它也坚持看自己的“旧”版本。
  • 实现复杂性: MVCC的实现比纯粹的锁机制要复杂,因为它需要维护多版本数据(通过undo log),并管理读视图和版本可见性规则。但这种复杂性带来的回报是更高的并发性能。
  • 资源开销: MVCC需要额外的存储空间来保存旧版本数据(undo log),并且需要CPU开销来遍历undo log链条以找到合适的版本。锁机制也有锁管理和死锁检测的开销。两者各有侧重。

在我看来,MVCC的出现,让数据库的并发控制从“排队等候”的模式,转向了“各取所需”的模式,这无疑是其魅力所在。

卡拉OK视频制作
卡拉OK视频制作

卡拉OK视频制作,在几分钟内制作出你的卡拉OK视频

卡拉OK视频制作 178
查看详情 卡拉OK视频制作

MVCC的实现细节中,Undo Log扮演了什么角色?

在MVCC的舞台上,

undo log
登录后复制
绝对是一个不可或缺的幕后英雄,它的作用远不止我们字面上理解的“撤销”那么简单。我个人认为,没有
undo log
登录后复制
,MVCC的诸多精妙设计都将无从谈起。

Undo Log在MVCC中的核心角色包括:

  1. 版本数据的存储库: 这是
    undo log
    登录后复制
    最直接也是最重要的功能。每当InnoDB中的一行数据被修改(
    UPDATE
    登录后复制
    DELETE
    登录后复制
    ),原始数据(修改前的值)并不会立即被丢弃,而是会被记录到
    undo log
    登录后复制
    中。这些被记录下来的旧数据,就构成了行数据的“历史版本”。当一个事务需要读取某个行数据,但当前最新的版本对它不可见时(比如,最新版本是由一个尚未提交的事务修改的,或者是在当前事务启动之后才提交的),数据库就会沿着
    DB_ROLL_PTR
    登录后复制
    (回滚指针)指向的
    undo log
    登录后复制
    链条,回溯到
    undo log
    登录后复制
    中存储的旧版本,直到找到一个对当前事务的读视图可见的版本。
  2. 事务回滚的基石: 当然,
    undo log
    登录后复制
    的本职工作——提供事务回滚的能力——在MVCC中也同样重要。如果一个事务执行到一半需要撤销所有操作(
    ROLLBACK
    登录后复制
    ),数据库就会利用
    undo log
    登录后复制
    中记录的信息,将所有修改过的数据恢复到事务开始前的状态。这保证了事务的原子性。
  3. 提供一致性读(Consistent Read):
    undo log
    登录后复制
    是实现MVCC“一致性读”的关键。一致性读意味着一个事务在读取数据时,会看到一个在它事务开始时就已经存在的数据快照,即使其他事务在这期间修改了数据并提交了。如果当前数据版本不符合这个快照要求,
    undo log
    登录后复制
    就提供了追溯历史版本的能力,让读事务总能看到符合其隔离级别和读视图要求的数据。
  4. 数据清理(Purge)的依据:
    undo log
    登录后复制
    记录的数据并不会永久保存。当一个
    undo log
    登录后复制
    记录不再被任何活跃事务引用(即,没有事务需要读取这个旧版本,也没有事务需要回滚到这个状态),它就可以被清除以回收空间。这个清理过程通常由一个后台的
    Purge
    登录后复制
    线程完成。
    undo log
    登录后复制
    的存在,为数据库判断何时可以安全地删除旧版本数据提供了明确的依据。

可以说,

undo log
登录后复制
就像一个时光机,它存储了数据的“过去”,让不同的事务可以根据自己的时间线去查看相应的数据版本。这使得读写操作能够和谐共存,是InnoDB高并发性能的秘密武器之一。

在MySQL中,哪些隔离级别受益于MVCC,又有哪些不适用?

隔离级别和MVCC的关系,在我看来,是理解MySQL并发控制不可或缺的一环。MVCC并不是对所有隔离级别都“一视同仁”的,它的作用和效果会因隔离级别的不同而有显著差异。

主要受益于MVCC的隔离级别:

  1. READ COMMITTED (RC): 这个隔离级别是MVCC的典型应用场景之一。在
    READ COMMITTED
    登录后复制
    级别下,一个事务的每次
    SELECT
    登录后复制
    查询都会创建一个新的读视图(snapshot)。这意味着,如果其他事务在两次
    SELECT
    登录后复制
    查询之间提交了数据修改,当前事务的第二次
    SELECT
    登录后复制
    可能会看到这些新的提交。MVCC在这里的作用是,它确保了任何
    SELECT
    登录后复制
    查询都只能看到已提交的数据,避免了“脏读”。但由于每次
    SELECT
    登录后复制
    都有新的读视图,它无法避免“不可重复读”。
  2. REPEATABLE READ (RR): 这是MySQL InnoDB的默认隔离级别,也是MVCC发挥最大作用的隔离级别。在
    REPEATABLE READ
    登录后复制
    级别下,一个事务的读视图是在事务开始时(第一次
    SELECT
    登录后复制
    语句执行时)创建的,并且在整个事务的生命周期内保持不变。这意味着,即使其他事务在这期间修改并提交了数据,当前事务的后续
    SELECT
    登录后复制
    查询仍然会看到事务开始时的那个一致快照。MVCC在这里彻底解决了“不可重复读”的问题。结合InnoDB的Next-Key Locks,它还能有效地防止“幻读”。

不适用或较少依赖MVCC来实现读一致性的隔离级别:

  1. READ UNCOMMITTED (RU): 这个隔离级别是最宽松的。它允许一个事务读取其他事务尚未提交的数据,也就是允许“脏读”。在这种情况下,MVCC的机制——即通过
    undo log
    登录后复制
    来查找旧版本以提供一致性视图——就显得不那么重要了,或者说,它被刻意绕过了。数据库会直接读取最新的、可能尚未提交的数据版本,而不会去判断其可见性。显然,这牺牲了数据的一致性来换取最高的并发度(因为几乎不需要等待)。
  2. SERIALIZABLE: 这是最高的隔离级别,它通过强制事务串行执行来避免所有并发问题,包括脏读、不可重复读和幻读。实现
    SERIALIZABLE
    登录后复制
    隔离级别,MySQL通常会通过对所有
    SELECT
    登录后复制
    语句自动添加共享锁(
    LOCK IN SHARE MODE
    登录后复制
    ),或者在
    SELECT
    登录后复制
    语句中使用
    FOR UPDATE
    登录后复制
    FOR SHARE
    登录后复制
    显式加锁。这意味着,读操作也会像写操作一样,通过加锁来阻塞其他事务的写操作,从而保证数据的一致性。在这种情况下,MVCC的多版本机制在提供读一致性方面的作用就被锁机制所取代了。虽然MVCC的底层机制可能仍然存在,但其核心的非阻塞读特性在这里并没有被用于实现隔离。它本质上回到了传统的锁机制来确保串行化。

所以,我们可以看到,MVCC是InnoDB在

READ COMMITTED
登录后复制
REPEATABLE READ
登录后复制
这两个隔离级别下实现高并发和数据一致性的核心技术。而在
READ UNCOMMITTED
登录后复制
,它被“忽略”;在
SERIALIZABLE
登录后复制
,它被更严格的锁机制所“替代”,以达到更高的隔离要求。理解这一点,对于我们选择合适的隔离级别,优化数据库性能至关重要。

以上就是MVCC(多版本并发控制)在MySQL中是如何工作的?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号