mysql的备份和恢复
对于某些企业来说,数据就是该企业的核心元素,一旦数据丢失都将会对该企业造成致命的打击,因此,作为一名DBA要定期的对数据做好备份工作,以便出现故障时,可以即时恢复,从而保证企业数据的完整性。根据不同的需求,我们可以划分如下备份类型:
mysql的备份类型
1、根据mysql服务器是否在线,备份类型可以这样划分:
热备分:使用这种方式mysql服务器可以在线,且读写操作不受影响
温备:这种方式mysql服务器也可以在线,读操作不受影响,但是写操作受影响,需要手动加读锁(共享锁)。
冷备:这是方式mysql服务器必须停止运行,即离线备份,因此,读写操作都不会受影响
2、根据备份的是表中的数据文件还是通过mysql导出的文件,可以这样划分:
物理备份:这种方式是直接复制或归档文件(即使用cp命令或tar命令)
逻辑备份:这种方式是将数据导出到文本文件中(利用数据重定向功能),因此可以直接利用编辑器编译。如果导出的文本文件有十几个G或者更大的话,那就千万不要使用vim编辑器来编译了。
3、根据备份是整个数据还是仅变化的数据,可以这样划分:
完全备份:就是备份所有的数据
增量备份:仅备份上次完全备份或增量备份以后变化的数据
差异备份:仅备份上次完全备份以后变化的数据,相对于增量备份该方式备份比较慢,但还原速度比较快。
4、根据备份的数据集范围,可以这样划分:
完全备份:也是备份这个数据库中的数据或者备份某个库的数据
部分备份:只备份某个库中的一分部数据,如仅备份库中的某一个表数据。
这几种备份类型彼此之间没有什么对应关系,可以根据需求相互结合使用。
为什么要备份?
之所以要备份,主要是防止数据丢失,给企业造成重大影响,对于信息时代,数据对于一个企业是至关主要的,因此,如果保护好数据也是非常重要的。
备份的目的主要有如下几个因素:
1、做灾难恢复。防止其他突发事件导致数据丢失或者不可用了,因此做好数据防灾工作是必须的。
2、审计。有些网站需要统计下某个栏目的访问量,那么就需要对数据进行审计了。
3、恢复测试。一般说来,当数据备份完成之后,还需要对备份的数据对一些测试工作,以检验这些备份的数据是否可以正常恢复。
物理备份和逻辑备份的特点
物理备份:该方式备份速度快,且还原也比较快,属于文件系统级别的
逻辑备份:该方式仅是备份数据,因此在还原过程中,需要手动建立表结构,且这种方式备份的速度慢、易丢失浮点数精度。备份出来的数据会占用更多的存储空间,其压缩后可大大节省空间。但是由于将数据直接存储在本文文件中,因此,可以利用文本工具直接处理,其移植能力强。但是不适合对大数据库做完全备份。
增量备份和差异备份的比较
在上面已经讲述了增量备份和差异备份的概念,如果还是看不懂,这里我给出一个比较直观的图形界面,大家可以直观的看出,这两种方式的差异在哪里。
备份的对象
一般来说,我们需要对如下这些数据进行备份:
数据:这个就不多说了,这就是要备份的核心东西
二进制日志文件:如果mysql服务器上的存储数据的文件损坏了,那么二进制日志文件就可以用来恢复备份之后的数据。因此,这个一般我们也要备份,一般我们会对二进制日志使用增量备份或者差异备份的方式来备份。
事务日志文件:如果某个事务线程正在运行,且事务日志文件存放的数据满时,即时事务没有提交,事务日志会将数据同步到磁盘中去,因此,事务日志中很可能存在一半的事务(即只有一部分数据写入到磁盘中去)。一旦服务器宕机,就可以利用事务日志来进行撤销。使数据保持不受影响。因此,事务日志一般也要备份。
mysql的配置文件:由于mysql的配置文件可以定义各种服务器变量,因此,不同的mysql服务器可能定义的属性不一样,因此,一般我们也要对mysql的配置文件做备份。
代码:包括存储函数、存储过程、触发器等等。
备份策略
一般的我们需要一个月做一次完全备份,一周做一次增量备份或差异备份;或者一周做一次完全备份,每天做一次增量备份或差异备份。
因此,一般使用完全备份+增量备份或者完全备份+差异备份来结合备份数据和其他重要文件(上述提到)
备份时需要考虑的因素:
使用何种备份方式
何时进行备份,一般的在服务器比较空闲的时候,备份数据比较好,如在凌晨进行备份。
备份时长,如果一个数据备份的时间太长的话,那么我们应该采用增量或者差异的方式进行备份。
备份负载,数据备份时也会占用很多的io和网络带宽,因此,在服务器不是很繁忙的时候进行备份比较好。
备份工具
我们所需要的备份工具有如下这些:
其中mysqldump是一个mysql客户端的逻辑备份工具,备份数据和恢复数据比较慢,它对MyISAM存储引擎支持温备份;对Aria存储引擎支持温备;对Innodb存储引擎支持热备。mysqldump适用于备份数据集比较小的数据。
select into outfile是一个逻辑备份工具,需要手动创建表结构。相比mysqldump来说,该工具备份速度和还原速度比mysqldump快,且占用空间小。
mysqlhotcopy是一个物理备份工具,它仅对MyISAM存储引擎支持温备份。
Snapshot:利用LVM的快照功能实现几乎热备功能,是一个物理备份工具。
第三方备份工具:
innobackup是由Innobase公司研发的,是一个商业备份工具。
xtrabackup是由Percona组织研发的,是一个开源备份工具。它对MyiSAM存储引擎只能做完全备份,即使是做增量备份,该增量备份也是属于完全备份。对于InnoDB存储引擎来将,他可以做完全备份、增量备份和差异备份。
利用mysqldump工具来实现数据的完全备份
由于mysqldump是一个逻辑备份工具,备份和恢复速度慢,因此使用该工具备份数据时,数据的体积不能太大。mysqldump备份方式是将表中的一些sql语句备份起来,还原时,将这些语句批量插入。
mysqldump的使用语法格式
1、备份单个数据库或者其他中的某个表
mysql> mysqldump -uUSERNAME -p DB_NAME [tb1_name] [tb2_name] > /path/to/somefile.sql
说明:使用这种方式需要手动创建数据库名称或表结构
2、备份多个数据库
mysql> mysqldump -uUSERNAME -p options... > /path/to/somefile.sql
options:
--all-databases:备份所有的数据库,不需要创建数据库名
--databases DB1_NAME,DB2_NAME..:备份多个指定数据库,不需要创建数据库名
--lock-all-tables:备份时锁定所有表。对MyiSAM、Aria、InnoDB存储引擎做温备时使用的选项。
--flush-logs:执行日志flush
--master-data={0|1|2}
0:表示不记录二进制日志文件和路径
1:以CHNAGE MASTER TO的方式记录位置,可用于恢复后直接启动从服务器;
2:以CHANGE MASTER TO的方式记录位置,但该行默认为被注释掉了;
--events:备份数据库中的创建事件的调度器代码
--routines:备份存储函数和存储过程
--triggers:备份触发器
--single-transaction:对InnoDB存储引擎实现热备。该选项不能和--lock-all-tables一起使用。
利用mysqldump来实现对hellodb这个数据库做温备
备份时的操作
1、备份时执行如下命令
# mysqldump -uroot -p --databases hellodb --flush-logs --lock-all-tables > first_wb.sql
--databases hellodb:指定要备份的数据库。
--flush-logs:在备份前执行二进制日志滚动,这样做的好处在于,当以后有数据写入时,这些修改的操作会被记录到二进制日志文件中去,即使一不小心把数据删除了,也可以利用二进制日志文件来进行恢复,因此,我们需要准确的知道当前的二进制日志文件是哪一个,及其事件处于哪一个position。
--lock-all-tables:在备份前加锁,防止数据写入。
2、临时关闭二进制日志功能
由于mysqldump备份的数据都是一些insert、create语句,因此,当这些数据恢复时,其 实就是再把这些语句重新执行一次,因此,会改变数据库,所以这些修改操作都会记录到二进制日志文件中。由于我们已经有了备份文件数据,因此,这些数据不应 该再次写入到二进制日志文件中去。
mysql> set session sql_log_bin=off;
Query OK, 0 rows affected (0.00 sec)
3、记录当前的使用的二进制日志文件及其事件的position。
# mysql -uroot -p -e 'show master status;' > /mybackup/current-bin
显示current-bin文件的内容
# cat current-bin
File Position Binlog_Do_DB Binlog_Ignore_DB
mysql-bin.000005 107
当前的二进制日志文件为mysql-bin.000005,下一个事件的起始位置为107。
恢复时的操作(恢复时服务器需要处于离线状态)
4、模拟数据库hellodb一不小心被删除了
mysql> drop database hellodb;
Query OK, 7 rows affected (0.03 sec)
删除成功后,显示所有的库,发现hellodb,已经被删除了。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| good |
| he |
| mysql |
| nginxdb |
| performance_schema |
| test |
+--------------------+
7 rows in set (0.00 sec)
5、将备份数据倒入到数据库中
由于刚刚修改的服务器变量sql_log_bin只是会话级别的,因此,他只会在当前会发生效,所以,此时将备份文件倒入到数据库中,需要在mysql中执行source命令来完成。如:
mysql> source /mybackup/first_wb.sql
Query OK, 0 rows affected (0.00 sec)
执行成功过后,这个Query OK行会显示很多条的。
6、查看hellodb库是否已经恢复额
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| good |
| he |
| hellodb |
| mysql |
| nginxdb |
| performance_schema |
| test |
+--------------------+
8 rows in set (0.00 sec)
7、验证上述写操作是否记录到了二进制日志文件中
mysql> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000005 | 107 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
之前已经将二进制日志功能临时关闭了,因此这些写操作都没有记录进二进制日志文件中。
此致,对hellodb做温备份过程已经完成了。虽然恢复过程已经完成,但是不要忘记了 开启二进制日志功能。因此,还需要执行如下命令:
mysql> set session sql_log_bin=on;
Query OK, 0 rows affected (0.00 sec)
模拟使用二进制日志文件来恢复数据
8、在hellodb库中创建表wb
mysql> use hellodb
Database changed
mysql> create table wb(name char(20),age tinyint unsigned not null);
Query OK, 0 rows affected (0.02 sec)
然后在插入几行数据
mysql> insert into wb (name,age) values ('tom',30),('boy',19);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
显示表wb的内容
mysql> select * from wb;
+------+-----+
| name | age |
+------+-----+
| tom | 30 |
| boy | 19 |
+------+-----+
2 rows in set (0.00 sec)
此时如果该表没有备份,一不小心表wb被删除了话,该如何恢复。此时就需要借助二进制日志来完成数据恢复功能。
9、模拟表table被删除
mysql> drop table wb;
Query OK, 0 rows affected (0.00 sec)
此时发现二进制日志文件中的position位置发生改变的了,这是因为它将drop table wb该操作写入到了二进制日志文件中去了。那么待会还原的时候,不要将这部分数据倒入到文件中。
mysql> show master status;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000005 | 558 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
10、利用二进制日志文件导出刚刚创建表的过程。
# mysqlbinlog --start-position --stop-position=451 /mydata/binary/master-bin.000005 > /mybackup/table_wb.sql
11、临时关闭二进制日志功能
mysql> set session sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
12、将/mybackup/table_wb.sql文件导入到数据库中
mysql> source /root/table_wb.sql;
13、查看表table文件是否存在
mysql> use hellodb;
Database changed
mysql> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| scores |
| students |
| teachers |
| toc |
| wb |
+-------------------+
8 rows in set (0.01 sec)
显示结果表示表wb已经恢复完成。
查询表table
mysql> select * from wb;
+------+-----+
| name | age |
+------+-----+
| tom | 30 |
| boy | 19 |
+------+-----+
2 rows in set (0.00 sec)
14、最后开启二进制日志功能
mysql> set session sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
总结:
使用mysqldump做温备份或热备前需要注意的事项:
1、如果做温备,在备份前加读锁,避免有数据写入,但不影响读操作,执行flush tables with read lock命令即可。或者在mysqldump后面加上--lock-all-tables选项即可。
如果做热备,前提是存储引擎为InnoDB,且备份时不需要手动加锁,需要在mysqldump后面加上--single-transaction选项即可。
2、执行flush logs命令,或者在mysqldump命令后加上--flush-logs选项,用来滚动二进制日志文件,这样下一次的操作都会记录在后面生产的二进制文件中,以便于数据恢复。
3、记录下当前正在使用的二进制日志文件及其下一个事件的position。
4、如果是使用flush tables with read lock来加锁的话,那么备份完成后,执行unlock tables;命令来解锁
5、由于mysqldump备份后的文件都是一些insert、drop等DDL、DML语句,因此,在还原数据过程中,会将该操作记录到二进制日志文件中。因此,在数据恢复过程中,临时关闭二进制日志功能。即使用该命令即可实现set session sql_log_bin=0;
6、恢复完成后还需要开启二进制日志功能。set session sql_log_bin=1;
7、利用二进制文件做恢复时,先使用mysqlbinlog来查看文件并筛选符合的事件条目,然后在重定向到SOMEFILE.sql文件中,然后临时关闭二进制日志功能,最后利用mysql> source SOMEFILE.sql来恢复数据。
8、利用二进制还原完成后,开启二进制功能set session sql_log_bin=1;
逻辑备份工具select into outfile
该工具备份后是一个文本文件,且备份数据和还原速度比较快,占用空间小,不适合对数据库做备份。一般用来做某个表或表中的某个语句做备份。
备份语法格式:
SELECT * INTO OUTFILE '/path/to/somefile.txt' FROM tb_name [WHERE clause];
还原语法格式:
LOAD DATA INFILE '/path/to/somefile.txt' INTO TABLE tb_name;
还原前需要手动创建表结构。