MySQL的日志相关内容
本篇文章介绍一下mysql的备份和日志,由于备份时需要用到日志,所以在讲备份前,如果日志内容篇幅过长,将会把日志和备份分开单独来讲,先简单介绍一下mysql的日志相关内容。
MySQL日志
日志是mysql数据库的重要组成部分。日志文件中记录着mysql数据库运行期间发生的变化;也就是说用来记录mysql数据库的客户端连接状况、SQL语句的执行情况和错误信息等。当数据库遭到意外的损坏时,可以通过日志查看文件出错的原因,并且可以通过日志文件进行数据恢复。
mysql主要包含:错误日志、查询日志、慢查询日志、事务日志、二进制日志,中继日志;比较重要的日志有错误日志,慢查询日志,二进制日志。下面对这几种日志内容做简单介绍:
错误日志
错误日志是mysql的重要日志之一,它记录了mysql启动和停止时,以及服务器在运行过程中发生的任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时,可以首先查看错误日志。
错误日志的定义在my.cnf中定义:
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
如果没有在my.cnf中定义错误日志,那么mysqld会使用host_name.err(主机名命名),并默认存放在DATADIR定义的目录下。
慢查询日志
慢查询日志记录了所有执行时间超过参数long_query_time(单位:秒)设置的值,long_query_time的默认时间为10秒,最小为0,精度可以到微妙。
MariaDB [(none)]> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)
慢查询日志默认没有开启:查看慢查询是否启用:
MariaDB [(none)]> show variables like 'slow%';
+---------------------+---------------------------------+
| Variable_name | Value |
+---------------------+---------------------------------+
| slow_launch_time | 2 |
| slow_query_log | ON |
| slow_query_log_file | /var/log/mariadb/mysql_slow.log |
+---------------------+---------------------------------+
3 rows in set (0.00 sec)
启用慢查询
slow_query_log是全局变量,支持命令设置启用或关闭,要注意的是,在终端使用指令设置不能永久生效:
MariaDB [(none)]> set global slow_query_log=ON | OFF;
要永久生效需要在配置文件中进行定义:
[mysqld]
slow_query_log=on
重启服务后生效。查看开启状态:
MariaDB [(none)]> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name | Value |
+----------------+-------+
| slow_query_log | ON |
+----------------+-------+
1 row in set (0.00 sec)
同时,开启慢查询后,会默认在将日志写入DATADIR目录下,命名为host_name_slow.log;当然,可以使用slow_query_log_file=/path/filename,的方式来定义慢查询日志存放路径。下面是自定义日志路径:
[mysqld]
slow_query_log=on
slow_query_log_file=/var/log/mariadb/mysql_slow.log
重启服务查看/var/log/mariadb/mysql_slow.log是否生成
systemctl restart mariadb
[root@localhost mysql]# ls /var/log/mariadb/
mariadb.log mariadb.log.rpmsave mysql_slow.log
设置long_query_time的阀值
上面提到了只要查询时间超过long_query_log设置的值才会被记录到慢查询日志中,所以这个阀值要根据实际的应用环境来定。
设置long_query_time阀值:
MariaDB [(none)]> set long_query_time=1;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show variables like 'long_query_time';
+-----------------+----------+
| Variable_name | Value |
+-----------------+----------+
| long_query_time | 1.000000 |
+-----------------+----------+
1 row in set (0.00 sec)
为了测试一下慢查询日志,在上将查询时间设置成了一秒
MariaDB [db4]> select sleep(2), id from tb1 where id = 55;
+----------+------+
| sleep(2) | id |
+----------+------+
| 0 | 55 |
+----------+------+
1 row in set (3.90 sec) #查询时间3.9秒
MariaDB [db4]> select id from tb1 where id = 55;
+------+
| id |
+------+
| 55 |
+------+
1 row in set (0.00 sec)
查看慢查询日志
# User@Host: root[root] @ localhost []
# Thread_id: 5 Schema: db4 QC_hit: No
# Query_time: 3.898127 Lock_time: 1.889486 Rows_sent: 1 Rows_examined: 49
SET timestamp=1528775278;
select sleep(2), id from tb1 where id = 55;
可以看到,查询时间超过1秒的查询被记录在日志中,最后的查询则没有被记录。
官方提供的mysqldumpshow 慢查询分析工具可实现功能如下
- 统计不同慢sql的
- 出现次数(Count),
- 执行最长时间(Time),
- 累计总耗费时间(Time),
- 等待锁的时间(Lock),
- 发送给客户端的行总数(Rows),
- 扫描的行总数(Rows),
其他定义参数
log_slow_filter:
log_slow_filter是慢查询的一个过滤机制,在log_slow_filter所定义的操作如果执行时间超过慢查询定义的阀值,操作将会被记录到慢查询日志中
log_queries_not_using_indexes
log_queries_not_using_indexes是定义是否记录没有使用索引查询语句,默认为OFF
MariaDB [db4]> show variables like 'log_queries_not_using_indexes';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| log_queries_not_using_indexes | OFF |
+-------------------------------+-------+
1 row in set (0.00 sec)
启用该参数:
MariaDB [db4]> set global log_queries_not_using_indexes=on;
Query OK, 0 rows affected (0.00 sec)
log_slow_rate_limit = 1
log_slow_rate_limit 定义多少次查询才会记录到日志中
查看慢查询状态
MariaDB [db4]> show variables like '%slow%';
+---------------------+--------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------------+--------------------------------------------------------------------------------------------------------------+
| log_slow_filter | admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk |
| log_slow_queries | ON |
| log_slow_rate_limit | 1 |
| log_slow_verbosity | |
| slow_launch_time | 2 |
| slow_query_log | ON |
| slow_query_log_file | /var/log/mariadb/mysql_slow.log |
+---------------------+--------------------------------------------------------------------------------------------------------------+
7 rows in set (0.00 sec)
二进制日志
二进制日志(bin-log)记录了所有DDL(数据定义语句)和DML(数据操纵语句),对数据库结构,内容产生改变的操作都被记录到二进制日志中。
日志的位置格式
在配置文件中定义bin-log选项即可启用二进制日志,mysqld开始将数据变更情况写入日志文件,如果没有定义日志文件名,系统默认会用主机名后面跟‘-bin’,如果指定了文件名称没有指定日志存放路径,默认存放在DATADIR的目录下。
[mysqld]
log_bin=master-log
查看bin-log是否启用
MariaDB [(none)]> show variables like '%log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
| sql_log_bin | ON |
+---------------+-------+
2 rows in set (0.00 sec)
log_bin与 sql_log_bin要同时启用,sql_log_bin默认开启,log_bin默认为OFF,需要定义存放位置与名称。
bin-log日志记录格式
binlog_format=STATEMENT|ROW|MIXED:二进制日志记录的格式,默认为STATEMENT
Row :bin-log会记录成【每一行数据被修改的形式】,然后在Slave端再对相同的数据进行修改。
优点:在Row Level模式下,Binnary Log可以不记录执行的Query语句的上下文相关信息,只要记录哪一行修改了,修改成什么样子。Row Level会详细的记录下每一行数据的修改细节,而且不会出现某个特定情况下的存储过程,或Function,以及Trigger的调用和触发无法被正确复制问题。
缺点:所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如一条update语句,修改多条记录,则binlog中每一条修改都会有记录,这样造成binlog日志量会很大,特别是当执行alter table之类的语句的时候,由于表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。
Statment :【每一条会修改的SQL语句】都会记录到Master的Binnary中。Slave端在复制的时候,SQL线程会解析成和原来Master端执行过相同的SQL语句,并再次执行。
优点:首先,解决了Row Level下的缺点,不须要记录每一行的数据变化,减少了Binnary Log日志量,节约了IO成本,提高了性能。(相比row能节约多少性能与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条件的update操作,以及整表删除,alter表等操作,ROW格式会产生大量日志,因此在考虑是否使用ROW格式日志时应该跟据应用的实际情况,其所产生的日志量会增加多少,以及带来的IO性能问题。)
缺点:由于它是记录的执行语句,为了让这些语句在Slave端也能正确执行。那么它还必须记录每条语句在执行时的一些相关信息,即上下文信息,以保证所有语句在Slave端被执行的时候能够得到和在Master端执行时相同的结果。
Mixed :在Mixed模式下, 是以上两种level的混合使用。
Mixed 混合了Statment 和 Row两种日志,默认情况下才用Statment 格式来记录,但是在一些特定的情况下使用row来记录更优更合理,mixed,可以让系统自行判定该基于哪种方式进行,这正是比较好的地方,但是在主从环境下,可能会产生主从之间的数据不一致。
Mysql默认是使用Statement日志格式,推荐使用MIXED.
查看默认bin-log记录格式
MariaDB [(none)]> show variables like 'binlog_format';
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)
二进制日志相关定义参数
在配置文件中定义好log_bin=master-log之后,在数据库数据存放目录中会生成名为master-log.000001的文件,该文件就是二进制日志文件,而master-log.index文件是索引日志文件。
一些相关参数定义
-
sql_log_bin= ON | OFF:是否记录二进制日志,默认ON
-
log_bin=/PATH/BIN_LOG_FILE:指定文件位置;默认OFF,表示不启用二进制日志功能,上述两项都开启才可
-
binlog_format=STATEMENT|ROW|MIXED:二进制日志记录的格式,默认STATEMENT
以上参数上面内容已经提到过 -
max_binlog_size=1073741824;单个二进制日志文件的最大体积,到达最大值会自动滚动,默认为1G
查看当前二进制日志文件的大小定义
MariaDB [(none)]> show variables like 'max_binlog_size';
+-----------------+------------+
| Variable_name | Value |
+-----------------+------------+
| max_binlog_size | 1073741824 | #1G
+-----------------+------------+
1 row in set (0.00 sec)
- sync_binlog=1|0;设定是否启动二进制日志即时同步磁盘功能,默认0,由操
作系统负责同步日志到磁盘
sync_binlog 参数是比较重要的参数,在mysql的复制中,可以增加slave节点的复制可靠性。在主从复制中应该启用为 1
MariaDB [(none)]> set global sync_binlog=1;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show variables like 'sync_binlog';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sync_binlog | 1 |
+---------------+-------+
1 row in set (0.00 sec)
- expire_logs_days=N:二进制日志可以自动删除的天数。 默认为0,即不自动
删除
MariaDB [(none)]> show variables like 'expire_logs_days';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| expire_logs_days | 0 |
+------------------+-------+
1 row in set (0.00 sec)
Mysql BInlog日志格式可以通过mysql的my.cnf指定。如以下:
log_bin=master-bin #binlog日志名
binlog_format = MIXED # binlog日志格式
expire_logs_days = 7 #binlog过期清理时间
max_binlog_size 100m #binlog每个日志文件大小
sync_binlog=1 #启用bin-log同步功能
二进制日志读取-mysqlbinlog
由于日志是以二进制方式存储的,不能直接读取,需要使用mysqlbinlog工具来查看。
shell> mysqlbinlog log-file
mysqlbinlog 指令常用选项:
-d dbname: 指定数据库名称
-o #: 忽略掉日志中的前#个命令
-r : 将输出的文件格式日志输出到指定文件,重定向
-s : 简单格式显示,忽略掉一些信息
--set-charset=charname : 在输出文件时加上set name charname ,装载数据时有用
--start-datetime= # : 指定从开始时间显示内容
--stop-datetime= # : 指定内容到结束的时间点
--start-position= # :指定开始的pos值位置
--stop-position= # : 指定到结束的pos值位置
测试创建一张空白查看二进制日志记录的内容
MariaDB [db5]> create table tb1 (
-> id int,
-> name varchar(20)
-> ) charset=utf8;
Query OK, 0 rows affected (0.33 sec)
查看bin-log
[root@localhost mysql]# mysqlbinlog master-bin.000006
# at 245
#180612 16:26:22 server id 1 end_log_pos 370 Query thread_id=4 exec_time=0 #该行记录了当前最新的pos值,使用show master status查看: error_code=0
use `db5`/*!*/;
SET TIMESTAMP=1528791982/*!*/;
SET @@session.pseudo_thread_id=4/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=0/*!*/;
SET @@session.auto_increment_increment=2, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
create table tb1 (
id int,
name varchar(20)
) charset=utf8
/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
MariaDB [db5]> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000006 | 370 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
也可以使用指定pos值的方式来查看
[root@localhost mysql]# mysqlbinlog --start-position=245 --stop-position=370 master-bin.000006
二进制日志的删除
在繁忙的系统中,每天都会生成大量的日志文件,如果时间长不进行清理会对磁盘空间造成负担,定义备份好日志文件并清理日志是很有必要的工作。
删除日志的方式
- 方法1
执行reset master; 指令
该命令将删除所有bin-log日志,新的日志编号从000001开始。
- 方法2
执行purge master logs to 'master-bin.******' , 执行该命令将会删除指定该编号前的所有的bin-log日志文件。
MariaDB [db5]> purge master logs to 'master-bin.000006';
Query OK, 0 rows affected (0.81 sec)
只保留了master-bin.000006以后的日志
关于一些比较的重要的日志就说这么多,后面再介绍mysql的备份内容。