一、MySQL的二进制日志binlog可以说是MySQL最重要的日志,它记录了所有的DDL和DML语句(除了数据查询语句select),以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。

   一般来说开启binlog日志大概会有1%的性能损耗。但开启后可以用来恢复数据。

二、开启binlog

show variables like 'log_%';  #查看binlog是否开启,log_bin值为ON 则已开启

如未开启,则可以按下面方法开启;

编辑打开mysql配置文件/etc/my.cnf在[mysqld]区块添加

log-bin=mysql-bin(也可指定二进制日志生成的路径,如:log-bin=/opt/Data/mysql-bin)
server-id=1  # id值唯一
binlog-format = ROW  #选择行模式
binlog_format=MIXED(加入此参数才能记录到insert语句)

 配置好后,重启mysql即可。

三、常用binlog命令

            1、 查看所有binlog日志列表

    show master logs;

    

mysql8.0 开启binlog日志 mysql开启binlog日志影响性能吗?_mysql8.0 开启binlog日志

   2、 查看master状态,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Position)值。

    show master status;

    

mysql8.0 开启binlog日志 mysql开启binlog日志影响性能吗?_mysql_02

  3、flush 刷新log日志,自此刻开始产生一个新编号的binlog日志文件;

    flush logs;

      注意:每当mysqld服务重启时,会自动执行此命令,刷新binlog日志;在mysqlddump备份数据时加-F选项也会刷新binlog日志;

  4、重置(清空)所有binlog日志

    reset master;

 

四、查看binlog内容

binlog为二进制文件,查看内容必须使用自带的mysqlbinlog命令查看

使用mysqlbinlog命令查看binlog日志内容,下面截取其中的一个片段分析分析:

        

mysql8.0 开启binlog日志 mysql开启binlog日志影响性能吗?_mysql8.0 开启binlog日志_03

        解释:

          server id 1:数据库主机的服务号

          end_log_pos 796 :sql结束时的pos节点

          thread_id=11:线程号

也可以根据时间查看

mysqlbinlog --no-defaults mysql-bin.000720 --start-datetime="2018-09-12 18:45:00" --stop-datetime="2018-09-12:18:47:00"

 

上面这种办法读取出binlog日志的全文内容比较多,不容易分辨查看到pos点信息,下面介绍一种更为方便的查询命令:

    mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];

    参数解释:

      a、IN 'log_name':指定要查询的binlog文件名(不指定就是第一个binlog文件)

      b、FROM pos:指定从哪个pos起始点开始查起(不指定就是从整个文件首个pos点开始算)

      c、LIMIT【offset】:偏移量(不指定就是0)

      d、row_count :查询总条数(不指定就是所有行)

      

mysql8.0 开启binlog日志 mysql开启binlog日志影响性能吗?_mysql_04

  2、上面这条语句可以将指定的binlog日志文件,分成有效事件行的方式返回,并可使用limit指定pos点的起始偏移,查询条数!

    a、查询第一个最早的binlog日志:

      show binlog events\G;

    b、指定查询mysql-bin.000002这个文件

      show binlog events in 'mysql-bin.000002'\G;

    c、指定查询mysql-bin.000002这个文件,从pos点:624开始查起:

      show binlog events in 'mysql-bin.000002' from 624\G;

    d、指定查询mysql-bin.000002这个文件,从pos点:624开始查起,查询10条(即10条语句)

      show binlog events in 'mysql-bin.000002' from 624 limit 10\G;

    e、指定查询 mysql-bin.000002这个文件,从pos点:624开始查起,偏移2行(即中间跳过2个)查询10条(即10条语句)。

      show binlog events in 'mysql-bin.000002' from 624 limit 2,10\G; 

 

五、使用binlog恢复数据

 一般mysql数据都会定时备份,比如每天凌晨5点备份一次:

mysqldump -utan -p***** -d --databases xxx > /mysql_bak/dump.sql  #-d只备份表结构
mysqldump -utan -p***** -F -R --databases xxx > /mysql_bak/$DATE.sql  #备份表数据

 

其中在全备份的时候使用了-F选项,那么当数据备份操作刚开始的时候系统就会自动刷新log,这样就会自动产生一个新的binlog日志,这个新的binlog日志就会用来记录备份之后的数据库'增删改操作'。

  -R:备份存储过程等

这样如果在早上9点上班后悲剧发生了,不小心删了库。。。

这个时候千万不要慌张,既然悲剧已经发生,尽快弥补

首先,通知相关人员知悉此事

然后,停止业务,避免新的数据产生

接着,登录服务器查看最后一个binlog文件,比如mysql-bin.000003 然后备份一下,这个是最重要的文件,不能再有闪失了,然后数据库内执行flush logs;生成一个新的日志文件,

然后,读取binlog文件,查看删库的时间点

mysql> show binlog events in 'mysql-bin.000003';

 

mysql> show binlog events in 'mysql-bin.000003';
+------------------+-----+----------------+-----------+-------------+------------------------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                               |
+------------------+-----+----------------+-----------+-------------+------------------------------------------------------------------------------------+
| mysql-bin.000003 |   4 | Format_desc    |         1 |         123 | Server ver: 5.7.27-log, Binlog ver: 4                                              |
| mysql-bin.000003 | 123 | Previous_gtids |         1 |         154 |                                                                                    |
| mysql-bin.000003 | 154 | Anonymous_Gtid |         1 |         219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                               |
| mysql-bin.000003 | 219 | Query          |         1 |         298 | BEGIN                                                                              |
| mysql-bin.000003 | 298 | Intvar         |         1 |         330 | INSERT_ID=22                                                                       |
| mysql-bin.000003 | 330 | Query          |         1 |         474 | use `data`; insert into `user_info` (sex,age) values (0,77777),(0,88888),(0,99999) |
| mysql-bin.000003 | 474 | Xid            |         1 |         505 | COMMIT /* xid=8138 */                                                              |
| mysql-bin.000003 | 505 | Anonymous_Gtid |         1 |         570 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                               |
| mysql-bin.000003 | 570 | Query          |         1 |         670 | create  database `xxxxx`                                                           |
| mysql-bin.000003 | 670 | Anonymous_Gtid |         1 |         735 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                               |
| mysql-bin.000003 | 735 | Query          |         1 |         827 | drop database data                                                                 |
| mysql-bin.000003 | 827 | Anonymous_Gtid |         1 |         892 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                               |
| mysql-bin.000003 | 892 | Query          |         1 |         989 | create  database `qqqq`                                                            |
+------------------+-----+----------------+-----------+-------------+------------------------------------------------------------------------------------+
13 rows in set (0.00 sec)

 通过分析发现,删库pos点是827,只要回复到相应pos点之前即可。

 先用备份文件恢复5点之前的数据

mysql> source /root/dump.sql   #恢复表结构
source /root/mysql.2019-08-01.mysql; #恢复上次dump备份的数据

 

此时恢复了截止凌晨5:00前的备份数据了,接着从binlog中恢复5:00到删库之间的数据

恢复格式如下:

mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名

 

常用参数选项解释:

      --start-position=875 起始pos点
      --stop-position=954 结束pos点
      --start-datetime="2016-9-25 22:01:08" 起始时间点
      --stop-datetime="2019-9-25 22:09:46" 结束时间点
      --database=ops指定只恢复ops数据库(一台主机上往往有多个数据库,只限本地log日志)

 

因为我们删库pos点是827,上一条sql语句pos点是735,所以可以执行

mysqlbinlog mysql-bin.000003  --stop-position=735 --database=mysqlbinlog mysql-bin.000003  --stop-position=735 --database=data | mysql -uroot -p -vdata | mysql -uroot -p -v

 

切记不要把结束点写成827,否则会执行827的语句再次删库

因为加了--database=data因此不会恢复二进制日志中关于其他库的相应操作,如果需要恢复其他库的相应操作,则再加上--database=xxx即可

还可以按时间区间,按pos点区间恢复,步骤原理大同小异。

 

六、总结:

  所谓恢复,就是让mysql将保存在binlog日志中指定段落区间的sql语句逐个重新执行一次而已。