小型網站MYSQL問題二:Percona Xtrabackup實現數據庫備份和恢復

故事背景:前面大膽的選擇了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

(1)
陳近南陳近南
上一篇 2015-12-19
下一篇 2015-12-19

相關推薦

  • linux分區管理工具—fdisk

    一、關于為什么要分區       (1)為了數據的安全:當文件系統只有一個分區時,如果遇到分區需要格式化的情況,則硬盤里的數據無法保留,而如果提前對硬盤做了分區那么就可以很好地額解決這個問題;       (2)為了提升效率:硬盤(這里單指機械硬盤)分為外圈和…

    Linux干貨 2016-03-12
  • SElinux管理

                                                      &nbsp…

    系統運維 2016-09-26
  • Java中的CopyOnWrite容器

    Copy-On-Write簡稱COW,是一種用于程序設計中的優化策略。其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才會真正把內容Copy出去形成一個新的內容然后再改,這是一種延時懶惰策略。從JDK1.5開始Java并發包里提供了兩個使用CopyOnWrite機制實現的并發容器,它們是CopyOnWriteArrayList和…

    Linux干貨 2016-08-15
  • centos6安裝docker

    使用的操作系統是是centos6.3,按照官方的推薦的配置,把linux內核升級到3.8以上。安裝步驟如下: 1、升級內核版本(包含aufs) cd /etc/yum.repos.d     wget http://www.hop5.in/yum/el6/hop5.repo   …

    Linux干貨 2016-05-05
  • PHP SOCKET編程

    1. 預備知識        一直以來很少看到有多少人使用php的socket模塊來做一些事情,大概大家都把它定位在腳本語言的范疇內吧,但是其實php的socket模塊可以做很多事情,包括做ftplist,http post提交,smtp提交,組包并進行特殊報文的交互(如smpp協議),whois查詢。這些都是比較常見…

    Linux干貨 2015-04-10
  • 如何在CentOS 6上安裝配置Samba

    Samba主要用于windows與Linux之間的文件共享,使用SMB/CIFS協議。CentOS 6默認安裝不包括samba軟件包,所以需要我們手動進行安裝。 Step 1 >> 安裝samba [root@localhost ~]# yum install samba -y Step 2 >> 創建一個共享用戶名和密碼 [root…

    Linux干貨 2016-03-22

評論列表(3條)

  • stanley
    stanley 2015-12-19 20:22

    非常不錯,久違的好博客,已置頂

  • 以馬內利
    以馬內利 2015-12-21 08:54

    我也發現innodb_log_file_size的問題了,哈哈。 這個坑貌似配過的都得踩一腳

  • bigwinner
    bigwinner 2016-04-14 11:05

    樓主寫的十分詳細,線上如果出問題,不會有時間一步一步的這么去恢復的,都是通過腳本實現的;

欧美性久久久久