备份和恢复概念
备份和恢复的意义
备份:目的用于恢复。请注意要对备份数据做恢复测试,防止备份的不能恢复,到时候就麻烦了。
备份类型
1.根据备份时,数据库服务器是否在线:
- 冷备:cold backup。服务器离线,数据库读写操作都不能执行。
- 温备:warm backup。全局施加共享锁,所有业务只能读,不能写。
- 热备:hot backup。服务器不离线,读写操作都能进行。这就可能会有问题了。我们去备份,数据量很大,我们得夜间备份,在你复制的过程中,如果文件发生了改变,前一半后一半时间戳不一致,备份好的文件恢复过来是不允许访问的。在文件系统上,这样的文件属于时间点不一致文件,因此是不允许访问的。我们可以把整个数据库锁定,然后创建一快照,通过快照进行备份。通过快照备份,时间点一定是一致的,但是也有一些其他的问题。首先你要锁定整个库,你一锁定,别人就读写不了了。所以这也不能算是热备。真正的热备是指任何业务不终止,它能够自动在背后进行备份,而且自动保证时间点是一致的。【注意】:要想完成热备,通常是基于事务的存储引擎才能完成的。
2.根据备份的数据集:
- 完全备份:full backup
- 部分备份: partial backup
3.根据备份时的接口(直接备份数据文件还是通过mysql服务器导出数据):
- 物理备份:直接复制(归档)数据文件的备份方式;physical backup。
copy命令就可以备份了,还可以tar归档压缩备份,因此不需要额外的工具就可以备份。恢复也很简单,把备份的文件复制到数据库里面就可以了,但是要兼容才行。但好在MySQL的InnoDB和MyISAM非常容易跨平台,一般来说,在windows上备份的在Linux上也能用,在Linux上备份的在windows上也能用。物理备份比较适合大数据量备份,比如超过10G,甚至几十个G,千万别用逻辑备份。 - 逻辑备份:把数据从库中提出出来保存为文本文件;logical backup。
从根本上来讲,逻辑备份备份后为文本文件,我们可以使用grep、sed、awk来处理查看,物理备份的文件则不能被如此处理。而且逻辑备份恢复简单,导入就可以了。逻辑备份也有缺点,比如说与物理备份恢复速度比,逻辑备份恢复更慢,占据空间更大。还有逻辑备份有个重要缺点,无法保证浮点数的精度,因为我们必须把二进制数据转换成文本格式。更重要的是使用逻辑备份还原数据以后还需要重建索引。 对于非常大的表,重建索引是相当消耗时间和资源的,由其是CPU资源。逻辑备份的工具:mysqldump
4.根据备份时是备份整个数据还是仅备份变化的数据:
- 完全备份:full backup
- 增量备份:incremental backup。得使用专业的备份工具进行增量备份。
- 差异备份:differential backup
增量和差异:差异,每一次起始点不是上一次备份,而是上一次完全备份。见下图。将来设计备份策略的时候,需要根据你的数据量变化频度来设计。
备份策略
- 选择备份方式
- 选择备份时间
- 考虑到恢复成本
- 恢复时长
- 备份成本:
- 锁时间
- 备份时长
- 备份负载
备份对象
- 数据
- 配置文件
- 代码:存储过程,存储函数,触发器
- OS相关的配置文件,如crontab配置计划及相关的脚本
备份工具
1.mysqldump:MySQL原生自带的逻辑备份工具,单线程工具。
- InnoDB热备、温备和冷备,MyISAM温备,Aria温备
- 因为是逻辑备份,所以备份和恢复过程较慢
2.mysqldumper: 多线程的mysqldump。装上percona的tools之后,mysqldumper就在里面。多线程同时备份多个库,在必要的场景下缩短备份时间是很有必要的。
这两个备份工具很难实现差异或增量备份;
3.lvm-snapshot: 基于lvm的逻辑卷快照进行备份。
- 这是接近于热备的工具:为什么叫接近于?因为要先请求全局锁,而后创建快照,并在创建快照完成后释放全局锁;
- 使用cp、tar等工具进行物理备份;
- 备份和恢复速度较快;
很难实现增量备份,并且请求全局需要等待一段时间,在繁忙的服务器上尤其如此;
4.部分备份工具:
SELECT clause INTO OUTFILE '/path/to/somefile'
LOAD DATA INFILE '/path/from/somefile' #恢复时得使用这个命令恢复。
- 部分备份工具, 不会备份关系定义,仅备份表中的数据;
- 也是个逻辑备份工具,快于mysqldump。
5.mysqlhotcopy:几乎冷备。
6.专业备份工具:
- Innobase: 商业备份工具, innobackup
- Xtrabackup: 由Percona提供的开源备份工具。需要单独安装。
- InnoDB热备,增量备份;
- MyISAM温备,只是完全备份,不支持增量;
- 物理备份,速度快;
mysqldump备份
mysqldump备份介绍
【注意】:数据量在10G以下。
相当于一个MySQL客户端工具,你的服务器在远程,mysqldump在本地,没有任何问题,也就意味着二者可以在不同的主机上。可实现完全备份和部分备份,但是还原一个库时,这个库得事先存在,就是说在还原前,先得CREATE DATABASE。
man mysqldump
mysqldump [options] [db_name [tbl_name ...]]
备份单个库:
mysqldump [options] db_name
恢复时:如果目标库不存在,需要事先手动创建。
【示例1】:备份和恢复。
1.先备份库
[root@db ~]# mysqldump -uroot -hlocalhost -p hellodb >/tmp/hdb.sql
Enter password:
2.连接上mysql数据库,删除库hellodb
mysql> DROP DATABASE hellodb;
Query OK, 7 rows affected (0.01 sec)
3.恢复,得事先创建库
[root@db ~]# mysql -uroot -hlocalhost -p </tmp/hdb.sql
Enter password:
ERROR 1046 (3D000) at line 22: No database selected
mysql> CREATE DATABASE hellodb DEFAULT CHARSET 'utf8';
Query OK, 1 row affected (0.00 sec)
[root@db ~]# mysql -uroot -hlocalhost -p hellodb </tmp/hdb.sql
Enter password:
所以说指定数据库进行备份的这种方式,它只是备份这个库里的东西,它以为这个库是事先存在的,所以恢复时是不会自动创建库的。也可以备份某个表。
--all-databases: 备份所有库。恢复时不需要事先创建库名。
--databases db1 db2 ...: 备份指定的多个库。多个库名间用空格隔开,事先不需要创建库名。
【示例2】:备份前加锁。(这才是真正的备份,要锁表)
- –lock-all-tables:请求锁定所有表之后再备份,对MyISAM、InnoDB、Aria做温备。
- –lock-tables:备份哪张表,就锁定哪张表。这种并不理想,不建议使用,使用上面的那个。
- –single-transaction: 能够对InnoDB存储引擎实现热备;
|
|
【注意】:上面两句,第二句在备份单个表时也加了–databases参数,这样备份后的文件里是有CREATE DATABASE语句的。但是–lock-all-tables这种方式也不是很理想,其他的请求会被阻塞,如果你能确保你要备份的数据库的表的底层存储引擎都是InnoDB的话,可以使用另外一种备份方式,–single-transaction,基于多版本并发控制完成对InnoDB存储的热备,和–lock-all-tables不要同时使用。
备份代码:mysqldump只备份数据,不备份代码。
- –events: 备份事件调度器代码
- –routines: 备份存储过程和存储函数
- –triggers:备份触发器
备份时滚动日志:
--flush-logs: 备份前、请求到锁之后滚动日志。
为什么要滚动日志呢?恢复是要采用完全备份+增量备份或差异备份,最后是恢复不到数据损坏的那一刻的,比如你周日做的完全备份,周三中午崩掉了,你可以采用完全备份+周一、周二的增量备份,或者完全备份+差异备份,但是你周三凌晨到周三中午的数据怎么恢复?依靠二进制日志。滚动之后,恢复时你就知道从哪个文件向后是要用到的。因此用mysqldump做完全备份时都应该做–flush-logs。
复制时的同步位置标记:
主从复制架构中的主服务器数据,说白了它就是在你没有flush-logs时怎么知道下一次恢复时用这个文件怎么恢复到时间点。–master-data帮我们备份那一刻二进制日志的文件名及事件所处的位置。
--master-data=[0|1|2]
0: 不记录
1:记录为CHANGE MASTER语句
2:记录为注释的CHANGE MASTER语句
【总结】:使用mysqldump备份需要使用的参数:
- 请求锁:–lock-all-tables或使用–singe-transaction进行innodb热备;
- 滚动日志:–flush-logs
- 选定要备份的库:–databases
- 记录二进制日志文件及位置:–master-data=
mysqldump备份示例
【示例1】:手动施加锁,然后进行备份。
【注意】:刷写所有表:把所有表在缓冲区中的内容通通同步到磁盘上。如果你的数据量很大,这句刷写和加锁语句要等很长时间。
然后用mysqldump备份就可以了。
[root@db ~]# mysqldump -uroot -p --databases hellodb >/tmp/hellodb2.sql
Enter password:
备份完了记得释放锁:
mysql> UNLOCK TABLES;
Query OK, 0 rows affected (0.00 sec)
【示例2】:手动施加锁太麻烦,直接用mysqldump备份。
[root@db ~]# mysqldump -uroot -p --databases hellodb --lock-all-tables --flush-logs >/tmp/hellodb3.sql
Enter password:
如果有代码块,也需要把相应选项加进来。
- –events: 备份事件调度器代码
- –routines: 备份存储过程和存储函数
- –triggers:备份触发器
热备,你得确定库中所有表的存储引擎都是InnoDB存储引擎
[root@db ~]# mysqldump -uroot -p --databases hellodb --single-transaction --flush-logs >/tmp/hellodb4.sql
Enter password:
还应该指定–master-data=[0|1|2]
[root@db ~]# mysqldump -uroot -p --databases hellodb --lock-all-tables --flush-logs --master-data=2 >/tmp/hellodb5.sql
Enter password:
[root@db ~]# vim /tmp/hellodb5.sql
恢复:
建议:临时性关闭二进制日志,关闭其它用户连接。因为恢复时经常会创建数据库,创建表,插入数据,这部分没必要记录二进制日志。用这个备份恢复时只能恢复到上一次完全备份的位置,要想做时间点还原,还需要二进制日志。
【示例3】:数据库即时点恢复。
[root@db ~]# mysqldump -uroot -p --databases hellodb --lock-all-tables --flush-logs --master-data=2 >/tmp/hellodb6.sql
Enter password:
备份后,我们在hellodb库中创建了表,插入了一些数据。
没注意把数据库hellodb删除了
恢复过程:
①让服务器离线,最起码你得保证服务器不能被别人连进来。
开启防火墙或者其他。
②把即时点前的二进制日志导出来。
二进制日志是master-bin.000013的120位置。
[root@db ~]# vim /tmp/hellodb6.sql
[root@db ~]# cd /data/binlog/
[root@db binlog]# mysqlbinlog --start-position=120 master-bin.000013 #这个日志文件和文件名是在配置文件中定义的
[root@db binlog]# mysqlbinlog --start-position=120 --stop-position=446 master-bin.000013 >/tmp/helldb6.inc.sql
③连上mysql服务器做恢复,先临时性关闭二进制日志
千万不要xshell另起一个会话,导入完全备份,因为session sql_log_bin=0只对当前会话生效,另起一会话导入备份,那么同时也会写到二进制日志中,这是我们不期望的。
④恢复到即时点。
但事实上这个开不开没什么影响,只要你自己不在当前session中操作就行。
【总结】:备份策略:基于mysqldump
1.备份:mysqldump+二进制日志文件
周日做一次完全备份:备份的同时滚动日志
周一至周六:备份二进制日志;(可以每天都FLUSH LOGS,然后把备份之前的那个二进制日志,每天备份每天的二进制日志,直接copy就可以备份二进制日志文件。这里其实是把二进制日志当增量备份)。
2.恢复
完全备份+各二进制日志文件中至此刻的事件
日志滚动也可以使用mysqladmin工具:
[root@db binlog]# mysqladmin -uroot -p flush-logs
Enter password:
对MySQL配置文件,以及与MySQL相关的OS配置文件在每次修改后都应该直接进行备份。cp一份放在一个地方就行。
我们可以写一个备份脚本:
1、备份所有数据库;
2、在每周日凌晨自动执行;
【注意】:crontab的PATH环境变量和系统的PATH环境变量是不一样的,无论你在命令行中使用命令多么顺当,在crontab中未必会执行,所以你写一个脚本的目的不是在命令行中执行,而是在crontab中执行,请使用命令全路径。