MySQL二进制binlog日志说明以及利用binlog日志恢复数据
MySQL的binlog日志对于mysql数据库来说是十分重要的。在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定时全量备份+binlog日志恢复增量数据部分)。
一、关于binlog
MySQL的二进制日志binlog可以说是MySQL数据库服务最重要的日志,它记录了所有的DDL和DML语句(除了数据查询语句select),以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。
DDL:
- Data Definition Language 数据库定义语言
主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用。
DML:
- Data Manipulation Language 数据操纵语言
主要的命令是SELECT、UPDATE、INSERT、DELETE,就像它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言。
mysqlbinlog常见的选项有以下几个:
--start-datetime:从二进制日志中读取指定等于时间戳或者晚于本地服务器的时间。
--stop-datetime:从二进制日志中读取指定小于时间戳或者等于本地服务器的时间取值和上述一样。
--start-position:从二进制日志中读取指定position 事件位置作为开始。
--stop-position:从二进制日志中读取指定position 事件位置作为截止。
一般来说,开启MySQL数据库的binlog日志功能大概会有1%的性能损耗。
binlog日志有两个最重要的使用场景:
(1)MySQL主从复制:MySQL Replication在Master端开启binlog,Master把它的二进制日志传递给slaves来达到master-salve 数据一致的目的。
(2)自然就是数据恢复,通过使用mysqlbinlog工具来恢复数据。
binlog日志包括两类文件:
(1)二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件。
(2)二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查询语句select)语句事件。
二、开启binlog日志功能
(1) 编辑打开mysql配置文件/etc/my.cnf
[root@localhost ~]# vim /etc/my.cnf
在[mysqld] 块添加
log-bin=mysql-bin 确认是打开状态(mysql-bin 是日志的基本名或前缀名)
注意:每次服务器(数据库)重启,服务器会调用flush logs;,新创建一个binlog日志!
(2) 重启mysqld服务使配置生效
[root@localhost /]# /etc/init.d/mysql stop Shutting down MySQL. SUCCESS! [root@localhost /]# /etc/init.d/mysql start Starting MySQL.. SUCCESS! [root@localhost /]# /etc/init.d/mysql restart Shutting down MySQL. SUCCESS! Starting MySQL.. SUCCESS!
(3) 查看binlog日志是否开启
mysql> show variables like 'log_%'; +---------------------------------+------------------------------------------------+ | Variable_name | Value | +---------------------------------+------------------------------------------------+ | log_bin | ON | | log_bin_trust_function_creators | OFF | | log_error | /usr/local/mysql/var/localhost.localdomain.err | | log_output | FILE | | log_queries_not_using_indexes | OFF | | log_slave_updates | OFF | | log_slow_queries | OFF | | log_warnings | 1 | +---------------------------------+------------------------------------------------+ 8 rows in set (0.00 sec)
三、常用的binlog日志操作命令
(1) 查看所有binlog日志列表
mysql> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 966 | | mysql-bin.000002 | 1033 | | mysql-bin.000003 | 1827 | | mysql-bin.000004 | 126 | | mysql-bin.000005 | 126 | | mysql-bin.000006 | 107 | +------------------+-----------+ 6 rows in set (0.00 sec)
(2) 查看master状态,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Position)值
mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000006 | 107 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
(3) flush刷新log日志,自此刻开始产生一个新编号的binlog日志文件
mysql> flush logs; Query OK, 0 rows affected (0.00 sec) mysql> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 966 | | mysql-bin.000002 | 1033 | | mysql-bin.000003 | 1827 | | mysql-bin.000004 | 126 | | mysql-bin.000005 | 126 | | mysql-bin.000006 | 150 | | mysql-bin.000007 | 107 | +------------------+-----------+ 7 rows in set (0.00 sec)
注意:每当mysql服务重启时,会自动执行此命令,刷新binlog日志;在执行mysqldump备份数据时加 -F 选项也会刷新binlog日志;
(4)重置(清空)所有binlog日志
mysql> reset master; Query OK, 0 rows affected (0.01 sec) mysql> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 107 | +------------------+-----------+ 1 row in set (0.00 sec)
四、查看binlog日志内容
常用有两种方式:
1)使用MySQL自带命令mysqlbinlog查看:
注意:
-->binlog是二进制文件,普通文件查看器cat、more、vim等都无法打开,必须使用自带的mysqlbinlog命令查看.
-->binlog日志与数据库文件在同目录中.
-->在MySQL5.5以下版本使用mysqlbinlog命令时如果报错,就加上 “--no-defaults”选项.
查看mysql的数据存放目录,从下面结果可知是/usr/local/mysql/var
[root@localhost /]# ps -ef |grep mysql |grep -v 'grep' root 4191 1 0 15:05 pts/0 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/usr/local/mysql/var --pid-file=/usr/local/mysql/var/localhost.localdomain.pid mysql 4504 4191 0 15:05 pts/0 00:00:00 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/var --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/usr/local/mysql/var/localhost.localdomain.err --pid-file=/usr/local/mysql/var/localhost.localdomain.pid --socket=/tmp/mysql.sock --port=3306 root 4525 2789 0 15:06 pts/0 00:00:00 mysql
[root@localhost var]# cd /usr/local/mysql/var/
[root@localhost var]# ls
ibdata1 localhost.localdomain.err mysql-bin.000002 mysql-bin.000006 mysql-bin.000010 mysql-bin.000014 performance_schema
ib_logfile0 localhost.localdomain.pid mysql-bin.000003 mysql-bin.000007 mysql-bin.000011 mysql-bin.000015 test
ib_logfile1 mysql mysql-bin.000004 mysql-bin.000008 mysql-bin.000012 mysql-bin.000016 ultrax
jiaowu mysql-bin.000001 mysql-bin.000005 mysql-bin.000009 mysql-bin.000013 mysql-bin.index
使用mysqlbinlog命令查看binlog日志内容。
2)另外一种更为方便的查询命令:
命令格式:
mysql> show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count];
参数解释:
IN 'log_name' :指定要查询的binlog文件名(不指定就是第一个binlog文件)
FROM pos :指定从哪个pos起始点开始查起(不指定就是从整个文件首个pos点开始算)
LIMIT [offset,] :偏移量(不指定就是0)
row_count :查询总条数(不指定就是所有行)
上面这条语句可以将指定的binlog日志文件,分成有效事件行的方式返回,并可使用limit指定pos点的起始偏移,查询条数!
如下操作示例:
(a)查询第一个(最早)的binlog日志:
mysql> show binlog events\G;
(b)指定查询 mysql-bin.000002这个文件:
mysql> show binlog events in 'mysql-bin.000002'\G;
(c)指定查询 mysql-bin.000002这个文件,从pos点624开始查起:
mysql> show binlog events in 'mysql-bin.000002' from 624\G;
(d)指定查询 mysql-bin.000002这个文件,从pos点:624开始查起,查询10条(即10条语句)
mysql> show binlog events in 'mysql-bin.000002' from 624 limit 10\G;
(e)指定查询 mysql-bin.000002这个文件,从pos点:624开始查起,偏移2行(即中间跳过2个),查询10条
mysql> show binlog events in 'mysql-bin.000002' from 624 limit 2,10\G;
五、利用binlog日志恢复mysql数据
以下对jiaowu库的member表进行操作 mysql> create database jiaowu; Query OK, 1 row affected (0.00 sec) mysql> use jiaowu; Database changed mysql> 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; Query OK, 0 rows affected (0.10 sec) mysql> show tables; +------------------+ | Tables_in_jiaowu | +------------------+ | member | +------------------+ 1 row in set (0.00 sec) mysql> desc member; +---------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+---------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(16) | NO | | NULL | | | sex | enum('m','w') | NO | | m | | | age | tinyint(3) unsigned | NO | | NULL | | | classid | char(6) | YES | | NULL | | +---------+---------------------+------+-----+---------+----------------+ 5 rows in set (0.00 sec)
插入两条数据:
mysql> insert into member(`name`,`sex`,`age`,`classid`) values('zhangsan','m',27,'class1'),('lisi','w',28,'class2'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from member; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | zhangsan | m | 27 | class1 | | 2 | lisi | w | 28 | class2 | +----+----------+-----+-----+---------+ 2 rows in set (0.00 sec)
假设有如下场景:
(1)jiaowu 库会在每天的凌晨1点进行一次完全备份的定时任务计划,如下:
[root@localhost /]# crontab -u root -l 0 1 * * * /usr/bin/mysqldump -uroot -p -B -F -R -x --master-data=2 jiaowu|gzip >/opt/backup/jiaowu_$(date +%F).sql.gz
这里我们手动执行,将 jiaowu 数据库备份到/opt/backup 目录下:
[root@localhost /]# mysqldump -u root -p -B -F -R -x --master-data=2 jiaowu |gzip >/opt/backup/jiaowu_$(date +%F).sql.gz Enter password: [root@localhost /]# ls /opt/backup/ jiaowu_2019-09-10.sql.gz
参数说明:
-B :指定数据库
-F :刷新日志
-R :备份存储过程等
-x :锁表
--master-data:在备份语句里添加CHANGE MASTER语句以及binlog文件及位置点信息,参数为:0|1|2
0:表示不记录
1:表示记录并打开的状态
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000019', MASTER_LOG_POS=107;
2:表示记录但是以注释的方式
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000019', MASTER_LOG_POS=107;
由于上面在完全备份的时候使用了-F选项,那么当数据备份操作刚开始的时候系统就会自动刷新log,这样就会自动产生一个新的binlog 日志,这个新的binlog日志就会用来记录备份之后的数据库的‘增删改’操作。
mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000002 | 107 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
mysql-bin.000002 是用来记录完全备份之后(凌晨1点以后)对数据库的所有“增删改”操作。
(2)由于需求,现需要对数据库进行第二次的 ‘增删改’ 操作;
比如:在jiaowu 库的member表中插入,修改了数据等等;
首先是执行了插入数据的操作:
mysql> insert into jiaowu.member(`name`,`sex`,`age`,`classid`) values('wangwu','w',20,'class3'),('zhaoliu','m',22,'class4'),('hongqi','w',21,'cls5'),('bajie','m',20,'class6'); Query OK, 4 rows affected (0.01 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> select * from member; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | zhangsan | m | 27 | class1 | | 2 | lisi | w | 28 | class2 | | 3 | wangwu | w | 20 | class3 | | 4 | zhaoliu | m | 22 | class4 | | 5 | hongqi | w | 21 | cls5 | | 6 | bajie | m | 20 | class6 | +----+----------+-----+-----+---------+ 6 rows in set (0.00 sec)
(3)接着继续执行修改数据的操作
mysql> update jiaowu.member set classid='class5' where name ='hongqi'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update jiaowu.member set name='李四' where id='2'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update jiaowu.member set name='洪七' where id='5'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from member; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | zhangsan | m | 27 | class1 | | 2 | 李四 | w | 28 | class2 | | 3 | wangwu | w | 20 | class3 | | 4 | zhaoliu | m | 22 | class4 | | 5 | 洪七 | w | 21 | class5 | | 6 | bajie | m | 20 | class6 | +----+----------+-----+-----+---------+ 6 rows in set (0.00 sec)
(4)最后模拟数据库损坏,这里直接drop掉数据库;
mysql> drop database jiaowu; Query OK, 1 row affected (0.01 sec)
(5)查看最后一个binlog日志,并记录关键的pos点,确定是哪个pos点的操作执行了数据库的删除操作;
先备份一下最后一个binlog日志文件
[root@localhost backup]# ls jiaowu_2019-09-10.sql.gz [root@localhost backup]# cd /usr/local/mysql/var/ [root@localhost var]# ls ibdata1 ib_logfile0 ib_logfile1 localhost.localdomain.err localhost.localdomain.pid mysql mysql-bin.000001 mysql-bin.000002 mysql-bin.index performance_schema test ultrax [root@localhost var]# cp -v mysql-bin.000002 /opt/backup/ `mysql-bin.000002' -> `/opt/backup/mysql-bin.000002' [root@localhost var]# ls /opt/backup/ jiaowu_2019-09-10.sql.gz mysql-bin.000002
接着执行一次刷新日志操作,重新开始新的binlog日志记录文件。此时mysql-bin.000002这个文件不会再有后续写入了,因为便于分析原因及查找jiaowu节点,以后所有数据库操作都会写入到下一个日志文件。
mysql> show binary logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 880 | | mysql-bin.000002 | 1199 | +------------------+-----------+ 2 rows in set (0.00 sec) mysql> flush logs; Query OK, 0 rows affected (0.01 sec) mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000003 | 107 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
(6) 读取binlog 日志文件,并分析日志
方 法 一 :使用mysqlbinlog 读取binlog 日志:
[root@localhost var]# cd /usr/local/mysql/var/ [root@localhost var]# mysqlbinlog mysql-bin.000002
方 法 二 :登录MySQL服务器,并查看(推荐此方法)
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 | 107 | Server ver: 5.5.42-log, Binlog ver: 4 | | mysql-bin.000002 | 107 | Query | 1 | 177 | BEGIN | | mysql-bin.000002 | 177 | Intvar | 1 | 205 | INSERT_ID=3 | | mysql-bin.000002 | 205 | Query | 1 | 437 | use `jiaowu`; insert into jiaowu.member(`name`,`sex`,`age`,`classid`) values('wangwu','w',20,'class3'),('zhaoliu','m',22,'class4'),('hongqi','w',21,'cls5'),('bajie','m',20,'class6') | | mysql-bin.000002 | 437 | Xid | 1 | 464 | COMMIT /* xid=101 */ | | mysql-bin.000002 | 464 | Query | 1 | 534 | BEGIN | | mysql-bin.000002 | 534 | Query | 1 | 661 | use `jiaowu`; update jiaowu.member set classid='class5' where name ='hongqi' | | mysql-bin.000002 | 661 | Xid | 1 | 688 | COMMIT /* xid=103 */ | | mysql-bin.000002 | 688 | Query | 1 | 758 | BEGIN | | mysql-bin.000002 | 758 | Query | 1 | 874 | use `jiaowu`; update jiaowu.member set name='李四' where id='2' | | mysql-bin.000002 | 874 | Xid | 1 | 901 | COMMIT /* xid=104 */ | | mysql-bin.000002 | 901 | Query | 1 | 971 | BEGIN | | mysql-bin.000002 | 971 | Query | 1 | 1086 | use `jiaowu`; update jiaowu.member set name='洪七'where id='5' | | mysql-bin.000002 | 1086 | Xid | 1 | 1113 | COMMIT /* xid=105 */ | | mysql-bin.000002 | 1113 | Query | 1 | 1199 | drop database jiaowu | | mysql-bin.000002 | 1199 | Rotate | 1 | 1242 | mysql-bin.000003;pos=4 | +------------------+------+-------------+-----------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 16 rows in set (0.00 sec)
或者:
mysql> show binlog events in 'mysql-bin.000002'\G; *************************** 1. row *************************** Log_name: mysql-bin.000002 Pos: 4 Event_type: Format_desc Server_id: 1 End_log_pos: 107 Info: Server ver: 5.5.42-log, Binlog ver: 4 *************************** 2. row *************************** Log_name: mysql-bin.000002 Pos: 107 Event_type: Query Server_id: 1 End_log_pos: 177 Info: BEGIN *************************** 3. row *************************** Log_name: mysql-bin.000002 Pos: 177 Event_type: Intvar Server_id: 1 End_log_pos: 205 Info: INSERT_ID=3 *************************** 4. row *************************** Log_name: mysql-bin.000002 Pos: 205 Event_type: Query Server_id: 1 End_log_pos: 437 Info: use `jiaowu`; insert into jiaowu.member(`name`,`sex`,`age`,`classid`) values('wangwu','w',20,'class3'),('zhaoliu','m',22,'class4'),('hongqi','w',21,'cls5'),('bajie','m',20,'class6') *************************** 5. row *************************** Log_name: mysql-bin.000002 Pos: 437 Event_type: Xid Server_id: 1 End_log_pos: 464 Info: COMMIT /* xid=101 */ *************************** 6. row *************************** Log_name: mysql-bin.000002 Pos: 464 Event_type: Query Server_id: 1 End_log_pos: 534 Info: BEGIN *************************** 7. row *************************** Log_name: mysql-bin.000002 Pos: 534 Event_type: Query Server_id: 1 End_log_pos: 661 Info: use `jiaowu`; update jiaowu.member set classid='class5' where name ='hongqi' *************************** 8. row *************************** Log_name: mysql-bin.000002 Pos: 661 Event_type: Xid Server_id: 1 End_log_pos: 688 Info: COMMIT /* xid=103 */ *************************** 9. row *************************** Log_name: mysql-bin.000002 Pos: 688 Event_type: Query Server_id: 1 End_log_pos: 758 Info: BEGIN *************************** 10. row *************************** Log_name: mysql-bin.000002 Pos: 758 Event_type: Query Server_id: 1 End_log_pos: 874 Info: use `jiaowu`; update jiaowu.member set name='李四' where id='2' *************************** 11. row *************************** Log_name: mysql-bin.000002 Pos: 874 Event_type: Xid Server_id: 1 End_log_pos: 901 Info: COMMIT /* xid=104 */ *************************** 12. row *************************** Log_name: mysql-bin.000002 Pos: 901 Event_type: Query Server_id: 1 End_log_pos: 971 Info: BEGIN *************************** 13. row *************************** Log_name: mysql-bin.000002 Pos: 971 Event_type: Query Server_id: 1 End_log_pos: 1086 Info: use `jiaowu`; update jiaowu.member set name='洪七'where id='5' *************************** 14. row *************************** Log_name: mysql-bin.000002 Pos: 1086 Event_type: Xid Server_id: 1 End_log_pos: 1113 Info: COMMIT /* xid=105 */ *************************** 15. row *************************** Log_name: mysql-bin.000002 Pos: 1113 Event_type: Query Server_id: 1 End_log_pos: 1199 Info: drop database jiaowu *************************** 16. row *************************** Log_name: mysql-bin.000002 Pos: 1199 Event_type: Rotate Server_id: 1 End_log_pos: 1242 Info: mysql-bin.000003;pos=4 16 rows in set (0.00 sec)
通过查看,造成数据库删除的pos点是介于1113--1199(这是按照日志区间的pos节点算的),只要恢复到1113之前的位置即可、
(7)先把凌晨1点的完全备份数据恢复至数据库jiaowu
[root@localhost var]# cd /opt/backup/ [root@localhost backup]# ls jiaowu_2019-09-10.sql.gz mysql-bin.000002 [root@localhost backup]# gzip -d jiaowu_2019-09-10.sql.gz [root@localhost backup]# mysql -u root -p -v <jiaowu_2019-09-10.sql Enter password: -------------- /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */ -------------- -------------- /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */ -------------- -------------- /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */ -------------- -------------- /*!40101 SET NAMES utf8 */ -------------- -------------- /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */ -------------- -------------- /*!40103 SET TIME_ZONE='+00:00' */ -------------- -------------- /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */ -------------- -------------- /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */ -------------- -------------- /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */ -------------- -------------- /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */ -------------- -------------- CREATE DATABASE /*!32312 IF NOT EXISTS*/ `jiaowu` /*!40100 DEFAULT CHARACTER SET utf8 */ -------------- -------------- DROP TABLE IF EXISTS `member` -------------- -------------- /*!40101 SET @saved_cs_client = @@character_set_client */ -------------- -------------- /*!40101 SET character_set_client = utf8 */ -------------- -------------- CREATE TABLE `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 AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 -------------- -------------- /*!40101 SET character_set_client = @saved_cs_client */ -------------- -------------- LOCK TABLES `member` WRITE -------------- -------------- /*!40000 ALTER TABLE `member` DISABLE KEYS */ -------------- -------------- INSERT INTO `member` VALUES (1,'zhangsan','m',27,'class1'),(2,'lisi','w',28,'class2') -------------- -------------- /*!40000 ALTER TABLE `member` ENABLE KEYS */ -------------- -------------- UNLOCK TABLES -------------- -------------- /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */ -------------- -------------- /*!40101 SET SQL_MODE=@OLD_SQL_MODE */ -------------- -------------- /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */ -------------- -------------- /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */ -------------- -------------- /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */ -------------- -------------- /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */ -------------- -------------- /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */ -------------- -------------- /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */ --------------
这样就恢复了截止到凌晨1点的备份:
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | jiaowu | | mysql | | performance_schema | | test | | ultrax | +--------------------+ 6 rows in set (0.00 sec) mysql> use jiaowu; Database changed mysql> select * from member; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | zhangsan | m | 27 | class1 | | 2 | lisi | w | 28 | class2 | +----+----------+-----+-----+---------+ 2 rows in set (0.00 sec)
凌晨1点之后的数据还没有恢复回来,这个如何操作? 根据上述提到的,我们可以利用mysql-bin.000002日志进行恢复操作。
(8) 从binlog 日志恢复数据
恢复命令的语法格式:
mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名
----------------------------------------------------------------------------------------------------------------
常用参数选项解释:
--start-position=875 起始pos点
--stop-position=954 结束pos点
--start-datetime="2019-9-10 22:01:08" 起始时间点
--stop-datetime="2019-9-10 22:09:46" 结束时间点
--database=jiaowu 指定只恢复 jiaowu 数据库(一台主机上往往有多个数据库,只限本地log日志)
----------------------------------------------------------------------------------------------------------------
不常用选项:
-u --user=name 连接到远程主机的用户名
-p --password[=name] 连接到远程主机的密码
-h --host=name 从远程主机上获取binlog日志
--read-from-remote-server 从某个MySQL服务器上读取binlog日志
A 、 完全恢复(需要手动vim编辑mysql-bin.000002,将那条drop语句剔除掉)
[root@localhost backup]# cp /usr/local/mysql/var/mysql-bin.000002 /opt/backup [root@localhost backup]# mysqlbinlog /opt/backup/mysql-bin.000002 > /opt/backup/000002.sql [root@localhost backup]# vim /opt/backup/000002.sql #删除里面的drop语句 [root@localhost backup]# mysql -uroot -p -v < /opt/backup/000002.sql
B、指定pos结束点恢复(部分恢复)
当前表数据:
mysql> select * from jiaowu.member; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | zhangsan | m | 27 | class1 | | 2 | lisi | w | 28 | class2 | +----+----------+-----+-----+---------+ 2 rows in set (0.00 sec)
b1.恢复介于‘member表原始数据’ 到 增加‘wangwu’ ,'zhaoliu','hongqi','bajie' 之间的数据;
[root@localhost ~]# /usr/local/mysql/bin/mysqlbinlog --stop-position=464 --database=jiaowu /usr/local/mysql/var/mysql-bin.000002 | /usr/local/mysql/bin//mysql -uroot -p123456 -v jiaowu -------------- /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/ -------------- -------------- /*!40019 SET @@session.max_insert_delayed_threads=0*/ -------------- -------------- /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/ -------------- -------------- BINLOG ' VmB3XQ8BAAAAZwAAAGsAAAAAAAQANS41LjQyLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAVAAEGggAAAAICAgCAA== ' -------------- -------------- SET TIMESTAMP=1568104614 -------------- -------------- SET @@session.pseudo_thread_id=3 -------------- -------------- SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1 -------------- -------------- SET @@session.sql_mode=1075838976 -------------- -------------- SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1 -------------- -------------- /*!*/ -------------- -------------- SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33 -------------- -------------- SET @@session.lc_time_names=0 -------------- -------------- SET @@session.collation_database=DEFAULT -------------- -------------- BEGIN -------------- -------------- SET INSERT_ID=3 -------------- -------------- SET TIMESTAMP=1568104614 -------------- -------------- insert into jiaowu.member(`name`,`sex`,`age`,`classid`) values('wangwu','w',20,'class3'),('zhaoliu','m',22,'class4'),('hongqi','w',21,'cls5'),('bajie','m',20,'class6') -------------- -------------- COMMIT -------------- -------------- ROLLBACK -------------- -------------- /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/ -------------- -------------- /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/ --------------
再次查看数据库:
mysql> select * from jiaowu.member; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | zhangsan | m | 27 | class1 | | 2 | lisi | w | 28 | class2 | | 3 | wangwu | w | 20 | class3 | | 4 | zhaoliu | m | 22 | class4 | | 5 | hongqi | w | 21 | cls5 | | 6 | bajie | m | 20 | class6 | +----+----------+-----+-----+---------+ 6 rows in set (0.00 sec)
数据已全部恢复。
b2. 恢复截止到更改hongqi 的classid =class5 的数据;按照事务区间算开始区间是464 结束区间是688)
[root@localhost ~]# /usr/local/mysql/bin/mysqlbinlog --start-position=464 --stop-position=688 --database=jiaowu /usr/local/mysql/var/mysql-bin.000002 | /usr/local/mysql/bin//mysql -uroot -p123456 -v jiaowu
b3. 单独恢复到name='李四' 这步操作,可这样:
[root@localhost ~]# /usr/local/mysql/bin/mysqlbinlog --start-position=688 --stop-position=901 --database=jiaowu /usr/local/mysql/var/mysql-bin.000002 | /usr/local/mysql/bin//mysql -uroot -p123456 -v jiaowu
b4.单独恢复到name= '洪七‘ 这步操作,可这样:
[root@localhost ~]# /usr/local/mysql/bin/mysqlbinlog --start-position=901 --stop-position=1113 --database=jiaowu /usr/local/mysql/var/mysql-bin.000002 | /usr/local/mysql/bin//mysql -uroot -p123456 -v jiaowu
查看数据库:
mysql> select * from jiaowu.member; +----+----------+-----+-----+---------+ | id | name | sex | age | classid | +----+----------+-----+-----+---------+ | 1 | zhangsan | m | 27 | class1 | | 2 | 李四 | w | 28 | class2 | | 3 | wangwu | w | 20 | class3 | | 4 | zhaoliu | m | 22 | class4 | | 5 | 洪七 | w | 21 | class5 | | 6 | bajie | m | 20 | class6 | +----+----------+-----+-----+---------+ 6 rows in set (0.00 sec)
这样,就恢复了删除前的状态了!