在生產環境中,數據的安全性是至關重要的,任何數據的丟失都可能產生嚴重的後果。所以數據庫需要備份。這裏以新版mysql5.7爲例。
一、數據庫備份分類:
-
從物理與邏輯的角度,備份可分爲物理備份和邏輯備份。
(1)物理備份:對數據庫操作系統的物理文件(如數據文件、日誌文件等)的備份。又可以分爲冷備份和熱備份。
冷備份:關閉數據庫時進行的備份操作
熱備份:在數據庫運行狀態中進行備份操作,這種備份方法依賴於數據庫的日誌文件。
(2)邏輯備份:對數據庫邏輯組件(如表等數據庫對象)的備份。
-
從數據庫的備份策略角度,備份可分爲完全備份、差異備份、增量備份。
(1)完全備份:每次對數據庫進行完整的備份。可以備份單個數據庫,多個數據庫,所有數據庫,也可以備份數據庫中的單個表,多個表。
(2)差異備份:備份那些自從上次完全備份之後被修改過的文件,只備份數據庫部分內容,但是存儲和恢復速度快。
(3)增量備份:只有那些在上次完全備份或者增量備份後被修改的文件纔會被備份。
二、完全備份與恢復
-
備份:
使用mysqldump工具可以靈活的控制備份的內容,比如某幾個表或庫都可以單獨備份。
1. 對單個庫進行完全備份。命令格式如下:
mysqldump -u用戶名 -p[密碼] [選項] [數據庫名] > /備份路徑/備份文件名
2. 對多個庫進行完全備份。命令格式如下:
mysqldump -u用戶名 -p[密碼] [選項] --databases 庫名1 庫名2 ... > /備份路徑/備份文件名
3. 對所有庫進行完全備份。命令格式如下:
mysqldump -u用戶名 -p[密碼] --opt --all-databases > /備份路徑/備份文件名
4. 對錶結構進行完全備份。命令格式如下:
mysqldump -u用戶名 -p[密碼] -d 數據庫名 表名 > /備份路徑/備份文件名
5. 對錶進行完全備份。命令格式如下:
mysqldump -u用戶名 -p[密碼] 數據庫名 表名 > /備份路徑/備份文件名
下面演練完全備份的實驗。
完全備份單個庫:
[root@localhost ~]# mysqldump -uroot -pabc123 school > /opt/school-$(date +%F).sql
[root@localhost ~]# ls /opt/
school-2018-07-19.sql
完全備份單個表:
[root@localhost ~]# mysqldump -uroot -pabc123 school info > /opt/school_info-$(date +%F).sql
[root@localhost ~]# ls /opt/
school_info-2018-07-19.sql
-
恢復:
1. 登錄mysql,使用source命令恢復庫。命令格式如下:
source 庫備份腳本的路徑
2. 在不登錄MySQL的情況下,使用mysql命令直接恢復整庫。命令格式如下:
mysql -u用戶名 -p[密碼] < 庫備份腳本的路徑
下面演練完全備份後恢復的實驗。
恢復單個庫:
假設數據庫損壞,刪除數據庫school。
[root@localhost ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> drop database school;
Query OK, 1 row affected (0.02 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
1)使用source命令恢復。
注意:先創建一個同名的數據庫,再進入數據庫,用surce命令恢復,否則會報錯。
mysql> create database school;
Query OK, 1 row affected (0.01 sec)
mysql> use school;
Database changed
mysql> source /opt/school-2018-07-19.sql
Query OK, 0 rows affected (0.01 sec)
...
...
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
...
Query OK, 0 rows affected (0.00 sec)
2)使用mysql命令恢復。
再一次刪掉數據庫school。
注意:在恢復操作之前要創建一個同名的數據庫,否則會報錯。
mysql> create database school;
Query OK, 1 row affected (0.00 sec)
mysql> exit
Bye
[root@localhost ~]# mysql -uroot -pabc123 school < /opt/school-2018-07-19.sql
兩種方法恢復完成後查看數據庫恢復成功。
恢復單個表:
假設數據損壞,刪除數據庫school中的表info。
mysql> use school;
Database changed
mysql> select * from info;
+----------+-------+
| name | score |
+----------+-------+
| zhangsan | 75.00 |
| lisi | 85.00 |
+----------+-------+
2 rows in set (0.00 sec)
mysql> drop table info;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables;
Empty set (0.00 sec)
1)使用source命令恢復。
mysql> use school;
Database changed
mysql> source /opt/school_info-2018-07-19.sql
Query OK, 0 rows affected (0.00 sec)
...
...
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
...
Query OK, 0 rows affected (0.00 sec)
2)使用mysql命令恢復。
再一次刪除表info,然後進行恢復操作。
[root@localhost ~]# mysql -uroot -pabc123 school < /opt/school_info-2018-07-19.sql
兩種方法恢復完成後查看錶info恢復成功。
mysql> use school;
Database changed
三、增量備份與恢復
MySQL沒有提供直接的增量辦法,但是可以通過對MySQL的二進制日誌間接實現增量備份。二進制日誌保存了所有更新或者可能更新數據庫的操作。
特點:
- 沒有重複數據,備份量不大,時間短
- 需要上次完全備份及完全備份之後所有的增量備份才能恢復,而且要進行逐個反推恢復,操作繁瑣。
1.實現增量備份
(1)要進行MySQL增量備份,首先要開啓二進制日誌功能。
在mysql的配置文件的[mysqld]選項中加入log-bin=mysql-bin,然後重啓服務。
vim /etc/my.cnf
[mysqld]
log-bin=mysql-bin
systemctl restart mysqld.service
(2)使用mysqldump完全備份school庫。
[root@localhost ~]# mysqldump -uroot -pabc123 school > /opt/school-$(date +%F).sql
[root@localhost ~]# ls /opt/
school-2018-07-19.sql
(3)使用mysqladmin的選項flush-logs生成新的二進制文件,這樣在插入新的數據後,新的二進制文件對應的就是數據庫的變化的內容。
[root@localhost ~]# cd /usr/local/mysql/data/
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.000001
mysql-bin.index
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs //進行日誌分割
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.000001
mysql-bin.000002 //產生新的二進制文件mysql-bin.000002
mysql-bin.index
(4)插入一條新的數據,以模擬數據的增加或變更。
mysql> use school;
Database changed
mysql> insert into info (name,score) values ('tom','65');
Query OK, 1 row affected (0.01 sec)
mysql> exit
Bye
此時的數據庫變化保存在編號2 的二進制文件中,使用mysqlbinlog命令可以查看二進制文件的內容,裏面保存了插入數據的語句。
[root@localhost data]# mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000002
(5)再次執行flush- logs操作生成新的二進制文件,而新的二進制文件會保存之後的數據操作。
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.000001
mysql-bin.000002
mysql-bin.000003 //產生新的二進制文件mysql-bin.000003
mysql-bin.index
(6)再次向數據庫插入一條數據。
mysql> use school;
Database changed
mysql> insert into info (name,score) values ('lucy','70');
Query OK, 1 row affected (0.00 sec)
mysql> exit
Bye
(7)最後再執行一次flush-logs操作,確保之前的二進制文件不再發生變化。
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.000001
mysql-bin.000002
mysql-bin.000003
mysql-bin.000004 //產生新的二進制文件,保存之後的數據操作語句
mysql-bin.index
2.丟失完全備份之後更改的數據的恢復
(1)使用delete刪除插入的兩條數據,也就是假設完全備份後的數據丟失了。
mysql> use school;
Database changed
mysql> delete from info where name='tom';
Query OK, 1 row affected (0.01 sec)
mysql> delete from info where name='lucy';
Query OK, 1 row affected (0.00 sec)
(2)使用二進制文件恢復時需要注意的是恢復順序,要先恢復最先生成的二進制文件,然後依次執行。
[root@localhost ~]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000002|mysql -uroot -pabc123
[root@localhost ~]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000003|mysql -uroot -pabc123
查看數據庫內容,完全備份之後新插入的兩條數據找回來了,說明數據恢復成功。
3. 完全備份之後丟失所有數據的恢復
當完全備份和增量備份之後,所有數據丟失,需要把完全備份和所有增量備份文件逐個恢復。
(1)執行flush-logs操作分割日誌,插入一條數據。
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.000001
mysql-bin.000002
mysql-bin.000003
mysql-bin.000004
mysql-bin.000005 //產生新的二進制文件,保存之後的數據操作語句
mysql-bin.index
mysql> use school;
Database changed
mysql> insert into info (name,score) values ('jack','55');
Query OK, 1 row affected (0.01 sec)
mysql> exit
Bye
這條插入語句保存在mysql-bin.000005二進制文件中。
(2)再執行一次flush-logs操作,插入一條數據,之後還要再執行一次flush-logs操作,確保插入數據保存在二進制文件中,不再改變。
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.000001
mysql-bin.000002
mysql-bin.000003
mysql-bin.000004
mysql-bin.000005
mysql-bin.000006 //產生新的二進制文件,保存之後的數據操作語句
mysql-bin.index
mysql> use school;
Database changed
mysql> insert into info (name,score) values ('xixi','45');
Query OK, 1 row affected (0.00 sec)
mysql> exit
Bye
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.000001
mysql-bin.000002
mysql-bin.000003
mysql-bin.000004
mysql-bin.000005
mysql-bin.000006
mysql-bin.000007 //產生新的二進制文件,保存之後的數據操作語句
mysql-bin.index
這條插入語句保存在mysql-bin.000006二進制文件中。
(3)使用drop刪除表info,也就是假設完全備份前info的數據和完全備份後的數據都丟失了。
mysql> use school;
Database changed
mysql> drop table info;
Query OK, 0 rows affected (0.03 sec)
(4)先使用mysql命令進行完全備份的恢復操作。
[root@localhost data]# mysql -uroot -pabc123 school < /opt/school-2018-07-19.sql
[root@localhost data]# mysql -uroot -pabc123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> use school;
Database changed
mysql> select * from info;
+----------+-------+
| name | score |
+----------+-------+
| zhangsan | 75.00 |
| lisi | 85.00 |
| wangwu | 95.00 |
+----------+-------+
3 rows in set (0.00 sec)
被刪除的表的數據又可以查詢出來
(5)使用二進制文件恢復時需要注意的是恢復順序,要先恢復最先生成的二進制文件,然後依次執行。
[root@localhost ~]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000005|mysql -uroot -pabc123
[root@localhost ~]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000006|mysql -uroot -pabc123
可以看到數據全部恢復出來了。
4. 基於時間點與位置恢復
利用二進制日誌可實現基於時間點與位置的恢復,例如由於誤操作刪除了一張表,這時完全恢復時沒有用的,因爲日誌裏面還存在誤操作的語句。我們需要的是恢復到誤操作前的狀態,然後跳過誤操作的語句,再恢復後面操作的語句。
mysql> use school;
Database changed
mysql> select * from info;
+----------+-------+
| name | score |
+----------+-------+
| zhangsan | 75.00 |
| lisi | 85.00 |
| wangwu | 95.00 |
+----------+-------+
3 rows in set (0.00 sec)
首先對數據庫進行備份。
[root@localhost ~]# mysqldump -uroot -pabc123 school > /opt/school-$(date +%F).sql
[root@localhost ~]# ls /opt/
school-2018-07-20.sql
(1)基於時間點恢復
將某個起始時間的二進制日誌導入數據庫中,從而跳過某個發生錯誤的時間點實現數據的恢復。
1)執行flush-logs操作生成新的二進制文件。
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.0000020
//產生新的二進制文件,保存之後的數據操作語句
2)插入兩條數據,但由於誤操作,兩條插入語句中間刪除了一條數據,而這條數據是不應該刪除的。爲了確保數據保存在二進制文件中不改變,執行一次flush-logs操作。
mysql> use school;
Database changed
mysql> insert into info (name,score) values ('coco','65');
Query OK, 1 row affected (0.00 sec)
mysql> delete from info where name='lisi';
Query OK, 1 row affected (0.06 sec)
mysql> insert into info (name,score) values ('momo','85');
Query OK, 1 row affected (0.00 sec)
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.0000021
//產生新的二進制文件,保存之後的數據操作語句
3)假設數據損壞,刪除表info。
mysql> use school;
Database changed
mysql> drop table info;
Query OK, 0 rows affected (0.01 sec)
4)使用mysql命令進行完全備份的恢復操作。
[root@localhost data]# mysql -uroot -pabc123 school < /opt/school-2018-07-20.sql
[root@localhost data]# mysql -uroot -pabc123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> use school;
Database changed
mysql> select * from info;
+----------+-------+
| name | score |
+----------+-------+
| zhangsan | 75.00 |
| lisi | 85.00 |
| wangwu | 95.00 |
+----------+-------+
3 rows in set (0.00 sec)
5)查看數據操作語句保存的二進制文件mysql-bin.0000020。
[root@promote data]# mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000020
6)根據二進制文件的數據操作語句的時間點進行完全備份後增量備份的恢復操作。
[root@promote data]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000020 --stop-datetime='18-07-20 0:36:18'|mysql -uroot -pabc123
[root@promote data]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000020 --start-datetime='18-07-20 0:36:41'|mysql -uroot -pabc123
(2)基於位置恢復
使用基於時間點的恢復可能會出現在一個時間點裏既同時存在正確的操作又存在錯誤的操作,基於位置是一種更爲精確的恢復方式。
假設數據損壞,刪除表info。**
mysql> use school;
Database changed
mysql> drop table info;
Query OK, 0 rows affected (0.01 sec)
使用mysql命令進行完全備份的恢復操作。
[root@localhost data]# mysql -uroot -pabc123 school < /opt/school-2018-07-20.sql
[root@localhost data]# mysql -uroot -pabc123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> use school;
Database changed
mysql> select * from info;
+----------+-------+
| name | score |
+----------+-------+
| zhangsan | 75.00 |
| lisi | 85.00 |
| wangwu | 95.00 |
+----------+-------+
3 rows in set (0.00 sec)
1)執行flush-logs操作生成新的二進制文件。
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.0000024
//產生新的二進制文件,保存之後的數據操作語句
2)插入兩條數據,但由於誤操作,兩條插入語句中間刪除了一條數據,而這條數據是不應該刪除的。爲了確保數據保存在二進制文件中不改變,執行一次flush-logs操作。
mysql> use school;
Database changed
mysql> insert into info (name,score) values ('lili','65');
Query OK, 1 row affected (0.00 sec)
mysql> delete from info where name='wangwu';
Query OK, 1 row affected (0.06 sec)
mysql> insert into info (name,score) values ('mimi','85');
Query OK, 1 row affected (0.00 sec)
[root@localhost data]# mysqladmin -uroot -pabc123 flush-logs
[root@localhost data]# ls ./ | grep mysql.bin.*
mysql-bin.0000025
//產生新的二進制文件,保存之後的數據操作語句
3)查看數據操作語句保存的二進制文件mysql-bin.0000024。
[root@promote data]# mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000024
4)根據二進制文件的數據操作語句的時間點進行完全備份後增量備份的恢復操作。
[root@promote data]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000024 --stop-position='615'|mysql -uroot -pabc123
[root@promote data]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000024 --start-position='661'|mysql -uroot -pabc123