MySQL 之binlog日志说明及利用binlog日志恢复数据操作记录

用binlog日志功能进行数据恢复(定时全备份+binlog日志恢复增量数据部分)

本案例适用于人为SQL语句造成的误操作或者没有主从复制等的热备情况宕机时的修复

恢复条件为mysql要开启binlog日志功能,并且要全备和增量的所有数据

恢复时建议对外停止更新,即禁止更新数据库

先恢复全量,然后把全备时刻点以后的增量日志,按顺序恢复成SQL文件,然后把文件中有问题的SQL语句删除(也可通过时间和位置点),再恢复到数据库。

一、简单了解binlog

一般来说开启binlog日志大概会有1%的性能损耗。

binlog日志有两个最重要的使用场景

1)MySQL主从复制。

2)数据恢复。

binlog日志包括两类文件

1)二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件

2)二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查询语句select)语句事件。

二、开启binlog日志功能

1)编辑打开mysql配置文件/etc/my.cnf

[root@vm-002 ~]# vim /etc/my.cnf

在[mysqld] 区块添加

log-bin=mysql-bin 确认是打开状态(mysql-bin 是日志的基本名或前缀名)

注意:每次服务器(数据库)重启,服务器会调用flush logs;,新创建一个binlog日志!

2)重启mysqld服务使配置生效

/etc/init.d/mysqld restart

3)查看binlog日志是否开启

mysql> show variables like 'log_%';
+---------------------------------+---------------------+
| Variable_name | Value |
+---------------------------------+---------------------+
| log_bin | ON |
| log_bin_trust_function_creators | OFF |
| log_bin_trust_routine_creators | OFF |
| log_error | /var/log/mysqld.log |
| log_output | FILE |
| log_queries_not_using_indexes | OFF |
| log_slave_updates | OFF |
| log_slow_queries | OFF |
| log_warnings | 1 |

 

三、常用的binlog日志操作命令

1)查看所有binlog日志列表

show master logs;

2)查看master状态,最新一个binlog日志的编号名称,及最后一个操作事件Position值

show master status;

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

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

flush logs;

show master logs;

4)重置(清空)所有binlog日志,重置成mysql-bin.000001

reset master;

show master logs;

 

四、查看binlog日志内容,常用有两种方式

1)使用mysqlbinlog自带查看命令法:

注意:

-->binlog是二进制文件,普通文件查看器cat、more、vim等都无法打开,必须使用自带的mysqlbinlog命令查看

-->binlog日志与数据库文件在同目录中

-->在MySQL5.5以下版本使用mysqlbinlog命令时如果报错,就加上 “--no-defaults”选项

#查看mysql的数据存放目录datadir,basedir,pid,socket客户端连接文件
ps -ef|grep mysql
cd /var/lib/mysql/
ls
#使用mysqlbinlog命令查看binlog日志内容:
mysqlbinlog mysql-bin.000002

 

2)上面这种办法读取出binlog日志的全文内容比较多,不容易分辨查看到pos点信息

show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
show master logs;
show binlog events in 'mysql-bin.000002'\G;

上面这条语句可以将指定的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条
show binlog events in 'mysql-bin.000002' from 624 limit 2,10\G;

 

五、利用binlog日志恢复mysql数据

以下对ops库的member表进行操作

use ops;
CREATE TABLE IF NOT EXISTS `member` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(16) NOT NULL,
`sex` enum('m','w') NOT NULL DEFAULT 'm',
`age` tinyint(3) unsigned NOT NULL,
`classid` char(6) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
show tables;
desc member;
insert into member(`name`,`sex`,`age`,`classid`) values('wangshibo','m',27,'cls1'),('guohuihui','w',27,'cls2');
select * from member;

 

下面开始进行场景模拟:

1)

ops库会在每天凌晨4点进行一次完全备份的定时计划任务,如下:

crontab -l

crontab -e

 

0 4 * * * /usr/bin/mysqldump -uroot -p -B -F -R -x --master-data=2 ops|gzip >/opt/backup/ops_$(date +%F).sql.gz

 

#这里手动执行下,将ops数据库备份到/opt/backup/ops_$(date +%F).sql.gz文件中:

参数说明:-B:指定数据库,-F:刷新日志,-R:备份存储过程等,-x:锁表,--master-data:在备份语句里添加CHANGE MASTER语句以及binlog文件及位置点信息

mysqldump -uroot -p -B -F -R -x --master-data=2 ops|gzip >/opt/backup/ops_$(date +%F).sql.gz

ls /opt/backup/

show master status;

2)

早上9点上班了,由于业务的需求会对数据库进行各种“增删改”操作。

比如:在ops库下member表内插入、修改了数据等等:

先是早上进行插入数据:

use ops;
insert into ops.member(`name`,`sex`,`age`,`classid`) values('yiyi','w',20,'cls1'),('xiaoer','m',22,'cls3'),('zhangsan','w',21,'cls5'),('lisi','m',20,'cls4'),('wangwu','w',26,'cls6');
select * from member;
3)

中午又执行了修改数据操作:

update ops.member set name='李四' where id=4;
update ops.member set name='小二' where id=2;
select * from member;

4)

在下午18:00的时候,悲剧莫名其妙的出现了!

手贱执行了drop语句,直接删除了ops库!吓尿!

drop database ops;

5)

这种时候,一定不要慌张!!!

先仔细查看最后一个binlog日志,并记录下关键的pos点,到底是哪个pos点的操作导致了数据库的破坏(通常在最后几步);

#先备份一下最后一个binlog日志文件:

cd /var/lib/mysql/
cp -v mysql-bin.000003 /opt/backup/
ls /opt/backup/

 

接着执行一次刷新日志索引操作,重新开始新的binlog日志记录文件。按理说mysql-bin.000003

这个文件不会再有后续写入了,因为便于我们分析原因及查找ops节点,以后所有数据库操作都会写入到下一个日志文件。

#mysqlmaster-bin.000032 154
flush logs;
show master status;

 

6)

读取binlog日志,分析问题。

方法一:使用mysqlbinlog读取binlog日志:

cd /var/lib/mysql/

mysqlbinlog mysqlmaster-bin.000031

 

--或者,需要加-vv参数才能显示对应的dml结构 by zhuyj

mysqlbinlog --no-defaults -vv --base64-output=decode-rows 'mysqlmaster-bin.000031' -r 31.sql

方法二:登录服务器,并查看(推荐此种方法),查看flush logs之前的日志

show binlog events in 'mysqlmaster-bin.000031';
 
#或者:
#show binlog events in 'mysqlmaster-bin.000031'\G;
 
+------------------+-----+-------------+-----------+-------------+----------------------------------------------------------------------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+-------------+-----------+-------------+----------------------------------------------------------------------------------------------------------------------------+
| mysql-bin.000003 | 4 | Format_desc | 1 | 106 | Server ver: 5.1.73-log, Binlog ver: 4 |
| mysql-bin.000003 | 106 | Query | 1 | 173 | BEGIN |
| mysql-bin.000003 | 173 | Intvar | 1 | 201 | INSERT_ID=3 |
| mysql-bin.000003 | 201 | Query | 1 | 444 | use `ops`; insert into ops.member(`name`,`sex`,`age`,`gsan','w',21,'cls5'),('lisi','m',20,'cls4'),('wangwu','w',26,'cls6') |
| mysql-bin.000003 | 444 | Xid | 1 | 471 | COMMIT /* xid=66 */ |
| mysql-bin.000003 | 471 | Query | 1 | 538 | BEGIN |
| mysql-bin.000003 | 538 | Query | 1 | 646 | use `ops`; update ops.member set name='李四' where id= |
| mysql-bin.000003 | 646 | Xid | 1 | 673 | COMMIT /* xid=68 */ |
| mysql-bin.000003 | 673 | Query | 1 | 740 | BEGIN |
| mysql-bin.000003 | 740 | Query | 1 | 848 | use `ops`; update ops.member set name='小二' where id= |
| mysql-bin.000003 | 848 | Xid | 1 | 875 | COMMIT /* xid=69 */ |
| mysql-bin.000003 | 875 | Query | 1 | 954 | drop database ops |
| mysql-bin.000003 | 954 | Rotate | 1 | 997 | mysql-bin.000004;pos=4 |
+------------------+-----+-------------+-----------+-------------+----------------------------------------------------------------------------------------------------------------------------+

 

#执行结果如下,未出现dml语句,只有table_id: 223 (ops.member)和Update_rows | 14 | 1125 | table_id: 223 flags: STMT_END_F

mysql> show binlog events in 'mysqlmaster-bin.000031';
+------------------------+------+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------------+------+----------------+-----------+-------------+---------------------------------------+
| mysqlmaster-bin.000031 | 4 | Format_desc | 14 | 123 | Server ver: 5.7.18-log, Binlog ver: 4 |
| mysqlmaster-bin.000031 | 123 | Previous_gtids | 14 | 154 | |
| mysqlmaster-bin.000031 | 154 | Anonymous_Gtid | 14 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 219 | Query | 14 | 287 | BEGIN |
| mysqlmaster-bin.000031 | 287 | Table_map | 14 | 345 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 345 | Write_rows | 14 | 473 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 473 | Xid | 14 | 504 | COMMIT /* xid=3084 */ |
| mysqlmaster-bin.000031 | 504 | Anonymous_Gtid | 14 | 569 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 569 | Query | 14 | 640 | BEGIN |
| mysqlmaster-bin.000031 | 640 | Table_map | 14 | 698 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 698 | Write_rows | 14 | 826 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 826 | Xid | 14 | 857 | COMMIT /* xid=3091 */ |
| mysqlmaster-bin.000031 | 857 | Anonymous_Gtid | 14 | 922 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 922 | Query | 14 | 993 | BEGIN |
| mysqlmaster-bin.000031 | 993 | Table_map | 14 | 1051 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 1051 | Update_rows | 14 | 1125 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 1125 | Xid | 14 | 1156 | COMMIT /* xid=3102 */ |
| mysqlmaster-bin.000031 | 1156 | Anonymous_Gtid | 14 | 1221 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 1221 | Query | 14 | 1292 | BEGIN |
| mysqlmaster-bin.000031 | 1292 | Table_map | 14 | 1350 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 1350 | Update_rows | 14 | 1427 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 1427 | Xid | 14 | 1458 | COMMIT /* xid=3103 */ |
| mysqlmaster-bin.000031 | 1458 | Anonymous_Gtid | 14 | 1523 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 1523 | Query | 14 | 1612 | drop database ops |
| mysqlmaster-bin.000031 | 1612 | Rotate | 14 | 1665 | mysqlmaster-bin.000032;pos=4 |
mysql> show binlog events in 'mysqlmaster-bin.000031';
+------------------------+------+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------------+------+----------------+-----------+-------------+---------------------------------------+
| mysqlmaster-bin.000031 | 4 | Format_desc | 14 | 123 | Server ver: 5.7.18-log, Binlog ver: 4 |
| mysqlmaster-bin.000031 | 123 | Previous_gtids | 14 | 154 | |
| mysqlmaster-bin.000031 | 154 | Anonymous_Gtid | 14 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 219 | Query | 14 | 287 | BEGIN |
| mysqlmaster-bin.000031 | 287 | Table_map | 14 | 345 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 345 | Write_rows | 14 | 473 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 473 | Xid | 14 | 504 | COMMIT /* xid=3084 */ |
| mysqlmaster-bin.000031 | 504 | Anonymous_Gtid | 14 | 569 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 569 | Query | 14 | 640 | BEGIN |
| mysqlmaster-bin.000031 | 640 | Table_map | 14 | 698 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 698 | Write_rows | 14 | 826 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 826 | Xid | 14 | 857 | COMMIT /* xid=3091 */ |
| mysqlmaster-bin.000031 | 857 | Anonymous_Gtid | 14 | 922 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 922 | Query | 14 | 993 | BEGIN |
| mysqlmaster-bin.000031 | 993 | Table_map | 14 | 1051 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 1051 | Update_rows | 14 | 1125 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 1125 | Xid | 14 | 1156 | COMMIT /* xid=3102 */ |
| mysqlmaster-bin.000031 | 1156 | Anonymous_Gtid | 14 | 1221 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 1221 | Query | 14 | 1292 | BEGIN |
| mysqlmaster-bin.000031 | 1292 | Table_map | 14 | 1350 | table_id: 223 (ops.member) |
| mysqlmaster-bin.000031 | 1350 | Update_rows | 14 | 1427 | table_id: 223 flags: STMT_END_F |
| mysqlmaster-bin.000031 | 1427 | Xid | 14 | 1458 | COMMIT /* xid=3103 */ |
| mysqlmaster-bin.000031 | 1458 | Anonymous_Gtid | 14 | 1523 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysqlmaster-bin.000031 | 1523 | Query | 14 | 1612 | drop database ops |
| mysqlmaster-bin.000031 | 1612 | Rotate | 14 | 1665 | mysqlmaster-bin.000032;pos=4 |

+------------------------+------+----------------+-----------+-------------+---------------------------------------+

25 rows in set (0.00 sec)

 

通过分析,造成数据库破坏的pos点区间是介于 875--954 之间(这是按照日志区间的pos节点算的),只要恢复到875前就可。

7)

先把凌晨4点全备份的数据恢复:

cd /opt/backup/

ls

gzip -d ops_2016-09-25.sql.gz

#106这是全备时刻的binlog文件位置

#即mysql-bin.000002的106行,因此在该文件之前的binlog文件中的数据都已经包含在这个全备的sql文件中了

grep CHANGE ops_2016-09-25.sql

 

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=106;

 

mysql -uroot -p -v < ops_2016-09-25.sql

#这样就恢复了截至当日凌晨(4:00)前的备份数据都恢复了。

show databases;

use ops;

show tables;

select * from member;

 

8)

从binlog日志恢复数据

恢复命令的语法格式:

mysqlbinlog mysqlmaster-bin.000031 | mysql -uroot -pmysql ops

--------------------------------------------------------

常用参数选项解释:

--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=zyyshop 指定只恢复zyyshop数据库(一台主机上往往有多个数据库,只限本地log日志)

--------------------------------------------------------

不常用选项:

-u --user=name 连接到远程主机的用户名

-p --password[=name] 连接到远程主机的密码

-h --host=name 从远程主机上获取binlog日志

--read-from-remote-server 从某个MySQL服务器上读取binlog日志

--------------------------------------------------------

小结:实际是将读出的binlog日志内容,通过管道符传递给mysql命令。这些命令、文件尽量写成绝对路径;

a)完全恢复(需要手动vim编辑mysql-bin.000003,将那条drop语句剔除掉),至此恢复到drop database前

#cp /var/lib/mysql/mysql-bin.000003 /opt/backup

mysqlbinlog /opt/backup/mysqlmaster-bin.000031 > /opt/backup/000031.sql

vim /opt/backup/000003.sql #删除里面的drop语句,不能看到明文dml sql

mysql -uroot -p -v < /opt/backup/000031.sql

 

ERROR 1790 (HY000) at line 121: @@SESSION.GTID_NEXT cannot be changed by a client that owns a GTID. The client owns ANONYMOUS. Ownership is released on COMMIT or ROLLBACK.

 

温馨提示:

在恢复全备数据之前必须将该binlog文件移出,否则恢复过程中,会继续写入语句到binlog,最终导致增量恢复数据部分变得比较混乱!

可参考:

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

b)指定pos结束点恢复(部分恢复):

--stop-position=471 pos结束节点(按照事务区间算,是471)

注意:

此pos结束节点介于“member表原始数据”与更新“name='李四'”之前的数据,这样就可以恢复到更改“name='李四'”之前的数据了。

操作如下:

[root@vm-002 ~]# /usr/bin/mysqlbinlog --stop-position=471 --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops
mysql> select * from member;
+----+-----------+-----+-----+---------+
| id | name | sex | age | classid |
+----+-----------+-----+-----+---------+
| 1 | wangshibo | m | 27 | cls1 |
| 2 | guohuihui | w | 27 | cls2 |
| 3 | yiyi | w | 20 | cls1 |
| 4 | xiaoer | m | 22 | cls3 |
| 5 | zhangsan | w | 21 | cls5 |
| 6 | lisi | m | 20 | cls4 |
| 7 | wangwu | w | 26 | cls6 |
+----+-----------+-----+-----+---------+

7 rows in set (0.00 sec)

恢复截止到更改“name='李四'”之间的数据(按照事务区间算,是673)

[root@vm-002 ~]# /usr/bin/mysqlbinlog --stop-position=673 --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops
mysql> select * from member;
+----+-----------+-----+-----+---------+
| id | name | sex | age | classid |
+----+-----------+-----+-----+---------+
| 1 | wangshibo | m | 27 | cls1 |
| 2 | guohuihui | w | 27 | cls2 |
| 3 | yiyi | w | 20 | cls1 |
| 4 | 李四 | m | 22 | cls3 |
| 5 | zhangsan | w | 21 | cls5 |
| 6 | lisi | m | 20 | cls4 |
| 7 | wangwu | w | 26 | cls6 |
+----+-----------+-----+-----+---------+
7 rows in set (0.00 sec)

c)指定pso点区间恢复(部分恢复):

更新 name='李四' 这条数据,日志区间是Pos[538] --> End_log_pos[646],按事务区间是:Pos[471] --> End_log_pos[673]

更新 name='小二' 这条数据,日志区间是Pos[740] --> End_log_pos[848],按事务区间是:Pos[673] --> End_log_pos[875]

c1)

单独恢复 name='李四' 这步操作,可这样:

按照binlog日志区间单独恢复:

/usr/bin/mysqlbinlog --start-position=538 --stop-position=646 --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops

按照事务区间单独恢复

/usr/bin/mysqlbinlog --start-position=471 --stop-position=673 --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops

c2)

单独恢复 name='小二' 这步操作,可这样:

按照binlog日志区间单独恢复:

/usr/bin/mysqlbinlog --start-position=740 --stop-position=848 --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops

按照事务区间单独恢复

/usr/bin/mysqlbinlog --start-position=673 --stop-position=875 --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops

c3)

将 name='李四'、name='小二' 多步操作一起恢复,需要按事务区间,可这样:

/usr/bin/mysqlbinlog --start-position=471 --stop-position=875 --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops

select * from member;

 

======================================================================================

另外:也可以指定时间节点区间恢复(部分恢复),就是说除了用pos节点的办法进行恢复,也可以通过指定时间节点区间进行恢复,

按时间恢复需要用mysqlbinlog命令读取binlog日志内容,找时间节点。

如上,误删除ops库后:

先进行全备份恢复

mysql -uroot -p -v < ops_2016-09-25.sql
#查看mysq-bin00003日志,找出时间节点
cd /var/lib/mysql
mysqlbinlog mysql-bin.000003
 
.............
.............
BEGIN
/*!*/;
# at 173
#160925 21:57:19 server id 1 end_log_pos 201 Intvar
SET INSERT_ID=3/*!*/;
# at 201
#160925 21:57:19 server id 1 end_log_pos 444 Query thread_id=3 exec_time=0 error_code=0
use `ops`/*!*/;
SET TIMESTAMP=1474811839/*!*/;
insert into ops.member(`name`,`sex`,`age`,`classid`) values('yiyi','w',20,'cls1'),('xiaoer','m',22,'cls3'),('zhangsan','w',21,'cls5'),('lisi','m',20,'cls4'),('wangwu','w',26,'cls6')                               #执行的sql语句
/*!*/;
# at 444
#160925 21:57:19 server id 1 end_log_pos 471 Xid = 66    #开始执行的时间
COMMIT/*!*/;
# at 471
#160925 21:58:41 server id 1 end_log_pos 538 Query thread_id=3 exec_time=0 error_code=0    #结束时间
SET TIMESTAMP=1474811921/*!*/;
BEGIN
/*!*/;
# at 538
#160925 21:58:41 server id 1 end_log_pos 646 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1474811921/*!*/;
update ops.member set name='李四' where id=4     #执行的sql语句
/*!*/;
# at 646
#160925 21:58:41 server id 1 end_log_pos 673 Xid = 68    #开始执行的时间
COMMIT/*!*/;
# at 673
#160925 21:58:56 server id 1 end_log_pos 740 Query thread_id=3 exec_time=0 error_code=0   #结束时间
SET TIMESTAMP=1474811936/*!*/;
BEGIN
/*!*/;
# at 740
#160925 21:58:56 server id 1 end_log_pos 848 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1474811936/*!*/;
update ops.member set name='小二' where id=2      #执行的sql语句
/*!*/;
# at 848
#160925 21:58:56 server id 1 end_log_pos 875 Xid = 69   #开始执行的时间
COMMIT/*!*/;
# at 875
#160925 22:01:08 server id 1 end_log_pos 954 Query thread_id=3 exec_time=0 error_code=0    #结束时间
SET TIMESTAMP=1474812068/*!*/;
drop database ops
/*!*/;
# at 954
#160925 22:09:46 server id 1 end_log_pos 997 Rotate to mysql-bin.000004 pos: 4
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
 
#恢复到更改“name='李四'”之前的数据
/usr/bin/mysqlbinlog --start-datetime="2016-09-25 21:57:19" --stop-datetime="2016-09-25 21:58:41" --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops
select * from member;
/usr/bin/mysqlbinlog --start-datetime="2016-09-25 21:58:41" --stop-datetime="2016-09-25 21:58:56" --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops
select * from member;
/usr/bin/mysqlbinlog --start-datetime="2016-09-25 21:58:56" --stop-datetime="2016-09-25 22:01:08" --database=ops /var/lib/mysql/mysql-bin.000003 | /usr/bin/mysql -uroot -p123456 -v ops
select * from member;