MySQL數據庫備份與恢復


MySQL數據庫備份與恢復

數據備份介紹

在生產環境中我們數據庫可能會遭遇各種各樣的不測從而導致數據丟失, 大概分為以下幾種.

  • 硬件故障

  • 軟件故障

  • 自然災害

  • 黑客攻擊

  • 誤操作 (占比最大)

須知在生產環境中,服務器的硬件壞了可以維修或者換新,軟件崩潰可以修復或重新安裝, 但是如果數據沒了那可就毀了,生產環境中最重要的應該就是數據了。所以, 為了在數據丟失之后能夠恢復數據, 我們就需要定期的備份數據。

備份什么

一般情況下, 我們需要備份的數據分為以下幾種

  • 二進制日志, InnoDB事務日志

  • 代碼(存儲過程、存儲函數、觸發器、事件調度器)

  • 服務器配置文件

備份的類型

按照備份時數據庫的運行狀態,可以分為三種,分別是:冷備、溫備、熱備。、

  • 冷備:停庫、停服務來備份,即當數據庫進行備份時, 數據庫不能進行讀寫操作, 即數據庫要下線。

  • 溫備:不停庫、不停服務來備份,會(鎖表)阻止用戶的寫入,即當數據庫進行備份時, 數據庫的讀操作可以執行, 但是不能執行寫操作 。

  • 熱備:不停庫、不停服務來備份,也不會(鎖表)阻止用戶的寫入 即當數據庫進行備份時, 數據庫的讀寫操作均不是受影響 。

MySQL中進行不同類型的備份還要考慮存儲引擎是否支持?

存儲引擎 冷備 溫備 熱備
InnoDB 支持 支持 支持
MyISAM 支持 支持 不支持

邏輯備份與物理備份

按照備份的內容分,可以分為兩種,分別是邏輯備份與物理備份

  • 1、物理備份:直接將底層物理文件備份
  • 2、邏輯備份:通過特定的工具從數據庫中導出sql語句或者數據,可能會丟失數據精度

備份方式之全量、差異、增量

按照每次備份的數據量,可以分為全量備份、差異備份以及增量備份。

  • 全量備份/完全備份(Full Backup):備份整個數據集( 即整個數據庫 )

  • 部分備份:備份部分數據集(例如: 只備份一個表的變化)

    • 差異備份
      • 增量備份
# 1、差異備份(Differential Backup)
每次備份時,都是基於第一次完全備份的內容,只備份有差異的數據(新增的、修改的、刪除的),例如

第一次備份:完全備份
第二次備份:以當前時間節點的數據為基礎,備份與第一次備份內容的差異
第三次備份:以當前時間節點的數據為基礎,備份與第一次備份內容的差異
第四次備份:以當前時間節點的數據為基礎,備份與第一次備份內容的差異
第五次備份:以當前時間節點的數據為基礎,備份與第一次備份內容的差異
。。。

# 2、增量備份(Incremental Backup )
每次備份時,都是基於上一次備份的內容(注意是上一次,而不是第一次),只備份有差異的數據(新增的、修改的、刪除的),所以增量備份的結果是一條鏈,例如

第一次備份:完全備份
第二次備份:以當前時間節點的數據為基礎,備份與第一次備份內容的差異
第三次備份:以當前時間節點的數據為基礎,備份與第二次備份內容的差異
第四次備份:以當前時間節點的數據為基礎,備份與第三次備份內容的差異
第五次備份:以當前時間節點的數據為基礎,備份與第四次備份內容的差異
。。。

針對上述三種備份方案,如何恢復數據呢?

# 1、全量備份的數據恢復
只需找出指定時間點的那一個備份文件即可,即只需要找到一個文件即可

# 2、差異備份的數據恢復
需要先恢復第一次備份的結果,然后再恢復最近一次差異備份的結果,即需要找到兩個文件

# 3、增量備份的數據恢復
需要先恢復第一次備份的結果,然后再依次恢復每次增量備份,直到恢復到當前位置,即需要找到一條備份鏈

綜上,對比三種備份方案
1、占用空間:全量 > 差異 > 增量
2、恢復數據過程的復雜程度:增量 > 差異 > 全量

備份的工具

備份工具 備份速度 恢復速度 便捷性 適用存儲引擎 支持的備份類型 功能 應用場景
cp、tar等(物理) 一般 所有 冷備、全量、差異、增量 很弱 少量數據備份
lvm2快照(物理) 一般 所有 支持幾乎熱備(即差不多是熱備,哈哈),是借助文件系統管理工具進行的備份 一般 中小型數據量的備份
xtrabackup(物理) 較快 較快 是一款非常強大的熱備工具 由percona提供,只支持InnoDB/XtraDB 熱備、全量、差異、增量 強大 較大規模的備份
mysqldump(邏輯) 一般 所有 支持溫備、完全備份、部分備份、對於InnoDB存儲引擎支持熱備 一般 中小型數據量的備份

此外,如果考慮到增量備份,還需要結合binlog日志(binlog只屬於增量恢復),需要用到工具mysqlbinlog,相當於邏輯備份的一種。

備份實戰

下面我們采用多種方法實戰MySQL數據備份實戰。

使用cp進行備份

mysql> FLUSH TABLES WITH READ LOCK; 
Query OK, 0 rows affected (0.00 sec)

[root@localhost ~]# mkdir /data
[root@localhost ~]# cp -a /usr/local/mysql-5.7.34/data/* /data/

模擬數據丟失

[root@localhost ~]# mv /usr/local/mysql-5.7.34/data .

數據恢復

[root@localhost ~]# mkdir /usr/local/mysql-5.7.34/data
[root@localhost ~]# chown mysql.mysql /usr/local/mysql-5.7.34/data
[root@localhost ~]# cp -a /data/* /usr/local/mysql-5.7.34/data/
[root@localhost ~]# systemctl restart mysqld
[root@localhost ~]# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.34-log Source distribution

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

使用mysqldump

MySQL數據庫自帶的一個很好用的備份命令。是邏輯備份,導出 的是SQL語句。也就是把數據MySQL庫中以邏輯的SQL語句的形式直接輸出或生成備份的文件的過程。

語法

mysqldump  -h 服務器  -u用戶名  -p密碼  選項與參數 > 備份文件.sql

參數

參數 解釋
-A --all-databases 導出全部數據庫
-Y --all-tablespaces 導出全部表空間
--add-drop-database 每個數據庫創建之前添加drop數據庫語句。
--add-drop-table 每個數據表創建之前添加drop數據表語句。(默認為打開狀態,使用--skip-add-drop-table取消選項)
--add-locks 在每個表導出之前增加LOCK TABLES並且之后UNLOCK TABLE。(默認為打開狀態,使用--skip-add-locks取消選項)
--comments 附加注釋信息。默認為打開,可以用--skip-comments取消
--compact 導出更少的輸出信息(用於調試)。去掉注釋和頭尾等結構。可以使用選項:--skip-add-drop-table --skip-add-locks --skip-comments --skip-disable-keys
-c --complete-insert 使用完整的insert語句(包含列名稱)。這么做能提高插入效率,但是可能會受到max_allowed_packet參數的影響而導致插入失敗。
-C --compress 在客戶端和服務器之間啟用壓縮傳遞所有信息
-B --databases 導出幾個數據庫。參數后面所有名字參量都被看作數據庫名。
--debug 輸出debug信息,用於調試。
--debug-info 輸出調試信息並退出
--default-character-set 設置默認字符集,默認值為utf8
--delayed-insert 采用延時插入方式(INSERT DELAYED)導出數據
-E --events 導出事件。
--master-data 在備份文件中寫入備份時的binlog文件。值為1時,binlog文件名和位置沒有注釋,為2時,則在備份文件中將binlog的文件名和位置進行注釋。
--flush-logs 開始導出之前刷新日志。請注意:假如一次導出多個數據庫(使用選項--databases或者--all-databases),將會逐個數據庫刷新日志。除使用--lock-all-tables或者--master-data外。在這種情況下,日志將會被刷新一次,相應的所以表同時被鎖定。因此,如果打算同時導出和刷新日志應該使用--lock-all-tables 或者--master-data 和--flush-logs。
--flush-privileges 在導出mysql數據庫之后,發出一條FLUSH PRIVILEGES 語句。為了正確恢復,該選項應該用於導出mysql數據庫和依賴mysql數據庫數據的任何時候。
--force 在導出過程中忽略出現的SQL錯誤。
-h --host 需要導出的主機信息
--ignore-table 不導出指定表。指定忽略多個表時,需要重復多次,每次一個表。每個表必須同時指定數據庫和表名。例如:--ignore-table=database.table1 --ignore-table=database.table2 ……
-x --lock-all-tables 提交請求鎖定所有數據庫中的所有表,以保證數據的一致性。這是一個全局讀鎖,並且自動關閉--single-transaction 和--lock-tables 選項。
-l --lock-tables 開始導出前,鎖定所有表。用READ LOCAL鎖定表以允許MyISAM表並行插入。對於支持事務的表例如InnoDB和BDB,--single-transaction是一個更好的選擇,因為它根本不需要鎖定表。請注意當導出多個數據庫時,--lock-tables分別為每個數據庫鎖定表。因此,該選項不能保證導出文件中的表在數據庫之間的邏輯一致性。不同數據庫表的導出狀態可以完全不同。
--single-transaction 適合innodb事務數據庫的備份。保證備份的一致性,原理是設定本次會話的隔離級別為Repeatable read,來保證本次會話(也就是dump)時,不會看到其它會話已經提交了的數據。
-F 刷新binlog,如果binlog打開了,-F參數會在備份時自動刷新binlog進行切換。
-n --no-create-db 只導出數據,而不添加CREATE DATABASE 語句。
-t --no-create-info 只導出數據,而不添加CREATE TABLE 語句。
-d --no-data 不導出任何數據,只導出數據庫表結構。
-p --password 連接數據庫密碼
-P --port 連接數據庫端口號
-u --user 指定連接的用戶名。
-R 備份存儲過程和函數數據(如果開發寫了函數和存儲過程,就備,沒寫就不備)
--triggers 備份觸發器數據(現在都是開發寫觸發器)

案例

# 在命令行執行命令,進行全量備份
[root@localhost mysql]# mysqldump -uroot -p123456 -A -R --triggers --master-data=2 --single-transaction | gzip > /tmp/full.sql.gz
mysqldump: [Warning] Using a password on the command line interface can be insecure.
[root@localhost mysql]# ll /tmp/full.sql.gz 
-rw-r--r--. 1 root root 191963 Oct 14 00:01 /tmp/full.sql.gz

# 在命令行執行命令,刷新binlog,便於日后查找
[root@localhost mysql]# mysql -uroot -p123456 -e "flush logs"
mysql: [Warning] Using a password on the command line interface can be insecure.

# 登錄數據庫,再插入一些數據,模擬增量,這些數據寫入了新的binlog
mysql> insert t1 values(4),(5),(6);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0


# 案例2:要求每天凌晨3點半的時候,做數據庫備份

1、編寫腳本
[root@localhost ~]# cat mysqldump.sh 
#!/bin/bash

USERNAME=root
PASSWORD=123456
DATABASE=linux14

/usr/local/mysql/bin/mysqldump -u${USERNAME} -p${PASSWORD} -R --triggers -B ${DATABASE} --master-data=2 --single-transaction  | gzip > /tmp/MySQL_`date +"%F".sql.gz`


2、加入定時任務
30 03 * * *  /root/mysqldump.sh

模擬數據丟失

# 模擬數據丟失
mysql> drop database db1;

# 恢復數據
# 1、mysql數據導入時,臨時關閉binlog,不要將恢復數據的寫操作也記入
mysql> set sql_log_bin=0;

# 2、先恢復全量
mysql> source /tmp/MySQL_2021-10-15.sql

如果是壓縮包呢,那就這么做
mysql> system zcat /tmp/MySQL_2021-10-15.sql.gz | mysql -uroot -p123456

# 3、模擬恢復數據
mysql> drop database db01;
Query OK, 1 row affected (0.01 sec)

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> system zcat /tmp/MySQL_2021-10-15.sql.gz | mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
mysql> use db01;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from t1;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

測試在線熱備份

可以先准備一個存儲過程,一直保持寫入操作,然后驗證熱備。

#1. 准備庫與表
create database if not exists db01;
use db01;
create table s1(
  id int,
  name varchar(20),
  gender char(6),
  email varchar(50)
);

#2. 創建存儲過程,每隔3秒插入一條
delimiter $$
create procedure auto_insert1()
BEGIN
    declare i int default 1;
    while(i<3000000)do
        insert into s1 values(i,'shanhe','male',concat('shanhe',i,'@oldboy'));
     select concat('shanhe',i,'_ok') as name,sleep(3);
  set i=i+1;
    end while;
END$$
delimiter ;

#3. 查看存儲過程
show create procedure auto_insert1\G 

備份

# 1、先打開binlog日志
mysql> SET sql_log_bin=ON; 
Query OK, 0 rows affected (0.00 sec)

# 2、登錄數據庫,執行存儲過程
mysql> use db01;
mysql> call auto_insert1();

若想殺死存儲過程
mysql> show processlist; -- 查出id
mysql> kill id號;


# 3、在命令行執行下述命令,進行全量備份
[root@localhost mysql]# mysqldump -uroot -p123456  -A -R --triggers --master-data=2 --single-transaction | gzip > /tmp/full.sql.gz 
mysqldump: [Warning] Using a password on the command line interface can be insecure.

# 4、全量備份完畢后的一段時間里,數據依然插入,寫入了mybinlog.000001中
#    然后我們在命令行刷新binlog,產生了新的mybinlog.000002
[root@localhost mysql]# mysql -uroot -p123456 -e "flush logs"
mysql: [Warning] Using a password on the command line interface can be insecure.

# 5、此時數據依然在插入,但都寫入了最新的mybinlog.000002中,所以需要知道的是,增量的數據在mysqlbinlog.000001與mybinlog.000002中都有
我們登錄數據庫,殺掉存儲過程,觀察到最新的數據插到了id=55的行
mysql> show processlist; -- 查出id
mysql> kill id號;

刪除數據

mysql> drop database db01;
Query OK, 1 row affected (0.12 sec)

恢復數據

# 登錄數據庫,先恢復全量
mysql> set sql_log_bin=0;
mysql> system zcat /tmp/full.sql.gz | mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.

-- 查看恢復到了id = 16
mysql> select * from db01.s1;
+------+--------+--------+-----------------+
| id   | name   | gender | email           |
+------+--------+--------+-----------------+
|    1 | shanhe | male   | shanhe1@oldboy  |
|    2 | shanhe | male   | shanhe2@oldboy  |
|    3 | shanhe | male   | shanhe3@oldboy  |
|    4 | shanhe | male   | shanhe4@oldboy  |
|    5 | shanhe | male   | shanhe5@oldboy  |
|    6 | shanhe | male   | shanhe6@oldboy  |
|    7 | shanhe | male   | shanhe7@oldboy  |
|    8 | shanhe | male   | shanhe8@oldboy  |
|    9 | shanhe | male   | shanhe9@oldboy  |
|   10 | shanhe | male   | shanhe10@oldboy |
|   11 | shanhe | male   | shanhe11@oldboy |
|   12 | shanhe | male   | shanhe12@oldboy |
|   13 | shanhe | male   | shanhe13@oldboy |
|   14 | shanhe | male   | shanhe14@oldboy |
|   15 | shanhe | male   | shanhe15@oldboy |
|   16 | shanhe | male   | shanhe16@oldboy |
+------+--------+--------+-----------------+
16 rows in set (0.00 sec)

物理備份之Xtrabackup

Xtrabackup 是一個對 InnoDB 做數據備份的工具,據官方介紹,這也是世界上惟一一款開源的能夠對innodb和xtradb數據庫進行熱備的工具;支持在線熱備份(備份時不影響數據讀寫),是商業備份工具 InnoDB Hotbackup 的一個很好的替代品。

官方文檔:http://www.percona.com/doc/percona-xtrabackup/2.1/

Xtrabackup有兩個主要的工具:

    1. xtrabackup只能備份InnoDB和XtraDB兩種數據表,而不能備份MyISAM數據表。
    2. innobackupex 是參考了 InnoDB Hotbackup 的 innoback 腳本修改而來的.innobackupex 是一個 perl 腳本封裝,封裝了 xtrabackup。主要 是為了方便的同時備份InnoDB和MyISAM引擎的表,但在處理myisam時需要加一個讀鎖。並且加入了一些使用的選項。如slave-info可以記錄備份 恢復后,作為slave需要的一些信息,根據這些信息,可以很方便的利用備份來重做slave。

Xtrabackup可以做些做什么?

在線(熱)備份整個庫的InnoDB、 XtraDB表 。

在xtrabackup的上一次整庫備份基礎上做增量備份(innodb only) ,以流的形式產生備份,可以直接保存到遠程機器上(本機硬盤空間不足時很有用) 。

MySQL數據庫本身提供的工具並不支持真正的增量備份,二進制日志恢復是point-in-time(時間點)的恢復而不是增量備份。

Xtrabackup工具支持

對InnoDB存儲引擎的增量備份,工作原理如下:

    1. 首先完成一個完全備份,並記錄下此時檢查點的LSN(Log Sequence Number)。
    2. 在進程增量備份時,比較表空間中每個頁的LSN是否大於上次備份時的LSN,如果是,則備份該頁,同時記錄當前檢查點的LSN。

首先,在 logfile 中找到並記錄最后一個 checkpoint(“last checkpoint LSN”),然后開始從 LSN 的位置開始拷貝 InnoDB 的 logfile 到xtrabackup_logfile;接着,開始拷貝全部的數據文件.ibd;在拷貝全部數據文件結束之后,才停止拷貝logfile。 因為logfile里面記錄全部的數據修改情況,所以,即時在備份過程中數據文件被修改過了,恢復時仍然能夠通過解析xtrabackup_logfile保持數據的一致。

XtraBackup備份的優點

個人理解

    1. 無需停止數據庫進行InnoDB熱備,快速、可靠的完成備份
    2. 備份期間不間斷事務處理
    1. 節省磁盤空間和網絡帶寬
    2. 自動對備份文件進行驗證
    1. 快速恢復,保障在線運行時間持久性

官方說明

  1. 在不停庫的情況下,對InnoDB數據庫進行熱備
  2. 支持增量備份MySQL數據庫
  3. 通過流壓縮備份MySQL數據到另外一台服務器
  4. 在線MySQL服務器之間進行表空間遷移

Xtrabackup的備份原理圖

  1. innobackupex啟動后,會先fork一個進程,用於啟動xtrabackup,然后等待xtrabackup備份ibd數據文件

  2. xtrabackup在備份innoDB數據是,有2種線程:redo拷貝線程和ibd數據拷貝線程。xtrabackup進程開始執行后,會啟動一個redo拷貝的線程,用於從最新的checkpoint點開始順序拷貝redo.log

  3. 再啟動ibd數據拷貝線程,進行拷貝ibd數據。這里是先啟動redo拷貝線程的。在此階段,innobackupex進行處於等待狀態(等待文件被創建)

  4. xtrabackup拷貝完成ibd數據文件后,會通知innobackupex(通過創建文件),同時xtrabackup進入等待狀態(redo線程依舊在拷貝redo.log)

  5. innobackupex收到xtrabackup通知后哦,執行FLUSH TABLES WITH READ LOCK(FTWRL),取得一致性位點,然后開始備份非InnoDB文件(如frm、MYD、MYI、CSV、opt、par等格式的文件),在拷貝非InnoDB文件的過程當中,數據庫處於全局只讀狀態。

  6. 當innobackup拷貝完所有的非InnoDB文件后,會通知xtrabackup,通知完成后,進入等待狀態

  7. xtrabackup收到innobackupex備份完成的通知后,會停止redo拷貝線程,然后通知innobackupex,redo.log文件拷貝完成

  8. innobackupex收到redo.log備份完成后,就進行解鎖操作,執行:UNLOCK TABLES

  9. 最后innbackupex和xtrabackup進程各自釋放資源,寫備份元數據信息等,innobackupex等xtrabackup子進程結束后退出。

Xtrabackup 安裝

mysql 5.7以下版本,可以采用percona xtrabackup 2.4版本。

mysql 8.0以上版本,可以采用percona xtrabackup 8.0版本,xtrabackup8.0也只支持mysql8.0以上的版本。

比如,接觸過一些金融行業,mysql版本還是多采用mysql 5.7,當然oracle官方對於mysql 8.0的開發支持力度日益加大,新功能新特性迭代不止。生產環境采用mysql 8.0的版本比例會日益增加。

下載地址:https://www.percona.com/downloads/

# 安裝方式一

# 安裝yum倉庫
[root@localhost ~]# yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm -y

# 安裝XtraBackup命令
[root@localhost ~]# yum install percona-xtrabackup-24 -y


# 安裝方式二
#下載epel源
[root@localhost ~]# wget -O /etc/yum.repos.d/epel.repo  https://mirrors.aliyun.com/repo/epel-7.repo

#安裝依賴
[root@localhost ~]# yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL

#下載Xtrabackup
[root@localhost ~]# wget https://downloads.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.24/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.24-1.el7.x86_64.rpm

# 安裝
[root@localhost ~]# yum localinstall -y percona-xtrabackup-24-2.4.24-1.el7.x86_64.rpm

安裝完后會生成命令

xtrabackup      以前使用該命令
innobackupex    現在使用該命令

innobackupex是xtrabackup的前端配置工具,使用innobackupex備份時, 會調用xtrabackup備份所有的InnoDB表, 復制所有關於表結構定義的相關文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相關文件, 同時還會備份觸發器和數據庫配置文件信息相關的文件, 這些文件會被保存至一個以時間命名的目錄。

Xtrabackup 備份方式(物理備份)

1.對於非innodb表(比如myisam)是直接鎖表cp數據文件,屬於一種溫備。

2.對於innodb的表(支持事務),不鎖表,cp數據頁最終以數據文件方式保存下來,並且把redo和undo一並備走,屬於熱備方式。

3.備份時讀取配置文件/etc/my.cnf

Xtrabackup 參數說明

--host     								指定主機
--user     								指定用戶名
--password    						指定密碼
--port    								指定端口
--databases     					指定數據庫
--incremental    					創建增量備份
--incremental-basedir   	指定包含完全備份的目錄
--incremental-dir      		指定包含增量備份的目錄   
--apply-log        				對備份進行預處理操作。一般情況下,在備份完成后,數據尚且不能用於恢復操作,因為備份的數據中可能會包含尚未提交的事務或已經提交但尚未同步至數據文件中的事務。因此,此時數據文件仍處理不一致狀態。“准備”的主要作用正是通過回滾未提交的事務及同步已經提交的事務至數據文件也使得數據文件處於一致性狀態。
--redo-only      					不回滾未提交事務
--copy-back     					恢復備份目錄

Xtrabackup全量備份與恢復

使用innobackupex備份時,其會調用xtrabackup備份所有的InnoDB表,復制所有關於表結構定義的相關文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相關文件,同時還會備份觸發器和數據庫配置信息相關的文件,這些文件會被保存到一個以時間命名的目錄當中。

#1、創建備份目錄,會把mysql的datadir中的內容備份到改目錄中
[root@localhost ~]# mkdir /backup

#2、全備
#2.1 在本地執行下述命令,輸入登錄數據的本地賬號與密碼
#2.2 指定備份目錄為/backup下的full目錄
[root@localhost ~]# innobackupex --user=root  --password=123456 /backup/full

#3、查看:默認會在備份目錄下生成一個以時間戳命名的文件夾
[root@localhost ~]# cd /backup/full/
[root@localhost full]# ls
2021-10-14_22-39-02
[root@localhost full]# ls 2021-10-14_22-39-02 #備份目錄
。。。
[root@localhost full]# ls /var/lib/mysql # 數據目錄
。。。

# 4、去掉時間戳,讓備份數據直接放在備份目錄下
我們在寫備份腳本和恢復腳本,恢復的時候必須指定上一次備份的目錄,如果備份目錄帶着時間戳,該時間戳我們很難在腳本中確定,無為了讓腳本編寫更加方便,我們可以使用選項--no-timestamp去掉時間戳,讓備份內容直接放置於我們指定的目錄下(ps:金融公司喜歡每天全備,每小時增備,如果備份目錄帶着時間戳,看似合理,但確實會很讓頭疼)
[root@localhost full]# rm -rf 2021-10-14_22-39-02
[root@localhost backup]# innobackupex --user=root --password=123456 --no-timestamp /backup/full

[root@localhost backup]# ll /backup/full/
total 12340
-rw-r-----. 1 root root      487 Oct 14 22:42 backup-my.cnf
drwxr-x---. 2 root root       48 Oct 14 22:42 db01
drwxr-x---. 2 root root       48 Oct 14 22:42 db02
-rw-r-----. 1 root root      646 Oct 14 22:42 ib_buffer_pool
-rw-r-----. 1 root root 12582912 Oct 14 22:42 ibdata1
drwxr-x---. 2 root root     4096 Oct 14 22:42 mysql
drwxr-x---. 2 root root     8192 Oct 14 22:42 performance_schema
drwxr-x---. 2 root root     8192 Oct 14 22:42 sys
-rw-r-----. 1 root root       20 Oct 14 22:42 xtrabackup_binlog_info
-rw-r-----. 1 root root      135 Oct 14 22:42 xtrabackup_checkpoints
-rw-r-----. 1 root root      484 Oct 14 22:42 xtrabackup_info
-rw-r-----. 1 root root     2560 Oct 14 22:42 xtrabackup_logfile


# 如果要使用一個最小權限的用戶進行備份,則可基於如下命令創建此類用戶:
mysql> CREATE USER 'bkpuser'@'localhost' IDENTIFIED BY '123456';  #創建用戶
mysql> REVOKE ALL PRIVILEGES,GRANT OPTION FROM 'bkpuser';  #回收此用戶所有權限
mysql> GRANT RELOAD,LOCK TABLES,RELICATION CLIENT ON *.* TO 'bkpuser'@'localhost';  #授權刷新、鎖定表、用戶查看服務器狀態
mysql> FLUSH PRIVILEGES;  #刷新授權表

實戰

1、全量備份
[root@master backups]# innobackupex --user=root --password=123456 --host=127.0.0.1 /backups/  
#在master上進行全庫備份#語法解釋說明:
#--user=root 指定備份用戶
#--password=123456  指定備份用戶密碼
#--host  指定主機
#/backups  指定備份目錄

2、恢復
[root@slave tools]# innobackupex --apply-log /backups/2021-10-14_11-01-37/   #合並數據,使數據文件處於一致性的狀態
[root@slave ~]# rm -rf /usr/local/mysql/data/  #在slave上刪除原有的數據
[root@slave ~]# vim /etc/my.cnf  #配置my.cnf的數據目錄路徑,否則會報錯,要和master一致
datadir=/usr/local/mysql/data
[root@slave ~]# innobackupex --copy-back /backups/2021-10-14_11-01-37/  #在slave上數據恢復
[root@slave ~]# ll /usr/local/mysql/data/  #slave上查看數據目錄,可以看到數據已經恢復,但是屬主會有問題,需要進行修改,所以一般使用mysql的運行用戶進行恢復,否則需要進行修改屬主和屬組信息
[root@slave ~]# chown -R mysql.mysql /usr/local/mysql/data/  #修改屬主屬組
[root@slave ~]# mysql -uroot -p -e "show databases;"  #查看數據,是否恢復

總結全庫備份與恢復三步曲:

  1. innobackupex全量備份,並指定備份目錄路徑。

  2. 在恢復前,需要使用--apply-log參數先進行合並數據文件,確保數據的一致性要求。

  3. 恢復時,直接使用--copy-back參數進行恢復,需要注意的是,在my.cnf中要指定數據文件目錄的路徑。

Xtrabackup增量備份與恢復

使用innobackupex進行增量備份,每個InnoDB的頁面都會包含一個LSN信息,每當相關的數據發生改變,相關的頁面的LSN就會自動增長。這正是InnoDB表可以進行增量備份的基礎,即innobackupex通過備份上次完全備份之后發生改變的頁面來實現。在進行增量備份時,首先要進行一次全量備份,第一次增量備份是基於全備的,之后的增量備份都是基於上一次的增量備份的,以此類推。

要實現第一次增量備份,可以使用下面的命令進行:

基於全量備份的增量備份與恢復,做一次增量備份(基於當前最新的全量備份)

--incremental    					創建增量備份
--incremental-basedir   	指定包含完全備份的目錄
--incremental-dir      		指定包含增量備份的目錄 



innobackupex --user=root --password=root --defaults-file=/etc/my.cnf --incremental /backups/ --incremental-basedir=/backups/2021-10-14_22-39-02

1. 准備基於全量
innobackupex --user=root --password=root --defaults-file=/etc/my.cnf --apply-log --redo-only /backups/2021-10-14_22-39-02

2. 准備基於增量
innobackupex --user=root --password=root --defaults-file=/etc/my.cnf --apply-log --redo-only /backups/2018-07-30_11-01-37 --incremental-dir=/backups/2021-10-14_22-39-02

3. 恢復
innobackupex --copy-back --defaults-file=/etc/my.cnf /opt/2021-10-14_22-39-02

需要注意的是,增量備份僅能應用於InnoDB或XtraDB表,對於MyISAM表而言,執行增量備份時其實進行的是完全備份。

案例

1、備份數據
[root@master backups]# innobackupex --user=root --password=123456 --host=127.0.0.1 /backups/   #全備數據
[root@master ~]# mysql -uroot -p  #在master上創建student庫並創建testtb表插入若干數據
Enter password: 
mysql> create database student;
Query OK, 1 row affected (0.03 sec)

mysql> use student;
Database changed
mysql> create table testtb(id int);
Query OK, 0 rows affected (0.07 sec)

mysql> insert into testtb values(1),(10),(99);
Query OK, 3 rows affected (0.04 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from testtb;
+------+
| id   |
+------+
|    1 |
|   10 |
|   99 |
+------+
3 rows in set (0.00 sec)

mysql> quit;



#使用innobackupex進行增量備份
[root@master backups]# innobackupex --user=root --password=123456 --host=127.0.0.1 --incremental /backups/ --incremental-basedir=/backups/2021-10-15_11-01-37/
[root@localhost 2021-10-15_17-10-01]# cat xtrabackup_info 
innodb_from_lsn = 0							# 備份開始的ID
innodb_to_lsn = 998385358				# 全量備份結束的ID
[root@localhost 2021-10-15_17-10-01]# cat /backup/full3/2021-10-15_17-14-04/xtrabackup_info 
innodb_from_lsn = 998385358		# 增量備份開始的ID
innodb_to_lsn = 998388146			# 增量備份結束的ID

2、增量備份后數據恢復演示
(1)模擬mysql故障,刪除數據目錄所有數據
[root@master ~]# /etc/init.d/mysqld stop  #模擬mysql故障,停止mysql
Shutting down MySQL.. SUCCESS! 
[root@master ~]# rm -rf /usr/local/mysql/data/*  #刪除數據目錄中的所有數據
(2)合並全備數據目錄,確保數據的一致性
[root@master ~]# innobackupex --apply-log --redo-only /backups/2021-10-15_11-01-37/
(3)將增量備份數據合並到全備數據目錄當中
[root@master ~]# innobackupex --apply-log --redo-only /backups/2021-10-15_11-01-37/ --incremental-dir=/backups/2021-10-15_13-51-47/
(4)恢復數據
[root@master ~]# innobackupex --copy-back /backups/2021-10-15_11-01-37/

[root@master ~]# chown -R mysql.mysql /usr/local/mysql/data  #更改數據的屬主屬組
[root@master ~]# /etc/init.d/mysqld start  #啟動mysql
Starting MySQL.Logging to '/usr/local/mysql/data/master.err'.
.. SUCCESS! 
[root@master ~]# mysql -uroot -p -e "show databases;"  #查看數據是否恢復
Enter password: 
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kim                |
| mysql              |
| performance_schema |
| repppp             |
| student            |
| wordpress          |
+--------------------+

總結

  1. 增量備份需要使用參數--incremental指定需要備份到哪個目錄,使用incremental-dir指定全備目錄。

  2. 進行數據備份時,需要使用參數--apply-log redo-only先合並全備數據目錄數據,確保全備數據目錄數據的一致性。

  3. 再將增量備份數據使用參數--incremental-dir合並到全備數據當中

  4. 最后通過最后的全備數據進行恢復數據。

注意:如果有多個增量備份,需要逐一合並到全備數據當中,再進行恢復。

數據的快速導入與導出

在公司中,如果運營或者產品手里有幾千萬甚至幾億條數據,要求你將其導入數據中,請問如何做?

如果你依據運營或產品交給你的數據文件直接使用insert語句,一行一行地批量插入,那至少需要1-2天時間才能插入完畢,顯然是不可行的。

此時我們可以用LOAD DATA INFILE語句。LOAD DATA INFILE語句可以從一個文本文件中,將數據以很高的速度讀入一個表中。MySQL官方文檔也說明了,該方法比一次性插入一條數據性能快20倍。

此外,mysql也支持快速導出語句SELECT INTO OUTFILE,使用MySQL的SELECT INTO OUTFILE 、LOAD DATA INFILE快速導出導入數據,12G的數據導出用時3分鍾左右,導入用時4分鍾左右(執行時間根據機器的配置會有所不同,不具有參考價值)。

快速導入與導出的語法

  • 快速導出
語法:
SELECT... INTO OUTFILE 導出文本文件

要想導出成功,需要設置安全目錄才行
vim /etc/my.cnf
[mysqld]
secure-file-priv=/tmp

示例:
SELECT * FROM db1.t1
    INTO OUTFILE '/tmp/db1_t1.txt'
    FIELDS TERMINATED BY ','      -- 定義字段分隔符
    OPTIONALLY ENCLOSED BY '"'    -- 定義字符串使用什么符號括起來
    LINES TERMINATED BY '\n';     -- 定義換行符
  • 快速導入
語法
LOAD DATA INFILE 導入的文本文件路徑

示例
mysql> DELETE FROM student1;
mysql> create table new_t1(表結構與文件中數據保持一致);
mysql> LOAD DATA INFILE '/tmp/db1_t1.txt'
            INTO TABLE new_db.new_t1
            FIELDS TERMINATED BY ','
            OPTIONALLY ENCLOSED BY '"'
            LINES TERMINATED BY '\n';

數據庫遷移

數據庫遷移是我們經常可遇到的問題,對於少量的數據,遷移基本上不會有什么問題。生產環境中,有以下情況需要做遷移工作:

  1. 磁盤空間不夠比如一些老項目,選用的機型並不一定適用於數據庫。隨着時間的推移,硬盤很有可能出現短缺。

  2. 業務出現瓶頸比如項目中采用單機承擔所有的讀寫業務,業務壓力增大,不堪重負。如果 IO 壓力在可接受的范圍,會采用讀寫分離方案。

  3. 機器出現瓶頸機器出現瓶頸主要在磁盤 IO 能力、內存、CPU,此時除了針對瓶頸做一些優化以外,選擇遷移是不錯的方案。

  4. 項目改造某些項目的數據庫存在跨機房的情況,可能會在不同機房中增加節點,或者把機器從一個機房遷移到另一個機房。再比如,不同業務共用同一台服務器,為了緩解服務器壓力以及方便維護,也會做遷移。

附錄:參數

--compress:該選項表示壓縮innodb數據文件的備份。
--compress-threads:該選項表示並行壓縮worker線程的數量。
--compress-chunk-size:該選項表示每個壓縮線程worker buffer的大小,單位是字節,默認是64K。
--encrypt:該選項表示通過ENCRYPTION_ALGORITHM的算法加密innodb數據文件的備份,目前支持的算法有ASE128,AES192,AES256。
--encrypt-threads:該選項表示並行加密的worker線程數量。
--encrypt-chunk-size:該選項表示每個加密線程worker buffer的大小,單位是字節,默認是64K。
--encrypt-key:該選項使用合適長度加密key,因為會記錄到命令行,所以不推薦使用。
--encryption-key-file:該選項表示文件必須是一個簡單二進制或者文本文件,加密key可通過以下命令行命令生成:openssl rand -base64 24。
--include:該選項表示使用正則表達式匹配表的名字[db.tb],要求為其指定匹配要備份的表的完整名稱,即databasename.tablename。
--user:該選項表示備份賬號。
--password:該選項表示備份的密碼。
--port:該選項表示備份數據庫的端口。
--host:該選項表示備份數據庫的地址。
--databases:該選項接受的參數為數據名,如果要指定多個數據庫,彼此間需要以空格隔開;如:"xtra_test dba_test",同時,在指定某數據庫時,也可以只指定其中的某張表。如:"mydatabase.mytable"。該選項對innodb引擎表無效,還是會備份所有innodb表。此外,此選項也可以接受一個文件為參數,文件中每一行為一個要備份的對象。
--tables-file:該選項表示指定含有表列表的文件,格式為database.table,該選項直接傳給--tables-file。
--socket:該選項表示mysql.sock所在位置,以便備份進程登錄mysql。
--no-timestamp:該選項可以表示不要創建一個時間戳目錄來存儲備份,指定到自己想要的備份文件夾。
--ibbackup:該選項指定了使用哪個xtrabackup二進制程序。IBBACKUP-BINARY是運行percona xtrabackup的命令。這個選項適用於xtrbackup二進制不在你是搜索和工作目錄,如果指定了該選項,innoabackupex自動決定用的二進制程序。
--slave-info:該選項表示對slave進行備份的時候使用,打印出master的名字和binlog pos,同樣將這些信息以change master的命令寫入xtrabackup_slave_info文件。可以通過基於這份備份啟動一個從庫。
--safe-slave-backup:該選項表示為保證一致性復制狀態,這個選項停止SQL線程並且等到show status中的slave_open_temp_tables為0的時候開始備份,如果沒有打開臨時表,bakcup會立刻開始,否則SQL線程啟動或者關閉知道沒有打開的臨時表。如果slave_open_temp_tables在--safe-slave-backup-timeount(默認300秒)秒之后不為0,從庫sql線程會在備份完成的時候重啟。
--rsync:該選項表示通過rsync工具優化本地傳輸,當指定這個選項,innobackupex使用rsync拷貝非Innodb文件而替換cp,當有很多DB和表的時候會快很多,不能--stream一起使用。
--kill-long-queries-timeout:該選項表示從開始執行FLUSH TABLES WITH READ LOCK到kill掉阻塞它的這些查詢之間等待的秒數。默認值為0,不會kill任何查詢,使用這個選項xtrabackup需要有Process和super權限。
--kill-long-query-type:該選項表示kill的類型,默認是all,可選select。
--ftwrl-wait-threshold:該選項表示檢測到長查詢,單位是秒,表示長查詢的閾值。
--ftwrl-wait-query-type:該選項表示獲得全局鎖之前允許那種查詢完成,默認是ALL,可選update。
--galera-info:該選項表示生成了包含創建備份時候本地節點狀態的文件xtrabackup_galera_info文件,該選項只適用於備份PXC。
--stream:該選項表示流式備份的格式,backup完成之后以指定格式到STDOUT,目前只支持tar和xbstream。
--defaults-file:該選項指定了從哪個文件讀取MySQL配置,必須放在命令行第一個選項的位置。
--defaults-extra-file:該選項指定了在標准defaults-file之前從哪個額外的文件讀取MySQL配置,必須在命令行的第一個選項的位置。一般用於存備份用戶的用戶名和密碼的配置文件。
----defaults-group:該選項表示從配置文件讀取的組,innobakcupex多個實例部署時使用。
--no-lock:該選項表示關閉FTWRL的表鎖,只有在所有表都是Innodb表並且不關心backup的binlog pos點,如果有任何DDL語句正在執行或者非InnoDB正在更新時(包括mysql庫下的表),都不應該使用這個選項,后果是導致備份數據不一致,如果考慮備份因為獲得鎖失敗,可以考慮--safe-slave-backup立刻停止復制線程。
--tmpdir:該選項表示指定--stream的時候,指定臨時文件存在哪里,在streaming和拷貝到遠程server之前,事務日志首先存在臨時文件里。在 使用參數stream=tar備份的時候,你的xtrabackup_logfile可能會臨時放在/tmp目錄下,如果你備份的時候並發寫入較大的話 xtrabackup_logfile可能會很大(5G+),很可能會撐滿你的/tmp目錄,可以通過參數--tmpdir指定目錄來解決這個問題。
--history:該選項表示percona server 的備份歷史記錄在percona_schema.xtrabackup_history表。
--incremental:該選項表示創建一個增量備份,需要指定--incremental-basedir。
--incremental-basedir:該選項表示接受了一個字符串參數指定含有full backup的目錄為增量備份的base目錄,與--incremental同時使用。
--incremental-dir:該選項表示增量備份的目錄。
--incremental-force-scan:該選項表示創建一份增量備份時,強制掃描所有增量備份中的數據頁。
--incremental-lsn:該選項表示指定增量備份的LSN,與--incremental選項一起使用。
--incremental-history-name:該選項表示存儲在PERCONA_SCHEMA.xtrabackup_history基於增量備份的歷史記錄的名字。Percona Xtrabackup搜索歷史表查找最近(innodb_to_lsn)成功備份並且將to_lsn值作為增量備份啟動出事lsn.與innobackupex--incremental-history-uuid互斥。如果沒有檢測到有效的lsn,xtrabackup會返回error。
--incremental-history-uuid:該選項表示存儲在percona_schema.xtrabackup_history基於增量備份的特定歷史記錄的UUID。
--close-files:該選項表示關閉不再訪問的文件句柄,當xtrabackup打開表空間通常並不關閉文件句柄目的是正確的處理DDL操作。如果表空間數量巨大,這是一種可以關閉不再訪問的文件句柄的方法。使用該選項有風險,會有產生不一致備份的可能。
--compact:該選項表示創建一份沒有輔助索引的緊湊的備份。
--throttle:該選項表示每秒IO操作的次數,只作用於bakcup階段有效。apply-log和--copy-back不生效不要一起用。

--apply-log:該選項表示同xtrabackup的--prepare參數,一般情況下,在備份完成后,數據尚且不能用於恢復操作,因為備份的數據中可能會包含尚未提交的事務或已經提交但尚未同步至數據文件中的事務。因此,此時數據 文件仍處理不一致狀態。--apply-log的作用是通過回滾未提交的事務及同步已經提交的事務至數據文件使數據文件處於一致性狀態。
--use-memory:該選項表示和--apply-log選項一起使用,prepare 備份的時候,xtrabackup做crash recovery分配的內存大小,單位字節。也可(1MB,1M,1G,1GB),推薦1G。
--defaults-file:該選項指定了從哪個文件讀取MySQL配置,必須放在命令行第一個選項的位置。
--export:這個選項表示開啟可導出單獨的表之后再導入其他Mysql中。
--redo-only:這個選項在prepare base full backup,往其中merge增量備份(但不包括最后一個)時候使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM