MVCC多版本并发控制机制

MVCC: Multi Version Concurrency Control
在一个事务中,同一个select多次的结果是一致的,保证其他事务的修改不对当前的数据有印象
这种隔离就是MVCC保证的。
对一行数据的读写操作不会通过加锁互斥,保证隔离,避免频繁加锁互斥
串行化,就是加锁保证的较高隔离性
读已提交,课重复度: 是MVCC机制保证

undo 日志版本链, read view 机制

前提:表的隐藏列

  1. trx_id:: 事务ID ,该行的来源事务ID
  2. roll_pointer:上个历史的记录版本链

1651587029(1).png

  1. 事务中第一次查询会生成当前事务,该查询的一致性视图read-view,视图不在变化
    如果是读已提交会更新
    视图:所有未提交事务ID 的数组, min_id max_id
  2. 比较,就算是这条行记录被修改多次,但是视图记录的事务id以固定
  3. 会根据行的事务id ,判断是不是视图中的Id
  4. 不是就会通过roll_pointer溯源,直到是视图中的ID对应,返回

对于删除的情况:一种特殊的update,trx_id 会更新,该记录的头信息 record header 的deleted_flag = true

只有在具体操作是 才会申请事务ID , 而不是在begin
总结
MVCC机制的实现就是通过read-view机制与undo版本链比对机制,
使得不同的事务会根据数据版本链对比规则读取同一条数据在版本链上的不同版本数据。

Innodb引擎SQL执行的BufferPool缓存机制

Mysql%E8%AF%AD%E5%8F%A5%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B.png

步骤:

  1. 根据id 加载Id所在的那一页 到 buffer pool
  2. 把旧值,写入undo文件,回滚用
  3. 执行update更新的是buffer pool 的记录
  4. 写入redo日志,就是待update, redo log buffer
  5. 把redo日志写入磁盘 Io ,
  6. 准备提交事务,把binlog 写入磁盘
  7. redo中写入commit标记,保证redo记录与bin log一致
  8. buffer-pool数据写入磁盘

为什么Mysql不能直接更新磁盘上的数据而且设置这么一套复杂的机制来执行SQL了?

因为来一个请求就直接对磁盘文件进行随机读写,然后更新磁盘文件里的数据性能可能相当差。
因为磁盘随机读写的性能是非常差的,所以直接更新磁盘文件是不能让数据库抗住很高并发的。
Mysql这套机制看起来复杂,但它可以保证每个更新请求都是更新内存BufferPool,然后顺序写日志文件,同时还能保证各种异常情况下的数据一致性。
更新内存的性能是极高的,然后顺序写磁盘上的日志文件的性能也是非常高的,要远高于随机读写磁盘文件。
正是通过这套机制,才能让我们的MySQL数据库在较高配置的机器上每秒可以抗下几干甚至上万的读写请求。

执行流程

随机IO

顺序IO