对于Mysql更新的一些思考
Innodb简要架构是怎么样的?

InnoDB内存结构包含哪些核心组件?
(1)缓冲池(Buffer Pool):缓存数据页和索引页,加速查询操作,避免每次查询都需要进行磁盘随机IO(优化磁盘IO随机读)。
(2)写缓冲区(Change Buffer):写数据时,当数据不在缓冲池中,将数据直接写入写缓冲区中,数据不写入磁盘数据页(优化磁盘随机写)。
(3)日志缓冲区(log Buffer):redo log,binlog都先写入到日志缓冲区,然后再追加写入到磁盘日志文件中,主要的目的是把磁盘随机IO写优化成磁盘批量写和顺序写(磁盘顺序写的性能要比随机写高非常多)。
(4)自适应哈希索引:目的是提升InnoDB性能,加速读请求,减少索引查询的寻路路径。
InnoDB各个日志文件的作用?
redo log:重做日志,主要记录已提交的事务操作日志,包含一些系统操作,数据操作日志,核心作用是safe-crash(异常重启后的数据恢复),底层数据结构是一个环形数组,默认大小为4G,无法一直无限扩容。
binlog:归档日志,归档数据库各个时刻的数据,主要用于主从复制和数据备份,恢复,可以无限扩容
undo log:回滚日志,记录了各个事务id对应的数据状态,主要用于事务回滚和MVCC版本数据回查
我们来分析一个更新操作流程:

一次更新操作,我们需要重点关注的点:
一、数据是如何更新到缓冲池中?更新后的缓冲池数据(脏页)是如何持久化到磁盘中?


(1)查找内存缓冲区中是否待更新数据行,插入数据的话查看是否存在待插入的页。
(2)如果待更新数据存在内存缓冲区中,直接更新缓冲区中的记录行(该记录页变成脏页)。
(3)如果待更新数据不在内存缓冲区中,方式一:将磁盘中的改行数据读取到缓冲区,并且将数据更新为最新数据。方式二:将更新操作缓存在写缓冲区中,当下次读取该记录时,从磁盘中把数据读取到内存缓冲区(pool buffer)中,并且通过写缓冲区(write pool buffer)的记录将缓冲区中的记录更新为最新值。
经过上述分析知道,innodb更新操作核心思想是将磁盘随机IO优化成内存缓冲区操作,让缓冲区中的数据跟磁盘数据短暂不一致(脏页),然后再异步把数据持久化到磁盘中。
思考一个问题:写完change Buffer时数据库宕机了,重启之后change Buffer内存中的数据丢失了,这时岂不是会出现更新丢失的情况?
其实从上图我们可知,写入change Buffer内容也会记录日志到redo log中,所以数据库重启后,可以通过redo log来恢复change Buffer中的数据
脏页是什么时候刷新到磁盘中?
(1)系统空闲时期,会主动进行脏页刷入磁盘的操作,将脏页数据更新到磁盘数据空间,清楚内存空间,并且清除对应的redo log。
(2)内存缓冲区空间不足时,更新操作会先触发脏页刷盘操作来释放足够的内存缓冲区空间,再进行更新操作。
(3)redo log空间不足时,会触发脏页刷盘操作。释放redo log空间来执行新的更新操作。
(4)数据库主动关闭时,会进行脏页刷盘操作。
通过上诉分析我们可以知道,如果内存缓冲区满了或者redo log文件空间满了,都会影响客户端的写请求,因为在写请求执行之前都需要通过脏页刷盘来释放出足够的空间来执行本次更新操作。所以innodb会通过一定的策略来控制缓冲区和redo log文件空间有足够的闲余空间来执行客户端请求,通过一定的参数来控制缓冲区的脏页占比不会超过75%(默认配置),通过配置参数来控制redo log有足够的空间来写入新增日志,通过配置主机的IOPS来评估磁盘的IO性能,从而控制IO的频率和IO读写的数据量。
浙公网安备 33010602011771号