故事背景:前面大膽的選擇了innodb,接下來就要考慮數據庫的備份和恢復。俗話說“常在河邊走,哪能不濕鞋“,自從接觸數據這塊,使我一直對它保持敬畏之心。在這里使用了percona公司的xtrabckup工具來實現數據庫備份和恢復。操作步驟記錄如下:
1、安裝軟件倉庫(不要問我為什么不用源碼安裝,好吧,其實我懶。)
wget https://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm rpm -ivh percona-release-0.1-3.noarch.rpm rpm -ql percona-release /etc/pki/rpm-gpg/RPM-GPG-KEY-Percona /etc/yum.repos.d/percona-release.repo /usr/share/doc/percona-release-0.1 /usr/share/doc/percona-release-0.1/RPM-GPG-KEY-Percona yum -y install percona-xtrabackup
2、備份策略及準備測試數據
采用先全備份加增量備份的方案。在利用xtrabackup對innodb表做備份工作時,建議mysql啟用“innodb_file_per_table=1”變量且同時啟用innodb_file_per_table = 1 innodb_expand_import = 1
這樣使每表都有一個自己的表空間,不然很難進行單表備份和還原。還有二進制日志文件就不要與數據文件放在同一個目錄了,你不想當數據丟失時,二進制日志也一同丟了。
測試數據:
mysql> SELECT VERSION(); +------------+ | VERSION() | +------------+ | 5.5.36-log | +------------+ 1 row in set (0.00 sec) mysql> SHOW DATABASES; #創建了一個mydb1數據庫 +--------------------+ | Database | +--------------------+ | information_schema | | mydb1 | | mysql | | performance_schema | | test | +--------------------+ mysql> SELECT * FROM mydb1.tb1; #表中只有一條數據 +----+------+------+ | id | name | age | +----+------+------+ | 1 | tom | 10 | +----+------+------+
創建備份數據存放目錄:
mkdir -pv /backup/{fullbackup,incremental} #fullbackup 存放全備份數據 #incremental 存放增量備份數據
創建復制用戶:
mysql> GRANT RELOAD,LOCK TABLES,REPLICATION CLIENT ON *.* TO 'bkuser'@'localhost' IDENTIFIED BY '123456'; mysql> FLUSH PRIVILEGES;
3、全備份數據
innobackupex --user=bkuser --password=123456 /backup/fullbackup/ #最后出現“150415 16:30:23 innobackupex: completed OK!”這樣的信息表示備份完成 ls /backup/fullbackup/2015-04-15_16-30-19/ backup-my.cnf mysql xtrabackup_binary xtrabackup_logfile ibdata1 performance_schema xtrabackup_binlog_info mydb1 test xtrabackup_checkpoints cat /backup/fullbackup/2015-04-15_16-30-19/xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 1644877 last_lsn = 1644877 compact = 0
4、增量備份數據
先做一些數據修改:
mysql> INSERT INTO mydb1.tb1 (name,age) VALUES ('jack',20); mysql> SELECT * FROM tb1; #增加一條數據 +----+------+------+ | id | name | age | +----+------+------+ | 1 | tom | 10 | | 2 | jack | 20 | +----+------+------+
做第一次增量備份:
innobackupex --user=bkuser --password=123456 --incremental /backup/incremental/ --incremental-basedir=/backup/fullbackup/2015-04-15_16-30-19/ ls /backup/incremental/2015-04-15_16-42-00/ backup-my.cnf mydb1 test xtrabackup_checkpoints ibdata1.delta mysql xtrabackup_binary xtrabackup_logfile ibdata1.meta performance_schema xtrabackup_binlog_info cat /backup/incremental/2015-04-15_16-42-00/xtrabackup_checkpoints backup_type = incremental from_lsn = 1644877 #這是全備時的"to_lsn"值 to_lsn = 1645178 last_lsn = 1645178 compact = 0
再做數據修改:
mysql> INSERT INTO mydb1.tb1 (name,age) VALUES ('jason',30); mysql> SELECT * FROM tb1; +----+-------+------+ | id | name | age | +----+-------+------+ | 1 | tom | 10 | | 2 | jack | 20 | | 3 | jason | 30 | +----+-------+------+
做第二次增量備份:
innobackupex --user=bkuser --password=123456 --incremental /backup/incremental/ --incremental-basedir=/backup/incremental/2015-04-15_16-42-00/ #這里的"--incremental-basedir"是指向第一次增量備份的目錄 ls /backup/incremental/2015-04-15_16-49-07/ backup-my.cnf mydb1 test xtrabackup_checkpoints ibdata1.delta mysql xtrabackup_binary xtrabackup_logfile ibdata1.meta performance_schema xtrabackup_binlog_info cat /backup/incremental/2015-04-15_16-49-07/xtrabackup_checkpoints backup_type = incremental from_lsn = 1645178 #這是第一次增量的"to_lsn"值 to_lsn = 1645463 last_lsn = 1645463 compact = 0
再來做一次數據修改,以便演示根據二進制日志做時間點的恢復:
mysql> INSERT INTO mydb1.tb1 (name,age) VALUES ('lucky',40); mysql> SELECT * FROM tb1; +----+-------+------+ | id | name | age | +----+-------+------+ | 1 | tom | 10 | | 2 | jack | 20 | | 3 | jason | 30 | | 4 | lucky | 40 | +----+-------+------+
5、恢復
5.1、數據破壞
service mysqld stop rm -rf /mnt/mydata/data/* #把數據目錄數據全部刪除
對于xtrabackup做數據恢復的理解:
xtrabackup做數據恢復與mysqldump這樣的邏輯備份工作的恢復有很大的區別,xtrabackup進行數據恢復時需要把各個增量的數據備份與全備份的數據進行合并,
對每次增量備份的合并只能將已提交的事務進行重放(redo),對合備份的數據恢復也只能做redo操作,把各個增量都合并完成后再把沒有提交的事務進行回滾(undo)操作,
合并完增量備份后,全備份的“xtrabackup_checkpoints”文件中的“last_lsn”應該是最后一次增量備份時的值,這些合并做redo的過程就是恢復數據前的準備工作(prepare)。
而真正在做數據恢復,建議先把全備和增量備份的文件都copy一份為副本,避免操作失誤導致備份文件的損壞。
5.2、數據恢復的準備(prepare)工作
#準備全備份的數據 innobackupex --apply-log --redo-only /backup/fullbackup/2015-04-15_16-30-19/ #準備第一次增量數據 innobackupex --apply-log --redo-only /backup/fullbackup/2015-04-15_16-30-19/ --incremental-dir=/backup/incremental/2015-04-15_16-42-00/ #準備第二次增量數據 innobackupex --apply-log --redo-only /backup/fullbackup/2015-04-15_16-30-19/ --incremental-dir=/backup/incremental/2015-04-15_16-49-07/
cat /backup/fullbackup/2015-04-15_16-30-19/xtrabackup_checkpoints backup_type = full-prepared from_lsn = 0 to_lsn = 1645463 #這是最后一次增量備份的位置,到此數據已全部合并 last_lsn = 1645463 compact = 0
5.3、真正數據恢復
innobackupex --copy-back /backup/fullbackup/2015-04-15_16-30-19/ #僅一個“--copy-back”選項 ls /mnt/mydata/data/ ibdata1 mydb1 mysql performance_schema test chown -R mysql.mysql /mnt/mydata/data/ #修改恢復數據的屬主與屬組 service mysqld start Starting MySQL.. SUCCESS! mysql> SELECT * FROM mydb1.tb1; #檢查數據 +----+-------+------+ | id | name | age | +----+-------+------+ | 1 | tom | 10 | | 2 | jack | 20 | | 3 | jason | 30 | +----+-------+------+ #lucky信息還沒有恢復
5.4、利用二進制日志文件基于時間點恢復
查看最后一次增量備份時的二進制日志文件及position信息: cat /backup/incremental/2015-04-15_16-49-07/xtrabackup_binlog_info mysql-bin.000031 1665 mysqlbinlog --start-position=1665 /var/log/mysql_log/mysql-bin.000031 > /tmp/position.sql #用mysqlbinlog工具導出最后一次增量備份后的sql操作
導入數據: mysql> source /tmp/position.sql mysql> SELECT * FROM mydb1.tb1; +----+-------+------+ | id | name | age | +----+-------+------+ | 1 | tom | 10 | | 2 | jack | 20 | | 3 | jason | 30 | | 4 | lucky | 40 | +----+-------+------+ #數據全部恢復
6、總結
利用innobackupex工具可對在有混合存儲引擎的場景下對數據庫進行全備份,當是備份innodb表時innobackupex腳本內部會自動調用xtrabackup工具來進行備份操作,
在數據還原時應停止mysql實例,清空數據目錄,然后先做prepare準備工作,第二步才是真正的數據還原(–copy-back),數據還原到數據目錄后不要忘記修改數據目錄的權限。
當然innobackupex工具也能實現對單庫單表的導出、導出,如果是對Innodb表,那建議直接用xtrabackup工具,這樣更直觀的使用各個選項進行備份。
============================華麗分隔線(下面是重點)================================================
背景:在到第5.3步的時候,數據庫啟動失敗。why、what、fuck。說好的一條龍服務?
痛定思痛,上日志。
151216 11:16:20 mysqld_safe Starting mysqld daemon with databases from /data/mysql 151216 11:16:20 [Note] /usr/libexec/mysqld (mysqld 5.5.47-log) starting as process 2931 ... 151216 11:16:20 [Note] Plugin 'FEDERATED' is disabled. 151216 11:16:20 InnoDB: The InnoDB memory heap is disabled 151216 11:16:20 InnoDB: Mutexes and rw_locks use GCC atomic builtins 151216 11:16:20 InnoDB: Compressed tables use zlib 1.2.3 151216 11:16:20 InnoDB: Using Linux native AIO 151216 11:16:20 InnoDB: Initializing buffer pool, size = 128.0M 151216 11:16:20 InnoDB: Completed initialization of buffer pool InnoDB: Error: log file ./ib_logfile0 is of different size 0 50331648 bytes #這里是48M InnoDB: than specified in the .cnf file 0 5242880 bytes! #這里是5M 151216 11:16:20 [ERROR] Plugin 'InnoDB' init function returned error. 151216 11:16:20 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed. #注冊引擎失敗,打擊好大 151216 11:16:20 [ERROR] Unknown/unsupported storage engine: innodb #什么,又不支持innodb 151216 11:16:20 [ERROR] Aborting 151216 11:16:20 [Note] /usr/libexec/mysqld: Shutdown complete 151216 11:16:20 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
首先我刪除了恢復到/data/mysql目錄下面的ibdata1和ib_logfile0、ib_logfile1,此時可以啟動數據庫,然而提示表不存在。
向各位老師請教后,修改innodb_log_file_size=48M并寫入/etc/my.cnf,啟動正常。
總結:innodb_log_file_size參數屬于mysql系統參數,當配置不當時,mysql會啟動失敗。使用xtrabackup備份時默認值是5M,但是當遷移到新的環境后,初始化為48M,導致不匹配。后續應該將此參數寫入/etc/my.cnf防止遷移帶來的參數不匹配問題。
Command-Line Format | --innodb_log_file_size=# |
||
System Variable | Name | innodb_log_file_size |
|
Variable Scope | Global | ||
Dynamic Variable | No | ||
Permitted Values | Type | integer |
|
Default | 5242880 |
||
Min Value | 1048576 |
||
Max Value | 4GB / innodb_log_files_in_group |
The size in bytes of each log file in a log group. The combined size of log files (innodb_log_file_size
* innodb_log_files_in_group
) cannot exceed a maximum value that is slightly less than 4GB. A pair of 2047 MB log files, for example, would allow you to approach the range limit but not exceed it. The default value is 5MB. Sensible values range from 1MB to 1/N
-th of the size of the buffer pool, where N
is the number of log files in the group. The larger the value, the less checkpoint flush activity is needed in the buffer pool, saving disk I/O. Larger log files also make crash recovery slower, although improvements to recovery performance in MySQL 5.5 and higher make the log file size less of a consideration. For general I/O tuning advice,
具體參考:http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_log_file_size
原創文章,作者:陳近南,如若轉載,請注明出處:http://www.www58058.com/10139
非常不錯,久違的好博客,已置頂
我也發現innodb_log_file_size的問題了,哈哈。 這個坑貌似配過的都得踩一腳
樓主寫的十分詳細,線上如果出問題,不會有時間一步一步的這么去恢復的,都是通過腳本實現的;