簡介:
在這之前都是通過 mysqldump 來備份數據庫的,由於是邏輯備份,所以采用這種備份方式數據是很安全的,跨平台、版本都很容易。
凡事有利必有弊,邏輯備份在你數據庫比較大時,備份、恢復數據所耗費的時間也是蠻長的,所以要不斷改進,使用物理備份。
由於線上數據庫表使用的是混合引擎 MyISAM 跟 Innodb ,所以也不能使用 mysqlhotcopy ,這個工具還是蠻好用的,可惜只能備份 MyISAM。
Percona XtraBackup 是 Percona 公司開發的一個用於 MySQL 數據庫物理熱備的備份工具,且是開源項目。
了解到 XtraBackup 工具下有一個 innobackupex 支持 MyISAM 跟 Innodb 的備份,所以來搞一搞。
一、安裝 XtraBackup
shell > yum -y install https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
# 或者
shell > wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm shell > yum -y install epel-release shell > yum -y install rsync libev-devel numactl-devel perl-DBD-MySQL shell > rpm -ivh percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
# 需要解決依賴關系
二、innobackupex 全備
shell > innobackupex --user=user --password=passwd --no-timestamp ./2016/09-29/`date +%H-%M`.dbname
# --no-timestamp 如果不加的話會在備份目錄下生成一個備份時間的目錄,備份數據存在該目錄下
# 將整個數據庫備份到 ./2016/09-29/ 以備份時間加自定義名稱的一個目錄下
# 雖然可以使用 --stream=tar 加 | gzip > 的方式直接打包並壓縮,但是備份速度就下降了,所以我寧願快速備份,之后再去處理打包、壓縮。
# 全備腳本
shell > vim script/backupdb.sh #!/bin/bash # 0 0 */2 * * sh /root/script/backupdb.sh # author: Wang XiaoQiang 2016/09/29 dbname='alldatabases' dbuser='user' dbpassword='passwd' backup_dir='/data/backup_db' backup_log='/root/script/logs/backup.log' ymtime=`date +%Y-%m` dtime=`date +%d` wlog(){ echo -e "`date "+%F %T"` DBname: $1 State: $2\n" >> $backup_log } [ ! -d $backup_dir/$ymtime ] && mkdir -p $backup_dir/$ymtime cd $backup_dir/$ymtime && /usr/bin/innobackupex --user=$dbuser --password=$dbpassword --no-timestamp $dbname > /dev/null 2>&1 if [ $? -eq 0 ];then wlog $dbname 'Backup success.' dbakfile=$dbname.$dtime.tar.gz tar zcf $dbakfile $dbname --remove-files [ $? -eq 0 ] && wlog $dbakfile 'Packaging success.' || wlog $dbakfile 'Packaging failed.' else wlog $dbname 'Backup failed.' fi # End
三、innobackupex 全備恢復
shell > /etc/init.d/mysql.server stop # 首先關閉數據庫 shell > cd /data/backup_db # 切換到備份目錄 shell > mv /usr/local/mysql-5.5.52/data data.old # 將原來的數據目錄備份一下 shell > tar zxf alldatabase.11.tar.gz # 然后將原來的備份解壓縮 shell > innobackupex --apply-log alldatabase # 在備份上應用日志,一般沒有看到報錯且最后顯示 OK 就沒有問題 ( --use-memory 使用該參數加快速度 ) 161011 12:07:33 completed OK! shell > innobackupex --copy-back alldatabase # 將備份還原到 my.cnf 指定的 datadir 中,不指定 --defaults-file,默認 /etc/my.cnf Error: datadir must be specified. # 報錯信息顯示,在默認配置文件 /etc/my.cnf 中,沒有找到 datadir 配置項 shell > vim /etc/my.cnf # 加入 datadir 配置項 datadir = /usr/local/mysql-5.5.52/data shell > innobackupex --copy-back alldatabase # 再次執行 copy 動作,沒有報錯且顯示 OK 161011 12:17:52 completed OK! shell > ll -d /usr/local/mysql-5.5.52/data drwxr-x--- 6 root root 4096 10月 11 12:17 /usr/local/mysql-5.5.52/data shell > chown -R mysql.mysql /usr/local/mysql-5.5.52/data # 修改數據目錄權限 shell > /etc/init.d/mysql.server start
# 備份已經恢復!
# 回顧整個恢復過程,發現一個問題:之前數據庫里的東西全部沒有了...
# 也就是說,innobackupex 只適用於該 MySQL 中除系統庫外,只有一個庫的備份。
# 雖然有選項 --databases 可以指定備份哪個數據庫,但是備出來的結果卻是 all databases,且恢復的時候也是全部覆蓋。
# 1、采用 innobackupex 備份整庫,然后恢復到一台新庫上,再通過 mysqldump 將需要還原的單庫備份一次,之后導入需要恢復的數據庫中 ( 要考慮恢復時間 )。
# 2、采用 innobackupex 備份只有一個業務庫的 MySQL Server,恢復到只有該業務庫的 MySQL Server 中。
# 3、如果一個 MySQL Server 中有多個數據庫,又只想備份某個庫,且該庫體積比較小的情況下,建議使用 mysqldump 備份。
三、innobackupex 增備
shell > mysql -uuser -ppassword -A # 創建測試庫、表,插入測試數據 mysql> create database test_incre character set utf8; mysql> create table test_incre.incre(id int(10) not null,name varchar(20)); mysql> insert into test_incre.incre values(1,'Wang XiaoQiang'); mysql> quit shell > innobackupex --user=user --password=password --database=test_incres --no-timestamp /data/backup_db/test_incre # 第一次全備
# 再次證明:--databases 就是來賣萌的,你可以去源數據庫目錄 du -sh 跟 目標備份目錄 du -sh 比對,真的是一毛一樣。
shell > mysql -uuser -ppassword -A # 添加測試數據 mysql> insert into test_incre.incre values(2,'Xiao GuaiShou'); mysql> quit shell > innobackupex --user=user --password=password --database=test_incres --no-timestamp --incremental-basedir=/data/backup_db/test_incre --incremental /data/backup_db/test_incre01
# --incremental-basedir=/data/backup_db/test_incre 第一次增備指定全備路徑
# --incremental 參數說明這是一次增備,並指定增備路徑
# 全備目錄 du -sh 跟 增備目錄 du -sh 比較發現,增備目錄只比全備目錄少了 1G,這說明對於 MyISAM 表來講,還是全備!!!
shell > mysql -uuser -ppassword -A # 再次添加測試數據 mysql> insert into test_incre.incre values(3,'King'); mysql> quit shell > innobackupex --user=user --password=password --database=test_incres --no-timestamp --incremental-basedir=/data/backup_db/test_incre01 --incremental /data/backup_db/test_incre02
# 第二次增備是在第一次增備的基礎上,所以 --incremental-basedir 指定的是第一次增備目錄,最后指定的第二次增備目錄
shell > cat test_incre/xtrabackup_checkpoints # backup_type 提示:這是一次全備,from_lsn 從 0 開始至 1601917 結束 backup_type = full-backuped from_lsn = 0 to_lsn = 1601917 last_lsn = 1601917 compact = 0 recover_binlog_info = 0 shell > cat test_incre01/xtrabackup_checkpoints # backup_type 提示:這是一次增備,from_lsn 從上次結束 lsn 1601917 開始至 1602789 結束 backup_type = incremental from_lsn = 1601917 to_lsn = 1602789 last_lsn = 1602789 compact = 0 recover_binlog_info = 0 shell > cat test_incre02/xtrabackup_checkpoints # backup_type 提示;這是一次增備,from_lsn 從上次結束 lsn 1602789 開始至 1603652 結束 backup_type = incremental from_lsn = 1602789 to_lsn = 1603652 last_lsn = 1603652 compact = 0 recover_binlog_info = 0
# 好了,這就是增量備份了,可以發現:對於 MyISAM 來說全部是全量備份,並且根本沒有什么 --databases 一說。
# 增備腳本
四、innobackupex 增備恢復
shell > /etc/init.d/mysql.server stop # 關閉數據庫 shell > cd /data/backup_db shell > mv /usr/local/mysql-5.5.52/data data.old02 # 備份原有數據庫 shell > innobackupex --apply-log --redo-only test_incre # 指定全備目錄,--redo-only 對已提交的事務進行前滾,僅最后一次增備恢復不需要添加該參數 shell > innobackupex --apply-log --redo-only test_incre --incremental-dir=/data/backup_db/test_incre01 # --incremental-dir 指定第一次增備目錄 ( 絕對路徑 ) shell > innobackupex --apply-log test_incre --incremental-dir=/data/backup_db/test_incre02 # 指定第二次增備目錄,最后一次增備還原不需要添加 --redo-only 參數 shell > innobackupex --copy-back test_incre # 最后一步,復制整合后的全備文件,位置為 my.cnf 中 datadir 指定路徑 shell > chown -R mysql.mysql /usr/local/mysql-5.5.52/data shell > /etc/init.d/mysql.server start # 啟動數據庫,查看數據是否恢復 shell > mysql -uuser -ppassword -A mysql> select * from test_incre.incre; +----+----------------+ | id | name | +----+----------------+ | 1 | Wang XiaoQiang | | 2 | Xiao GuaiShou | | 3 | King | +----+----------------+
# OK,木有問題!