ITPub博客

首页 > 数据库 > 数据库开发技术 > MySQL的日志类型篇

MySQL的日志类型篇

原创 数据库开发技术 作者:DBA修行之路 时间:2021-06-28 08:26:47 0 删除 编辑




点击上方“蓝字”,发现更多精彩。





MySQL的日志类型篇

MySQL日志类型总览

MySQL中常见有以下7种日志,如下:

重做日志(redo log)

回滚日志(undo log)

二进制日志(binlog)

错误日志(errorlog)

慢查询日志(slow query log)

通用日志(general log)

中继日志(relay log)

不同的日志具有不同的功能,先总体了解下吧。



Redo日志

在MySQL中,如果每次更新操作都直接写进磁盘,写磁盘过程中,需要先找到那条记录,然后再更新。会导致整个IO成本,查找成本很高,因此,催生了WAL技术,WAL全称Write-ahead Logging,其核心思想是先写日志,再写磁盘。

当进行记录更新时,InnoDB先将记录写入redo log里,然后更新内存,此时更新操作就算完成了,然后InnoDB引擎会在系统空闲或者达到刷写条件的时候将redo log中的操作记录更新到磁盘中。

通过redo log,Innodb可以保证数据库即使发生异常重启,之前提交的记录都不会丢失,该能力称为crash-safe。

对于redo log,从以下几个点来进行总结:

redo log功能:

redo log是innodb引擎特有的日志,功能是为了保证事务的持久性。


redo log内容:

redo log是物理格式的日志,记录的是物理数据页面的修改的信息。


redo log生命周期:

redo log产生于事务开始,结束于对应事务的脏页写入到磁盘后,然后redo log占用的空间就可以被覆盖以实现重用。


redo log刷盘方式:

master线程周期性每秒一次刷新redo log buffer到redo log文件。

每个事务提交时刷新redo log buffer中数据到redo log文件。

当redo log buffer空间少于一般时,将会将redo log buffer中数据刷新到redo log文件。


redo log对应文件:

redo log对应ib_logfileN文件,相关参数有:

innodb_log_group_home_dir:日志文件路径。

innodb_log_files_in_group:重做日志文件组中文件个数,默认为2。

innodb_log_file_size:重做日志文件的大小。

innodb_mirrored_log_groups:日志镜像文件组的数量,默认为1。


redo log写入流程:

事务运行过程中,会不断地产生redo log,redo log不会直接写入磁盘中,而是先写入redo log buffer中,经过转换,在触发刷新条件时,顺序地写入到磁盘中。另外,redo log写入磁盘时,写入单位为512B,不需要double write机制。





binlog相关

binlog是MySQL中Server层面的日志,主要用于主从复制和定点恢复,binlog与redo写入方式不同,redo log是循环写的,而binlog是追加写的。binlog有三种模式,row,statement,mixed模式。目前不少工具的使用前提条件都是日志格式基于row格式的,因此生产上建议使用row格式。


row日志的三种格式:

statement格式:

优点:

1).技术成熟

2).写入日志文件数据较少,当更新或删除涉及多行时,可有效减少存储空间,可以快速根据二级制日志备份和恢复。

3).记录所有数据变更的原始语句,可用于数据库审计。


缺点:

1).执行结果不确定的DML语句,UDF和存储过程,以及不带order by的limit子句,可能会造成主备数据不一致。

2).一些内置函数,如uuid(),user(),sysdate()等时无法正确复制。

3).insert into ...select语句在基于statement的复制时需要的行级锁比基于row的复制多。

4).未使用索引的update语句需要进行表扫描,基于statement的复制时需要的行级锁比基于row的复制多。

5).对于复制语句,需要评估数据一致性风险。


row格式:

优点:

1).可以正确地复制所有数据的变更,是最安全的复制格式。

2).对于Insert into ...select,update或delete语句中where条件未使用索引等场景性能更好。


缺点:

1).生成更多的二进制日志数据,每行数据的变更都会写入二进制日志。

2).利用二进制日志进行备份和恢复是时间更长,另外,二进制日志持有的文件锁时间更长,可能会对数据块并发造成影响。

3).生成大字段的BLOB值会比基于statement的复制消耗更长的时间。

4).无法直接看到从库中执行的语句,需要使用mysqlbinlog工具的--base64-output=decode-rows和--verbose选项查看。

5).对于非事务性表,insert操作多行数据时需要更多的表级锁。


mixed格式:

对于mixed格式的日志,被视作不安全的语句在记录到二进制日志时会被自动转换为row格式,安全的语句会使用statement格式。






undo log相关:

回滚日志保存了事务发生之前的数据的版本。

undo log功能:

1).保证数据的原子性。

2).用于回滚。

3).应用于MVCC版本下的读。


undo log内容:

逻辑格式的日志,执行undo时,将数据从逻辑上恢复至事务之前的状态。


undo log生命周期

事务开始之前,将当前事务的版本生成undo log,undo还会产生redo log保证undo log的可靠性。当事务提交之后,undo log不会马上被删除,而是放入带清理的链表,由purge线程判断是否由其他事务使用undo段中表的上一个事务之前的版本信息,来决定是否清理。


undo log物理文件:

MySQL5.6前,undo log表空间位于共享表空间的回滚段中,共享表空间的默认名称为ibdata,MySQL5.6之后,undo表空间可以配置成独立文件。完成初始化后undo log文件个数无法改变。


undo log配置:

innodb_undo_directory:独立表空间的存放目录。

innodb_undo_logs:undo log在独立表空间中的大小。

innodb_undo_tablespaces:undo log文件个数。

innodb_data_file_path:共享表空间文件目录。



其他日志

其他四种日志相较于前三种重要性略低,因此在一起进行总结。

errorlog(错误日志):

errorlog记录着mysqld启动和停止,以及服务器在运行过程中发生的错误的相关错误,在服务器运行出现错误时,有助于相关人员进行问题分析,定位问题。

可通过以下参数配置:

log-error:错误日志路径。


slow query log(慢查询日志):

slow query log记录执行时间过长和没有使用索引的查询语句,不会记录执行报错的语句,只会记录执行成功的语句。慢日志可以通过mysqldumpslow,pt-query-digest等工具进行分析。为了便于分析,可对慢日志文件按天进行切割。

可通过以下参数配置:

slow_query_log:是否开启慢日志,on或1为开启。

slow_query_log_file:慢日志路径。

log_query_time:慢查询时间。


通用日志(general log)

general log记录了服务器接收到的每一个查询或者命令,无论这些查询或命令是否正确。默认是关闭的,因为开启general log会对服务器产生不小的系统开销。


中继日志(relay log):

relay log的功能是实现主从同步数据复制。在主从复制中,从库的io线程读取主库的binlog日志,将其转换为relay日志,然后sql线程读取relay log。进行操作回放。






MySQL的两阶段提交

两阶段提交从以下几个方面进行理解:

两阶段提交的功能:

简单来说是为了实现两份日志的逻辑一致。再次温习下redo log与binlog日志的差别:

1).redo log是InnoDB引擎独有的,binlog是MySQL的Server层实现的。

2).redo log是物理日志,记录在某个数据页上做了啥修改,binlog是逻辑日志,记录语句的原始逻辑。

3).redo log是循环写,binlog是追加写。


两阶段提交流程:

两阶段提交分为两个阶段,prepare阶段,commit阶段。

1).一条更新记录操作通过连接器,分析器,优化器等,通过调用操作引擎,将新数据更新到内存中,同时将该更新操作记录在redo log中,然后redo log处于prepare状态。

2).执行器生成该操作的binlog日志,并将binlog写入磁盘。

3).执行器调用引擎的提交事务接口,将刚刚写入的redo log状态更新为commit,完成更新操作。


Crash recovery的三种场景:

1).binlog有记录,redo log状态为commit:该场景下事务正常完成,无需恢复。

2).binlog有记录,redo log状态为prepare:该场景下binlog写完后提交事务之前发生了crash,恢复后会提交该事务。

3).binlog中没记录,redo log状态为prepare:该场景下在binlog写完之前发生了crash,恢复后会回滚事务。





事务提交后才会进行redo log落盘吗?

重做日志写入磁盘,不一定是事务提交后才会写入重做日志文件的,而是随着事务的开始,逐步开始的,即使某个事务还没提交,InnoDB引擎仍然可以每秒将redo log buffer刷新到redo log中,这点从即使很大的事务提交时间也很短暂可以看出。


为什么要配置独立undo表空间?

当undo文件使用共享表空间时,如果数据库中发生大事务操作时,需要生成大量的undo信息,这些信息保存在共享表空间中,可能会导致共享表空间变得很大,默认情况下,共享表空间不会也不能自动收缩。



为什么要采取两阶段提交?

从两种场景分析:

1).先写redo log再写binlog:此时如果MySQL在一条语句操作redo log后崩溃了,binlog中没有记录该语句操作,系统在crash recovery时重新执行时binlog中便会少了这一次修改,恢复的数据库中少了这条更新。

2).先写binlog再写redo log:此时如果MySQL在一条语句操作binlog后崩溃了,redo log中没有记录该语句操作,系统在crash recovery时重新执行时binlog便会多一次修改,恢复的数据库便会多一条更新。

因此,如果不使用两阶段提交,数据库状态就可能与用日志恢复出来的状态不一致。






结尾小结

今天系统学习总结了MySQL的各种日志,之前虽然零零散散接触过,但是没有详细的认知,通过总结,对MySQL的日志结构整体有了更深的认识。




END



扫码关注我
每天进步一点点,未来才可期,我们共同的目标是星辰大海。



原文作者:DBA修行之路;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2021-05-25

  • 博文量
    64
  • 访问量
    23946