I blogged a while ago about
MySQL fault-tolerance and disaster recovery techniques. At that time I was experimenting with the non-free
InnoDB Hot Backup product. In the mean time I discovered Percona's
XtraBackup (thanks Robin!). Here's how I tested XtraBackup for doing a hot backup and a restore of a MySQL database running Percona XtraDB (XtraBackup works with vanilla InnoDB too).
First of all, I use the following Percona .deb packages on a 64-bit Ubuntu Lucid EC2 instance:
# dpkg -l | grep percona
ii libpercona-xtradb-client-dev 5.1.43-xtradb-1.0.6-9.1-60.jaunty.11 Percona SQL database development files
ii libpercona-xtradb-client16 5.1.43-xtradb-1.0.6-9.1-60.jaunty.11 Percona SQL database client library
ii percona-xtradb-client-5.1 5.1.43-xtradb-1.0.6-9.1-60.jaunty.11 Percona SQL database client binaries
ii percona-xtradb-common 5.1.43-xtradb-1.0.6-9.1-60.jaunty.11 Percona SQL database common files (e.g. /etc
ii percona-xtradb-server-5.1 5.1.43-xtradb-1.0.6-9.1-60.jaunty.11 Percona SQL database server binaries
I tried using the latest stable XtraBackup .deb package from the
Percona downloads site but it didn't work for me. I started a hot backup with /usr/bin/innobackupex-1.5.1 and it ran for a while before dying with "InnoDB: Operating system error number 9 in a file operation." See this
bug report for more details.
After unsuccessfully trying to compile XtraBackup from source, I tried XtraBackup-1.3-beta for Lucid from the
Percona downloads. This worked fine.
Here's the scenario I tested against a MySQL Percona XtraDB instance running with DATADIR=/var/lib/mysql/m10 and a customized configuration file /etc/mysql10/my.cnf. I created and attached an EBS volume which I mounted as /xtrabackup on the instance running MySQL.
1) Take a hot backup of all databases under that instance:
/usr/bin/innobackupex-1.5.1 --defaults-file=/etc/mysql10/my.cnf --user=root --password=xxxxxx /xtrabackup
This will take a while and will create a timestamped directory under /xtrabackup, where it will store the database files from DATADIR. Note that the InnoDB log files are not created unless you apply step 2 below.
As the documentation says, make sure the output of innobackupex-1.5.1 ends with:
100901 05:33:12 innobackupex-1.5.1: completed OK!
2) Apply the transaction logs to the datafiles just created, so that the InnoDB logfiles are recreated in the target directory:
/usr/bin/innobackupex-1.5.1 --defaults-file=/etc/mysql10/my.cnf --user=root --password=xxxxxx --apply-log /xtrabackup/2010-09-01_05-21-36/
At this point, I tested a disaster recovery scenario by stopping MySQL and moving all files in DATADIR to a different location.
To bring the databases back to normal from the XtraBackup hot backup, I did the following:
1) Brought back up a functioning MySQL instance to be used by the XtraBackup restore operation:
i) Copied the contents of the default /var/lib/mysql/mysql database under /var/lib/mysql/m10/ (or you can recreate the mysql DB from scratch)
ii) Started mysqld_safe manually:
mysqld_safe --defaults-file=/etc/mysql10/my.cnf
This will create the data files and logs under DATADIR (/var/lib/mysql/m10) with the sizes specified in the configuration file. I had to wait until the messages in /var/log/syslog told me that the MySQL instance is ready and listening for connections.
2) Copied back the files from the hot backup directory into DATADIR
Note that the copy-back operation below initially errored out because it tried to copy the mysql directory too, and it found the directory already there under DATADIR. So the 2nd time I ran it, I moved /var/lib/mysql/m10/mysql to mysql.bak. The copy-back command is:
/usr/bin/innobackupex-1.5.1 --defaults-file=/etc/mysql10/my.cnf --user=root --copy-back /xtrabackup/2010-09-01_05-21-36/
You can also copy the files from /xtrabackup/2010-09-01_05-21-36/ into DATADIR using vanilla cp.
NOTE: verify the permissions on the restored files. In my case, some files in DATADIR were owned by root, so MySQL didn't start up properly because of that. Do a 'chown -R mysql:mysql DATADIR' to be sure.
3) If everything went well in step 2, restart the MySQL instance to make sure everything is OK.
At this point, your MySQL instance should have its databases restored to the point where you took the hot backup.
IMPORTANT: if the newly restored instance needs to be set up as a slave to an existing master server, you need to set the correct master_log_file and master_log_pos parameters via a 'CHANGE MASTER TO' command. These parameters are saved by innobackupex-1.5.1 in a file called xtrabackup_binlog_info in the target backup directory.
In my case, the xtrabackup_binlog_info file contained:
mysql-bin.000041 23657066
Here is an example of a CHANGE MASTER TO command I used:
STOP SLAVE;
CHANGE MASTER TO MASTER_HOST='masterhost', MASTER_PORT=3316, MASTER_USER='masteruser', MASTER_PASSWORD='masterpass', MASTER_LOG_FILE='mysql-bin.000041', MASTER_LOG_POS=23657066;
START SLAVE;
Note that XtraBackup can also run in a 'stream' mode useful for compressing the files generated by the backup operation. Details in the
documentation.