一、常用的MySQL日志概览
日志名称 | 说明 |
---|---|
错误日志 error_log | 记录MySQL在启动、运行、停止时出现的问题 |
常规日志 general_log | 记录所有客户端发送到MySQL服务端的请求 |
慢查询日志 slow_query_log | 记录慢查询SQL |
二进制日志 binary_log | 记录所有的有效数据修改 |
中继日志 relay_log | 用于主从复制,临时存储从主库同步的二进制日志 |
二、错误日志 error_log
1、获取错误日志相关设置
mysql> SHOW VARIABLES LIKE 'log_error%';
+----------------------------+----------------------------------------+
| Variable_name | Value |
+----------------------------+----------------------------------------+
| log_error | stderr |
| log_error_services | log_filter_internal; log_sink_internal |
| log_error_suppression_list | |
| log_error_verbosity | 2 |
+----------------------------+----------------------------------------+
4 rows in set (0.00 sec)
mysql>
(1)log_error
log_error 参数定义了错误日志的存储路径,如果没有设置该值,MySQL会将错误日志保存在数据目录下的 “主机名.err” 文件。
(2)log_error_verbosity
该参数在5.7及8.0版本中存在,在5.6版本中该参数名称为“log_warnings”。
该参数为记录错误日志级别,有三个可选值
参数值 | 具体记录什么级别的日志 |
---|---|
1 | error message |
2 | error message、warning message |
3 | error message、warning message、note message |
(3)log_error_services
MySQL8.0版本新增参数。该参数如果不额外设置,和5.7版本体验是一样的,但如果单独设置,就可以自己决定使用什么错误日志组件。
可以使用自己写的,也可以使用MySQL官方提供的。其实就是MySQL允许用户通过自定义日志组件来记录自己想要的错误。
# 参数设置格式
log_error_services=[日志服务组件1; 日志服务组件2]
#查看当前设置
mysql> show variables like 'log_error_services';
+--------------------+----------------------------------------+
| Variable_name | Value |
+--------------------+----------------------------------------+
| log_error_services | log_filter_internal; log_sink_internal |
+--------------------+----------------------------------------+
1 row in set (0.00 sec)
mysql>
当前MySQL官方提供的错误日志组件:
组件名称 | 作用 |
---|---|
log_filter_internal | 默认的日志过滤组件,依赖log_error_verbosity参数 |
log_sink_internal | 默认的日志输出组件,依赖log_error参数 |
log_sink_json | 将错误日志输出到json文件 |
log_sink_syseventlog | 将错误日志输出到系统日志文件 |
2、错误日志的使用场景
(1)MySQL启动、停止、重启等过程中,产生的错误信息来进行排错
(2)添加或修改参数配置后,重启MySQL失败,查看错误日志来排错
三、常规日志 general_log
1、概述
记录了客户端从与MySQL建立连接开始,到断开连接的时间内,由客户端发送到MySQL服务器端的所有请求信息。
不论请求是否被成功执行,都会被记录在常规日志中。
2、设置常规日志
# 获取常规日志当前设置
mysql> show variables like 'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log | OFF |
+---------------+-------+
1 row in set (0.00 sec)
# 获取常规日志目录设置
mysql> show variables like 'general_log_file';
+------------------+---------------------------------+
| Variable_name | Value |
+------------------+---------------------------------+
| general_log_file | /var/lib/mysql/72b7d0258d58.log |
+------------------+---------------------------------+
1 row in set (0.00 sec)
# 获取常规日志当前设置存储方式,有FILE、TABLE、NONE,默认为FILE
mysql> show variables like 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output | FILE |
+---------------+-------+
1 row in set (0.00 sec)
在MySQL8.0 中,可以通过set persist
来对参数进行持久化设置。与set session
和 set global
不同之处在于,通过 set persist
设置的参数,即使重启MySQL,参数仍然有效。
但值得注意的是,该日志因为记录了从客户端连接到结束内所有操作,所以在短时间内就可能大量日志,占用大量存储空间。因此平常时,要把它关掉。
3、使用场景举例
明明MySQL没有报错,但数据就是没有修改成功,这时就可以通过该日志来进行分析。
四、慢查询日志 slow_query_log
1、概述
MySQL会将执行成功并符合条件的查询 记录到日志中。
2、使用场景
通过慢查询日志,我们可以找到需要优化的SQL。
3、慢查询日志相关参数
# 查看当前是否打开了慢查询日志
mysql> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | OFF |
+----------------+-------+
1 row in set (0.00 sec)
# 查看当前设置慢查询日志存储在哪里
mysql> show variables like 'slow_query_log_file';
+---------------------+--------------------------------------+
| Variable_name | Value |
+---------------------+--------------------------------------+
| slow_query_log_file | /var/lib/mysql/72b7d0258d58-slow.log |
+---------------------+--------------------------------------+
1 row in set (0.00 sec)
# 超过多少秒,就记录SQL到慢查询日志
mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
# 是否把所有没有使用索引的SQL记录到慢查询日志中
mysql> show variables like 'log_queries_not_using_indexes';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| log_queries_not_using_indexes | OFF |
+-------------------------------+-------+
1 row in set (0.00 sec)
说明:如果设置了log_queries_not_using_indexes为on,则记录所有没有使用索引的SQL到慢查询日志中,并且被记录的SQL没有超时时间的限制,只要没有使用索引,都会被记录下来。
五、二进制日志 binlog
1、概述
二进制日志中记录了所有对数据库中数据的修改。
2、二进制的使用场景
(1)基于时间点的备份和恢复
(2)由于误操作删除或修改了数据,也可以利用二进制日志反向恢复
(3)实现MySQL高可用架构的基础
3、二进制日志相关参数
# 二进制日志开闭状态
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.00 sec)
# 二进制文件路径
mysql> show variables like 'log_bin_basename';
+------------------+-----------------------+
| Variable_name | Value |
+------------------+-----------------------+
| log_bin_basename | /var/lib/mysql/binlog |
+------------------+-----------------------+
1 row in set (0.00 sec)
# 二进制日志格式,有ROW、STATEMENT、MIXED三种值,推荐设置为ROW
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
# 在binlog_format设置为row时,该参数生效,参数值有FUll、MINIMAL、NOBLOB
mysql> show variables like 'binlog_row_image';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| binlog_row_image | FULL |
+------------------+-------+
1 row in set (0.00 sec)
# 当binlog_format为row时,设置记录原本执行的SQL到二进制日志,方便我们查看,推荐为on
mysql> show variables like 'binlog_rows_query_log_events';
+------------------------------+-------+
| Variable_name | Value |
+------------------------------+-------+
| binlog_rows_query_log_events | OFF |
+------------------------------+-------+
1 row in set (0.00 sec)
# 主从复制时使用,设置为on时会在slave上记录同步过来的二进制日志
mysql> show variables like 'log_slave_updates';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| log_slave_updates | ON |
+-------------------+-------+
1 row in set (0.00 sec)
# 控制MySQL如何刷新二进制日志到磁盘,设置为1时,写一次刷新一次,设置为0时,MySQL将不会主动刷新,推荐设为1,可以保证MySQL服务宕机日志记录也不会丢失。
mysql> show variables like 'sync_binlog';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog | 1 |
+---------------+-------+
1 row in set (0.00 sec)
# 查看某个二进制文件
mysqlbinlog --no-defaults -vv --base64-output=DECODE-ROWS binlog.000003
说明:
上面通过log_bin_basename
得到二进制文件路径是/var/lib/mysql/binlog,那么实际的bninlog日志就应该在/var/lib/mysql路径下,该路径下一定有binlog.xx这种文件。请看下面这张图:
上面参数binlog_row_image设置为row时,会将每一条记录都记录在二进制日志里面,而设置为MINIMAL时,则只会记录符合条件的记录修改。
而且如果我们查看某个二进制文件会发现,其中是以具体的id和值来体现的,并不是我们实际操作的SQL,它长这个样子:
# 实际操作的SQL语句是:
update inventory set num = 88 where product_id = 1001 and warehouse_id = 2;
# 该条语句操作的数据库是test_80。
# 二进制日志中该条SQL语句的体现
/*!80011 SET @@session.default_collation_for_utf8mb4=255*//*!*/;
BEGIN
/*!*/;
# at 322
#210818 13:09:11 server id 1 end_log_pos 383 CRC32 0x6ad5c0d4 Table_map: `test_80`.`inventory` mapped to number 110
# at 383
#210818 13:09:11 server id 1 end_log_pos 429 CRC32 0xc5170258 Update_rows: table id 110 flags: STMT_END_F
### UPDATE `test_80`.`inventory`
### WHERE
### @1=2 /* INT meta=0 nullable=0 is_null=0 */
### SET
### @4=88 /* INT meta=0 nullable=1 is_null=0 */
# at 429
#210818 13:09:11 server id 1 end_log_pos 460 CRC32 0x9640e2a8 Xid = 1035
COMMIT/*!*/;
注意:如果想让二进制日志记录的就是我们实际操作的SQL,我们应该怎么做呢?
方式一:把参数binlog_format的值设置为STATEMENT
但这种方式在主从复制中是不被推荐的,会非常不安全
方式二:把binlog_rows_query_log_events参数设置为on
这种方式是被推荐的。
从下面可以清除的看到我们实际执行的SQL
update inventory set num = 188 where product_id = 1001 and warehouse_id = 2
BEGIN
/*!*/;
# at 322
#210818 13:21:53 server id 1 end_log_pos 421 CRC32 0xa790db6c Rows_query
# update inventory set num = 188 where product_id = 1001 and warehouse_id = 2
# at 421
#210818 13:21:53 server id 1 end_log_pos 482 CRC32 0x8cf12014 Table_map: `test_80`.`inventory` mapped to number 110
# at 482
#210818 13:21:53 server id 1 end_log_pos 528 CRC32 0x11d132e9 Update_rows: table id 110 flags: STMT_END_F
### UPDATE `test_80`.`inventory`
### WHERE
### @1=2 /* INT meta=0 nullable=0 is_null=0 */
### SET
### @4=188 /* INT meta=0 nullable=1 is_null=0 */
# at 528
#210818 13:21:53 server id 1 end_log_pos 559 CRC32 0xedbcced1 Xid = 1039
COMMIT/*!*/;
4、定期清理MySQL二进制日志
方式一:
我们可以通过设置expire_logs_days
来定期清理过期的二进制日志。
方式二:
# 手动执行命令
purge binary logs to 'mysql-bin.010';
该命令可以把mysql-bin.001 到mysql-bin.009的二进制日志都删除掉。
方式三:
# 手动执行命令
purge binary logs before '2021-03-01 22:00:05';
该命令可以把在2021-03-01 22:00:05之前的二进制日志都删除掉。
六、中继日志 relay_log
1、概述
只存在于主从复制的slave上,它的作用是临时记录从主服务器同步的二进制日志。
2、重要参数
# 中继日志存放路径,如果不指定,将以主机名-relay-bin名称存储在数据目录,建议使用时要手动设置一下目录,不能像我这样不设置
mysql> show variables like 'relay_log';
+---------------+------------------------+
| Variable_name | Value |
+---------------+------------------------+
| relay_log | 72b7d0258d58-relay-bin |
+---------------+------------------------+
1 row in set (0.00 sec)
# 设置是否自动清理中继日志,设置为on时,如果中继日志中的记录已经被应用了,则会对relay_log自动清理
mysql> show variables like 'relay_log_purge';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| relay_log_purge | ON |
+-----------------+-------+
1 row in set (0.00 sec)