MySQL general log
本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net
文章目录
前言
前面的文章中我们介绍了 slow query log 慢查询日志、binlog 二进制日志、relaylog 中继日志、redolog 重做日志、undolog 回滚日志。今天我们来了解一下 general log 一般日志,有时候也叫做通用、普通、日志。
general log
在默认情况下,MySQL 是不会打开 general log 的,这个 log 里面会记录 MySQL 所有的 SQL 语句,不管是查询语句,还是 DML 语句,还是 DDL 语句,还是 DCL 语句,这些语句统统都会被记录在 general log 文件中。就连我们连接和断开 MySQL 数据库的这些语句。
MySQL 会把它收到的所有 SQL 语句按照接收的顺序依次记录在 general log 中。我们需要注意的是,这里接受的 SQL 语句的顺序,并不等于 SQL 语句就是按照这个接受的顺序来执行,因为有的时候,一些 SQL 可能需要等待其他锁被释放后才会被真正的执行,SQL 语句的执行顺序是和 binlog 中的顺序是相匹配的。
假如我们执行一个select
查询语句,在 binlog 中不会记录这样的 SQL 语句,但是在 general log 中就会记录这个select
查询语句。
General log 默认不开启的原因有两个:
- 日志将会非常大,对磁盘是一个很大的压力。因为所有的操作都会被记录下来。
- 对 MySQL 数据的性能有一定的影响。
所以,我们一般不会开启这个 general log 记录的功能,只有在排查某些错误的时候,才会临时打开一下,等到 debug 完成之后,再把它关闭。
如何开启 general log
如果在配置文件中永久开启:
[mysqld]
general_log=1
general_log_file=mysql_general_log.log
log_output=/var/lib/mysql
在 SQL 命令行中临时开启:
mysql> show variables like 'general_log'; -- 查看日志是否开启
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log | OFF |
+---------------+-------+
1 row in set (0.02 sec)
mysql>
mysql> show variables like 'general_log_file'; -- 看看日志文件保存位置
+------------------+-------------------------+
| Variable_name | Value |
+------------------+-------------------------+
| general_log_file | /var/lib/mysql/test.log |
+------------------+-------------------------+
1 row in set (0.02 sec)
mysql>
mysql> show variables like 'log_output'; -- 看看日志输出类型 table或file
+---------------+------------+
| Variable_name | Value |
+---------------+------------+
| log_output | FILE,TABLE |
+---------------+------------+
1 row in set (0.01 sec)
general log 的参数
general log 的参数主要有以下几个:
- genral_log:用于控制是否开启 general log。等于
0
表示关闭,等于1
表示开启。默认是0
。 - general_log_file:general log 日志的文件名是什么,如果不配置这个参数的话,默认会以 MySQL 服务器的 hostname 作为 general log 日志的文件名称,具体文件为:
<hostname>.log
,general log 日志的存放路径。如果不指定,则默认放在datadir
参数所指定的目录下。也可以在这个参数中指定具体的路径 + 名称。 - log_output:general log 输出的方式,是输出表中,还是保存到文件中。这个参数的取值范围为:table,或者 file。默认是保存到 file 文件中。这个参数是和慢查询日志是共用的,慢查询的日志是记录在表中还是只记录在文件中,也是用这个参数来控制。如果配置为 table,就会把慢查询日志和 general log 日志都写在
mysql.geneal_log
表中。如果这个参数配置为table,file
则表示即写入表中,也写入日志文件中,两个地方都写入日志。
在开启了 general log 的前提下,如果在某个 session 连接中,不想让此次操作的所有 SQL 被记录在 general log 中,则可以在 session 中执行set session sql_log_off=on
就可以关闭当前 session 的操作被记录在 general log 中。
general log 开启示例
接下里我们会针对开启 general log 做两个实验:
- 在命令行中,通过命令暂时开启。这种开启方式,在 MySQL 实例被重启的以后,会失效。
- 在配置文件中,配置参数开启。这种开启方式,永久生效,即便 MySQL 实例重启后,仍然有效。
通过命令暂时开启
我们来开启 general log 感受一下,下面我们登录到 MySQL 的命令行窗口,使用set global general_log=on;
命令来开启。开启过程如下所示:
mysql> set session general_log=on; -- 这是一个全局参数,不能只针对当前session启用。
ERROR 1229 (HY000): Variable 'general_log' is a GLOBAL variable and should be set with SET GLOBAL
mysql> set global general_log=on; -- 对全局开启general log
Query OK, 0 rows affected (0.03 sec)
因为我的log_output
参数配置的是FILE,TABLE
,所以我的 general log 会记录在两个地方,一个是 general log 日志文件,一个是表中。日志保持方式的参数配置如下所示:
mysql> show variables like 'log_output';
+---------------+------------+
| Variable_name | Value |
+---------------+------------+
| log_output | FILE,TABLE |
+---------------+------------+
1 row in set (0.02 sec)
查看 general log 文件中的日志,当log_output
参数有FILE
的时候,general log 日志文件的目录默认在datadir
目录下面。前面我们开启 general log 的时候,因为没有显示的去指定 general log 日志的文件目录和文件名称,所以它默认是存放在datadir
目录下,文件名称为<主机名称>.log
。我可以看到在datadir
目录下面如下日志:
root@test:/var/lib/mysql# pwd
/var/lib/mysql
root@test:/var/lib/mysql# ls -lstr *.log
8 -rw-r----- 1 mysql mysql 6293 Jan 13 15:40 test-slow.log
4 -rw-r----- 1 mysql mysql 2589 Jan 13 15:50 test.log
root@test:/var/lib/mysql# hostname
test.mysql
root@test:/var/lib/mysql#
我们来看下这个日志文件中的内容是什么,具体如下所示,可以看出所有的查询语句都会被记录在 general log 日志中。即便是查询语句也会被记录在里面。
上面我们看了 general log 日志文件中的内容,我们的配置还要去记录日志到表中,具体是记录在mysql.general_log
表中。我们看下这个表中记录的内容。使用下面的 SQL 语句来查看表中的内容。
select
event_time,user_host,thread_id,server_id,command_type,
convert(argument using utf8mb4) as sql_text
from general_log limit 100;
通过配置文件永久开启
上面我们是通过set
命令参数来开启的 general log,下面我们采用在配置文件中配置 general log 日志文件参数的方式来开启。在使用配置文件来开启之前,我们先把前面我们使用set
命令开启的操作给修改回去,然后再去修改配置文件来开启 general log 日志文件。先用下面的命令改回去。
mysql> set global general_log=off;
Query OK, 0 rows affected (0.02 sec)
改回去之后,我们再去看下日志文件中的内容。
我们在my.cnf
配置文件中配置的具体参数如下,为了测试,我把 general log 日志文件路径和名称都修改一下。看下效果如何。修改完成如下参数后,重启 MySQL 服务。
[mysqld]
# 一般日志的开启
general_log=1
general_log_file=/tmp/mysql_general_log.log
这里顺便说一下,我的 MySQL 实例是用 docker 启动的一个容器镜像。用 docker 启动 MySQL 示例,兼职不要太方便,把参数配置文件挂载到本地,随便怎么修改参数文件,然后直接一个docker restart <容器名称或容器id>
,直接搞定。在以后介绍一下关于 docker 的一些基本使用。
重启 MySQL 示例之后,啥都不做,直接去 MySQL 的/tmp
下面看是否有mysql_general_log.log
文件生成。检查结果如下,可以看到已经有 general log 文件生成。
root@test:/tmp# pwd
/tmp
root@test:/tmp# ls
mysql_general_log.log
root@test:/tmp# more mysql_general_log.log
mysqld, Version: 5.7.24-log (MySQL Community Server (GPL)). started with:
Tcp port: 0 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
root@test:/tmp#
接下来,我们来执行一些 SQL,看下日志是否可以正常记录在/tmp/mysql_general_log.log
文件中,验证过程如下所示:
去看下mysql.genenal_log
表中是否也会正常记录,检查结果如下:
关闭 general log
在关闭 general log 的时候,我们只要把对应的配置在配置文件中删除或使用#
注释掉或者删除掉,在修改完配置文件之后,然后再 MySQL 的命令行中,执行set global general_log=off;
命令就可以马上关闭 general log 记录的功能,因为我们已经修改过配置文件,所以即便是 MySQL 重启之后,general log 也不会开启了。
注意:如果只是修改了配置文件,但是没有在命令行中使用 set 命令关闭 general log,重启 MySQL 实例之后,general log 仍然处于开启状态。所以,即便是修改了配置文件,也要使用set global general_log=off
命令关闭日志才可以。
如果我们只是通过set
命令的方式去开启的,没有去修改配置文件。那么我们只需使用set
命令的方式关闭即可了,不用去动配置文件了。在真正的 debug 错误的时候,推荐使用这种set
命令的方式去临时开启和关闭 general log 日志,而不用去修改my.cnf
配置文件。
清理 general log 文件
开启 general log 之后,日志文件会增长得很快,如果我们需要清理历史的 general log 文件,我们该怎么做?
-
如果是记录在文件中,使用 cp 命令,把 general log 日志文件备份一下 (如果你确定这些历史的 general log 不在需要,那么可以不执行备份的这一步操作),然后使用管道命令把文件内容清空。操作大致如下:
cp mysql_general_log.log mysql_general_log.log.bak
echo "" > mysql_general_log.log** 注意:** 切记不要直接删除这个日志文件,否则这个文件不会自动生成,除非你重启 MySQL 数据实例。如果删除后,即便是你手动创建一个一样名称的日志文件,MySQL 也不会把 general 日志记录进去。所以,我们只能在 MySQL 自己生成的文件中进行编辑,删除里面的内容。
对于我们备份生产的文件
mysql_general_log.log.bak
,如果有必要留存,就拷贝到其他服务器或者其他归档存储中。如果没有必要留存,那么直接rm
删除这个 bak 的 log 文件就可以了。 -
如果是记录在表中。先使用
create table xx as select
命令备份个表 (如果你确认不需要历史的 general log,那么你可以不执行备份操作)。然后,执行truncate
命令删除表中数据。操作大致如下:create table mysql.general_log_bak as select * from mysql.general_log;
truncate table mysql.general_log; -- 注意:这个表只能执行select或者truncate,没有insert,update,delete权限来操作。慢查询日志的中mysq.slow_log也是这权限。对于我们创建的备份表
mysql.general_log_bak
,如果日志内容有必要留存,那么把这个表使用 mysqldump 备份出来然后归档存放,如果没有必要留存,那么直接drop
删除这个 bak 的表就可以了。
总结
一般情况我们不会开启 general log 日志,因为它的增长速度太快了。磁盘很快就会被占用完了。所以一般只有在需要 debug 一些特别难找的 bug 的时候,才会使用set global general_log=on
开启,在生产我们需要的 debug 日志以后,就直接使用set global general_log=off
关闭了。这里面的日志记录很详细,在排查一下比较隐蔽的问题的时候,还是可以提供很多有用的信息的。
MySQL 的 general log 就分享到这里了。后面我会分享关于 MySQL 的最后一个日志:error 错误日志。