1. Xtrabackup工具安裝
1. 系統(tǒng)環(huán)境說明
實(shí)驗(yàn)環(huán)境為CentOS 6.8单默,與其它Linux系統(tǒng)大同小異
2. 安裝Xtrabackup
1)配置epel源:
[root@oldboy ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
---CentOS 7系統(tǒng)把epel源改成7的即可
2)安裝Xtrabackup軟件需要的基礎(chǔ)環(huán)境包:
[root@oldboy ~]# yum install -y perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL
3)下載Xtrabackup軟件并安裝:
[root@oldboy ~]# 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
---如果地址無(wú)效次员,就去官網(wǎng)尋找合適的版本
[root@oldboy ~]# ll percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
-rw-r--r--. 1 root root 8534624 Jul 21 2016 percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm
[root@oldboy ~]# yum install -y percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm ---自動(dòng)解決依賴包
4)查看安裝后的結(jié)果:
[root@oldboy ~]# ll `which xtrabackup innobackupex`
lrwxrwxrwx. 1 root root 10 Apr 27 12:27 /usr/bin/innobackupex -> xtrabackup
-rwxr-xr-x. 1 root root 22136096 Jul 21 2016 /usr/bin/xtrabackup
2. Xtrabackup應(yīng)用實(shí)踐
1. 用于Xtrabackup數(shù)據(jù)備份的用戶
用于Xtrabackup數(shù)據(jù)備份的用戶也是需要一定權(quán)限的,具體配置如下(backup用戶):
mysql> CREATE USER 'backup@localhost' IDENTIFIED BY 'backup123';
Query OK, 0 rows affected (0.03 sec)
mysql> GRANT RELOAD,LOCK TABLES,PROCESS,REPLICATION CLIENT ON *.* TO 'backup'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
此外谆吴,用于操作備份的Linux系統(tǒng)用戶有讀取和寫入相關(guān)的目錄的權(quán)限辆布,一般情況下,還是建議使用root管理員權(quán)限進(jìn)行備份,不管是MySQL還是Linux系統(tǒng)瞳脓。
2. 用于恢復(fù)的MySQL配置文件
先創(chuàng)建存放MySQL日志文件的目錄,將MySQL日志和數(shù)據(jù)文件分離到不同的目錄中澈侠,以便于Xtrabackup恢復(fù)正式數(shù)據(jù):
[root@oldboy ~]# mkdir /application/mysql/logs -p
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/logs
然后劫侧,修改MySQL的配置文件,把二進(jìn)制日志、錯(cuò)誤日志烧栋、慢查詢?nèi)罩緩腗ySQL數(shù)據(jù)文件目錄中遷移出來写妥,并增加數(shù)據(jù)文件對(duì)應(yīng)得目錄。
[root@oldboy ~]# egrep -v "#|^$" /etc/my.cnf ---修改后的配置文件
[client]
user = root
password = oldboy123
[mysqld]
basedir = /application/mysql/ ---增加MySQL根目錄
datadir = /application/mysql/data/ ---MySQL數(shù)據(jù)目錄审姓,Xtrabackup恢復(fù)數(shù)據(jù)時(shí)需要這個(gè)目錄
---以下為binlog相關(guān)配置---
log_bin = /application/mysql/logs/oldboy-bin
expire_logs_days = 7
---以下為慢查詢?nèi)罩鞠嚓P(guān)配置---
slow-query-log = ON
long_query_time = 2
log_queries_not_using_indexes = ON
slow-query-log-file = /application/mysql/logs/slow.log ---慢查詢?nèi)罩韭窂秸{(diào)整
min_examined_row_limit = 800
[mysqld_safe]
log-error = /application/mysql/logs/oldboy.err ---錯(cuò)誤日志路徑調(diào)整
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
調(diào)整完配置文件后重啟MySQL
[root@oldboy ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL.190427 13:03:52 mysqld_safe error: log-error set to '/application/mysql/logs/oldboy.err', however file don't exists. Create writable for user 'mysql'.
ERROR! The server quit without updating PID file (/application/mysql/data//oldboy.pid).
---重啟時(shí)啟動(dòng)報(bào)錯(cuò)珍特,提示修改配置文件后沒有相關(guān)可寫的錯(cuò)誤日志文件,新建一個(gè)即可
[root@oldboy ~]# touch /application/mysql/logs/oldboy.err
[root@oldboy ~]# chown mysql.mysql !$
chown mysql.mysql /application/mysql/logs/oldboy.err
[root@oldboy ~]# ll !$
ll /application/mysql/logs/oldboy.err
-rw-r--r--. 1 mysql mysql 0 Apr 27 13:04 /application/mysql/logs/oldboy.err
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.... SUCCESS!
上面調(diào)整MySQL配置文件魔吐,是為了后面直接使用Xtrabackup(--copy-back)將數(shù)據(jù)文件還原到數(shù)據(jù)文件的目錄中扎筒,如果使用mv等命令移動(dòng)還原數(shù)據(jù)文件,則可以不調(diào)整對(duì)應(yīng)配置文件參數(shù)酬姆。
3. Xtrabackup軟件附帶的備份工具說明
Xtrabackup軟件主要包含兩個(gè)常用的工具:
(1)Xtrabackup命令
Xtrabackup命令是專門用于對(duì)InnoDB和XtraDB等事務(wù)引擎得數(shù)據(jù)庫(kù)熱備份的工具嗜桌,不能用于備份MyISAM等其他類型的引擎數(shù)據(jù),其主要特點(diǎn)是備份數(shù)據(jù)時(shí)完全不用鎖表辞色。
(2)Innobackupex命令
Innobackupex命令是將上述Xtrabackup命令使用perl腳本進(jìn)行二次封裝的工具骨宠,除了可以用于InnoDB和XtraDB等引擎之外,還可以備份MyISAM及多種引擎混合使用的場(chǎng)景相满,該命令的主要特點(diǎn)是備份事務(wù)引擎數(shù)據(jù)而不用鎖表层亿,可以備份非事務(wù)引擎數(shù)據(jù),但要鎖表雳灵。
國(guó)內(nèi)運(yùn)維人員和DBA在企業(yè)里通常使用功能更多的Innobackupex命令來進(jìn)行備份和恢復(fù)棕所。
4. Innobackupex工具語(yǔ)法介紹
Innobackupex工具語(yǔ)法如下:
innobackupex [--user=name] [--host=name] [--password=WORD] [--port=PORT] [--socket=SOCKET] [--defaults-file=MY.CNF] PATH
5. 全備與恢復(fù)全備實(shí)踐
5.1 數(shù)據(jù)準(zhǔn)備
mysql> use oldboy
Database changed
mysql> select * from test;
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
+----+----------+
7 rows in set (0.00 sec)
5.2 開始全備
1)先創(chuàng)建一個(gè)規(guī)范的備份目錄:
[root@oldboy backup]# mkdir /server/backup -p
執(zhí)行備份時(shí),屏幕會(huì)有非常多的輸出信息悯辙,其實(shí)就是備份的工作流程細(xì)節(jié)琳省,全備份與增量備份每當(dāng)命令操作成功時(shí),都會(huì)在日志的結(jié)尾處打印“completed ok!”作為標(biāo)識(shí):
[root@oldboy backup]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp /server/backup/full
---省略若干行提醒信息及讀取數(shù)據(jù)庫(kù)的innodb參數(shù)配置等
190427 17:58:46 >> log scanned up to (2010527) ---開始記錄并監(jiān)控redo日志
xtrabackup: Generating a list of tablespaces
InnoDB: Allocated tablespace ID 28 for oldboy/test, old maximum was 0
190427 17:58:47 [01] Copying ./ibdata1 to /server/backup/full/ibdata1
---開始復(fù)制innodb文件
190427 17:58:47 >> log scanned up to (2010527)
190427 17:58:48 [01] ...done
---省略若干行
190427 17:58:48 [01] Copying ./mysql/slave_worker_info.ibd to /server/backup/full/mysql/slave_worker_info.ibd
190427 17:58:48 [01] ...done
190427 17:58:48 Executing FLUSH NO_WRITE_TO_BINLOG TABLES...
190427 17:58:48 Executing FLUSH TABLES WITH READ LOCK... ---開始鎖表備份非事務(wù)引擎表
190427 17:58:48 Starting to backup non-InnoDB tables and files
190427 17:58:48 [01] Copying ./oldboy/test.frm to /server/backup/full/oldboy/test.frm
190427 17:58:48 [01] ...done
---省略若干復(fù)制MyISAM表的數(shù)據(jù)文件行
190427 17:58:49 Finished backing up non-InnoDB tables and files
---備份非事務(wù)引擎表完成
190427 17:58:49 [00] Writing xtrabackup_binlog_info ---記錄binlog位置
190427 17:58:49 [00] ...done
190427 17:58:49 Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...
xtrabackup: The latest check point (for incremental): '2010527'
---記錄最新的checkpoint
xtrabackup: Stopping log copying thread. ---停止日志監(jiān)控進(jìn)程
.190427 17:58:49 >> log scanned up to (2010527)
190427 17:58:49 Executing UNLOCK TABLES ---停止鎖表
190427 17:58:49 All tables unlocked
---省略備份結(jié)果信息提示
190427 17:58:49 completed OK! ---備份成功的標(biāo)識(shí)
最終的備份結(jié)果如下:
[root@oldboy ~]# ll /server/backup/full/
total 77860
-rw-r-----. 1 root root 418 Apr 27 17:58 backup-my.cnf ---配置文件備份
-rw-r-----. 1 root root 79691776 Apr 27 17:58 ibdata1 ---共享表空間備份
drwxr-x---. 2 root root 4096 Apr 27 17:58 mysql ---mysql庫(kù)的備份
drwxr-x---. 2 root root 4096 Apr 27 17:58 oldboy ---oldboy庫(kù)的備份
drwxr-x---. 2 root root 4096 Apr 27 17:58 oldboy_utf8 ------oldboy_utf8庫(kù)的備份
drwxr-x---. 2 root root 4096 Apr 27 17:58 performance_schema ---performance_schema庫(kù)的備份
-rw-r-----. 1 root root 22 Apr 27 17:58 xtrabackup_binlog_info ---binlog的位置信息
-rw-r-----. 1 root root 113 Apr 27 17:58 xtrabackup_checkpoints ---checkpoints信息
-rw-r-----. 1 root root 569 Apr 27 17:58 xtrabackup_info ---xtrabackup信息
-rw-r-----. 1 root root 2560 Apr 27 17:58 xtrabackup_logfile ---xtrabackup日志文件
[root@oldboy ~]# cd /server/backup/full/
[root@oldboy full]# cat xtrabackup_binlog_info
oldboy-bin.000001 120 ---binlog位置信息
[root@oldboy full]# cat xtrabackup_checkpoints ---存放備份的起始位置和結(jié)束位置
backup_type = full-backuped ---備份類型
from_lsn = 0 ---checkpoints起始點(diǎn)
to_lsn = 2010527 ---checkpoints結(jié)束點(diǎn)
last_lsn = 2010527
compact = 0
recover_binlog_info = 0
5.3 利用全備恢復(fù)數(shù)據(jù)
使用Innobackupex備份的數(shù)據(jù)有可能會(huì)處于不一致的狀態(tài)躲撰,因此在恢復(fù)數(shù)據(jù)之前针贬,首先要將數(shù)據(jù)調(diào)成一致性的狀態(tài),即需要應(yīng)用備份過程中記錄變化的日志(xtrabackup_logfile)拢蛋,同時(shí)回滾未提交的事務(wù)日志數(shù)據(jù):
[root@oldboy full]# innobackupex --apply-log --use-memory=32M /server/backup/full/
提示:
1)“--apply-log”用于記錄變化的日志桦他,并回滾未提交得事務(wù)日志數(shù)據(jù)
2)“use-memory=32M”是分配的使用內(nèi)存大小
執(zhí)行完此命令之后,備份的數(shù)據(jù)就可以用來恢復(fù)了谆棱。
使用Xtrabackup備份的本質(zhì)就是復(fù)制物理數(shù)據(jù)文件快压,因此,在進(jìn)行最終恢復(fù)時(shí)垃瞧,需要臨時(shí)關(guān)閉數(shù)據(jù)庫(kù)蔫劣,把物理文件復(fù)制回去進(jìn)行恢復(fù):
[root@oldboy ~]# /etc/init.d/mysqld stop ---先停庫(kù)
Shutting down MySQL.. SUCCESS!
[root@oldboy ~]# ss -lnt | grep 3306
[root@oldboy ~]# mv /application/mysql/data /application/mysql/data_ori ---模擬刪除數(shù)據(jù)文件
[root@oldboy ~]# mkdir -p /application/mysql/data ---創(chuàng)建原始數(shù)據(jù)目錄,目錄要為空
[root@oldboy ~]# mv /server/backup/full/* /application/mysql/data/ ---使用mv直接復(fù)制更舒服一些
---也可以使用下面的命令復(fù)制還原數(shù)據(jù)个从,和mv命令的功能是一樣的脉幢,下面的命令的缺點(diǎn)是要根據(jù)MySQL配置文件的路徑進(jìn)行回拷貝歪沃,因此
配置文件沒有指定數(shù)據(jù)文件路徑、數(shù)據(jù)文件目錄不為空等嫌松,都會(huì)導(dǎo)致無(wú)法回拷貝的問題沪曙。命令如下:
innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /server/backup/full/
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/data
---如果權(quán)限不對(duì),啟動(dòng)數(shù)據(jù)庫(kù)可能會(huì)報(bào)“Starting MySQL. ERROR! The server quit without updating PID file”錯(cuò)誤
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[root@oldboy ~]# mysql -e "select * from oldboy.test;" ---恢復(fù)成功
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
+----+----------+
6. 增量備份與恢復(fù)增量數(shù)據(jù)實(shí)踐
使用Xtrabackup程序做增量備份之前萎羔,首先要進(jìn)行一次全備份液走,第一次增量備份是基于全備進(jìn)行的,之后的每一次增量備份都會(huì)基于上一次增量備份的數(shù)據(jù)來實(shí)現(xiàn)贾陷,操作如下:
(1)創(chuàng)建基礎(chǔ)全備份
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp /server/backup/base_full
(2)模擬增加數(shù)據(jù)育灸,然后做增量備份
增加如下數(shù)據(jù):
mysql> use oldboy
Database changed
mysql> insert into test values(8,'outman');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(9,'outgirl');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
| 8 | outman | ---全備后模擬增加了以下兩行數(shù)據(jù)
| 9 | outgirl |
+----+----------+
9 rows in set (0.00 sec)
開始做第一次增量備份:
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --incremental-basedir=/server/backup/base_full --incremental /server/backup/one_inc
注意,這里指定的全備路徑是--incremental-basedir=/server/backup/base_full昵宇。
增量備份的結(jié)果在/server/backup/one_inc下,其實(shí)就是從全備信息里最后得LSN開始讀取redo數(shù)據(jù)儿子,對(duì)改變的數(shù)據(jù)進(jìn)行增量備份瓦哎,所以我們剛剛增加的增量數(shù)據(jù)很少,InnoDB數(shù)據(jù)文件備份得也很少柔逼,增量備份的InnoDB數(shù)據(jù)備份的關(guān)鍵輸出如下:
xtrabackup: using the full scan for incremental backup
190427 21:55:43 [01] Copying ./ibdata1 to /server/backup/one_inc/ibdata1.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./oldboy/test.ibd to /server/backup/one_inc/oldboy/test.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/innodb_index_stats.ibd to /server/backup/one_inc/mysql/innodb_index_stats.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/innodb_table_stats.ibd to /server/backup/one_inc/mysql/innodb_table_stats.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/slave_master_info.ibd to /server/backup/one_inc/mysql/slave_master_info.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/slave_relay_log_info.ibd to /server/backup/one_inc/mysql/slave_relay_log_info.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:43 [01] Copying ./mysql/slave_worker_info.ibd to /server/backup/one_inc/mysql/slave_worker_info.ibd.delta
190427 21:55:43 [01] ...done
190427 21:55:44 >> log scanned up to (2017505)
---省略無(wú)用行---
190427 21:55:45 [00] Writing xtrabackup_info
190427 21:55:45 [00] ...done
xtrabackup: Transaction log of lsn (2017505) to (2017505) was copied.
190427 21:55:45 completed OK!
根據(jù)輸出蒋譬,我們也大概了解了插入數(shù)據(jù)到數(shù)據(jù)庫(kù)時(shí),對(duì)數(shù)據(jù)庫(kù)會(huì)有什么影響愉适,面對(duì)于非事務(wù)引擎的備份犯助,則仍是鎖表進(jìn)行全備。
(3)再模擬增加的數(shù)據(jù)维咸,然后做第二次增量備份
增加如下數(shù)據(jù):
mysql> use oldboy
Database changed
mysql> insert into test values(10,'two_inc1');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(11,'two_inc2');
Query OK, 1 row affected (0.00 sec)
開始做第二次增量備份剂买,注意,這里要用到第一次增量備份的目錄癌蓖,而不是全備目錄:
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --parallel=3 --incremental-basedir=/server/backup/one_inc/ --incremental /server/backup/two_inc
到此為止瞬哼,已經(jīng)完成了1次全備,以及全備之后的兩次增量數(shù)據(jù)備份
(4)開始做增量數(shù)據(jù)恢復(fù)
增量恢復(fù)的步驟為先恢復(fù)全備(base_full目錄)數(shù)據(jù)租副,然后再恢復(fù)第一次增量(one_inc)的數(shù)據(jù)坐慰,以及第二次增量(two_inc)的數(shù)據(jù),如果有更多次增量備份就以此類推用僧。
1)應(yīng)用redo日志恢復(fù)全備數(shù)據(jù):
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --redo-only /server/backup/base_full/
注意:非最后一次合并增量數(shù)據(jù)一定要加--redo-only參數(shù)结胀,即只應(yīng)用redo日志恢復(fù)數(shù)據(jù),而不執(zhí)行undo回滾未提交的數(shù)據(jù)责循,等到最后一次增量備份合并完成后再進(jìn)行undo日志回滾數(shù)據(jù)糟港。
2)合并第一次的增量數(shù)據(jù)到全備數(shù)據(jù)目錄:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --redo-only --incremental-dir=/server/backup/one_inc /server/backup/base_full/
3)合并第二次的增量數(shù)據(jù)到全備數(shù)據(jù)目錄:
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --incremental-dir=/server/backup/two_inc /server/backup/base_full/
需要強(qiáng)調(diào)的是,最后一次合并增量數(shù)據(jù)到全備時(shí)沼死,取消了“redo-only”參數(shù)着逐。
4)對(duì)最終的全量數(shù)據(jù)做redo日志應(yīng)用,并執(zhí)行undo回滾數(shù)據(jù):
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M /server/backup/base_full/
提示:本命令取消了“--redo-only”參數(shù),目的是應(yīng)用undo日志回滾數(shù)據(jù)耸别,為最終的恢復(fù)數(shù)據(jù)做準(zhǔn)備健芭。
5)開始正式恢復(fù)數(shù)據(jù):
[root@oldboy ~]# /etc/init.d/mysqld stop
Shutting down MySQL.... SUCCESS!
[root@oldboy ~]# ss -lnt | grep 3306
[root@oldboy ~]# mv /application/mysql/data /tmp/data_ori1
[root@oldboy ~]# mkdir -p /application/mysql/data ---原始數(shù)據(jù)目錄要為空
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /server/backup/base_full/
---看看innobackupex效果和mv是不是一樣
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/data
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+----------+
| id | name |
+----+----------+
| 1 | oldboy |
| 2 | oldgirl |
| 3 | inca |
| 4 | zuma |
| 5 | kaka |
| 6 | bingbing |
| 7 | xiaoting |
| 8 | outman |
| 9 | outgirl |
| 10 | two_inc1 |
| 11 | two_inc2 |
+----+----------+
到此為止,全量和后增加的增量數(shù)據(jù)就都回來了秀姐,但上述恢復(fù)還未涉及binlog恢復(fù)的情況慈迈,因此,在實(shí)際生產(chǎn)中僅僅用上述方法來恢復(fù)數(shù)據(jù)省有,得到的數(shù)據(jù)將是不完整的痒留,還需要進(jìn)行binlog文件的恢復(fù)才行。
7. 中小企業(yè)MySQL Xtrabackup物理增量恢復(fù)案例實(shí)戰(zhàn)
什么樣的條件才能完整地物理恢復(fù)數(shù)據(jù)庫(kù)數(shù)據(jù)蠢沿?
- 具備全量備份(Xtrabackup備份的全備)
- 具備全量之后的所有增量備份(Xtrabackup備份的增量)
- 具備最后一次增量備份以后的所有MySQL的binlog增量日志
假設(shè)當(dāng)前數(shù)據(jù)庫(kù)內(nèi)的數(shù)據(jù)如下:
mysql> use oldboy
Database changed
mysql> truncate table test;
Query OK, 0 rows affected (0.05 sec)
mysql> insert into test values(1,'full01');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(2,'full02');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(3,'full03');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(4,'full04');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(5,'full05');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+----+--------+
| id | name |
+----+--------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
+----+--------+
5 rows in set (0.00 sec)
先模擬5月3日0點(diǎn)開始對(duì)數(shù)據(jù)庫(kù)oldboy數(shù)據(jù)進(jìn)行全備:
[root@oldboy ~]# date -s "2019/05/03"
Fri May 3 00:00:00 CST 2019
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp /server/backup/new_base_full
然后模擬5月3日0點(diǎn)全備之后(0:00-24:00點(diǎn))用戶繼續(xù)寫入數(shù)據(jù):
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(6,'new_inc_one_1');"
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(7,'new_inc_one_2');"
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
+----+---------------+
之后伸头,在5月4日0點(diǎn)做增量備份(沒做全備):
[root@oldboy ~]# date -s "2019/05/04"
Sat May 4 00:00:00 CST 2019
[root@oldboy ~]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --incremental-basedir=/server/backup/new_base_full/ --incremental /server/backup/new_one_inc
在5月4日0點(diǎn)增備之后(0:00-24:00)用戶繼續(xù)寫入數(shù)據(jù):
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(8,'binlog_data_1');"
[root@oldboy ~]# mysql -e "use oldboy;insert into test values(9,'binlog_data_2');"
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
| 8 | binlog_data_1 |
| 9 | binlog_data_2 |
+----+---------------+
假設(shè)5月4日上午10:00點(diǎn)管理人員誤刪除了oldboy數(shù)據(jù)庫(kù):
[root@oldboy ~]# date -s "2019/05/04 10:00"
Sat May 4 10:00:00 CST 2019
[root@oldboy ~]# mysql -e "drop database oldboy;show databases;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| oldboy_utf8 |
| performance_schema |
+--------------------+
數(shù)據(jù)庫(kù)出問題10分鐘后,公司的網(wǎng)站運(yùn)營(yíng)人員報(bào)網(wǎng)站故障舷蟀,聯(lián)系運(yùn)維人員恤磷、DBA解決。此時(shí)野宜,DBA或開發(fā)人員會(huì)查看網(wǎng)站報(bào)錯(cuò)(或者查看后臺(tái)日志)扫步,可以看到連不上oldboy數(shù)據(jù)庫(kù)的提示,然后登陸數(shù)據(jù)庫(kù)排查匈子,發(fā)現(xiàn)數(shù)據(jù)庫(kù)oldboy已經(jīng)不存在了河胎。登陸系統(tǒng)分析系統(tǒng)審計(jì)日志,以及分析數(shù)據(jù)庫(kù)binlog也可以發(fā)現(xiàn)庫(kù)丟失的原因虎敦;開發(fā)人員通過程序日志判斷應(yīng)該也可以查出來原因游岳。
開始進(jìn)行恢復(fù)前的準(zhǔn)備:
1)移走所有binlog增量文件,防止被二次破壞
[root@oldboy ~]# cp -a /application/mysql/logs /server/backup/binlog
2)開始恢復(fù)數(shù)據(jù)前的增量備份和全備合并
先合并全備數(shù)據(jù)到新全備目錄原茅,即恢復(fù)第一天0點(diǎn)前的所有數(shù)據(jù):
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --redo-only /server/backup/new_base_full/
再合并增量數(shù)據(jù)到新全備目錄吭历,即恢復(fù)第二天0點(diǎn)前的所有數(shù)據(jù):
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M --incremental-dir=/server/backup/new_one_inc/ /server/backup/new_base_full/
最后應(yīng)用所有redo日志,并回滾未提交的數(shù)據(jù):
[root@oldboy ~]# innobackupex --apply-log --use-memory=32M /server/backup/new_base_full/
3)開始恢復(fù)binlog日志數(shù)據(jù)
由于5月4日0點(diǎn)之后的所有數(shù)據(jù)并不在全備里擂橘,也不在增量里晌区,而是在MySQL的binlog日志里,因此還要進(jìn)行如下操作來完成恢復(fù)通贞。
首先查看5月4日0點(diǎn)最后一次增量的binlog位置信息:
[root@oldboy ~]# cat /server/backup/new_one_inc/xtrabackup_binlog_info
oldboy-bin.000003 1820
這個(gè)位置信息以后的binlog才是我們需要的朗若,以前的數(shù)據(jù)在Xtrabackup的全量和增量里已經(jīng)有了,然后查看問題出現(xiàn)后第一時(shí)間備份的binlog文件信息:
[root@oldboy ~]# ll /server/backup/binlog/oldboy-bin.*
-rw-rw----. 1 mysql mysql 143 Apr 27 21:16 /server/backup/binlog/oldboy-bin.000001
-rw-rw----. 1 mysql mysql 1951 Apr 27 23:17 /server/backup/binlog/oldboy-bin.000002
-rw-rw----. 1 mysql mysql 2386 May 4 10:00 /server/backup/binlog/oldboy-bin.000003
-rw-rw----. 1 mysql mysql 126 Apr 27 23:21 /server/backup/binlog/oldboy-bin.index
從上面的信息可知昌罩,需要使用的binlog文件為oldboy-bin.000003哭懈。(因?yàn)樽詈竺婢褪莖ldboy-bin.000003了)
現(xiàn)在從oldboy-bin.000003文件的1820位置點(diǎn)開始恢復(fù)增量數(shù)據(jù):
[root@oldboy binlog]# mysqlbinlog -d oldboy oldboy-bin.000003 --start-position=1820 -r bin.sql
這里要剔除誤刪除數(shù)據(jù)庫(kù)的drop語(yǔ)句,否則茎用,直接恢復(fù)就又進(jìn)入了刪庫(kù)故障的坑:
[root@oldboy binlog]# grep -w drop bin.sql ---找出誤刪除數(shù)據(jù)庫(kù)的語(yǔ)句
drop database oldboy
[root@oldboy binlog]# sed -i '/drop database oldboy/d' bin.sql ---剔除誤刪除數(shù)據(jù)庫(kù)的drop語(yǔ)句
[root@oldboy binlog]# grep -w drop bin.sql
需要注意的是遣总,本案例是刪除數(shù)據(jù)庫(kù)了睬罗,因此binlog日志就不再增長(zhǎng)了,所以可以利用上文第一時(shí)間備份的binlog恢復(fù)旭斥,如果是update操作誤改了數(shù)據(jù)又沒有停庫(kù)容达,那么,此時(shí)最好是在數(shù)據(jù)庫(kù)服務(wù)器上用Iptables控制應(yīng)用程序連接數(shù)據(jù)庫(kù)之后垂券,再?gòu)纳鲜鯾inlog位置點(diǎn)開始讀取正式日志目錄下的所有binlog日志花盐,一直將Iptables限制訪問時(shí)的所有binlog日志恢復(fù)完。
下面開始正式恢復(fù)數(shù)據(jù)庫(kù)數(shù)據(jù)菇爪。
1)停止數(shù)據(jù)庫(kù)對(duì)外訪問算芯。因?yàn)槭鞘褂胐rop命令刪除庫(kù),而且后面不會(huì)有寫入了凳宙,所以可以不用額外停止寫入熙揍,但如果是update導(dǎo)致的數(shù)據(jù)破壞,那么最好是在發(fā)現(xiàn)問題的第一時(shí)間就進(jìn)行停庫(kù)處理或?qū)ν馔V箤懭搿?/p>
[root@oldboy ~]# iptables -I INPUT -p tcp --dport 3306 ! -s 192.168.9.115 -j DROP ---非192.168.9.115禁止訪問數(shù)據(jù)庫(kù)3306端口
2)恢復(fù)處理好的Xtrabackup備份的全量及增量數(shù)據(jù):
[root@oldboy ~]# /etc/init.d/mysqld stop ---恢復(fù)時(shí)要停庫(kù)
Shutting down MySQL.. SUCCESS!
[root@oldboy ~]# ss -lnt | grep 3306
[root@oldboy ~]# mv /application/mysql/data /tmp/data3 ---移走舊的數(shù)據(jù)
[root@oldboy ~]# mkdir -p /application/mysql/data ---原始數(shù)據(jù)目錄要為空
[root@oldboy ~]# mv /server/backup/new_base_full/* /application/mysql/data/
---采用mv氏涩,而不是xtrabackup的--copy-back參數(shù)還原诈嘿,使用mv的時(shí)候,前文的MySQL配置就可以采用了
[root@oldboy ~]# chown -R mysql.mysql /application/mysql/data/ ---重新授權(quán)
[root@oldboy ~]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS!
[root@oldboy ~]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
+----+---------------+
到此削葱,使用Xtrabackup備份的到5月3日的全備數(shù)據(jù)和5月4日0點(diǎn)之前增量備份的數(shù)據(jù)都回來了。
接下來開始恢復(fù)5月4日0點(diǎn)到10點(diǎn)的數(shù)據(jù)庫(kù)數(shù)據(jù)淳梦。
這時(shí)需要恢復(fù)binlog數(shù)據(jù)析砸,即從binlog解析出數(shù)據(jù)并且清理了drop語(yǔ)句的bin.sql文件:
[root@oldboy ~]# cd /server/backup/binlog/
[root@oldboy binlog]# mysql oldboy < bin.sql
[root@oldboy binlog]# mysql -e "select * from oldboy.test;"
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
| 8 | binlog_data_1 | ---binlog里記錄的數(shù)據(jù)回來了
| 9 | binlog_data_2 |
+----+---------------+
到此,恢復(fù)完畢爆袍。
8. 使用Xtrabackup物理分庫(kù)分表備份
使用Xtrabackup物理分庫(kù)分表備份的前提是開啟獨(dú)立表空間模式首繁,即設(shè)置innodb_file_per_table=On,MySQL5.6默認(rèn)已經(jīng)開啟了此模式陨囊。
1)備份單個(gè)庫(kù)oldboy:
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --database="oldboy" /server/backup/oldboy_full
[root@oldboy binlog]# ll /server/backup/oldboy_full/
total 77860
-rw-r-----. 1 root root 418 May 4 12:52 backup-my.cnf
-rw-r-----. 1 root root 79691776 May 4 12:52 ibdata1
drwxr-x---. 2 root root 4096 May 4 12:52 mysql
drwxr-x---. 2 root root 4096 May 4 12:52 oldboy
drwxr-x---. 2 root root 4096 May 4 12:52 oldboy_utf8
drwxr-x---. 2 root root 4096 May 4 12:52 performance_schema
-rw-r-----. 1 root root 22 May 4 12:52 xtrabackup_binlog_info
-rw-r-----. 1 root root 113 May 4 12:52 xtrabackup_checkpoints
-rw-r-----. 1 root root 593 May 4 12:52 xtrabackup_info
-rw-r-----. 1 root root 2560 May 4 12:52 xtrabackup_logfile
2)備份多個(gè)庫(kù):
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy oldgirl" /server/backup/oldboy_oldgirl
[root@oldboy binlog]# ll /server/backup/oldboy_oldgirl/
total 77848
-rw-r-----. 1 root root 418 May 4 12:55 backup-my.cnf
-rw-r-----. 1 root root 79691776 May 4 12:55 ibdata1
drwxr-x---. 2 root root 4096 May 4 12:55 oldboy
drwxr-x---. 2 root root 4096 May 4 12:55 oldgirl
-rw-r-----. 1 root root 22 May 4 12:55 xtrabackup_binlog_info
-rw-r-----. 1 root root 113 May 4 12:55 xtrabackup_checkpoints
-rw-r-----. 1 root root 606 May 4 12:55 xtrabackup_info
-rw-r-----. 1 root root 2560 May 4 12:55 xtrabackup_logfile
3)備份單個(gè)表:
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy.test" /server/backup/oldboy_test
4)備份多個(gè)庫(kù)的多個(gè)表:
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy.test oldboy.student" /server/backup/oldboy_test_student
[root@oldboy binlog]# innobackupex --defaults-file=/etc/my.cnf --user=root --password=oldboy123 --socket=/application/mysql-5.6.41/tmp/mysql.sock --no-timestamp --databases="oldboy.test oldboy.student mysql.user" /server/backup/all
9. 使用Xtrabackup物理分庫(kù)分表備份的恢復(fù)
在使用Xtrabackup物理分庫(kù)分表備份的恢復(fù)時(shí)弦疮,需要使用“--export”來做恢復(fù)準(zhǔn)備,最終恢復(fù)時(shí)蜘醋,不能使用常規(guī)的“--copy-back”選項(xiàng)胁塞,而是要初始化一個(gè)帶有mysql庫(kù)(“mysql_install_db --user=mysql”)的干凈的數(shù)據(jù)文件目錄。
1)恢復(fù)準(zhǔn)備
[root@oldboy binlog]# innobackupex --apply-log --export /server/backup/oldboy_test/ ---恢復(fù)oldboy的test表
2)初始化數(shù)據(jù)庫(kù)(這里為了方便压语,直接在當(dāng)前環(huán)境測(cè)試)
[root@oldboy binlog]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS!
[root@oldboy binlog]# mv /application/mysql/data /tmp/data.ori ---備份前面的數(shù)據(jù)
[root@oldboy binlog]# mkdir /application/mysql/data
[root@oldboy binlog]# /application/mysql/scripts/mysql_install_db --basedir=/application/mysql/ --datadir=/application/mysql/data --user=mysql ---初始化新的mysql數(shù)據(jù)文件
[root@oldboy binlog]# cp /server/backup/oldboy_test/* /application/mysql/data/
[root@oldboy binlog]# chown -R mysql.mysql /application/mysql/data
[root@oldboy binlog]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
mysql> select * from oldboy.test; ---查看還原的數(shù)據(jù)
+----+---------------+
| id | name |
+----+---------------+
| 1 | full01 |
| 2 | full02 |
| 3 | full03 |
| 4 | full04 |
| 5 | full05 |
| 6 | new_inc_one_1 |
| 7 | new_inc_one_2 |
| 8 | binlog_data_1 |
| 9 | binlog_data_2 |
+----+---------------+
9 rows in set (0.00 sec)
如果有需要啸罢,可以通過mysqldump導(dǎo)出后恢復(fù)到正式庫(kù)
最后把當(dāng)前的環(huán)境恢復(fù)回來:
[root@oldboy binlog]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS!
[root@oldboy binlog]# mv /application/mysql/data /opt/data.new
[root@oldboy binlog]# mv /tmp/data.ori /application/mysql/data
[root@oldboy binlog]# chown -R mysql.mysql /application/mysql/data
[root@oldboy binlog]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!