MySQL重做日志(redo log)、回滚日志(undo log)、二进制日志(binglog)......等日志格式的简单总结

在任何系统库中,都会有各种各样的日志,记录着系统工作的方方面面,以帮助系统管理员追踪系统曾经发生过的各种事件。MySQL也不例外,MySQL中有六种日志文件,分别是:重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)、错误日志(errorlog)、慢查询日志(slow query log)、查询日志(general log),中继日志(relay log)。可以说,在数据库的世界里,数据从来都不重要,日志才是最重要的,有了日志就有了一切!!!

一、错误日志(error log)

错误日志是MySQL中最重要的日志之一, 它记录了当mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时,可以首先查看此日志。

该日志是默认开启的,默认存放目录为mysql的数据目录( var/lib/mysql ) ,默认的日志文件名为[hostname].err ( hostname是主机名)。

查看日志位置指令:

show varialbes like 'log_error%';

第一行log_error就是错误日志,这里是采用的是标准输出直接将错误打印在屏幕上。当然也可以配置把错误日志输出到某个文件。

1.1 错误日志配置

为了方便管理,用户可以根据自己的需求来配置错误日志存储位置和日志级别,配置参数如下:

  • log_error = on|文件路径 是否启用错误日志,on表示开启,文件路径表示指定自定义日志路径
  • log_warnings = 1|0 是否记录warnings信息到错误日志中
1.2 错误日志记录信息

1、服务器启动和关闭过程中的信息

未必是错误信息,比如mysql是如何去初始化存储引擎的过程记录在错误日志里等等

2、服务器运行过程中的错误信息

比如sock文件找不到,无法加载mysql数据库的数据文件,如果忘记初始化mysql或data dir路径找不到,或权限不正确等 都会记录在此

3、事件调度器运行一个事件时产生的信息

一旦mysql调度启动一个计划任务的时候,它也会将相关信息记录在错误日志中

4、在从服务器上启动从服务器进程时产生的信息

在复制环境下,从服务器进程的信息也会被记录进错误日志

1.3 删除错误日志

在mysql5.5.7之前:数据库管理员可以删除很长时间之前的错误日志,以保证mysql服务器上的硬盘空间。mysql数据库中,可以使用mysqladmin命令开启新的错误日志。mysqladmin命令的语法如下:

mysqladmin –u root –pflush-logs

二、二进制日志(binglog)

二进制日志( BINLOG )记录了所有的DDL (数据定义语言)语句和DML (数据操纵语言)语句,但是不包括数据查询语句。此日志对于灾难时的数据恢复起着极其重要的作用, MySQL的主从复制,就是通过该binlog实现的

二进制日志,默认情况下是没有开启的,需要到MySQL的配置文件中开启,并配置MySQL日志的格式。

Linux下同下MySQL的配置文件默认位置:/usr/my.cnf

日志存放位置:配置时,给定了文件名但是没有指定路径,日志默认写入Mysq的数据目录。

#配置开启binlog日志  ,日志文件的前缀名为 mysqlbin
log_bin=mysqlbin

#配置二进制日志的格式,日志格式有STATEMENT、ROW和MIXED三种
binlog_format=STATEMENT
2.1 binlog日志格式

binlog格式分为: STATEMENT、ROW和MIXED三种,详情如下:

  • STATEMENT

STATEMENT格式的binlog记录的是数据库上执行的原生SQL语句。这种方式有好处也有坏处。

好处就是相当简单,简单地记录和执行这些语句,能够让主备保持同步,在主服务器上执行的SQL语句,在从服务器上执行同样的语句。另一个好处是二进制日志里的时间更加紧凑,所以相对而言,基于语句的复制模式不会使用太多带宽,同时也节约磁盘空间。并且通过mysqlbinlog工具容易读懂其中的内容。

坏处就是同一条SQL在主库和从库上执行的时间可能稍微或很大不相同,因此在传输的二进制日志中,除了查询语句,还包括了一些元数据信息,如当前的时间戳。即便如此,还存在着一些无法被正确复制的SQL。另外一个问题就是基于语句的复制必须是串行化的。这要求大量特殊的代码,配置,例如InnoDB的next-key锁等。并不是所有的存储引擎都支持基于语句的复制。

  • ROW

从MySQL5.1开始支持基于行的复制,也就是基于数据的复制,基于行的更改。这种方式会将实际数据记录在二进制日志中,它有其自身的一些优点和缺点,最大的好处是可以正确地复制每一行数据。一些语句可以被更加有效地复制,另外就是几乎没有基于行的复制模式无法处理的场景,对于所有的SQL构造、触发器、存储过程等都能正确执行。主要的缺点就是二进制日志可能会很大,而且不直观,所以,你不能使用mysqlbinlog来查看二进制日志。也无法通过看二进制日志判断当前执行到那一条SQL语句了。

现在对于ROW格式的二进制日志基本是标配了,主要是因为它的优势远远大于缺点。并且由于ROW格式记录行数据,所以可以基于这种模式做一些DBA工具,比如数据恢复,不同数据库之间数据同步等。

  • MIXED

MIXED是MySQL默认使用的二进制日志记录方式,但MIXED格式默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。比如用到UUID()、USER()、CURRENT_USER()、ROW_COUNT()等无法确定的函数。

2.2 binlog的查看方式

binlog使用直接打开是我们看不懂的一堆“乱码”,我们需要借助工具来分析binlog日志,这个工具即使mysql自带的mysqlbinlog 语法:

mysqlbinlog  binlog文件路径

#一般binlog日志文件都比较大,因此我们会在命令的末尾加上 | more
mysqlbinlog  binlog文件路径   | more

示例:

mysqlbinlog  ./binlog.000001 | more

发现虽然不是乱码了,但是日志中的内容把人看的还是云里雾里的。我们还需要添加一个命令参数:--base64-output=decode-rows -v

mysqlbinlog --base64-output=decode-rows -v  binlog.000001 | more
2.3 binlog日志文件的删除

对于比较繁忙的系统,由于每天生成日志量大, 这些日志如果长时间不清楚,将会占用大量的磁盘空间。下面我们将会讲解几种删除日志的常见方法:

方式一

通过Reset Master指令删除全部binlog日志,删除之后,日志编号,将从xx.000001重新开始。

查询之前,先查询下日志文件:

执行删除日志的指令:

Reset master;

执行之后在查看日志文件:

方式二

执行指令purge master logs to 'mysqlbin.xxxxxx',该命令将会删除指定日志文件之前的所有日志文件

方式三

执行指令purge master logs before 'yyyy-mm-dd hh24:mi:ss',该命令将删除日志为“yyyy-mm-dd hh24:mi:ss”之前产生的所有日志文件。

方式四

在MySQL配置文件中设置参数--expire_logs_days=xxxx,此参数的含义就是设置日志的过期天数,过期之后会自动删除日志。比如设置 --expire_logs_days=3;的含义就是日志文件的过期天数是3天。

三、查询日志(general log)

查询日志在MySQL中被称为general log(通用日志),查询日志里的内容不要被"查询日志"误导,认为里面只存储select语句,其实不然,查询日志里面记录了数据库执行的所有命令,不管语句是否正确,都会被记录

默认情况下,查询日志是没有开启的。如果需要开启查询日志,可以在mysql配置文件中做如下配置:

#该选项用来开启查询日志,可选值 0或1。0表示关闭 ,1表示开启
general_log=1

#设置日志的文件名,默认为host_name.log
general_log_file=file_name

或者也可以使用命令设置:

#也可以设置变量那样更改,1开启(0关闭),即时生效,不用重启,首选当然是这样的了
set global general_log=1
set global log_output='table';

四、慢查询日志(slow_query_log)

慢查询会导致CPU,IOPS,内存消耗过高。当数据库遇到性能瓶颈时,大部分时间都是由于慢查询导致的。 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,之后运维人员通过定位分析,能够很好的优化数据库性能。

慢查询日志记录的慢查询不仅仅是执行比较慢的SELECT语句,还有INSERT,DELETE,UPDATE,CALL等DML操作,只要超过了指定时间,都可以称为"慢查询",被记录到慢查询日志中

默认情况下,慢查询日志是不开启的,只有手动开启了,慢查询才会被记录到慢查询日志中。当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。 慢查询日志支持将日志记录写入文件。

4.1 开启慢查询日志
#查看慢查询日志是否开启
show variables like '%slow_query_log%';

#开启慢查询日志
set global slow_query_log=1;

#查看慢查询时间阈值,单位:秒
show variables like 'long_query_time%'

#设定慢查询阈值,默认是10s,这里设置的时候单位也是秒
set long_query_time=60

如永久生效需要修改配置文件 my.cnf 中[mysqld]下配置

slow_query_log=1
slow_query_log_file=/var/lib/mysql/atguigu-slow.log
long_query_time=3
log_output=FILE
4.2 慢查询日志分析工具—mysqldumpslow

先看一下它的帮助

使用示例:

#得到返回记录集最多的 10 个 SQL
mysqldumpslow -s r -t 10 /var/lib/mysql/test-slow.log

#得到访问次数最多的 10 个 SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/test-slow.log

#得到按照时间排序的前 10 条里面含有左连接的查询语句
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/atguigu-slow.log

#另外建议在使用这些命令时结合 | 和 more 使用 ,否则有可能出现刷屏的情况
mysqldumpslow -s r -t 10 /var/lib/mysql/test-slow.log | more

五、事务日志(redo log 和 undo log)

数据库数据存放的文件称为data file;日志文件称为log file;数据库数据是有缓存的,如果没有缓存,每次都写或者读物理disk,那性能就太低下了。数据库数据的缓存称为data buffer,日志(redo)缓存称为log buffer;既然数据库数据有缓存,就很难保证缓存数据(脏数据)与磁盘数据的一致性。

但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据丢失而导致数据不一致怎么办?

为了保证事务的ACID特性,就不得不说MySQL InnoDB引擎的事务日志: 重做日志redo和回滚日志undo

innodb通过force log at commit机制实现事务的持久性,即在事务提交的时候,必须先将该事务的所有事务日志写入到磁盘上的redo log file和undo log file中进行持久化。

注: 在数据库的世界里,数据从来都不重要,日志才是最重要的,有了日志就有了一切!!!

5.1 Redo日志

Redo log的作用主要是确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。它是物理格式的日志,记录的是物理数据页面的修改的信息,其redo log是顺序写入redo log file的物理文件中去的。 redo log包括两部分:

  • 一是内存中的日志缓冲(redo log buffer),该部分日志是易失性的;
  • 二是磁盘上的重做日志文件(redo log file),该部分日志是持久的,并且是事务的记录是顺序追加的,性能非常高(磁盘的顺序写性能逼内存的写性能差不了太多)。

InnoDB使用日志来减少提交事务时的开销。因为日志中已经记录了事务,就无须在每个事务提交时把缓冲池的脏块刷新(flush)到磁盘中。事务修改的数据和索引通常会映射到表空间的随机位置,所以刷新这些变更到磁盘需要很多随机IO。InnoDB假设使用常规磁盘,随机IO比顺序IO昂贵得多,因为一个IO请求需要时间把磁头移到正确的位置,然后等待磁盘上读出需要的部分,再转到开始位置。

InnoDB用日志把随机IO变成顺序IO。一旦日志安全写到磁盘,事务就持久化了,即使断电了,InnoDB可以通过redo日志恢复已经提交的事务。

5.2 Undo日志

undo log有两个作用:保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。它是一个逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的

在数据修改的时候,不仅记录了redo,还记录了相对应的undo,如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。

undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。

当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。有时候应用到行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。

留言区

还能输入500个字符