MySQL中的MVCC

MySQL中的MVCC

作用

MVCC在MySQL中主要用于解决事务的隔离性, 具体来说, 不同的事务在同一时间点可以看到数据库不同的时间点快照, 而不会被其他事务的修改所影响, 主要是为了减少锁的使用, 提升系统的并发能力.

实现

  1. TxID​: 事务的ID, 一个递增的值, 值越大表示发生的时间越短.

  2. LastPtr​: 指向之前的版本

  3. ReadView​: 对于一个事务的一个操作而言, 一个ReadView​包含以下部分: CurrentTxId, RunningTX, MaxTX

    • CurrentTxId: 表示当前的事务的ID
    • RunningTX: 表示当前同时执行的事务ID
    • MaxTX: MAX(RunningTX)

​ReadView​

事务执行的某一步, 此时获取到了Record, 存在以下可能性

  • Record.TxID <= CurrentID, 表示是在自己前的事务生成的, 数据一定可见

  • Record.TxID >= MaxTX, 表示是将来可能执行的事务, 数据一定不可见: Record = Record.LastPtr

  • min(RunningTX) <= Record.TxID < MaxTX, 这部分稍微讨论下

    a. 如果TxID IN​ RunningTX中, 表示这个事务由未提交事务生成, 不可见

    b. 如果TxID NOT IN​RunningTX中, 表示这个事务由已提交事务生成, 可见

MVCC与隔离级别的关系

隔离级别

隔离级别

  1. 读未提交: 还没提交时, 更改就会影响到其他的事务

    效果最差, 事务A开启后, 做修改, 其他事务可以读到A的修改, 导致判断失误.

    读操作 + lock in share mode;

  2. 读提交: 提交之后, 其他事务才能看到更改

    总是获取最新的commited的日志

    只有在A提交之后, B才能查到最新的数据.

    所以多个事务完成后, 可能导致B查询的数据是变化的,

    所以读提交, 是不可以重复读的.

  3. 可重复读: 一个事务在执行过程中, 总是跟这个事务启动时看到的数据是一致的

    指向事务开始时的commited的日志

    B读取的数据总是和自己启动时的数据是一致的

    解决方案

    • 乐观锁

      新添加一个字段version

      version 和 查询数据保存在一起

      如果版本不一致, 等待重试.

    • 悲观锁

      对行加锁

      update Table SET a = a + 1 where b =1;

      这时候不会再读版本数据, 会使用最新的数据.

  4. 串行: 无冲突

    完全无冲突, 效率极差, 对并发事务支持非常差

从这个角度我们来看事务隔离级别会有一些不同的感受

  1. 读未提交, 不创建ReadView, 直接读取当前行的当前版本数据, 不考虑任何版本相关信息.
  2. 读提交, 在每个语句执行时, 都创建一个ReadView, 总是能够获取到最新的已提交数据.
  3. 可重复读, 只使用事务开始时创建的ReadView

MVCC与Undo-log的关系

Undo log

和实际操作相反的操作

如果insert, 写入delete

如果update, 写入rollback

如果delete, 写入update(delete 是一种特殊的update, 会将行标记为删除, 实际上是一种update)

为了保证事务的原子性和持久性 ACID: 原子性, 一致性, 隔离性, 持久性

如果事务全部成功, undo log为了保证数据成功会将备份数据页覆盖掉

如果事务有失败, 导致事务回滚, 那么会从undo log中取出备份数据页并且写回

因为事务的执行是线性的, 所以undo log 的写入在正常执行的时候也是线性的

而且undo log是写入文件的, 在掉电之后, 可以通过undo log复原事务前的数据, 保证数据的持久性

  • 数据一致性:MVCC允许多个事务看到同一数据的不同版本。Undo Log中保存的数据版本是实现这种多版本数据一致性的关键。
  • 回滚操作:当一个事务需要回滚时,MVCC需要确保所有数据可以回到事务开始之前的状态。Undo Log记录了足够的信息来撤销一个事务所做的改变。
  • 事务隔离级别:不同的隔离级别对应于不同的一致性需求。MVCC通过Undo Log提供的历史数据版本来实现这些隔离级别,比如可重复读(REPEATABLE READ)和读已提交(READ COMMITTED)。
posted @ 2024-03-25 11:32  pDJJq  阅读(6)  评论(0编辑  收藏  举报