MySQL通过二进制日志恢复数据
配置
开启二进制日志
[root@lyucan ~]# vim /etc/my.cnf
[mysqld]
server-id=1
log-bin=mysql-bin
sync-binlog=1
innodb_support_xa=1
binlog_format=statement
[root@lyucan ~]# service mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL.. SUCCESS!
上面的 binlog_format=statement 参数默认是row,表示用行来记录,这里为了方便观察,直接使用statement模式,这个参数可以动态修改
查看二进制日志是否开启
mysql> show variables like 'log_bin%';
+---------------------------------+-----------------------------+
| Variable_name | Value |
+---------------------------------+-----------------------------+
| log_bin | ON |
| log_bin_basename | /data/mysql/mysql-bin |
| log_bin_index | /data/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
+---------------------------------+-----------------------------+
常用binlog操作命令
1、查看所有binlog列表
mysql> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 2052 |
| mysql-bin.000002 | 943 |
| mysql-bin.000003 | 154 |
+------------------+-----------+
3 rows in set (0.00 sec)
2、查看master状态,即最后(最新)的一个binlog日志的编号及最后一个position的值
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
3、flush logs刷新日志
mysql> flush logs;
Query OK, 0 rows affected (0.01 sec)
mysql> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 2052 |
| mysql-bin.000002 | 943 |
| mysql-bin.000003 | 201 |
| mysql-bin.000004 | 154 |
+------------------+-----------+
4 rows in set (0.00 sec)
注意:当mysql服务器重启时,自动刷新binlog;
4、清空所有日志
mysql> reset master;
Query OK, 0 rows affected (0.01 sec)
mysql> show master logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 154 |
+------------------+-----------+
1 row in set (0.00 sec)
查看二进制日志的方法
1、使用mysqlbinlog工具来查看二进制日志;
[root@lyucan ~]# mysqlbinlog /data/mysql/mysql-bin.000002
......
# at 484 ##position号
#180410 15:51:27 server id 1 end_log_pos 484 CRC32 0xb489f444 IntvarSET INSERT_ID=1/*!*/;
#180410 15:51:27 server id 1 end_log_pos 606 CRC32 0xdbf27bfd Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1523346687/*!*/;
insert into t_user (user_name) values ('张三') ##当binlog_format设置为statement时,可以看到明文的DML语句;
/*!*/;
# at 606
......
[root@lyucan ~]# mysqlbinlog -v -v /data/mysql/mysql-bin.000001
......
# at 343
#180410 15:35:16 server id 1 end_log_pos 390 CRC32 0x554a373c Write_rows: table id 141 flags: STMT_END_F
BINLOG '
NGnMWhMBAAAANAAAAFcBAAAAAI0AAAAAAAEABHRlc3QABnRfdXNlcgACAw8CWgAAt/Mk7w==
NGnMWh4BAAAALwAAAIYBAAAAAI0AAAAAAAEAAgAC//wEAAAABuW8oOS4iTw3SlU=
'/*!*/;
### INSERT INTO `test`.`t_user` ##当binlog_format设置为row时,需要加上-v -v 才能看到明文的DML语句;
### SET
### @1=4 /* INT meta=0 nullable=0 is_null=0 */
### @2='张三' /* VARSTRING(90) meta=90 nullable=0 is_null=0 */
# at 390
......
2、在数据库里查;
mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
## FROM pos:起始position号,不指定就是当前文件的第一个开始;
## LIMIT offset:偏移量,就是从起始position跳过几个再开始
## row_count:查询多少行,不指定就查到文件尾行;
mysql> show binlog events in 'mysql-bin.000002';
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------+
| mysql-bin.000002 | 4 | Format_desc | 1 | 123 | Server ver: 5.7.21-log, Binlog ver: 4 |
| mysql-bin.000002 | 123 | Previous_gtids | 1 | 154 | |
| mysql-bin.000002 | 154 | Anonymous_Gtid | 1 | 219 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000002 | 219 | Query | 1 | 308 | use `test`; truncate t_user |
| mysql-bin.000002 | 308 | Anonymous_Gtid | 1 | 373 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000002 | 373 | Query | 1 | 452 | BEGIN |
| mysql-bin.000002 | 452 | Intvar | 1 | 484 | INSERT_ID=1 |
| mysql-bin.000002 | 484 | Query | 1 | 606 | use `test`; insert into t_user (user_name) values ('张三') |
| mysql-bin.000002 | 606 | Xid | 1 | 637 | COMMIT /* xid=18 */ |
| mysql-bin.000002 | 637 | Anonymous_Gtid | 1 | 702 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000002 | 702 | Query | 1 | 781 | BEGIN |
| mysql-bin.000002 | 781 | Query | 1 | 889 | use `test`; delete from t_user where user_id=1 |
| mysql-bin.000002 | 889 | Xid | 1 | 920 | COMMIT /* xid=21 */ |
| mysql-bin.000002 | 920 | Stop | 1 | 943 | |
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------+
14 rows in set (0.00 sec)
mysql> show binlog events in 'mysql-bin.000002' from 154 limit 5,5;
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------+
| mysql-bin.000002 | 484 | Query | 1 | 606 | use `test`; insert into t_user (user_name) values ('张三') |
| mysql-bin.000002 | 606 | Xid | 1 | 637 | COMMIT /* xid=18 */ |
| mysql-bin.000002 | 637 | Anonymous_Gtid | 1 | 702 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000002 | 702 | Query | 1 | 781 | BEGIN |
| mysql-bin.000002 | 781 | Query | 1 | 889 | use `test`; delete from t_user where user_id=1 |
+------------------+-----+----------------+-----------+-------------+--------------------------------------------------------------+
5 rows in set (0.00 sec)
恢复数据一定要和备份一起操作,否则即使有二进制日志,也不能完全恢复数据;
恢复二进制日志的方法
mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名
常用参数选项解释:
–start-position=123 起始pos点
–stop-position=456 结束pos点
–start-datetime=”2016-9-25 22:01:08” 起始时间点
–stop-datetime=”2019-9-25 22:09:46” 结束时间点
–database=test1 指定只恢复test1数据库(一台主机上往往有多个数据库,只限本地log日志)
不常用选项:
-u –user=name 连接到远程主机的用户名
-p –password[=name] 连接到远程主机的密码
-h –host=name 从远程主机上获取binlog日志
–read-from-remote-server 从某个MySQL服务器上读取binlog日志
例子:
假设t1表里有这几个字段,我们误将第四行记录delete掉了,再通过binlog找回;
mysql> select * from t1;
+----+--------+-----+--------+
| id | name | age | addr |
+----+--------+-----+--------+
| 1 | 张三 | 12 | 南京 |
| 2 | 李四 | 21 | 北京 |
| 3 | 王五 | 23 | 上海 |
| 4 | 二蛋 | 10 | 农村 |
+----+--------+-----+--------+
4 rows in set (0.00 sec)
mysql> delete from t1 where id=4;
Query OK, 1 row affected (0.00 sec)
mysql> show binlog events in 'mysql-bin.000004'\G;
......
*************************** 75. row ***************************
Log_name: mysql-bin.000004
Pos: 6566
Event_type: Query
Server_id: 1
End_log_pos: 6685
Info: use `test`; insert into t1 values(4,'二蛋',10,'农村')
*************************** 76. row ***************************
......
恢复这条数据
[root@lyucan mysql]# mysqlbinlog --start-position=6566 --stop-position=6685 mysql-bin.000004 | mysql -uroot -p test
上面的例子可能举得不是很恰当,因为我们都知道已经丢失的数据是什么了,但是在实际情况中,我们往往不知道丢失了哪些数据,万一drop掉了整个数据库,难道要一条条去恢复吗,显然不可能,这就需要我们定时做好备份工作,一个完整的备份往往是全量备份+增量备份+二进制日志备份,在进行全量备份的时候,我们需要知道当前二进制日志的position号,这样就可以进行完全恢复;
在进行mysqldump的时候,我们可以指定一个-F参数,在备份的时候刷新下binlog日志,这样新的操作都会记录到另一个新的binlog文件里面去,便于我们进行数据恢复,而不用费时费力去找要从哪里进行我二进制日志的恢复;
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com