1. 概览
1.1 备份命令
MySQL Backup企业版通常用的是两个命令, ibbackup以及mysqlbackup.
ibbackup是用来备份innodb表的, mysqlbackup则更具弹性, 可以备份innodb以及其他存储引擎的表, 并且还做了一些其他我们可能需要自己写脚本来做的事情, 例如为每一次备份创建一个以timestamp为名字的文件夹.
1.2 备份文件
innodb相关的备份文件主要是ibd文件, 以及从ib logfile中解析出来的变化数据, 保存在ibbackup_logfile中, 如果你选择了压缩备份, 那么ibd文件会以ibz的形式出现.
备份的初始文件不能直接用来恢复, 必须先使用apply步骤, 将备份过程中的变化, 也就是ibbackup_logfile中的记录补充到备份文件中去, 产生一个prepared backup, 这个备份才对应了数据库某一时间点的数据, 这个时候的备份才能够使用.
恢复innodb数据库时, 除了以上的数据, 还必须有frm文件, 这些文件是table的定义文件, 如果使用mysqlbackup, 那么frm文件会被自动备份, 但是如果使用的是ibbackup, 则这个动作需要备份者自己去完成.
上面说了mysqlbackup除了备份innodb存储引擎, 还能够备份其他存储引擎的文件, 默认会包含以下类型的文件ARM, ARZ, FRM, MRG, MYD, MYI, OPT, PAR, TRG, TRN
1.3
MySQL Backup企业版与InnoDB hot backup的比较
1) ibbackup可以在所有平台上使用, 通过incremental选项还能够实现innodb表的增量备份
2) mysqlbakcup, 作为一个跨平台的的innobackup替代品, 不仅能够备份innodb, 也能够备份其他存储引擎的数据, 并且不需要自己编写接口来调用ibbackup
3) mysqlbackup是一个C语言程序, 使用MySQL API来连接MySQL数据库, 而不是一个通过perl脚本调用mysql的命令, 因为其实际上不运行mysql命令, 所以不支持innobackup的--mysql-extra-args
4) 由InnoDB Hot Backup产生的备份可以使用MySQL Backup企业版来进行恢复
5) mysqbackup提供额外的选项可以用来制定连接信息
2. ibbackup
ibbackup可以用来在mysql运行时备份而不用打断mysql自身的工作, 并且得到的是一个一致的备份, 尽管该备份可能持续几分钟甚至几个小时, ibbackup同样可以用来产生一个replication库, 如果你准备在innodb上运行replication的话
产生一个备份的基本命令是ibbackup my.cnf my2.cnf, 命令读取my.cnf中关于ibdata文件以及ib logfile文件的路径, 并且将备份写入my2.cnf中指定的路径中
2.1 option files
在ibbackup的命令行中, 你要制定两个配置文件, 这些文件使用和mysql本身的配置文件相同的语法, 这些配置文件有以下要求:
1) 每个配置文件必须包含以下参数值
datadir=...
innodb_data_home_dir=...
innodb_data_file_path=...
innodb_log_group_home_dir=...
innodb_log_files_in_group=...
innodb_log_file_size=...
2) 路径必须是绝对路径
3) datafiles的个数以及size在my.cnf以及my2.cnf中必须一致
4) logfile的个数以及size必须明确指定, 但my.cnf和my2.cnf中可以不一样
5) 这两个文件中的其他选项都将被忽略, 不起作用
下面是一个例子,
my.cnf的内容:
[mysqld]
datadir = /home/heikki/data
innodb_data_home_dir = /home/heikki/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /home/heikki/data
innodb_log_files_in_group=2
innodb_log_file_size=20M
my2.cnf的内容:
datadir = /home/heikki/backup innodb_data_home_dir = /home/heikki/backup innodb_data_file_path = ibdata1:10M:autoextend innodb_log_group_home_dir = /home/heikki/backup innodb_log_files_in_group=2 innodb_log_file_size=20M
因为ibbackup不会覆盖任何文件, 所以请确保备份目标目录下不包含任何备份文件, 都将被忽略, 不起作用
3. Making a backup
ibbackup备份内容包含1) innodb系统表空间, 默认会包含所有的innodb表 2) 所有单独的数据文件如果使用了"file per table"设定 3) innodb表相关的索引文件 4) 存储在原来的"Antelope"以及新的"Barracuda"文件中的数据
尽管如此, ibbackup不会copy frm文件, myisam表或者myisam的索引文件
3.1 创建一个未压缩的innodb表备份
$ ibbackup /home/pekka/.my.cnf /home/pekka/.backup-my.cnf
下一步就是将备份log信息末尾的LSN记录下来, 在该次备份后如果你想在做一个增量备份的时候你将需要指定该LSN号
在未压缩的全备份文件上执行apply log动作, 这样该全备份就可以用来恢复了, 你可以将该备份移到另外一台server上, 这样你再做这个动作的时候就不会影响主server的运行了
全备份以后, 周期性的进行增量备份, 增量备份更快, 产生的备份集更小
3.2 创建一个压缩的innodb表备份
$ ibbackup --compress /home/pekka/.my.cnf /home/pekka/.backup-my.cnf
下一步就是将备份log信息末尾的LSN记录下来, 在该次备份后如果你想在做一个增量备份的时候你将需要指定该LSN号
在未压缩的全备份文件上执行apply log动作, 这样该全备份就可以用来恢复了, 你可以将该备份移到另外一台server上, 这样你再做这个动作的时候就不会影响主server的运行了
apply log以后备份以后, 周期性的进行增量备份, 增量备份更快, 产生的备份集更小
3.3 创建一个innodb表的增量备份
增量备份仅仅备份自上次备份以后发生的修改, 该技术使得设计一个比较弹性的备份策略从而节省备份占用的空间成为了可能, 因为增量备份通常需要apply到一个已经存在的备份集上, 所以在做增量备份之前, 请创建一个压缩的或者未压缩的全备份.
增量备份能够检测到数据文件的页级的修改, 而不是行级的修改.
增量备份是通过ibbackup的--incremental选项来实现的, 你必须通过--lsn选项指定上次全备份或者增量备份的lsn.
当你为一个增量备份执行apply log动作时, 必须按照以下顺序来制定参数, --apply-log, --incremental, 以及两个cnf文件的路径, 第一个cnf执行了你需要更新的全备份, 第二个cnf指向了增量备份文件, 如果自上次全备份以后, 执行过多次增量备份, 则必须执行多次apply log动作, 并且按照顺序, 从而使全备份达到最新.
如果你使用mysqlbackup来备份myisam表, 你同样可以使用它来进行增量备份, 只是语法上面有些微差别.
下面是一个例子, 上次全备份的lsn是2244068696:
ibbackup: Was able to parse the log up to lsn 2244068296
那么你的增量备份语句如下:
$ ibbackup --incremental 2614357436 /home/pekka/.my.cnf /home/pekka/.incr-backup-my.cnf
下一步:记录下来LSN, 将该增量备份apply到某个全备份中, 这样该全备份就随时可以用来恢复了根据数据库活动, 计划下一次增量备份, 或这按照备份策略执行权备份.
3.4 创建一个基于某一时间点的既包含INNODB又包含myisam的备份
你可以使用--suspend-at-end选项来做同时包含innodb以及包含myisam的备份, 该选项会在ibbackup结束的时候hold住, 这样你可以通过你写的脚本来做myisam表以及其他存储引擎表的备份, 因为ibbackup备份关联到备份结束的时间点, 而你的脚本在那个时间点也block住了对myisam表以及其他存储引擎相关表的改动, 所以从理论上来说, 这样产生的备份是一个一致的备份, 是数据库在某一时间点的快照.
你的脚本必须依照以下的顺序来做
1) ibbackup --suspend-at-end
2) 周期性的check ibbackup_suspended这个文件是否存在, 一旦出现, 你的脚本就必须做一下事情
a. FLUSH TABLES WITH READ LOCK;
b. 手动copy innodb的frm文件, myisam的文件, 以及其他非innodb存储引擎的文件
c. 删掉文件ibbackup_suspended, 从而恢复ibbackup
d. 等待ibbackup结束
e. UNLOCK TABLES;
4. 准备一个可恢复的备份
最初的备份文件可能不是一个一致的备份, 因为在备份的时候数据可能被修改, 这些初始的文件被成为raw backup, 下一步就是update这些文件使其与某个LSN相关, 成为一个一致的备份.(与Mysql自身的crash recovery一样). 当这一步完成, 该备份就成为一个prepared backup.
在备份过程中, ibbackup将累计的innodb logfile拷贝成为一个文件ibbackup_logfile. 这个日志文件用来前滚备份的数据文件, 使数据文件中的每一个数据页包含与innodb log一致的LSN. 应用这些log的选项就是--apply-log. 在以前的InnoDB Hot Backup产品中, 该选项称为--restore, 但是该选项被该名了因为它实际上不是用来resore的而仅仅是用来准备可以restore的数据, 该过程也会自动创建与这些文件相对应的ib_logfiles.
4.1 Applying the log to backup
在apply log之前, 备份文件如下:
$ ls -lh /sqldata-backup
total 489M
-rw-r--r-- 1 pekka pekka 158 2010-09-15 11:28 ibbackup_export_variables.txt
-rw-r----- 1 pekka pekka 1.0K 2010-09-15 11:28 ibbackup_logfile
-rw-r----- 1 pekka pekka 10M 2010-09-15 11:26 ibdata1
-rw-r----- 1 pekka pekka 20M 2010-09-15 11:26 ibdata2
-rw-r----- 1 pekka pekka 458M 2010-09-15 11:28 ibdata3
现在我们来运行ibbackup来前滚这些数据文件, 使其拥有一致的LSN
$ ibbackup --apply-log /home/pekka/.backup-my.cnf
前滚以后, 新产生了一些iblog文件, 并且也已经将这些log文件apply到数据文件中, 现在的备份文件如下:
$ ls -lh /sqldata-backup
total 519M
-rw-r--r-- 1 pekka pekka 158 2010-09-15 11:28 ibbackup_export_variables.txt
-rw-r----- 1 pekka pekka 1.0K 2010-09-15 11:28 ibbackup_logfile
-rw-r----- 1 pekka pekka 10M 2010-09-15 11:26 ibdata1
-rw-r----- 1 pekka pekka 20M 2010-09-15 11:26 ibdata2
-rw-r----- 1 pekka pekka 458M 2010-09-15 11:28 ibdata3
-rw-r----- 1 pekka pekka 10M 2010-09-15 11:29 ib_logfile0
-rw-r----- 1 pekka pekka 10M 2010-09-15 11:29 ib_logfile1
-rw-r----- 1 pekka pekka 10M 2010-09-15 11:29 ib_logfile2
4.2 Applying the log to a Compressed Backup
如果备份是压缩的, 那么我们在运行ibbackup来apply log的时候, 就必须使用--uncompress选项了.
$ ibbackup --apply-log --uncompress /home/pekka/.backup-my.cnf
因为在执行这个动作的时候, 我们不会对原有的备份文件做任何修改, 所以如果发生了问题, 我们完全可以重来一次.
4.3 Applying an incremental backup to a full backup
做完增量备份以后, 增量备份必须apply到一个全备份中, 这样全备份才是最新的, 这个方式与你apply二进制日志中的改变到数据文件中是一样的.
首先我们需要将全备份时候产生的日志apply, 这样初始的全备份数据文件才是一致的.
$ ibbackup --apply-log /home/pekka/.full-backup-my.cnf
然后我们将增量备份中的改变apply到这个全备份中:
ibbackup --apply-log --incremental /home/pekka/.incr-backup-my.cnf /home/pekka/.full-backup-my.cnf
注意第一个cnf文件指向的是增量备份的路径, 而第二个cnf文件指向的是全备份的路径.
4.4 Starting mysqld on a Restored Backup
在apply log并且重新创建的ibfile之后, 我们就可以在此基础上启动mysqld了, 备份目录看起来和我们备份之前的数据目录是一致的, 我们注意到该目录下面包含有数据库名字的子目录, 注意这些目录不是使用ibbackup创建的, 而是我们手动创建的或者是使用mysqlbackup创建的.
$ ls -lh /sqldata-backups
total 872M
-rw-r----- 1 pekka dev 41M Jan 22 15:33 ibbackup_logfile
-rw-r----- 1 pekka dev 100M Jan 22 15:38 ibdata1
-rw-r----- 1 pekka dev 200M Jan 22 15:38 ibdata2
-rw-r----- 1 pekka dev 500M Jan 22 15:32 ibdata3
-rw-r----- 1 pekka dev 10M Jan 22 15:40 ib_logfile0
-rw-r----- 1 pekka dev 10M Jan 22 15:38 ib_logfile1
-rw-r----- 1 pekka dev 10M Jan 22 15:38 ib_logfile2
drwxr-xr-x 2 pekka dev 4.0k Jan 22 15:33 mysql
drwxr-xr-x 2 pekka dev 4.0k Jan 22 15:33 test
drwxr-xr-x 2 pekka dev 4.0k Jan 22 15:33 test115
现在我们可以启动该备份数据库了
$ mysqld --defaults-file=/home/pekka/.backup-my.cnf
5. Recovering or Restoring a database
5.1 将热备份恢复到某一时间点
因为innodb引擎在commit一个事务的时候, 仅仅只是将二进制日志的位置记录到了表空间中, 为了让innodb知道当前二进制日志的位置, 当二进制日志启用的时候, 必须至少运行一个事务. 当你在备份文件上执行ibbackup --apply-log的时候, 如果ibbackup版本在1.0.3以上, 则会打印出来备份知道的最新的二进制日志位置. 同样在apply log后, mysqld启动的时候也会打印出来.
$ mysqld --defaults-file=/home/pekka/.backup-my.cnf
040122 15:41:57 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
…
InnoDB: Last MySQL binlog file position 0 27183537, file name ./binlog.000005
…
mysqld: ready for connections
mysql版本必须在5.1以上, 打印出来的二进制日志位置就是全备份完成的最后时候的二进制日志位置, 然后我们就可以从这个点开始apply二进制日志.
$ mysqlbinlog --start-position=27183537 /sqldata/binlog.000005 | mysql
如果我们需要将数据库恢复到某一时间点, 则需要将mysqlbinlog的结果output到一个文件, 而不知将其直接指向mysql, 这个文件包含二进制日志中的所有sql的timestamp, 我们可以将某一时间点以后的sql语句删除, 然后将其apply到mysql数据库中.
$ mysql < modified_output_file
5.2 在Replication中使用热备份创建一个新的从库
如果你使用MySQL Replication来复制InnoDB表, MySQL Backup企业版允许你不用停掉主库, 因为使用热备份完全可以创建出一个从库.
1) 在备份文件上使用ibbackup --apply-log来恢复, 并将恢复以后的文件放在合适的路径
2) 编辑My.cnf文件, 将skip-slave-start选项添加到[mysqld]部分中
3) 启动从库上的mysqld, 并记录好其打印出来的二进制日志位置
…
InnoDB: Last MySQL binlog file position 0 128760128, file name ./hundin-bin.006
…
4) 使用CHANGE MASTER语句来初始化从库
CHANGE MASTER TO
MASTER_LOG_FILE='hundin-bin.006',
MASTER_LOG_POS=128760128;
5) 使用SLAVE START语句启动从库
6) 将skip-slave-start从从库my.cnf文件中去掉
5.3 在Replication中恢复一个主库
现在假想我们Replication环境中的主库挂掉了
1) 使用主库的备份, 执行ibbackup --apply-log yourbackupmy.cnf, 然后将ibdatafile以及iblogfile放在合适的路径, 并且将frm文件放回到原来的路径, 当然前提是你备份过frm文件或者frm文件没有损坏
2) 编辑my.cnf, 将log-bin注释掉, 这样那些用来recover主库的二进制日志不会再次发送到从库
3) 停止从库的复制, 在从库上执行
mysql> STOP SLAVE;
4) 在主库已经恢复的备份上启动mysqld
$ mysqld
…
InnoDB: Doing recovery: scanned up to log sequence number 0 64300044
InnoDB: Last MySQL binlog file position 0 5585832, file name
./omnibook-bin.002
…
innodb会打印出能够恢复的二进制日志的位置.
5) 下一步就是将剩下的二进制日志apply到已经恢复的备份中去
$ mysqlbinlog --start-position=5585832mysqldatadir/omnibook-bin.002 | mysql
$ mysqlbinlog /mysqldatadir/omnibook-bin.003 | mysql
6) 现在主库已经恢复了, 停掉主库, 编辑my.cnf文件将其中的log-bin选项恢复
7) 重新启动主库
8) 重启启动从库的复制
mysql> START SLAVE;
6. mysqlbackup命令
mysqlbackup是一个比ibbackup更加完备易用的备份工具, 使用mysqlbackup可以用来备份以下内容:
1) 所有InnoDB表, 索引, 以及其他ibbackup可以备份的内容(实际上这部分mysqlbackup是调用ibbackup来进行的)
2) MyISAM表
3) 默认情况下, 数据文件目录下面的文件都会包含在备份中, 如果使用了--only-known-file-types选项, 那么仅仅以下扩展名的文件会被包含在备份中:
.ARM: Archive存储引擎的元数据文件
.ARZ: Archive存储引擎的数据文件
.FRM: 数据定义文件
.MRG: Merge存储引擎的引用表
.MYD: MyISAM的数据文件
.MYI: MyISAM的索引
.OPT: 数据库配置信息
.PAR: 分区表定义
.TRG: trigger参数
.TRN: trigger命名空间信息
除了备份以外, mysqlbackup可以在备份的基础上产生一个prepared backup, 并且能将copy数据, 索引, 以及日志文从备份目录copy到原来的目录.
mysqlbackup可以用来在线备份innodb表, 以及一个与innodb备份拥有同样二进制位置的MyISAM表快照, 同时也会备份.frm文件
下面是一个mysqlbackup的例子:
$ mysqlbackup --user=dba --password=xyz --compress /etc/my.cnf /backups
--user选项以及--password选项是用来指定如何连接到数据库, 该用户必须拥有FLUSH TABLES WITH READ LOCK的权限以及在mysql库下面创建ibbackup_binlog_marker表的权限. 备份的时候, mysqlbackup会在你在上边指定的/backups下创建的一个子目录, 然后将备份文件放在这个子目录下面. 子目录的名字是你备份时的时间来决定的.
需要保证运行mysqlbackup的user拥有将数据文件copy到备份目录的权限.
确保connection timeouts足够长, 保证备份正常运行.
Mysqlbackup运行的时候, 首先测试数据库的连接, 然后调用ibbackup来进行innodb表的热备份.(这个过程不会影响mysql数据库的正常运行) 当ibbackup快要跑完的时候, myqlbackup执行FLUSH TABLES WITH READ LOCK命令并将myisam的表copy到备份目录下, 如果这个时候你的数据库中没有运行长的查询, 并且你的myisam表也比较小, 那么这个备份锁定过程将只需要很短的时间, 否则你的整个数据库, 包括innodb表, 都会被锁定很长时间. 这个完成后, mysqlbackup让ibbackup完成备份并且释放锁定.
注意:
1) 虽然mysqlbackup可以在线备份innodb表, 而不会影响mysql的正常运行, 但是最后一步备份其他类型表的时候需要将整个数据库置于一个只读的状态, 所以为了保证备份的速度, 请注意以下要点:a. 在运行的时候尽量不要跑大的sql语句 b. 使MyISAM表尽可能的小
2) 对于大数据库来说, 备份可能耗时很长, 所以如果要检查mysqlbackup是否已经完成, 可以通过检查mysqlbackup是否返回了状态0, 或者观察是否打印出了“mysqlbackup completed OK!”字样
3) mysqlbakcup命令与mysql6.0源代码树中的MySQL Backup是不相同的
6.1. 备份InnoDB以及MyISAM表
$ mysqlbackup /home/pekka/.my.cnf /backups
该命令接收2个参数, 第一个是要备份的mysql的配置文件, 第二个参数是备份目录
6.2 检查backup
首先我们需要将备份apply成为一个prepaired backup
$ mysqlbackup --apply-log /home/pekka/.my.cnf /backups/2010-10-04_12-14-47
接下来我们基本上就可以在这个备份上启动mysqld了, 最后一步是准备一个可用的my.cnf文件, 我们不能重用备份目录下的backup-my.cnf, 因为它仅仅包含了ibbackup运行需要的商量几个选项, 我们必须要添加上其他的配置选项.
接下来我们就可以使用准备好的配置文件来启动mysqld了.
$ mysqld --defaults-file=/backups/2010-10-04_12-14-47/my.cnf
6.3 将mysql数据库在其本来的位置恢复
我们需要将innodb, myisam以及innodb的frm文件copy到其原来的位置,
$ mysqlbackup --copy-back /home/pekka/.my.cnf /backups/2010-10-04_12-14-47
然后我们就可以直接启动mysqld了
6.4为mysqlbakcup指定连接选项
--user, --password, --port, --socket
这几个选项都是用来指定连接信息的
6.5 设定备份用户需要的权限
$ mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 19 to server version: 4.1.1-alpha-debug-log
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> GRANT RELOAD ON *.* TO 'dba'@'localhost';
Query OK, 0 rows affected (0.10 sec)
mysql> GRANT CREATE, INSERT, DROP ON mysql.ibbackup_binlog_marker
-> TO 'dba'@'localhost';
Query OK, 0 rows affected (0.06 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.15 sec)
6.6 Innodb以及MyISAM的增量备份
$ mysqlbackup --incremental --lsn 2626689439 /home/pekka/.my.cnf /incr-backup
我们使用--lsn选项来指定上次全备份结束时打印出来的lsn
我们将全备份时候产生的变化apply到全备份当中
mysqlbackup --apply-log /home/pekka/.my.cnf /full-backup/2010-10-04_13-03-45
我们apply增量备份到全备份当中
$ mysqlbackup --apply-log --incremental /incr-backup/2010-10-04_13-04-31/backup-my.cnf /full-backup/2010-10-04_13-03-45/backup-my.cnf
现在全备份当中包含的数据就已经是最新的了.
7. 部分备份
如果我们启用了mysql的多表空间特性, 我们就可以使用mysql来执行innodb表的部分备份.
使用mysqlbackup的--include选项, 我们就可以指定部分备份哪些per-table数据文件, 部分备份只会备份系统表空间以及指定的per-table表空间中的表
在--inclued选项中指定要备份哪些表的时候, 应该采用db_name.table_name的形式.
注意: 在当前的mysqlbackup版本中, 虽然可以使用--include来备份部分table, 但是那些没有在指定list中的表的frm文件也会被备份, 所以在恢复之前, 应该在备份目录中删掉那些表的frm文件
注意: 在当前mysqkbackup版本中, 如果--include列表中没有找到任何mapping的表, 那么还是会备份所有的表, 但这个特性以后很有可能会变化, 请尽量不要依赖它
8. 使用备份日志记录
通过mysql.backup_progress你可以监控备份进度
mysql.backup_history则可以查看已经完成的备份, 因为这些表使用的是csv引擎, 所以你可以使用sql语句来查询, 也可以使用你的程序或者脚本来解析结果.