目的:通过不同类型的日志,完成不同的功能。

  • bin-log 更新日志:数据恢复、主从同步。
  • error-log 错误日志:mysql服务本身在启动关闭过程中遇到的错误信息。
  • general 普通日志:记录客户端连接信息和执行的SQL语句信息
  • slow query log 慢日志:记录执行时间超时的语句,用于问题排查

参考:https://blog.51cto.com/13178102/2082763

MySQL数据库日志介绍

binlog

介绍

记录mysql内部增删改等对mysql数据库有更新的内容的记录(对数据库的改动),对数据库查询的语句如show,select开头的语句,不会被binlog日志记录。binlog日志只要用于数据库的增量恢复,以及主从复制。

mysql数据目录下的如下文件就是mysql的binlog日志:

  1. [root@test3 ~]# ll /data/3306/
  2. total 88
  3. -rw-rw---- 1 mysql mysql 703 Feb 3 14:21 mysql-bin.000001 #<==binlog日志文件
  4. -rw-rw---- 1 mysql mysql 126 Feb 3 14:23 mysql-bin.000002
  5. -rw-rw---- 1 mysql mysql 126 Feb 3 14:24 mysql-bin.000003
  6. -rw-rw---- 1 mysql mysql 479 Feb 3 14:36 mysql-bin.000004
  7. -rw-rw---- 1 mysql mysql 477 Feb 3 14:39 mysql-bin.000005
  8. -rw-rw---- 1 mysql mysql 18699 Feb 4 03:05 mysql-bin.000006
  9. -rw-rw---- 1 mysql mysql 150 Feb 4 03:05 mysql-bin.000007
  10. -rw-rw---- 1 mysql mysql 13334 Feb 4 04:08 mysql-bin.000008

开启

需要在配置文件my.cnf中打开log-bin功能,才会生成对应的binlog日志文件

  1. [root@localhost 3306]# grep "log-bin" /data/3306/my.cnf
  2. [mysqld]
  3. log-bin = /data/3306/mysql-bin #<==在mysqld配置里面添加log-bin功能

查看bin-log功能开启状况:

  1. mysql> show variables like '%log_bin%';
  2. +---------------------------------+-------+
  3. | Variable_name | Value |
  4. +---------------------------------+-------+
  5. | log_bin | ON | #<==记录binlog开关
  6. | log_bin_trust_function_creators | OFF |
  7. | sql_log_bin | ON | #<==临时不记录binlog开关
  8. +---------------------------------+-------+
  9. 3 rows in set (0.00 sec)

临时不记录bin-log:

  1. mysql> set session sql_log_bin = OFF;

三种模式

Row Level

日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改。
优点:在row level模式下,bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录哪一条记录被修改了,修改成什么样了。所以row level的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程或function,以及trigger的调用和触发无法被正确复制的问题。
缺点:row level下,所有的执行语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如有一条这样的update语句:update product set owner_member_id=‘b’ where owner_member_id=’a’,执行了之后,日志中记录的不是这条update语句所对应的事件(MySQL以事件的形式来记录bin-log日志),而是这条语句所更新的每一条记录的变化情况,这样就记录成很多条记录被更新的时间。自然,bin-log日志的量就会很大。尤其是当执行alter table之类的语句的时候,产生的日志量是惊人的,因为MySQL对于alter table之类的表结构变更语句的处理方式是整个表的每一条记录都需要变动,实际上就是重建了整个表,那么该表的每一条记录都会被记录到日志中。

Statement Level

每一条会修改数据的sql都会记录到master的bin-log中。slave在复制的时候sql进程会解析成和原来master端执行过程相同的sql来再次执行。
优点:statement level下的优点首先就是解决了row level下的缺点,不要需要记录每一行数据的变化,减少bin-log日志量,节约IO,提高性能。因为它只需要记录在master上所执行的语句细节,以及执行语句时候的上下文信息。
缺点:由于他是记录的执行语句,所以,为了让这些语句在slave端也能正确执行,那么它还必须记录每条语句在执行时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端被执行的时候能够得到和在master端执行时候相同的结果。另外就是,由于MySQL发展很快,很多新功能不断的加入,使MySQL的复制遇到了不小的挑战。自然复制的时候涉及到的内容越复杂,bug也就越容易出现。在statement level下,目前已经发现的就有不少情况会照成MySQL的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如sleep()函数在有些版本中就不能正确复制;在存储过程中使用了last_insert_id()函数,就可能会使slave和master上得到不一致的id等等。由于row level是基于每一行来记录的变化,所以不会出现类似的问题。

Mixed

  1. 实际上就是前两种模式的结合。在Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在statementRow之间选择一种。新版本中的statement level还是和以前一样,仅仅记录执行的语句。而新版本的MySQL中对row level模式也做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录,如果sql语句确实就是update或者delete等修改数据的语句,那么还是会记录所有行的变更。

如何选择使用binlog的模式

1、互联网公司,使用MySQL的功能相对少(存储过程、触发器、函数)
选择默认的语句模式,statement Level模式
2、如果用到MySQL的特殊功能(存储过程、触发器、函数)则选择Mixed模式。
3、公司如果用到使用MySQL的特殊功能(存储过程、触发器、函数),数据最大化一致,此时最好行模式。

如何设置binlog的模式

  1. mysql> show global variables like '%binlog_format%';
  2. +---------------+-----------+
  3. | Variable_name | Value |
  4. +---------------+-----------+
  5. | binlog_format | STATEMENT |
  6. +---------------+-----------+
  7. 1 row in set (0.00 sec)

q 在配置文件里面修改

  1. [mysqld]
  2. log-bin=mysql-bin
  3. #binlog_format="STATEMENT"
  4. #binlog_format="ROW"
  5. binlog_format="MIXED"

q 直接修改

  1. SET GLOBAL binlog_format = 'STATEMENT'
  2. SET GLOBAL binlog_format = 'ROW'
  3. SET GLOBAL binlog_format = 'MIXED'

1.4 binlog文件解析工具mysqlbinlog

默认情况下,binlog是二进制格式的,不能使用查看文本工具的命令查看,例如:cat,vi,find等

1.4.1 解析整个log-bin文件

  1. [root@test3 3306]# mysqlbinlog mysql-bin.000001

1.4.2 解析指定的数据库

q -d 只解析对应的数据库
使用-d参数,能够解析出对应log-bin文件里面的数据库,如下所示:

  1. [root@test3 3306]# mysqlbinlog -d oldboy mysql-bin.000001

q -r 数据导出到指定文件
将解析的结果存入另一个sql文件:

  1. [root@test3 3306]# mysqlbinlog -d oldboy mysql-bin.000001 -r oldboy.sql

mysqlbinlog工具分库导出binlog,如果使用-d参数,那更新数据时,必须有use database,才能分出指定库的binlog,例如:’’

  1. use oldboy;
  2. insert into student values(1,'oldboy ')

下面的写法就不行:

  1. insert into oldboy.student values(2, 'oldboy' )

1.4.3 按照位置截取

mysqlbinlog mysqlbin.000001 —start-position=365 —stop-position=456 -r pos.sql
指定开始位置,不指定结束位置:
mysqlbinlog mysqlbin.000001 —start-position=365 -r pos.sql
指定结束位置,不指定开始位置:
mysqlbinlog mysqlbin.000001 —stop-position=456 -r pos.sql

1.4.4 按照时间截取

mysqlbinlog mysql-bin000020 —start-datatime=’2017-10-16 17:14:15’ —stop-datetime=’2017-10-16 18:14:15’ -r time.sql
指定开始时间,不指定结束时间:
mysqlbinlog mysql-bin000020 —start-datatime=’2017-10-16 17:14:15’ -r time.sql
指定结束时间,不指定开始时间:
mysqlbinlog mysql-bin000020 —stop-datetime=’2017-10-16 18:14:15’ -r time.sql

1.4.5 mysqlbinlog命令小结

1、该命令作用是把binlog解析为sql语句(包含位置和时间点)
2、-d参数根据指定库拆分binlog(拆分单表binlog可以通过SQL关键字过滤)
3、通过位置参数截取部分binlog:—start-position=265 —stop-position=345,精确定位取部分内容。
4、通过时间参数截取部分binlog:—start-datetime= 180203 14:21:56 —stop-datetime= 180203 14:21:56,模糊取内容
5、-r文件名,相当于重定向”>”
6、解析ROW级别binlog日志的方法
mysqlbinlog —base64-output=decode-rows -v mysql-bin.000016

binlog数据恢复

  1. # 查看当前binlog文件
  2. show master status;

image.png

  1. # 执行 flush logs 操作,生成新的 BINLOG,便于恢复之前的数据
  2. flush logs;
  1. # 根据时间确定位置信息
  2. mysqlbinlog --no-defaults --base64-output=decode-rows -v \
  3. --start-datetime "2019-11-22 14:00:00" \
  4. --database test_binlog mysql-bin.000034 | less

image.png

  1. # 根据位置导出 SQL 文件
  2. mysqlbinlog --no-defaults --base64-output=decode-rows -v \
  3. --start-position "2508132" --stop-position "2511004" \
  4. --database test_binlog mysql-bin.000034 \
  5. > /home/mysql_backup/test_binlog_step1.sql
  6. mysqlbinlog --no-defaults --base64-output=decode-rows -v \
  7. --start-position "2508813" --stop-position "2509187" \
  8. --database test_binlog mysql-bin.000034 \
  9. > /home/mysql_backup/test_binlog_step2.sql
  10. # 使用 mysql 进行恢复
  11. mysql -u cisco -p < /home/mysql_backup/test_binlog_step1.sql
  12. mysql -u cisco -p < /home/mysql_backup/test_binlog_step2.sql

第2章 错误日志error log

2.1 error log日志介绍

MySQL的错误日志(error log)记录MySQL服务进程mysqld在启动/关闭或运行过程中遇到的错误信息。

2.2 error log日志功能的开启

在配置文件中调整参数:

  1. [root@test3 3306]# grep log-error my.cnf
  2. [mysqld]
  3. log-error = /data/3306/mysql_3306.err #<==在mysqld配置里面添加log-error功能

在启动命令里加入:

  1. mysqld_safe --defaults-file=/data/3306/my.cnf --log-error=/data/3306/mysql_3306.err &

查看error log:

  1. mysql> show variables like '%log_error%';
  2. +---------------+---------------------------+
  3. | Variable_name | Value |
  4. +---------------+---------------------------+
  5. | log_error | /data/3306/mysql_3306.err |
  6. +---------------+---------------------------+
  7. 1 row in set (0.00 sec)

第3章 普通查询日志

3.1 general query log日志介绍

普通查询日志(general query log):记录客户端连接信息和执行的SQL语句信息;

3.2 general query log日志功能的卡其

在配置文件中调整参数:

  1. [root@test3 3306]# grep general_log my.cnf
  2. [mysqld]
  3. general_log = on
  4. general_log_file = /data/3306/data/MySQL.log #<==在mysqld配置里面添加general_log功能

第4章 慢查询日志

4.1 slow query log介绍

慢查询日志(slow query log):记录执行时间超出指定值(long_query_time)的SQL语句。

4.2 slow query log日志功能的开启

  1. long_query_time = 1
  2. log-slow-queries = /data/3306/slow.log
  3. log_queries_not_using_indexes

慢查询日志的设置,对于数据库的SQL的优化非常重要。

4.3 切割慢查询日志

将慢查询日志按天切割,脚本如下:

  1. [root@test3 scripts]# cat cut_slow_log.sh
  2. #/bin/bash
  3. cd /data/3306/ &&\
  4. /bin/mv slow.log.$(date +%F) &&\
  5. mysqladmin -uroot -p123456 -S /data/3306/mysql.sock flush-log

设置切割日志文件的定时任务:

  1. [root@test3 scripts]# tail -2 /var/spool/cron/root
  2. #cut mysql slow log
  3. 00 00 * * * /bin/sh /server/scripts/cut_slow_log.sh &>/dev/null