您的位置:首页 > 数据库 > MySQL

mysql备份和恢复

2015-12-15 18:02 549 查看
一、mysql备份和恢复
1、为什么要备份?

灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击;误操作;
测试:恢复测试

要注意的要点:
可容忍丢失多少数据;
恢复需要在多长时间内完成;
需要恢复什么;
2、备份类型

完全备份,部分备份:
部分备份:仅备份其中的一张表或多张表;
完全备份,增量备份,差异备份
增量备份:仅备份从上次完全备份或增量备份之后变化的数据部分;
差异备份:备份从上次完全备份之后变化的数据部分;
热备份、温备份和冷备份:
热备份:在线备份,读写操作不受影响; #最复杂
温备份:在线备份,读操作可继续进行,但写操作不允许;
冷备份:离线备份,数据库服务器离线,备份期间不能为业务提供读写服务;

MyISAM: 温备,无法实现热备
InnoDB: 热备,

物理备份和逻辑备份:
物理备份:直接复制数据文件进行的备份;
优点:
跨平台(但需要考虑大小写问题)
速度快
缺点:
逻辑备份:从数据库中“导出”数据另存而进行的备份;mysqldump,mydumper,phpMyAdmin
优点:
与存储引擎无关
备份的数据文件方便使用文本工具2次加工
恢复过程简单
可以使用网络来备份和恢复
mysqldump实现备份时语句灵活
缺点:
由于存储为文本数据,备份文件比原文件大,压缩可避免此问题
无法保证还原后数据与原数据一模一样
Schema和数据存储一起、巨大的SQL语句、单个巨大的备份文件
索引需要重建
规则备份时需要考虑的因素:
持锁的时长
备份过程时长
备份负载
恢复过程时长
3、备份什么?
数据、额外的数据(二进制日志和InnoDB的事务日志)、代码(存储过程和存储函数、触发器、事件调度器等)、服务器配置文件
设计备份方案:完全备份+增量备份
4、备份工具
mysqldump: 逻辑备份工具,适用于所有存储引擎,温备;完全备份,部分备份;对InnoDB存储引擎支持热备(但不实用?);
cp, tar等文件系统工具:物理备份工具,适用于所有存储引擎;冷备;完全备份,部分备份,
lvm2的快照:几乎热备;借助于文件系统工具实现物理备份;
mysqlhotcopy: 几乎冷备;仅适用于MyISAM存储引擎;
备份方案之备份工具的选择:
mysqldump+binlog: mysqldump:完全备份,通过备份二进制日志实现增量备份;
lvm2快照+binlog:几乎热备,物理备份
xtrabackup:
对InnoDB:热备,支持完全备份和增量备份
对MyISAM引擎:温备,只支持完全备份
二、mysqldump
mysqldump: 客户端,通过mysql协议连接至mysqld;
-A, --all-databases:备份所有库

MyISAM,InnoDB 温备:
-x, --lock-all-tables:锁定所有表
-l, --lock-tables:锁定备份的表

InnoDB:热备
--single-transaction:启动一个大的单一事务实现备份

-B, --databases db_name1 db_name2 ...:备份指定的数据库 #自动创建空库
-C, --compress:压缩传输;

命令的语法格式:

mysqldump [OPTIONS] database [tables]:备份单个库,或库指定的一个或多个表
mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]:备份一个或多个库
mysqldump [OPTIONS] --all-databases [OPTIONS]:备份所有库
其它选项:
-E, --events:备份指定库的事件调度器;
-R, --routines:备份存储过程和存储函数;
--triggers:备份触发器
--master-data[=#]:
#为1时:记录CHANGE MASTER TO语句;此语句未被注释;
#为2时:记录为注释语句;
-F,--flush-logs, :锁定表之后执行flush logs命令; #滚动二进制日志文件

注意:二进制日志文件与数据文件不应该放置于同一磁盘;为什么?

案例:每周完全备份,每日增量备份,hellodb单个库:
MariaDB [hellodb]> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| teachers          |
| toc               |
+-------------------+
7 rows in set (0.01 sec)
[root@BAIYU_180 tmp]# mysqldump -p123 -F -B hellodb --lock-all-tables --master-data=2 > /tmp/hellodb-$(date +%F-%H-%M-%S).sql            #完全备份
[root@BAIYU_180 tmp]# ls
hellodb-2015-10-29-12-57-58.sql  mysql.sock

MariaDB [hellodb]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       981 |
| mysql-bin.000002 |      9585 |
| mysql-bin.000003 |       668 |
| mysql-bin.000004 |      1102 |
| mysql-bin.000005 |       493 |       #从04滚动到了05
+------------------+-----------+
5 rows in set (0.00 sec)
MariaDB [hellodb]> create table tb1(id int);
Query OK, 0 rows affected (0.07 sec)

MariaDB [hellodb]> show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| tb1               |
| teachers          |
| toc               |
+-------------------+
8 rows in set (0.00 sec)

MariaDB [hellodb]> select * from tb1;
Empty set (0.00 sec)
[root@BAIYU_180 tmp]# mysqlbinlog --start-datetime='2015-10-29 12:57:58' --stop-datetime ='2015-10-29 13:08:14' /data/mydata/mysql-bin.* > /tmp/incre-$(date +%F-%H%M%S).sql  #备份二进制日志,增量备份。忘记了这里应该也要滚动一次二进制日志,后面复制二进制日志文件就是06了,否则重复复制了已经增量备份的数据,这里就不改了。

MariaDB [hellodb]> insert into tb1 values(1,2,3);            #再插入数据
ERROR 1136 (21S01): Column count doesn't match value count at row 1
MariaDB [hellodb]> insert into tb1 values(1),(2),(3);
Query OK, 3 rows affected (0.11 sec)
Records: 3  Duplicates: 0  Warnings: 0

MariaDB [hellodb]> select * from tb1;             #误操作删除了数据库tb1
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

MariaDB [hellodb]> drop databases hellodb;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'databases hellodb' at line 1
MariaDB [hellodb]> drop database hellodb;
Query OK, 8 rows affected (0.08 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)
恢复:
1、复制没有备份到的数据
mysqlbinlog /data/mydata/mysql-bin.000005 > /tmp/a.sql   #复制没有备份到的数据
56 # at 695
57 #151029 13:32:28 server id 1  end_log_pos 782   Query   thread_id=4     exec_time=0     error_code=0
58 SET TIMESTAMP=1446096748/*!*/;
59 drop database hellodb
60 /*!*/;
61 DELIMITER ;
62 # End of log file
63 ROLLBACK /* added by mysqlbinlog */;
64 /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
65 /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
查看该mysql二进制日志文件可以看到误操作是从at 695开始的,所以不需要从at 695开始的内容
[root@BAIYU_180 tmp]# mysqlbinlog --stop-position=695 /data/mydata/mysql-bin.000005 > /tmp/b.sql
2、恢复完全备份的数据
[root@BAIYU_180 tmp]# mysql -p123 < hellodb-2015-10-29-12-57-58.sql

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| hellodb            |
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

MariaDB [(none)]> use hellodb;
Database changed
MariaDB [hellodb]> show tables;        #可以看到已经恢复了完全备份的数据
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| teachers          |
| toc               |
+-------------------+
7 rows in set (0.00 sec)
3、恢复增量备份的数据
[root@BAIYU_180 tmp]# mysql -p123 < incre-2015-10-29-132723.sql

MariaDB [hellodb]> show tables;   #可以看到已经恢复了增量备份的数据
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| tb1               |
| teachers          |
| toc               |
+-------------------+
8 rows in set (0.00 sec)

MariaDB [hellodb]> select * from tb1;
Empty set (0.00 sec)
4、恢复备份的二进制日志数据
[root@BAIYU_180 tmp]# mysql -p123 < b.sql

MariaDB [hellodb]> select * from tb1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)


注意:恢复数据时:
1、关闭sql_log_bin会话变量,暂时停止二进制日志的记录。恢复过程中的修改语句就不要写入日志了。
2、恢复完全备份。3、恢复增量备份(没有增量备份就是完全备份之后的所有二进制日志了)例如:
MariaDB [hellodb]> SET sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
MariaDB [hellodb]> source /backup/20151107_22:29.full.sql
MariaDB [hellodb]> source /backup/20151107_22:52.1.sql
MariaDB [hellodb]> SET sql_log_bin=1;
恢复后就再把增量备份之后的二进制日志功能恢复一下就可以了。用mysqldump做备份再做增量太麻烦了。一般如果二进制日志所在磁盘的安全性高也就不用做增量了,到时候再直接恢复二进制日志也一样。而且如果数据量大也就不用mysqldump备份了。三、mysqlbinlog 如果每天都会生成大量的二进制日志,这些日志长时间不清理的话,将会对磁盘空间带来很大的浪费,所以定期清理日志是DBA维护mysql的一个重要工作
1、RESET MASTER
在上面查看日志存放的文件夹中,二进制日志命名的格式是以mysql-bin.*,*代表日志的序号,序号是递增的,其中还有mysql-bin.index是日志的索引文件,记录了日志的最大序号
我们执行RESET MASTER命令删除重置二进制日志



查看删除后的日志



可以看到,以前的日志全部被清空,新的日志从00001开始
2、[b]PURGE MASTER LOGS TO
& PURGE MASTER LOGS BEFORE
执行PURGE MASTER LOGS TO 'mysql-bin.******'命令,是将'******'编号之前的所有日志进行删除
执行PURGE MASTER LOGS BEFORE 'yyyy-mm-dd hh:mm:ss'命令,是将在'yyyy-mm-dd hh:mm:ss'时间之前的所有日志进行删除
3、-EXPIRE_LOGS_DAYS
此参数是设置日志的过期天数,过期的日志将会被自动删除,这有利于减少我们管理日志的工作量,需要修改my.cnf



这里我们设定保存日志为3天,3天之后过期的日志将被自动删除

恢复
bin-log是记录着mysql所有事件的操作,当mysql发生灾难性错误时,可以通过bin-log做完整恢复,基于时间点的恢复,和基于位置的恢复[/b][b]完整恢复,假定我们每天凌晨2点都会使用mysqldump备份数据库,但在第二天早上9点由于数据库出现了故障,数据无法访问,需要恢复数据,先使用昨天凌晨备份的文件进行恢复到凌晨2点的状态,在使用mysqlbinlog恢复自mysqldump备份以来的binlog
这样数据库就可以完全的恢复到崩溃前的完全状态

基于时间点的恢复[/b],由于误操作,比如说删除了一张表,这时使用上面讲的完全恢复是没有用的,因为日志里面还存在误操作的语句,,我们需要的是恢复到误操作前的状态,然后跳过误操作的语句,再恢复后面操作的语句,假定我们删除了一张表的误操作发生在10:00这个时间点,我们可以使用下面的语句用备份和binlog将数据恢复到故障前
mysqlbinlog --stop-datetime='2010-09-04 9:59:59' /var/log/mysql-bin.000001 | mysql -uroot -p然后跳过误操作的时间点,继续执行后面的binlogmysqlbinlog --start-datetime='2010-09-04 10:01:00' /var/log/mysql-bin.000001 | mysql -uroot -p其中--stop-datetime='2010-09-04 9:59:59' 和 --start-date='2010-09-04 10:01:00' 其中的时间是你误操作的时间点,当然了,这个时间点你需要你自己计算的,而且这个时间点还可以涉及到的不只是误操作,还可以有正确的操作也被跳过去了。

基于位置恢复,由于上面提到的,使用基于时间点的恢复可能出现,在一个时间点里面可能存在误操作和其他正确的操作,所以我们需要一种更为精确的恢复方式
使用mysqlbinlog查看二进制,可看到



其中drop tables test1这个误操作的end_log_pos为8879917,几下这个id,得出它前后操作的id分别为8879916,8879918
我们将进行位置恢复操作mysqlbinlog --stop-position='8879916' /var/log/mysql-bin.000001 | mysql -uroot -p
mysqlbinlog --start-position='8879918' /var/log/mysql-bin.000001 | mysql -uroot -p服务器生成的二进制日志文件写成二进制格式。要想检查这些文本格式的文件,应使用mysqlbinlog实用工具。
3、–result-file=name, -r name #将输出指向给定的文件,相当于重定向—database=db_name,-d db_name #恢复指定库的数据(只用本地日志) -d只列出该数据库的条目(只用本地日志)。仅仅恢复指定数据库的数据,如下面的,仅仅恢复数据库lvnian的数据而已,其他库的数据不会恢复mysqlbinlog -d lvnian /var/log/mysql-bin.000001 | mysql -uroot -p作业:写脚本, 用mysqldump实现对指定数据库的备份;
写脚本,实现利用binary logs完成增量备份;

四、物理备份
物理备份:数据文件的时间一致性?
冷备:
几乎热备:lvm2快照

1、请求锁定所有表:
mysql> FLUSH TABLES WITH READ LOCK;

2、记录二进制日志文件及事件位置:
mysql> SHOW MASTER STATUS;

3、创建快照:
lvcreate -L SIZE -s -p r -n NAME /dev/VG_NAME/LV_NAME

4、释放锁:
mysql> UNLOCK TABLES

5、挂载快照卷,复制数据进行备份;
cp, rsync, tar等命令复制数据;

6、备份完成之后,删除快照卷;

思考?mysqldump做的备份,数据还原时,是否会产生二进制日志?
mysql> SET SESSION sql_log_bin=0;
mysql> SOURCE /path/from/somefile.sql;
mysql> SET SESSION sql_log_bin=1;
五、Xtrabackup

1、简介
Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备的工具。特点:
(1)备份过程快速、可靠;
(2)备份过程不会打断正在执行的事务;
(3)能够基于压缩等功能节约磁盘空间和流量;
(4)自动实现备份检验;
(5)还原速度快;
2、安装
其最新版的软件可从官网http://www.percona.com下载
[root@BAIYU_180 ~]# ls
anaconda-ks.cfg  install.log         libev-4.15-1.el6.rf.x86_64.rpm  mariadb-10.0.13.tar.gz  percona-xtrabackup-2.3.2-1.el6.x86_64.rpm
hellodb.sql      install.log.syslog  mariadb-10.0.13                 mysql                   trash.sh
[root@BAIYU_180 ~]# yum install percona-xtrabackup-2.3.2-1.el6.x86_64.rpm libev-4.15-1.el6.rf.x86_64.rpm -y

Dependencies Resolved

==========================================================================================================================================
Package                         Arch                Version                    Repository                                           Size
==========================================================================================================================================
Installing:
libev                           x86_64              4.15-1.el6.rf              /libev-4.15-1.el6.rf.x86_64                         202 k
percona-xtrabackup              x86_64              2.3.2-1.el6                /percona-xtrabackup-2.3.2-1.el6.x86_64               21 M
Installing for dependencies:
perl-DBD-MySQL                  x86_64              4.013-3.el6                c6-media                                            134 k
perl-DBI                        x86_64              1.609-4.el6                c6-media                                            705 k

Transaction Summary
==========================================================================================================================================
Install       4 Package(s)

[root@BAIYU_180 ~]# rpm -ql percona-xtrabackup
/usr/bin/innobackupex
/usr/bin/xbcloud
/usr/bin/xbcloud_osenv
/usr/bin/xbcrypt
/usr/bin/xbstream
/usr/bin/xtrabackup
/usr/share/doc/percona-xtrabackup-2.3.2
/usr/share/doc/percona-xtrabackup-2.3.2/COPYING
/usr/share/man/man1/innobackupex.1.gz
/usr/share/man/man1/xbcrypt.1.gz
/usr/share/man/man1/xbstream.1.gz
/usr/share/man/man1/xtrabackup.1.gz
innobackupex: 客户端工具, 以mysql协议连入mysqld,不支持离线备份
--user=
--password=
--host=name

3、备份的实现
1)完全备份
# innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/
如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:
mysql> CREATE USER ’bkpuser’@’localhost’ IDENTIFIED BY ’s3cret’;
mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM ’bkpuser’;
mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO ’bkpuser’@’localhost’;
mysql> FLUSH PRIVILEGES;
使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中。
#不会备份二进制日志文件

在备份的同时,innobackupex还会在备份目录中创建如下文件:
(1)xtrabackup_checkpoints —— 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;
每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。
(2)xtrabackup_binlog_info —— mysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置。
(3)xtrabackup_binlog_pos_innodb —— 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。
(4)xtrabackup_binary —— 备份中用到的xtrabackup的可执行文件(已经废弃了);
(5)backup-my.cnf —— 备份命令用到的配置选项信息;

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录;如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。

2)准备(prepare)一个完全备份
一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。
“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。
innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:
# innobackupex --apply-log /path/to/BACKUP-DIR
如果执行正确,其最后输出的几行信息通常如下:
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
120407 9:01:36 InnoDB: Starting shutdown...
120407 9:01:40 InnoDB: Shutdown completed; log sequence number 92036620
120407 09:01:40 innobackupex: completed OK!
在实现“准备”的过程中,innobackupex通常还可以使用--use-memory选项来指定其可以使用的内存的大小,默认通常为100M。如果有足够的内存可用,可以多划分一些内存给prepare的过程,以提高其完成速度。

3)从一个完全备份中恢复数据
注意:恢复不用启动MySQL
innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。
# innobackupex --copy-back /path/to/BACKUP-DIR #自动恢复回原目录
如果执行正确,其输出信息的最后几行通常如下:
innobackupex: Starting to copy InnoDB log files
innobackupex: in '/backup/2012-04-07_08-17-03'
innobackupex: back to original InnoDB log directory '/mydata/data'
innobackupex: Finished copying back files.

120407 09:36:10 innobackupex: completed OK!

请确保如上信息的最行一行出现“innobackupex: completed OK!”。
当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。
如:# chown -R mysql:mysql /mydata/data/

4)使用innobackupex进行增量备份
每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现。

要实现第一次增量备份,可以使用下面的命令进行:
# innobackupex --incremental /backup --incremental-basedir=BASEDIR
其中,BASEDIR指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backup目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录。

需要注意的是,增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。

“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:
(1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。
(2)基于所有的备份将未提交的事务进行“回滚”。

于是,操作就变成了:
# innobackupex --apply-log --redo-only BASE-DIR
接着执行:
# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1
而后是第二个增量:
# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-2
其中BASE-DIR指的是完全备份所在的目录,而INCREMENTAL-DIR-1指的是第一次增量备份的目录,INCREMENTAL-DIR-2指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,每一次都要执行如上操作;再使用 innobackupex --copy-up BASE-DIR 恢复。
注意:恢复后应该重新做一次完全备份

完整备份策略:完整备份 + 增量备份 + 二进制日志

注意:
1、将数据和二进制文件放置于不同的设备;二进制日志也应该周期性地备份;
2、将数据和备份分开存放,建议不在同一设备、同一主机、同一机房、同一地域;
3、每次灾难恢复后都应该立即做一次完全备份;
4、备份后的数据应该周期性地做还原测试;

从备份中恢复应该遵循的步骤:
1、停止MySQL服务器;
2、记录服务器配置和文件权限;
3、将备份恢复到MySQL数据目录;此步骤依赖具体的备份工具;
4、改变配置和文件权限;
5、以限制方式启动MySQL服务器:比如通过网络访问:
[mysqld]
skip-networking
socket=/tmp/mysql-recovery.sock
6、载入额外的逻辑备份;而检查和重放二进制日志;
7、检查已经还原的数据;
8、以完全访问模式重启服务器;

其它的备份工具:
SELECT ... INTO OUTFILE ''
LOAD FILE

mylvmbackup
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: