一、数据备份和恢复
数据备份是把文件或数据库从原来存储的地方复制到其他地方的活动,其目的是为了在设备发生故障或发生其他威胁数据安全的灾害时保护数据,将数据遭受破坏的程度减到最小。取回原先备份的文件的过程称为恢复数据。而备份的作用除了进行灾难恢复以外,还要用于审计及对备份数据做恢复测试等相关操作。
1、备份类型
根据备份时,数据库服务器是否在线:
- 冷备:cold backup,此时数据库处于关闭状态,能够较好的保证数据库的完整性。
- 温备:warm backup,将数据库执行写锁,在进行备份。
- 热备:hot backup,数据库正处于运行状态,这种方法依赖于数据库的日志文件进行备份。
根据备份时的接口(直接备份数据文件还是通过mysql服务器导出数据):
- 物理备份:physical backup,直接复制(归档)数据文件的备份方式;
- 逻辑备份:logical backup,把数据从库中提出出来保存为文本文件;
根据备份时是备份整个数据还是仅备份变化的数据:
- 完全备份(Full Backup)。这种备份策略的优点是当发生数据丢失的灾难时.可以迅速恢复丢失的数据。不足之处是每天都对整个系统进行完全备份.造成备份的数据大量重复。对于业务繁忙、备份时间有限的用户,选择这种备份策略是不明智的。
- 增量备份(Incremental Backup)。先进行一次完全备份,在接下来的时间里只对当天新的或被修改过的数据进行备份。这种备份策略的优点是节省了磁盘空间,缩短了备份时间;缺点是当灾难发生时,数据的恢复比较麻烦.备份的可靠性也很差。
- 差分备份(Differential Backup)。先进行一次系统完全备份,在接下来的几天里.再将当天所有与备份不同的数据(新的或修改过的)备份到磁盘上。差分备份策略在避免了以上两种策略的缺陷的同时.又具有了其所有优点。首先,它无须每天都对系统做完全备份,因此所需的备份时间短,并节省了磁盘空间。其次,它的灾难恢复也很方便.一旦发生问题,用户只需使用完全备份和发生问题前一天的备份就可以将系统恢复。
2、 备份策略
- 选择备份方式
- 选择备份时间
- 考虑到恢复成本
- 恢复时长
- 备份成本
- 锁时间
- 备份时长
- 备份负载
3、备份对象
- 数据
- 配置文件
- 代码:存储过程,存储函数,触发器
- OS相关的配置文件,如crontab配置计划及相关的脚本
二、MySQL备份工具
1、常见的备份工具
- mysqldump
mysqldump是一个安装mysql数据库后自动带的一个备份工具,这是一个逻辑备份工具,能支持InnoDB引擎数据的热备、MyISAM引擎数据的温备、Aria引擎数据的温备。由于是逻辑备份工具故其备份和恢复过程较慢。由于其在执行任务时是单线程的,故其性能较差。还有一个多线程版本的工具mysqldumper,使用此工具在备份多张库或者表时能够比mysqldump有更好的性能。同时这两种工具很难实现自动差异或增量备份,若需要此类备份需要人工手动执行。最后若你的数据量一旦超过5G就不建议使用此工具。
- 基于lvm-snapshot的备份
由于其是一个逻辑卷快照故这种备份接近于热备的工具,工作流程是要先请求全局锁,而后创建快照,并在创建快照完成后释放全局锁, 然后使用cp、tar等工具进行物理备份。这种方法备份和恢复速度较快,同时很难实现增量备份,并且请求全局需要等待一段时间,在繁忙的服务器上尤其如此。最后能够使用此种备份是基于你的数据是放在逻辑卷上的。
- 基于SQL语句的备份
在mysql的交互式接口执行SELECT clause INTO OUTFILE ‘/path/to/somefile‘;语句就可以将指定的数据保存在linux系统上有权限进行写入操作的目录中。若想恢复就执行LOAD DATA INFILE ‘/path/from/somefile‘;语句。部分备份工具, 不会备份关系定义,仅备份表中的数据。同时也是逻辑备份工具,速度略快于mysqldump。
- innobackup
这是Innobase公司所提供的商业备份工具,能够实现InnoDB引擎数据的热备,增量备份。MyISAM引擎数据的温备,但不支持增量。由于其是物理备份工具,故速度快。
- Xtrabackup
这是一款 由Percona提供的开源备份工具,能够实现InnoDB引擎数据的热备,增量备份。MyISAM引擎数据的温备,但不支持增量。由于其是物理备份工具,故速度快。
2、mysqldump工具介绍
语法:mysqldump [options] [db_name [tbl_name ...]]
注意:在使用基于mysqldump工具备份的数据执行恢复操作时,如果目标库不存在,需要事先手动创建 。
常用选项:
- --all-databases:备份所有库;
- --databases db1 db2 ...:备份指定的多个库;
- --lock-all-tables:请求锁定所有表之后再备份,对MyISAM、InnoDB、Aria做温备;
- --single-transaction: 能够对InnoDB存储引擎实现热备;
- --flush-logs:备份前、请求到锁之后滚动日志;
- --master-data=[0|1|2]:复制时的同步位置标记,0: 不记录、1:记录为CHANGE MASTER语句、2:记录为注释的CHANGE MASTER语句
备份代码:
- --events:备份事件调度器代码;
- --routines:备份存储过程和存储函数 ;
- --triggers:备份触发器;
3、使用mysqldump备份流程
备份前的准备:
- 请求锁:--lock-all-tables或使用--singe-transaction进行innodb热备;
- 滚动日志:--flush-logs
- 选定要备份的库:--databases
- 记录二进制日志文件及位置:--master-data=
恢复:
- 建议:关闭二进制日志,关闭其它用户连接;
4、基于数据库的备份
查看此库的所有表,然后发现这些表是基于MyISAM引擎存储的,故使用温备的方法。
MariaDB [hellodb]> SHOW TABLES; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | scores | | stu | | students | | teachers | | toc | +-------------------+ 8 rows in set (0.00 sec)
备份数据库:
[[email protected] ~]# mysqldump -uroot -hlocalhost -p --databases hellodb --lock-all-tables --flush-logs --master-data=2 > /tmp/hellodb.1.sql Enter password: [[email protected] ~]# ls -lh /tmp/hellodb.1.sql -rw-r--r-- 1 root root 9.3K 9月 1 09:06 /tmp/hellodb.1.sql
在备份文件中查看二进制文件的滚动信息注意尽量不要用vim等文本工具打开备份文件:
[[email protected] ~]# head -30 /tmp/hellodb.1.sql -- CHANGE MASTER TO MASTER_LOG_FILE=‘master-bin.000002‘, MASTER_LOG_POS=353;
更新hellodb数据库中的内容:
MariaDB [hellodb]> CREATE TABLE newtb(Name CHAR(30)); Query OK, 0 rows affected (0.04 sec) MariaDB [hellodb]> INSERT INTO newtb VALUES(‘bols‘),(‘longls‘); Query OK, 2 rows affected (0.07 sec) Records: 2 Duplicates: 0 Warnings: 0 MariaDB [hellodb]> SELECT * FROM newtb; +--------+ | Name | +--------+ | bols | | longls | +--------+ 2 rows in set (0.00 sec)
误删数据库:
MariaDB [mysql]> DROP DATABASE hellodb; Query OK, 9 rows affected (0.06 sec)
根据备份文进行恢复操作:
恢复前要先让服务器离线,然后查看二进制日志将在我们完整备份时看到的终点是353,而664是为删除数据库前的那一时刻。
[[email protected] ~]# mysqlbinlog --start-position=353 --stop-position=664 /data/binlog/master-bin.000002 > /tmp/hellodb.1.inc.sql
恢复操作:
MariaDB [(none)]> SHOW MASTER STATUS; +-------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-------------------+----------+--------------+------------------+ | master-bin.000003 | 10299 | | | +-------------------+----------+--------------+------------------+ 1 row in set (0.00 sec) MariaDB [(none)]> FLUSH LOGS; Query OK, 0 rows affected (0.01 sec) MariaDB [(none)]> SHOW MASTER STATUS; +-------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-------------------+----------+--------------+------------------+ | master-bin.000004 | 367 | | | +-------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
关闭二进制日志的记录功能:
MariaDB [(none)]> SET SESSION sql_log_bin=0; Query OK, 0 rows affected (0.00 sec)
导入数据:
MariaDB [(none)]> SOURCE /tmp/hellodb.1.sql; Query OK, 0 rows affected (0.00 sec)
发现在完整备份后的数据没有恢复:
MariaDB [hellodb]> SHOW TABLES; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | scores | | stu | | students | | teachers | | toc | +-------------------+ 8 rows in set (0.00 sec)
恢复完整备份后的数据:
MariaDB [hellodb]> SOURCE /tmp/hellodb.1.inc.sql Query OK, 0 rows affected (0.00 sec) MariaDB [hellodb]> SHOW TABLES; +-------------------+ | Tables_in_hellodb | +-------------------+ | classes | | coc | | courses | | newtb | | scores | | stu | | students | | teachers | | toc | +-------------------+ 9 rows in set (0.00 sec)
恢复完毕:
MariaDB [hellodb]> SELECT * FROM newtb; +--------+ | Name | +--------+ | bols | | longls | +--------+ 2 rows in set (0.00 sec)
开启记录二进制日志功能:
MariaDB [hellodb]> SET SESSION sql_log_bin=1; Query OK, 0 rows affected (0.00 sec)
以上就是基于mysqldump 备份+二进制日志进行的数据恢复,在生产环境中二进制日志和数据是分开存放的,同时二进制日志最好建在有冗余功能的设备上。我们在备份时不管只是简单的备份数据,同时还要备份二进制日志文件和相关的配置文件等,对MySQL配置文件,以及与MySQL相关的OS配置文件在每次修改后都应该直接进行备份。所以在日常中工作备份策略一定要做的健壮,以免造成不必要的损失!
三、如何使用shell脚本实现mysql全量,增量备份。
增量备份在周一-周六凌晨3点,会复制mysql-bin.00000*到指定目录;
而全量备份则使用mysqldump将所有的数据库导出,每周日凌晨3点执,并会删除上周留下的mysq-bin.00000*。然后对mysql的备份操作会保留在bak.log文件中。
实现脚本创建,脚本是在这个人的博客上找的:http://sohudrgon.blog.51cto.com/3088108/1607396
1、编写全量备份脚本
[[email protected] ~]# vim DBfullybak.sh #!/bin/bash # Program # use mysqldump to Fully backup mysql data per week! # History # 2015-01-22 guo # Path BakDir=/backup LogFile=/backup/bak.log Date=`date +%Y%m%d` Begin=`date +"%Y年%m月%d日 %H:%M:%S"` cd $BakDir DumpFile=$Date.sql GZDumpFile=$Date.sql.tgz /usr/local/mysql/bin/mysqldump -uroot -poracle --quick --all-databases --flush-logs --delete-master-logs --single-transaction > $DumpFile /bin/tar czvf $GZDumpFile $DumpFile /bin/rm $DumpFile Last=`date +"%Y年%m月%d日 %H:%M:%S"` echo 开始:$Begin 结束:$Last $GZDumpFile succ >> $LogFile cd $BakDir/daily rm -rf *
2、编写增量备份脚本
[[email protected] ~]# vim DBdailybak.sh #!/bin/bash # Program # use cp to backup mysql data everyday! # History #2015-01-22 guo # Path BakDir=/backup/daily BinDir=/mydata/data LogFile=/backup/bak.log BinFile=/mydata/data/mysql-bin.index /usr/local/mysql/bin/mysqladmin -uroot -poracle flush-logs #这个是用于产生新的mysql-bin.00000*文件 Counter=`wc -l $BinFile |awk ‘{print $1}‘` NextNum=0 #这个for循环用于比对$Counter,$NextNum这两个值来确定文件是不是存在或最新的。 for file in `cat $BinFile` do base=`basename $file` #basename用于截取mysql-bin.00000*文件名,如去掉./mysql-bin.000005前面的./ NextNum=`expr $NextNum + 1` if [ $NextNum -eq $Counter ] then echo $base skip! >> $LogFile else dest=$BakDir/$base if (test -e $dest) #test -e用于检测目标文件是否存在,存在就写exist!到$LogFile去。 then echo $base exist! >> $LogFile else cp $BinDir/$base $BakDir echo $base copying >> $LogFile fi fi done echo `date +"%Y年%m月%d日 %H:%M:%S"` $Next Bakup succ! >> $LogFile
3、设置计划任务每天执行
# crontab -l //内容为下 #每个星期日凌晨3:00执行完全备份脚本 0 3 * * 0 /root/DBfullybak.sh >/dev/null 2>&1 #周一到周六凌晨3:00做增量备份 0 3 * * 1-6 /root/DBdailybak.sh >/dev/null 2>&1