mysql dump备份结合binlog日志恢复
mysql备份一般采取全库备份加日志备份的方式,例如每天执行一次全库备份,每小时执行一次二进制日志备份。这样在mysql故障后可以使用全库备份和日志备份将数据恢复到最后一个二进制日志备份前的任意位置和时间。
1.binlog介绍
mysql二进制日志记录着该数据库的所有增删改的操作日志(前提是要在自己的服务器上开启binlog),还包括了这些操作
的执行时间,为了显示这些二进制的内容,我们可以使用mysqlbinlog命令来查看。
binlog的用途:
1.主从同步 2.恢复数据库
开启binary log功能
通过编辑my.cnf中的log-bin选项可以开启二进制日志;形式如下:
[client]
socket=/usr/local/mysql/mysql.sock
[mysqld]
server-id=1
log-bin=mysql-bin
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
pid-file=/usr/local/mysql/data/mysqld.pid
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/mysqld.err
log-bin[=DIR/[filename]]
其中,DIR参数指定二进制文件的存储路径;filename参数指定二进制文件的文件名,其形式为filename.number,number的形式为
000001、000002等。每次重启mysql服务或运行flush logs;
mysql>flush logs;
都会生成一个新的二进制日志文件,这些日志文件的number会不断地递增
除了生成上述的文件外还会生成一个名为filename.index的文件。这个文件中存储所有二进制日志文件的清单又称为二进制文件的索引
配置保存以后重启mysql的服务器,用mysql>show variables like 'log_bin'; 查看bin-log是否开启,如图:
mysql> show variables like 'log_bin';
查看产生的binary log 注意:查看binlog内容是为了恢复数据
binlog因为是二进制文件,不能通过文件内容查看命令直接打开查看,mysql提供了两种查看方式:
(1)查看MySQL Server上的二进制日志
mysql> show binary logs;
(2.)查看二进制日志信息的命令:
mysql> show binlog events in 'mysql-bin.000002' from 219 limit 1,3;
(3.)查看二进制日志中的事件
默认显示可找到的第一个二进制日志文件中的事件,包含了日志文件名,事件的开始位置、事件类型、结束位置、信息等内容
mysql> show binlog events;
(4.)查看指定的二进制日志中的事件
mysql> show binlog events in 'mysql-bin.000002';
//Xid时间是自动提交事务的动作
show binary logs等价于show master logs
purge binary logs :用于删除二进制日志
例如:
purge binary logs to ‘mysql-bin.00010‘;//把这个文件之前的其他文件都删除掉
purge binary logs before ‘2016-08-28 22:46:26’;//把指定时间之前的二进制文件删除了
reset master 与 reset slave作用
前者清空index文件列出的所有二进制日志,重置 index文件为空,并创建一个新的二进制日志文件,一般用于master首次启动时。
后者使slave忘记其在master二进制日志文件中的复制位置,它会删除master.info、relay-log.info和所有中继日志文件并开始一个新的
中继日志文件,以便于开始一个干净的复制。在使用reset slave 前需先关闭slave复制线程。
上述方式可以查看到服务器上存在的二进制日志文件及文件中的事件,但是想查看文件中具体的内容并应于恢复场景还得借助mysqlbinlog
这个工具。
mysqlbinlog 的可用选项可参考man手册
二进制日志文件的格式包含行模式、语句模式和混合模式(也即有服务器决定在什么情况下记录什么类型的日志),基于语句的日志中事件
信息包含执行的语句等,基于行的日志中事件信息包含的是行的变化信息等。混合模式的日志中两种类型的事件信息都会记录。
为了便于查看记录了行的变化信息的事件在当时具体执行了什么样的SQL语句可以使用mysqlbinlog工具的-v(version)选项,该选项
该选项会将行事件重构成被注释掉的伪SQL语句,如果想看到更详细的信息可以将该选项给两次如-vv,这样可以包含一些数据类型
和元信息是注释内容。
先切换到binlog所在的目录下
#mysqlbinlog mysql-bin.000001
#mysqlbinlog -v mysql-bin.000001
#mysqlbinlog -vv mysql-bin.000001
另外mysqlbinlog还可以通过--read-from-remote-server选项从远程服务器读取二进制日志文件,这时需要一些而外的连接参数,如-h,-P,-p,
-u等,这些参数仅在指定了--read-from-remote-server后面有效
无论是本地二进制日志文件还是远程服务器上的二进制日志文件,无论是行模式、语句模式还是混合模式的二进制日志文件,被mysqlbinlog
工具解析后都可直接应用与mysql server进行基于时间点、位置或数据库的恢复。
使用binlog日志进行恢复数据案例:
接下来我们就来演示如何使用binlog恢复之前删除的数据
在演示之前:
为了模拟被删除的数据,事先创建一个数据库、数据表、插入zhangsan、lisi两条数据,再删除lisi后,插入tom用户
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kang |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use kang;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+----------------+
| Tables_in_kang |
+----------------+
| test1 |
+----------------+
1 row in set (0.00 sec)
mysql> select * from test1;
+------+----------+
| id | name |
+------+----------+
| 1 | zhangsan |
| 2 | tom |
+------+----------+
2 rows in set (0.47 sec)
注意:在实际生产环境中,如果遇到需要恢复数据库的情况,不要让用户能访问到数据库,以避免新的数据插入进来,还有在主从的环境下,要关闭主从。
(1.)删除lisi后,查看binlog文件,从中找出lisi被删除的那条记录。
[root@kang ~]# cd /usr/local/mysql/data/
[root@kang data]# mysqlbinlog -v mysql-bin.000002
从上图可以看出delete事件发生position是1165,事件结束position是1292
恢复流程:直接用bin-log日志将数据库恢复到删除位置1165前,然后跳过故障点,再进行修复
(2.)由于之前没有做过全库备份,所以要使用binlog日志进行数据恢复,生产环境中需要很长时间恢复,导出相关binlog文件
[root@kang data]# mysqlbinlog /usr/local/mysql/data/mysql-bin.000001 >/opt/mysql-bin.000001.sql
[root@kang data]# mysqlbinlog --stop-position=1165 /usr/local/mysql/data/mysql-bin.000002 > /opt/1165.sql
[root@kang data]# mysqlbinlog --start-position=1292 /usr/local/mysql/data/mysql-bin.000002 > /opt/1292.sql
[root@kang data]#
(3.)删除kang数据库
mysql> drop database kang;
Query OK, 1 row affected (1.31 sec)
mysql>
(4.)利用binlog恢复数据
[root@kang ~]# mysql -uroot -ppwd123 (5.)恢复完成后,我们登录mysql数据库查看下表的数据是否完整
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kang |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use kang;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+----------------+
| Tables_in_kang |
+----------------+
| test1 |
+----------------+
1 row in set (0.00 sec)
mysql> select * from test1;
+------+----------+
| id | name |
+------+----------+
| 1 | zhangsan |
| 2 | lisi |
| 2 | tom |
+------+----------+
3 rows in set (0.00 sec)
ok没问题,所有数据都恢复过来了
mysqlbinlog常见的选项:
--start-datetime
从二进制日志中读取指定时间戳或者本地计算机时间之后的日志事件。
--stop-datetime
从二进制日志中读取指定时间戳或者本地计算机时间之前的日志事件。
--start-position
从二进制日志中读取指定position事件位置作为开始
--stop-position
从二进制日志中读取指定position事件位置作为事件截止。
2.mysqldump介绍
mysqldump是mysql用于备份和数据转移的一个工具。它主要产生一系列的SQL语句,可以封装到文件,该文件包含所有重建数据库所需要的SQL命令。如create database,create tables,insert等等。可以用来实现轻量级的快速迁移或恢复数据库。
mysqldump是将数据表导成SQL脚本文件,在不同的mysql版本之间升级时相对比较合适,这也是最常用的备份方法。
mysqldump一般在数据量很小的时候(几个G)可以用于备份。当数据量比较大的情况下,就不建议使用mysqldump工具进行备份了。
(1).数据库的导出:
导出对象说明:mysqldump可以针对单个表、多个表、单个数据库、多个数据库、所有数据库进行导出的操作。
导出数据库kang;
[root@kang ~]# mysqldump -uroot -p --flush-logs kang > /opt/kang.sql
Enter password:
//--flush-logs这个选项在完整备份数据库的时候重新开启一个新的binlog
数据库的导入
注:当备份文件只包含表的备份,而不包括创建库的语句时,则执行导入操作时必须指定库名,而且目标库必须存在。
[root@kang ~]# mysql -uroot -p kang < /opt/kang.sql
Enter password:
[root@kang ~]#
以上我们介绍了mysql的binlog和mysqldump工具
下面我们来学习如何实现mysqldump全库备份+binlog的数据恢复
环境准备:
(1.)检查是否开启binlog,如果没有开启那就请开启binlog。
[client]
socket=/usr/local/mysql/mysql.sock
[mysqld]
server-id=1
log-bin=mysql-bin
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
pid-file=/usr/local/mysql/data/mysqld.pid
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/mysqld.err
(2.)登录mysql数据库创建一些测试数据
mysql> create database t370;
Query OK, 1 row affected (0.01 sec)
mysql> use t370;
Database changed
mysql> create table student(id int,name varchar(10));
Query OK, 0 rows affected (0.36 sec)
mysql> insert into student values(1,'tom1');
Query OK, 1 row affected (0.07 sec)
mysql> insert into student values(1,'tom2');
Query OK, 1 row affected (0.01 sec)
mysql>
(3.)创建备份目录
[root@kang ~]# mkdir /opt/mysqlbackup
[root@kang ~]# mkdir /opt/mysqlbackup/daily
(4.)全库备份
这里我们模拟周一的完整备份数据库任务
[root@kang ~]# mysqldump -uroot -p --flush-logs t370 > /opt/mysqlbackup/t370.sql
Enter password:
(5.)接下来登录mysql数据库,模拟误删除一条数据。
mysql> delete from student where id=1;
Query OK, 2 rows affected (0.19 sec)
mysql> insert into student values(3,'tom3');
Query OK, 1 row affected (0.01 sec)
登入mysql数据查看内容:
(6.)备份来自mysqldump之后的binlog日志文件
[root@kang data]# cp /usr/local/mysql/data/mysql-bin.000004 /opt/mysqlbackup/daily/
上面模拟的误操作是删除了id=1的记录
(7.)现在我们使用mysqldump的全库备份和binlog日志来恢复数据库。
首先使用mysqldump的备份进行全库恢复:
[root@kang data]# mysql -uroot -p t370 < /opt/mysqlbackup/t370.sql
Enter password:
登入mysql数据库进行查看:
从显示结果可以看到使用mysqldump备份将数据还原到了备份时的状态,刚才删除的数据(id=1)恢复回来了,但是
发现刚才使用mysqldump备份全库后,新插入的数据不见了,所以还得利用binlog进一步还原,因为删除是在全库备份后发生的,所以只需要分析mysqldump使用--flush-logs产生的mysql-bin.000004这个binlog日志文件即可。
查看mysql-bin.000004中的事件,可以看到有删除事件
mysql> show binlog events in 'mysql-bin.000004';
注意:使用mysqlbinlog命令可以查看备份的binlog文件的详细事件。找到那条被删除的数据。
[root@kang ~]# mysqlbinlog -vv /opt/mysqlbackup/daily/mysql-bin.000004
恢复流程:我们直接用bin-log日志将数据库恢复到删除位置前,然后跳过故障点,再进行恢复删除后的所有操作。
通过mysqlbinlog命令所显示的结果可以看到误操作delete的开始position为291,结束position是430。
[root@kang ~]# mysqlbinlog --stop-position=291 /opt/mysqlbackup/daily/mysql-bin.000004 | mysql -u root -p
Enter password:
上面这条命令意思是:从二进制日志中读取指定position=291事件位置作为截止,即把数据恢复到delete删除前
[root@kang ~]# mysqlbinlog --start-position=430 /opt/mysqlbackup/daily/mysql-bin.000004 | mysql -u root -p
Enter password:
上面这条命令意思是:从二进制日志中读取指定position=430事件位置作为开始,即跳过删除事件,恢复删除事件之后对数据的正常操作。
接下来就可以到mysql数据库上查看恢复结果了:
从上图可以看出数据恢复到正常状态!!
到这里不得不说mysqldum+binlog进行数据备份与恢复算是完事了。
总结:
(1.)binlog用途:主从同步、数据恢复
(2. )mysqlbinlog:可以查看二进制日志文件、详细内容信息、
(3.)mysqldump:导出、导入数据、对单个表、多个表、单个库、多个库进行备份
(4.)reset master与reset slave:前者清除重置主数据库二进制日志文件,后者让从数据库忘记在主数据库复制日志的位置。