mysql MVCC Undo Redo

文章目录

  • mysql MVCC
    • 系列文章
    • MVCC是什么
    • MVCC逻辑流程
      • 数据准备
      • 插入
      • 删除
      • 修改
      • 查询
    • Undo log
      • 快照读
      • 当前读
    • Redo Log
      • Redo Log 其他知识点
    • 参考

mysql MVCC

系列文章

  • mysql 性能优化 | 第一篇 mysql B+Tree
  • mysql 性能优化 | 第二篇 MySql Myisam和innodb对比 索引优化建议
  • mysql 性能优化 | 第三篇 mysql存储引擎
  • mysql 性能优化 | 第四篇 mysql数据库的隔离级别
  • mysql 性能优化 | 第五篇 mysql 表锁 行锁
  • mysql 性能优化 | 第六篇 mysql MVCC Undo Redo
  • mysql 性能优化 | 第七篇 mysql 执行路径 执行计划 慢查询
  • mysql 性能优化 | 第八篇 mysql 配置优化

MVCC是什么

Multivesion concurrency control(多版本并发控制)

并发访问(读或写)数据库时,对正在事务内处理的数据做多版本的管理。以达到用来避免写操作的阻塞,从而引发读操作的并发问题。

MVCC逻辑流程

数据准备

user表

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(40) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '谢**');
INSERT INTO `user` VALUES ('2', '李**');
INSERT INTO `user` VALUES ('3', '张**');
INSERT INTO `user` VALUES ('4', '王**');

插入

数据库表的隐藏列

  • DB_TRX_ID:数据行的版本号
  • DB_ROLL_PT:删除版本号
    mysql MVCC Undo Redo_第1张图片
    插入数据,假设系统的事务ID号从1开始
#假设系统的事务ID号从1开始
begin; -- 拿到系统的全局事务ID=1
INSERT INTO `user` VALUES ('1', '谢**');
INSERT INTO `user` VALUES ('2', '李**');
commit;

插入数据之后
mysql MVCC Undo Redo_第2张图片

删除

拿到系统的全局事务ID=2

begin; -- 拿到系统的全局事务ID=2
delete from user where id =2;
commit;

删除之后
mysql MVCC Undo Redo_第3张图片

修改

拿到系统的全局事务ID=3

begin; -- 拿到系统的全局事务ID=3
update user set name = '谢*1' where id =1;
commit;

修改之后
mysql MVCC Undo Redo_第4张图片

查询

拿到系统的全局事务ID=4

begin; -- 拿到系统的全局事务ID=4
select * from user;
commit;

mysql MVCC Undo Redo_第5张图片

数据查询规则(同时满足下面两个条件)

  1. 查询数据行版本早于或等于当前事务版本的数据行

    确保事务读取的行,是在事务开始前一直存在的,或者是事务自身插入和修改过的

  2. 查找删除版本号为null,或者大于当前事务版本号的记录

    确保取出来的行记录在事务开启之前没有被删除

Undo log

Undo log 是什么:

undo意为取消,以撤销操作为目的,返回指定摸个状态的操作

undo log指事务开始之前,在操作任何数据之前,首先将需要操作的数据备份到一个地方

Undo Log实现事务原子性:

事务处理过程中出现了错误或者用户执行了ROLLBACK语句,mysql可以利用Undo Log中的备份将数据恢复到事务开始之前的状态

Undo Log在mysql innodb存储引擎中用来实现多版本并发控制

Undo Log实现多版本并发控制:

事务未提交之前,Undo保存了未提交之前的版本数据,Undo中的数据可作为数据旧版本快照供其他并发事务进行快照读取

mysql MVCC Undo Redo_第6张图片

  • 事务1修改user表中记录,mysql会将user表中的这条记录备份到Undo buffer
  • 如果rollback,mysql会重新将Undo buffer中的这条记录写回到user表中
  • 同时如果多个事务来读取这条记录,会从Undo buffer中读取这条记录(称为这条记录的快照)

快照读

sql读取的数据是快照版本,也就是历史版本,普通的select就是快照读

innodb快照读,数据的读取将由cache(事务修改过的数据)+undo buffer(备份原本数据)两部分组成

当前读

sql读取的数据是最新版本。通过锁机制来保证读取的数据无法通过其他事务进行修改

udpate/delete/insert/select…lock in share mode/select…for update都是当前读

Redo Log

Redo Log是什么

Redo(重做),以恢复操作为目的,重现操作

Redo Log 指事务操作的任何数据,将最新的数据备份到一个地方(Redo Log)

Redo Log持久

不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo中。具体的落盘策略可以进行配置

Redo Log是为了实现事务的持久性而出现的产物

Redo Log实现事务的持久性

防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的未入磁盘数据进行持久化这一特性

mysql MVCC Undo Redo_第7张图片

  • 一、事务开始

    1. 当事务修改user表中的数据

    2. mysql会将新的修改之后的数据备份到Redo buffer中(这个过程是实时发生的,并不需要commit)

  • 二、事务提交

    1. 事务commit之后,数据并不是直接持久化到user.IDB

    2. 当数据进入到Redo Log中,mysql会认为已经commit,通过这种方式可以提交mysql的性能(异步化处理),如果一直同步的写入磁盘,大量并发随机IO会造成数据库压力过大

Redo Log 其他知识点

  • 指定Redo log 记录在{datadir}/lb_logfile&ib_logfile2 可通过innodb_log_group_home_dir配置指定目录存储

  • 一旦事务成功提交且数据持久化落盘之后,此时Redo log中对应事务数据记录就会失去意义,所以Redo log的写入是日志文件循环写入的

  • 指定Redo log日志文件组中的数量innodb_log_files_in_group默认为2

  • 指定Redo log每一个日志文件最大存储量innodb_log_file_size默认48M

  • 指定Redo log在cache/buffer中的buffer池大小innodb_log_buffer_size默认16M

  • Redo buffer持久化Redo log的策略,innodb_flush_log_at_trx_commit

    • 取值0,每秒提交Redo buffer–> Redo log OS cache --> flush cache to disk[可能丢失一秒内的事务数据]
    • 取值1(默认值),每次事务提交执行Redo buffer --> Redo log OS cache --> flush cache to disk[最安全,性能最差]
    • 取值2,每次事务提交执行Redo buffer --> Redo log OS cache 再每隔一秒–> flush cache to disk

参考

腾讯课堂–咕泡学院–seven老师–mysql性能优化

你可能感兴趣的:(数据库,mysql,性能优化)