0
点赞
收藏
分享

微信扫一扫

多版本并发控制(MVCC)

最后的执着 2022-05-02 阅读 44
mysql

 多版本并发控制 (MVCC)

  • MVCC (multi-version concurrency control) 多版本并发控制。
  • MVCC 是一种并发控制的方法。
    • 在数据库管理系统中,实现对数据库的并发访问,主要是为了提高数据库的并发性能。InnoDB 引擎支持 MVCC,因为 myIsam 不支持事务所以也不支持 MVCC。
    • 在编程语言中实现事务内存。
    • 为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务的时间戳关联,读操作只读该事务开始前的数据库的快照。

InnoDB 的 MVCC 机制的实现主要是为了提高数据库的并发性能,用更好的不加锁的方式去处理读-写冲突,做到即使有读写冲突时,也能不加锁非阻塞的并发读。

MVCC 机制在读已提交 RC 和可重复读 RR 的隔离级别下起作用。

不加锁的读是快照读,加锁的读是当前读,所以 MVCC 的并发读是快照读。

  • 快照读
    • 是基于多版本并发控制即 MVCC机制,既然是多版本,那么快照读读到的数据不一定是当前最新的数据,有可能是之前历史版本的数据。
    • 如下的操作是快照读:不加锁的 select 操作(事务级别不是串行化,串行化的是当前读)
  • 当前读
    • 它读取的记录都是数据库中当前的最新版本,会对当前读取的数据进行加锁,防止其他事务修改数据,这种锁是一种悲观锁。
    • 如下操作都是当前读:
      • select lock in share mode (共享锁)
      • select for update (排他锁)
      • update (排他锁)
      • insert (排他锁)
      • delete (排他锁)
      • 串行化事务隔离级别

MVCC 的两种实现方式

  • 将数据记录的多个版本保存在数据库中,当这些不同版本的数据不再需要时,垃圾收集器回收这些记录。如:postgresql(VACUUM)
  • 数据库保存最新版本数据,旧版本的数据存储在单独的位置。比如: SQL Server(tempdb),Oracle/InnoDB(undo log)

MVCC 的好处

  • 提高了数据库的并发性能
  • 避免了加锁操作
  • 降低了开销
  • 通过多版本解决了脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题(更新的问题可以配合锁机制比如乐观锁悲观锁使用)
  • MVCC + 悲观锁/悲观锁 ,这种组合的方式最大程度的提高数据库并发性能,并解决读写冲突(用 MVCC 解决),和写写冲突导致的问题(用乐观锁/悲观锁来解决)。

InnoDB 实现 MVCC

它的实现依赖于以下 3 点:

  • 记录中的 3 个隐式字段
  • undo log
  • Read View

3 个隐式字段:

数据库的每行记录除了我们自定义的字段外,还有数据库隐式定义的 DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID 等字段。

  • DB_TRX_ID: 6byte,最近一次修改或插入操作的事务 ID,记录创建这条记录的 ID 或者最后一次修改这条记录的事务 ID。
  • DB_ROLL_PTR: 7byte,回滚指针,指向这条记录的上一个版本(存储于 rollback segment 里),用于配合 undo log 指向上一个旧版本。
  • DB_ROW_ID: 6byte,隐含的自增 ID (隐藏主键),如果数据表没有主键,InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引。有主键就是主键 ID。

undo log

undo log 保存了记录修改前的镜像。有以下两种 undo log

  • update undo log
    • 事务在进行 update 或 delete 时产生的 undo log;
    • 不仅在事务回滚时需要,在快照读时也需要;
    • 只有在快速读或事务回滚不涉及该日志时,对应的日志才会被 purge 线程统一清除。purge线程的作用,是清理回滚段(undo segment)的同时,把被删除的行也从数据块中清除,实现真正的物理上的删除。
  • insert undo log
    • 代表事务在 insert 即插入新记录时产生的 undo log;
    • 只在事务回滚时需要;
    • 在事务提交或回滚后可以被立即丢弃。

Read View

  • 可以理解为,对数据在每个时刻的状态,拍成照片记录下来,如果之后想要获取某时刻的数据,获取的还是原来照片上的数据,是不会变的。
  • 是事务开启时当前时刻所有活跃事务的一个集合,这个数据结构中记录并维护了当前活跃事务的 ID, 包括 Read View 中事务最大的 ID 和最小的 ID。
  • 还可以理解为一个版本链的集合,是 InnoDB 为实现 MVCC 所使用的内部快照。

RR (可重复读)隔离级别下会在第一次查询时创建 Read View。

RC (读已提交)隔离级别下会在每次查询时创建 Read View。

Read View 的好处

Read View 主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个 Read View 读视图,把它当做条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的 undo log 里面的某个版本的数据。

举报

相关推荐

0 条评论