MySQL之MVCC原理解析

Innodb MVCC
一。mvcc是什么?
MVCC: Multiversion concurrency control (多版本并发控制)
并发访问(读或写)数据库时,对正在事务内处理的数据做 多版本的管理。以达到用来避免写操作的堵塞,从而引发读操 作的并发问题。

二。MySQL中mvcc插入逻辑流程
Innodb 如何实现的mvcc呢?
假如一张表user有三个字段id,name,age,MySQL会默认的给每行后面加上一些隐藏的列,跟mvcc相关的有两列:DB_TRX_ID(数据行的版本号:本行数据入库时的版本号),DB_ROLL_PT(删除版本号)。这两列的值怎么来呢?开启一个事务(整个InnoDB的引擎有一个事务管理的地方,即全局事务id,自增型的),给表中插入两条数据,此时数据行的版本号就是全局事务id。
删除:假如当前进行了很多次的事务操作,要删除其中一条数据,MySQL就会找到要删除的这条数据,并把它的删除版本号记录为当前的事务id号。
修改:先将命中行的数据行copy一份到新的数据行,新的数据行的版本号是当前事务的id,将原行数据的删除版本号的值设置为当前事务的id。
查询:要同时满足两条规则,一是查找数据行版本号早于当前事务版本的数据行,即行的系统版本号小于等于当前事务的系统版本号,这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的,而是查找删除版本号要么是Null,要么大于当前事务版本号的记录,确保取出来的行记录在事务开启之前没有被删除。
解决不可重复读问题的不是mvcc,而是undo log和redo log。
三。undo log
Undo Log 是什么: undo意为取消,以撤销操作为目的,返回指定某个状态的操作 undo log指事务开始之前,在操作任何数据之前,首先将需操作的数据备份到一个地方 (Undo Log)。
为了解决事务的原子性和快照读
在这里插入图片描述

undo的两个作用:
UndoLog是为了实现事务的原子性而出现的产物
Undo Log实现事务原子性: 事务处理过程中如果出现了错误或者用户执行了 ROLLBACK语句,Mysql可以利用Undo Log中的备份 将数据恢复到事务开始之前的状态
UndoLog在Mysql innodb存储引擎中用来实现多版本并发控制
Undo log实现多版本并发控制: 事务未提交之前,Undo保存了未提交之前的版本数据,Undo 中的数据可作为数据旧版本快照供 其他并发事务进行快照读
在这里插入图片描述
示例:

IBD文件存放在磁盘中,undo放在磁盘的表空间里面,MySQL把磁盘中的数据加载到缓冲区里面,我们要操作的数据全部在缓存区里面,操作完以后,MySQL可以通过一些策略将缓冲区里面的数据持久化到ibd文件里面去。undo buffer可以通过一定的策略定时的写到undo log里面去。
undo log的工作原理:把buffer区的数据先备份。
一旦事务提交了,undo在这里就没有意义了,通过Mvcc读。

当前读,快照读
快照读:
SQL读取的数据是快照版本,也就是历史版本,普通的SELECT就是快照读
innodb快照读,数据的读取将由 cache(原本数据) + undo(事务修改过的数据) 两部分组成
当前读:
SQL读取的数据是最新版本。通过锁机制来保证读取的数据无法通过其他事务进行修改
UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE都是
当前读
在整个InnoDB引擎里面,通过快照读的mvcc解决幻读问题,通过当前读的next-key(临键锁)解决幻读问题。
如果在写数据的时候,不让其他人去读,那么并发性能会收到影响。如果完全按照mvcc的方式的话,读取的数据有可能和预期的结果不一致。
update的时候上了X锁,就会把数据拷贝到undo logI里面, select的时候读快照,快照就是通过读Undo日志返回数据。

四。redo log
Redo Log 是什么: Redo,顾名思义就是重做。以恢复操作为目的,重现操作; Redo log指事务中操作的任何数据,将最新的数据备份到一个地方 (Redo Log)

在这里插入图片描述

Redo log的持久: 不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo 中。具体 的落盘策略可以进行配置
作用:
RedoLog是为了实现事务的持久性而出现的产物
Redo Log实现事务持久性: 防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的未入磁盘数据进行持久化这一特性。
在这里插入图片描述
如果teacher.ibd有一个Update的操作加载到cache里面,update之后,没有提交,此时会立刻把这个数据更新到redo buffer里面,按照一定的策略写到redo log里面,(cache里面的数据相当于数据表在内存中的映射,每次提交的时候并不是把所有的数据都能刷到硬盘上,这样的话在commit的时候效率就会很低,因为要做很多次随机的io(redo buffer->log是顺序IO,log->ibd是随机IO,但是已经不影响效率了。)。每次cache里面的数据做了更新后,就会迅速更新到redo buffer里面,只要把redo buffer里面的数据写到了redo log里面,MySQL引擎就会认为此次事务提交成功了(持久化了),不会在乎脏页有没有刷到磁盘,脏页刷到磁盘的动作是在后台慢慢做的,(如果通过随机IO直接把数据包括脏页持久化到磁盘了,那么redo也就没有意义了,)但是数据并不一定已经刷到了磁盘里面。如果发生断电事故,只要redo buffer的数据写到了redo log里面,当再次重启的时候,MySQL会基于redo log日志进行数据的重做,会把提交过的数据全部恢复到teacher.ibd文件里面)。

指定Redo log 记录在{datadir}/ib_logfile1和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操作
建议取值2,MySQL挂了,损失一次事务数据,操作系统挂了,损失1秒事务数据。

上一篇:mysql-影响MySQL索引的因素
下一篇:mysql执行计划详解

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值