前言
上期根据一条查询语句查询流程分析MySQL的整体架构。同样,本期也使用一条查询SQL语句来做引子。可以肯定的是,查询语句执行的流程更新语句同样也会执行。
因此本期的着重点就不在MySQL架构图上,文章标题也给出了大家重点,就是要了解redo log、binlog。
一、redo log
第一步,创建一个表 user,主键是 id,下面是创建语句。
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `age` tinyint(4) NOT NULL, `time` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
插入一条数据
insert into user (`name`,`age`,`time`) values ("咔咔","25",unix_timestamp(now()))
若要将插入的这条数据的age改为26,则需要执行语句
update user set age = 26 where id = 1;
第一期文章中提到一条查询语句的执行流程,该流程与更新语句相同。这里将那幅图拿过来在熟悉一下。
每个模块的功能可以回到第一期文章去查看。
在MySQL8.0中redo log、binlog日志文件都位于/var/lib/mysql此目录下,如图
文件名为ib_logfile的是重做日志,undo开头的就是回滚日志,对于回滚日志后期进行详细的讨论。
redo log(重做日志)是实现事务持久性必备要素,当一个事务提交后,并非直接修改数据库的数据,而是首先保证在 redo log中记录相关的操作。
Innodb存储引擎中的redo log大小是固的,上图显示配置了一组两个文件,每个文件大小默认为48M,使用innodb_log_file_size参数来控制单个文件大小,在MySQL5.6.8以及之后版本都默认为48M。
然后redo log可以记录48M的操作,redo log是一个闭环的循环写。所设定的文件个数和文件大小不再增加。
write pos将记录当前位置,同时向后移动,在ib-log-file-3文件末尾后,然后返回ib-logfilg-0文件开始写。
check point记录的是当前擦除的位置,要使文件循环写入,必须一边擦除。清楚数据的前提是要将记录更新到数据文件。
上面的绿色部分就是可写的部分,假设如果 writepos追上了 checkpoint,那该怎么办?
你必须理解write pos的推进是因为在执行更新操作,这样就不能再执行更新操作,直到记录更新到数据文件,然后check point进行擦除后才可以继续执行更新操作。
对于innodb_log_file_size的设置也是有一些计算规则的,下面将为你介绍。
若innodb_log_file_size设置太小,将导致redo log文件频繁切换,频繁的触发数据库的检查点(check point),导致记录更新到数据文件的次数增加,从而影响IO性能。
同样,如果有一个大的事务,并且所有 redo log日志都已写满,但是还没有完成,将导致日志无法切换,从而导致 MySQL直接堵死。
innodb_log_file_size设置太大,虽然极大地提高了 IO性能,但是在 MySQL重启或宕机时,恢复时间会因为 redo log文件过大而延长。而这种恢复时间通常是无法控制的。
在设置合理的redo log大小和数量后,Innodb能够保证,即使数据库发生异常重启,以前提交的记录也不会丢失,这一点也称为crash-safe。
在这里,对crash-safe的理解先不提及它是什么,后面的文章会让你明白。
二、如何根据项目情况设置innodb_log_file_size
对于参数innodb_log_files_in_group设置3~4个就够用了,不用进行优化。
着重讨论innodb_log_file_size的大小设置或优化设置。
在 MySQL8.0之前,通常是计算在一段时间内生成的事务日志(redo log)大小,而 MySQL日志文件最小应承载一小时的业务日志量。
此处的一段时间必须视自己的业务情况而定,外界有用1分钟的日志量也有1小时的日志量来计算。
首先看一下 MySQL客户端的一个命令 pager,在 MySQL日常操作中,通过设置 pager的显示方式,可以大大提高工作效率。
目前,要查看 sequence在一分钟之内的值,您就可以执行 pager grep sequence,它对mysql> show engine innodb status\ G select sleep (60); show engine innodbstatus\ G;返回的结果。
禁止 pager设置执行 nopager,如果不执行该命令,则只有等到下一次重新启动该命令才会失效。
此处咔咔是在虚拟机上做的操作,可以看到一分钟内是没有任何操作,所以值前后相同,你可以在测试服务器做测试。
这样计算出来的select (后边数据-前面的数据)/1024/1024*60 asMB_per_hour;值是一个小时后 redo log的大小
但是用这种方法计算一定是不合适的,在一分钟内业务繁忙或者业务空闲时间计算出的值都会产生较大误差。
合适的方法是在一天中确定几个时间点,用一个脚本定时执行,然后记录相应的值,再取平均值,计算出的误差将减至最小。
什么是 sequece?
当每个 binlog生成时,该值从1开始,然后递增,每增加一个事务, sequenumber就加上1。