基础
MySQL
MySQL
  • 基础知识
    • MySQL 的安装与配置
      • Windows
        • 安装
        • 配置文件
      • Linux
        • 安装
        • 配置文件
      • docker
      • mysql 配置文件格式
    • MySQL 查询的执行过程
      • MySQL 的客户端/服务器通信协议
      • MySQL 查询优化器
        • 优化器可能选择错误的执行计划
        • MySQL 能够处理的优化类型
          • 优化 COUNT()、MIN() 和 MAX()
          • 预估并转化为常数表达式
          • 提前终止查询
          • 排序优化
      • MySQL如何执行联接查询
    • 事务
      • ACID
      • 隔离级别
      • 死锁
      • 事务日志
      • 两阶段锁定协议
      • 多版本并发控制(MVCC)
  • SQL 优化
    • schema 设计
      • 选择数据类型
        • 整数类型
        • 实数类型
        • 字符串类型
          • VARCHAR 和 CHAR
          • BINARY 和 VARBINARY
          • BLOB 和 TEXT
          • ENUM 和 SET
        • 日期类型
      • 选择标识符
    • 索引
      • HASH 索引
      • B-tree 索引
      • 聚簇索引
      • 覆盖索引
      • 前缀索引和索引的选择性
      • 索引合并
      • 选择合适的索引列顺序
      • 使用索引扫描来做排序
      • 维护索引和表
    • 查询优化
      • 优化 SQL 语句的一般步骤
        • 1. 通过 show status 命令了解各种 SQL 的执行频率
        • 2. 定位执行效率较低的 SQL 语句
        • 3. 通过 EXPLAIN 分析低效 SQL 的执行计划
        • 4. 通过 SHOW PROFILE 分析 SQL
        • 5. 通过 TRACE 分析优化器如何选择执行计划
        • 6. 确定问题并采取相应的优化措施
      • 两个简单实用的优化方法
      • 一个复杂查询还是多个简单查询
      • 常用 SQL 的优化
        • 大批量插入数据
        • 优化 GROUP BY 语句
        • 优化联接查询
        • 优化分页查询
        • 优化 SQL_CALC_FOUND_ROWS
        • 优化 UNION 查询
    • Performance Schema
      • 配置
      • 使用
        • 检查SQL语句
        • 检查预处理语句
        • 语句剖析
        • 检查读写性能
        • 检查内存使用情况
        • 检查变量
    • MySQL线程
    • 复制
      • 概述
        • 复制中的各类文件
        • 三种复制格式
        • 全局事务标识符(GTID)
        • 崩溃后的复制安全
      • 安装
        • 基于二进制日志文件位置的复制
        • 基于GTID的复制
      • 复制拓扑
        • 主动/被动模式
        • 主动/只读池模式
        • 多级复制架构
  • 其他
    • 查询缓存
    • 批量insert
    • MySQL 锁的类型
    • MySQL 的索引有哪些
    • INSERT ... ON DUPLICATE KEY UPDATE Statement
由 GitBook 提供支持
在本页
  1. 基础知识
  2. 事务

多版本并发控制(MVCC)

上一页两阶段锁定协议下一页schema 设计

最后更新于9个月前

MySQL 的大多数事务型存储引擎使用的都不是简单的行级锁机制。它们会将行级锁和可以提高并发性能的多版本并发控制(MVCC)技术结合使用。

可以认为 MVCC 是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。根据其实现方式,不仅实现了非阻塞的读操作,写操作也只锁定必要的行。

MVCC 的工作原理是使用数据在某个时间点的快照来实现的。这意味着,无论事务运行多长时间,都可以看到数据的一致视图,也意味着不同的事务可以在同一时间看到同一张表中的不同数据!

InnoDB 通过为每个事务在启动时分配一个事务 ID 来实现 MVCC,该 ID 在事务首次读取任何数据时分配。在该事务中修改记录时,向 Undo 日志写入一条说明如何恢复该修改的 Undo 记录,并且事务的回滚指针指向该 Undo 日志记录。这就是事务如何在需要时执行回滚的方法。

当不同的会话读取聚簇主键索引记录时,InnoDB 会将该记录的事务 ID 与该会话的读取视图进行比较。如果当前状态下的记录不应可见(更改它的事务尚未提交),那么 Undo 日志记录将被跟踪并应用,直到会话达到一个符合可见条件的事务 ID。这个过程可以一直循环到完全删除这一行的 Undo 记录,然后向读取视图发出这一行不存在的信号。

事务中的记录可以通过在记录的 “info flags” 中设置 “deleted” 位来删除。这在 Undo 日志中也被作为“删除标记”进行跟踪。

值得注意的是,所有 Undo 日志写入也都会写入 Redo 日志,因为 Undo 日志写入是服务器崩溃恢复过程的一部分,并且是事务性的。这些 Redo 日志和 Undo 日志的大小也是高并发事务工作机制中的重要影响因素。

在记录中保留这些额外信息带来的结果是,大多数读取查询都不再需要获取锁。它们只是尽可能快地读取数据,确保仅查询符合条件的行即可。缺点是存储引擎必须在每一行中存储更多的数据,在检查行时需要做更多的工作,并处理一些额外的内部操作。

MVCC 仅适用于 REPEATABLE READ 和 READ COMMITTED 隔离级别。

READ UNCOMMITTED 与 MVCC 不兼容,是因为查询不会读取适合其事务版本的行版本,而是不管怎样都读最新版本。

SERIALIZABLE 与 MVCC 也不兼容,是因为读取会锁定它们返回的每一行。