清理MySQL中的binlog

Posted 硅谷工具人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了清理MySQL中的binlog相关的知识,希望对你有一定的参考价值。

mysql的binlog开启后一直没清理,占用太大空间

1.查看binlog过期时间

show variables like 'expire_logs_days';

expire_logs_days=0:
这里的值如果为0,表示所有binlog日志永久都不会失效,不会自动删除;
这里的值如果为30,表示只保留最近30天。

2. 修改binlog过期时间

  1. 永久生效(重启后即生效)
    修改配置文件my.cnf文件: vim /etc/my.cnf
在[mysqld]标签内增加如下内容
expire_logs_days=30
max_binlog_size=1024M

修改保存后,以下3种情况才生效
1)当binlog大小超过max_binlog_size
2)手动执行flush logs
3)重新启动

为了使之生效,需要执行flush logs。
mysql> flush logs;
Query OK, 0 rows affected, 64 warnings (0.16 sec

3.手工清除历史binlog

如果binlog非常多,推荐使用purge命令予清除历史文件:
比如将mysql-bin.009560之前的binlog清掉:

mysql>purge binary logs to 'mysql-bin.009560';

或者指定时间之前的binlog清掉:

mysql>purge binary logs before '2022-01-01 23:59:59';

Mysql日志---binlog

Mysql日志---binlog


背景

MySQL中到底有多少种log?你是否经常听别人说什么binlog、binary log、redo log、undo log、回滚日志、重做日志、中继日志、错误日志、慢查询日志、一般日志等等。这些概念都分别是什么?MySQL生成这些日志的目的都是什么?

接下来我们一起来分析一下MySQL中到底有哪些log吧。

MySQL中的日志分类

MySQL中经常遇到的日有以下几种:

  • Binlog:全称是binary log,简称为binlog,就是我们平时说的二进制日志,
  • Relay log:中继日志
  • Redo log:重做日志
  • Undo log:回滚日志
  • Slow query log: 慢查询日志
  • General log:一般日志
  • Error log:错误日志

接下来,我们一个一个分别了解一下它们。今天这篇文章主要是分析一些binlog日志,其他的日志会在后续的文章中逐个分析。

Binlog

binlog是大家学习MySQL中经常遇到的,也是必须要了解的。它在MySQL中所起到的作用可是举足轻重的。

binlog在MySQL中默认是不开启的,因为开启它需要消耗一定的性能。如果我们需要使用到binlog则可以选择性的开启它。比如我们需要做主从同步的集群环境的时候,master主库上面的binlog是必须要打开的。这也是binlog存在的一个重要的功能,为主从同步提供支撑。

在做增量恢复的时候,binlog日志也起着至关重要的作用。比如:我们在今天凌晨零点的时候有一次全量的备份,然后今天上午有一个误操作把数据库给删除了。此时如果我们想要恢复数据库,则可以先恢复今天凌晨零担的全量备份文件,然后再基于还原后的数据库,再使用凌晨零点之后到当前删除数据库的时间点为止,这一段时间内的binlog做增量恢复,这样的数据库在还原之后,就是我们一个完整的数据库。

验证binlog日志是否开启

验证我们的MySQL数据库是否开启binlog可以使用show variables like '%log_bin%';命令,下面分别是在一个没有开启binlog和开启binlog日志的MySQL实例上验证的效果。

下面是在没有开启binlog日志的MySQL实例上验证的效果:

mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin                         | OFF   |/*这里显示OFF,表示没有开启binlog日志。*/
| log_bin_basename                |       |
| log_bin_index                   |       |
| log_bin_trust_function_creators | OFF   |
| log_bin_use_v1_row_events       | OFF   |
| sql_log_bin                     | ON    |
+---------------------------------+-------+
6 rows in set (0.02 sec)

下面是在开启了binlog日志的MySQL实例上验证的效果:

mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name                   | Value                          |
+---------------------------------+--------------------------------+
| log_bin                         | ON                             |/*这显示ON,表示已经开启binlog*/
| log_bin_basename                | /var/lib/mysql/mysql-bin       |/*这是binlog日志文件存放的目录和名称*/
| log_bin_index                   | /var/lib/mysql/mysql-bin.index |/*这是binlog日志文件的索引文件目录和名称*/
| log_bin_trust_function_creators | OFF                            |
| log_bin_use_v1_row_events       | OFF                            |
| sql_log_bin                     | ON                             |
+---------------------------------+--------------------------------+
6 rows in set (0.02 sec)

需要我们注意其中的两个参数:

  • log_bin_basename:这里是配置的binlog日志文件的存放的目录和名称,可以从上面查看的结果中看出,这里的没有配置binlog日志文件的后缀名。因为binlog日志是一个一直滚动追加的日志文件,当超过一个指定的默认值(通常是1GB大小)之后,他会自动切分为一个新的binlog日志文件。文件的后缀名就是它滚动增长的标识符。它是一个有规律增长的序列,000001,000002,000003…999999
  • log_bin_index:这个参数配置的是binlog日志的索引文件存储目录和名称,这里面记录了MySQL目前所有的有效的binlog日志文件列表。每一个binlog日志文件一行,按照binlog日志生成的时间顺序,依次排列下来。

开启和关闭binlog日志

如果我们想开启binlog日志,该如何开启呢?我们可以通过修改MySQL的my.cnf配置文件来开启。在MySQL的my.cnf配置文件中增加如下的配置即可开启binlog:

[mysqld]
# 启用二进制日志
log-bin=mysql-bin

# 主服务器唯一ID,可以使用主机IP地址的最后一个域值来作为MySQL集群中的serverid,5.7版本之后,在启用binlog的时候,这个参数也需要一并指定。否则启动MySQL服务失败。
server-id=100

# 设置binlog日志的格式
binlog_format=row
binlog_row_image=minimal

开启binlog之后,它会记录我们的哪些操作呢?我们平时对MySQL的操作有增、删、改、查,这些操作都会被记录在MySQL的binlog日志文件中吗?其实它只会记录我们的增、删、改的操作,查询的操作它是不会记录的。也就是说,它只记录对数据库有变更的操作,如果没有变更则不会记录在binlog日志文件中。

对于平时我们的一些DDL操作也会被记录在binlog日志文件中。比如我们删除一个表、增加一个列、创建一个索引、删除一个索引等这样的操作,也会被记录在binlog日志文件中。

我们知道,一个MySQL数据库实例下面可以有多个schema,也就是我们平时说的数据库。对于一个实例下面所有的数据库的操作的SQL语句,它们不会分开来存储在binlog日志文件中的。在binlog日志文件还没有切换新的文件的时候,在一定时间段内,所有的schema的操作语句都会记录在同一个binlog日志文件中。

如果我们要关闭binlog日志功能,可以把上面的参数log-bin=mysql-bin使用#注释掉这一行配置,然后重启MySQL实例就可以关闭binlog了。


如何选择性的开启binlog

如果一个MySQL数据库实例开启了binlog日志功能,那么能否做到只针对某几个schema(数据库)的操作才记录binlog日志,对其他schema(数据库)的操作不记录呢?

对于有些主从同步的业务场景下可能存在这样的业务需求。MySQL中可以使用两个参数binlog_do_db和binlog_ignore_db来满足这样的需求,如果不配置这两个参数,默认是会记录所有数据库的变更操作到binlog日志中。具体配置可以在my.cnf配置文件中参考如下的配置:

[mysqld]
# 此参数表示只记录制定数据库的二进制日志,下面配置的是只记录mydb1,mydb2,mydb3,mydb4着四个数据库的binlog日志,其他数据库的binlog日志不记录。
binlog_do_db=mydb1,mydb2,mydb3,mydb4

# 此参数标示不记录指定的数据库的二进制日志,下面的配置是忽略MySQL自带的几个数据库的binlog日志。
binlog_ignore_db=mysql,sys,information_schema,performance_schema

上面我们已经可以通过参数来为指定的数据库开启记录binlog日志,那么我们再细粒度分析一下,对于一个已经配置为需要记录binlog日志的schema(数据库)来说,难道对这个数据库所有有变更操作的SQL,都要被记录在binlog中吗?有没有办法让某一些操作不被记录在二进制日志中呢?

答案是肯定的。我们可以通过参数sql_log_bin参数来控制某些有变更的SQL语句是否可以被记录在binlog中。

该参数在配置开启binlog之后是默认为on的状态,表示所有有变更的SQL语句都会被记录在binlog中。如果不想记录某些SQL语句,只要在执行对应的SQL语句之前将这个参数设置为off就可以避免接下来执行的SQL语句被记录在binlog日志中。

下面是使用sql_log_bin参数来控制是否记录某些SQL语句到binlog日志中的实验示例,因为我没有在my.cnf配置文件中配置binlog_do_dbbinlog_ignore_db参数,所以,对于MySQL中所有的数据库的变更操作都会别记录在binlog日志文件中。实验步骤和结果如下:

  • 先检查当前session级别的sql_log_bin参数的值。
  • 将参数sql_log_bin的值设置为OFF。
  • 查看设置的结构是否为OFF。
  • 当前binlog日志文件的名称和位置。
  • 创建一个表t。
  • 再次检查binlog日志文件的名称和位置,看是否发生变化。
  • 查看binlog日志文件的具体内容,查看是否有记录前面创建表t的DDL语句。
  • 把当前session级别的sql_log_bin参数设置为ON。
  • 检查设置的结果是否为ON。
  • 检查当前binlog日志的文件名称和位置。
  • 创建一个表a。
  • 再次检查当前binlog日志的文件名称和位置,看是否发生变化。
  • 检查binlog日志的具体内容,看是否包含创建表a的DDL语句。
mysql> show variables like 'sql_log_bin';/*查看当前sql_log_bin参数的值为on,表示会记录所有当前session操作的SQL语句。*/
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin   | ON    |
+---------------+-------+
1 row in set (0.01 sec)

mysql> set session sql_log_bin=off;/*关闭当前session记录binlog的功能*/
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'sql_log_bin';/*查看后,确实关闭的session的binlog记录功能。*/
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin   | OFF   |
+---------------+-------+
1 row in set (0.01 sec)

mysql> show master status;/*查看当前binlog日志的文件名称和位置。*/
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000013 |      632 |              | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

mysql> create table t(id int);/*创建了一个表t,这个DDL语句应该不会被记录在binlog日志中。*/
Query OK, 0 rows affected (0.03 sec)

mysql> show master status;/*再次查看当前binlog日志的文件名称和位置,和创建表t之前的文件名称和位置是相同的,就是说binlog日志并没有向后滚动增加。*/
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000013 |      632 |              | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

mysql> show binlog events in 'mysql-bin.000013';/*查看binlog日志文件中内容,确实没有看到关于创建表t的SQL语句,证明我们的操作是正确的。*/
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                                   |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| mysql-bin.000013 |   4 | Format_desc    |       100 |         123 | Server ver: 5.7.24-log, Binlog ver: 4                                                  |
| mysql-bin.000013 | 123 | Previous_gtids |       100 |         154 |                                                                                        |
| mysql-bin.000013 | 154 | Anonymous_Gtid |       100 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                   |
| mysql-bin.000013 | 219 | Query          |       100 |         367 | use `feng`; create table test(id int primary key auto_increment, a varchar(16), b int) |
| mysql-bin.000013 | 367 | Anonymous_Gtid |       100 |         432 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                   |
| mysql-bin.000013 | 432 | Query          |       100 |         504 | BEGIN                                                                                  |
| mysql-bin.000013 | 504 | Table_map      |       100 |         555 | table_id: 115 (feng.test)                                                              |
| mysql-bin.000013 | 555 | Write_rows     |       100 |         601 | table_id: 115 flags: STMT_END_F                                                        |
| mysql-bin.000013 | 601 | Xid            |       100 |         632 | COMMIT /* xid=30 */                                                                    |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
9 rows in set (0.00 sec)

mysql> set session sql_log_bin=on;/*开启当前session,记录binlog日志的功能。*/
Query OK, 0 rows affected (0.01 sec)

mysql> show variables like 'sql_log_bin';/*验证是否真正的开启,下面结果为ON,表示确实开启了session级别记录binlog日志的功能。*/
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin   | ON    |
+---------------+-------+
1 row in set (0.01 sec)

mysql> show master status;/*查看当前binlog日志文件的名称和位置。*/
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000013 |      632 |              | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

mysql> create table a(id int);/*创建一个表a,这个创建表a的DDL语句应该被记录在binlog日志文件中。*/
Query OK, 0 rows affected (0.05 sec)

mysql> show master status;/*创建完表a之后,再次查看binlog日志文件的名称和位置,发现位置比之前增加了一些。从632变成了793。*/
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000013 |      793 |              | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql> show binlog events in 'mysql-bin.000013';/*查看binlog日志文件中的内容。发现里面确实记录了创建表a的DDL语句*/
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                                   |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
| mysql-bin.000013 |   4 | Format_desc    |       100 |         123 | Server ver: 5.7.24-log, Binlog ver: 4                                                  |
| mysql-bin.000013 | 123 | Previous_gtids |       100 |         154 |                                                                                        |
| mysql-bin.000013 | 154 | Anonymous_Gtid |       100 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                   |
| mysql-bin.000013 | 219 | Query          |       100 |         367 | use `feng`; create table test(id int primary key auto_increment, a varchar(16), b int) |
| mysql-bin.000013 | 367 | Anonymous_Gtid |       100 |         432 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                   |
| mysql-bin.000013 | 432 | Query          |       100 |         504 | BEGIN                                                                                  |
| mysql-bin.000013 | 504 | Table_map      |       100 |         555 | table_id: 115 (feng.test)                                                              |
| mysql-bin.000013 | 555 | Write_rows     |       100 |         601 | table_id: 115 flags: STMT_END_F                                                        |
| mysql-bin.000013 | 601 | Xid            |       100 |         632 | COMMIT /* xid=30 */                                                                    |
| mysql-bin.000013 | 632 | Anonymous_Gtid |       100 |         697 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                   |
| mysql-bin.000013 | 697 | Query          |       100 |         793 | use `feng`; create table a(id int)   /*这里就是记录的表a的DDL语句*/                                                  |
+------------------+-----+----------------+-----------+-------------+----------------------------------------------------------------------------------------+
11 rows in set (0.01 sec)

参数sql_log_bin在某些时候很有好用,比如在主从同步读写分离的情况下,为了避免在执行某些DDL语句而导致主从同步延迟的问题发生,我们会在主和从上分别执行我们的DDL语句,这个时候,我们是不希望在主上执行的DDL语句被记录在binlog日志文件中,因为我们不想通过组从同步的方式在从节点上执行DDL,我们想自己在从节点上执行DDL,此时参数sql_log_bin就可以满足我们的这个需求。

只要我们在主节点上执行DDL之前,把参数sql_log_bin设置为OFF,然后再去执行我们的DDL语句,这样这个DDL语句就不会被记录在binlog日志中,也就不会被同步到从节点上。


开启binlog日志后的效果

开启binlog日志文件之后,我们可以在对应的日志文件目录下面看到binlog日志,如下所示:

root@test:/var/lib/mysql# pwd
/var/lib/mysql
root@test:/var/lib/mysql# ls -lsr mysql-bin*
4 -rw-r----- 1 mysql mysql  133 Dec 30 18:00 mysql-bin.index
4 -rw-r----- 1 mysql mysql  154 Dec 30 18:00 mysql-bin.000007
4 -rw-r----- 1 mysql mysql  177 Dec 30 18:00 mysql-bin.000006
4 -rw-r----- 1 mysql mysql  177 Dec 30 17:56 mysql-bin.000005
8 -rw-r----- 1 mysql mysql 5703 Dec 30 17:39 mysql-bin.000004
4 -rw-r----- 1 mysql mysql  177 Dec 29 15:00 mysql-bin.000003
4 -rw-r----- 1 mysql mysql  177 Dec 28 15:45 mysql-bin.000002
4 -rw-r----- 1 mysql mysql  177 Dec 28 15:45 mysql-bin.000001
root@test:/var/lib/mysql# cat mysql-bin.index
./mysql-bin.000001
./mysql-bin.000002
./mysql-bin.000003
./mysql-bin.000004
./mysql-bin.000005
./mysql-bin.000006
./mysql-bin.000007
root@test:/var/lib/mysql#

从上面我们可以看到,binlog日志文件的索引文件中记录的是当前有效的binlog日志文件列表。当binlog文件的编号到达999999之后,它会再次从000001开始。

除了去服务器对应的日志文件目录上去查看binlog有哪些之外,我们可以直接在MySQL客户端工具或命令行中使用show binary logs;命令来查看当前有哪些binlog日志文件。如下所示:

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000011 |       177 |
| mysql-bin.000012 |       201 |
| mysql-bin.000013 |       154 |
+------------------+-----------+
7 rows in set (0.00 sec)

如果是在一个主从同步、读写分离集群环境中的主节点上,我们还可以使用下面的命令来查看binlog日志文件有哪些,已经查看当前使用的binlog日志文件名称和日志的偏移量是多少。

mysql> show master logs;
+------------------+-----------+
| Log_name         | File_size |
| mysql-bin.000011 |       177 |
| mysql-bin.000012 |       201 |
| mysql-bin.000013 |       793 |
+------------------+-----------+
7 rows in set (0.00 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000013 |      793 |              | mysql            |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

binlog日志文件记录的格式

我们知道在MySQL主从同步的时候,从库是靠读取主库的binlog日志的内容来同步主库的数据的。那么在binlog日志文件中,记录的SQL语句的方式可能会导致从库中的数据和主库不一致。

举例说明一下:假如我们在主库上有一个表t1,他们表结构如下,此时我们向表t1中执行一个insert语句:

mysql> desc t1;
+-------+----------------+------+-----+---------+----------------+
| Field | Type           | Null | Key | Default | Extra          |
+-------+----------------+------+-----+---------+----------------+
| c1    | int(11)        | NO   | PRI | NULL    | auto_increment |
| c2    | varchar(16)    | YES  |     | NULL    |                |
| c3    | decimal(16,16) | YES  |     | NULL    |                |
+-------+----------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql简谈mysql的binlog

清理MySQL中的binlog

清理MySql各种日志

htmlentities() 和 mysql_real_escape_string() 是不是足以清理 PHP 中的用户输入? [复制]

《MySQL实战45讲》读后笔记

MySQL 数据清理