數據丟失的原因:
ü 程序錯誤、人爲操作錯誤、運算錯誤
ü 磁盤故障、災難(如火災、地震)和盜竊等
數據庫備份的類型:
從物理和邏輯角度看,數據庫備份可以分爲物理備份和邏輯備份。
物理備份又分爲冷備份、熱備份和溫備份。
Ø 冷備份:在數據庫關閉狀態下進行備份操作
Ø 熱備份:在數據庫處於運行狀態下進行備份操作,此方法依賴數據庫的日誌文件
Ø 溫備份:數據庫鎖定表格(不可寫但可讀)的狀態下進行備份操作
邏輯備份:是對數據庫邏輯組件(如表等數據庫對象)的備份。
從數據庫備份策略角度看,數據庫備份可以分爲,完全備份,差異備份和增量備份
Ø 完全備份:每次都對整個數據庫備份,是差異備份和增量備份的基礎,缺點是會佔用大量的磁盤空間,備份時間也很長
Ø 差異備份:備份從上次完整備份後修改過的所有文件,缺點是備份的數據量會越來越大,優點是恢復的時候只恢復上次的完整備份和最近一次的差異備份就好了
Ø 增量備份:只備份完整備份後或者增量備份後被修改的文件,優點是備份的數據量小,佔用空間小,備份的速度快。缺點是在恢復的時候要從完整備份開始和增量備份的結束依次恢復,如果某次的備份損壞,將導致數據丟失
數據庫完整備份
1. 物理冷備份與恢復
①物理冷備份一般使用的是tar工具打包數據庫文件,在備份前需要先stop停掉數據庫服務
[root@123 /]# systemctl stop mysqld //停掉數據庫服務 [root@123 /]# tar czvf /backup/mysql_$(date +%F).tar.gz /usr/local/mysql/ //備份整個數據庫
②恢復數據庫
[root@123 backup]# tar xzvf mysql_2019-01-13.tar.gz //解壓備份的tar包 [root@123 backup]# cp -a usr/local/mysql/data /usr/local/mysql/ //將備份的date目錄複製到mysql目錄下
③重啓mysqld服務,驗證恢復效果
2. 使用mysqldump工具備份與恢復
該命令備份與恢復時不需要關閉數據庫的服務,通過該命令可以將指定的庫、表或全部的庫導出爲sql腳本
①備份數據庫
[root@123 backup]# mysqldump -uroot -p --databases log > log.sql //備份指定數據庫log,導出爲log.sql [root@123 backup]# mysqldump -uroot -p log biao1 biao2 > biao12.sql //備份log數據庫中的biao1和biao2表 [root@123 backup]# mysqldump -uroot -p --all-databases > all.sql //備份所有的數據庫
②恢復數據庫
注意:當備份文件中只有表備份的時候,恢復時需要指定一個現有的數據庫用來存放恢復的數據表
[root@iZtmm4mufhb0rgZ backup]# mysql -uroot -p < log.sql //恢復指定數據庫備份文件 [root@iZtmm4mufhb0rgZ backup]# mysql -u root -p < all.sql //恢復所有數據庫備份文件 [root@iZtmm4mufhb0rgZ backup]# mysql -u root -p test < biao12.sql //恢復數據表備份文件
數據庫增量備份
Mysql沒有提供直接的增量備份方法,我們可以使用mysql提供的二進制日誌間接的實現增量備份。使用增量備份前首先需要開啓數據庫的二進制日誌功能,二進制日誌文件擴展名是6位數字,如mysql-bin.000001
[root@nnv5 backup]# vim /etc/my.cnf //編輯mysql配置文件 ---------------------------------添加以下內容---------------------------------- log-bin=/usr/local/mysql/mysql-bin //開啓mysql二進制文件支持然後重啓mysqld服務
Mysql增量恢復
常用的增量恢復有三種:一般恢復、基於位置恢復和基於時間恢復
一般恢復:將所有備份的二進制日誌內容全部恢復
一般恢復語法: mysqlbinlog --no-defaults 增量備份文件名 | mysql -u用戶名 -p
基於位置恢復:將數據恢復到指定位置或指定開始恢復位置
基於位置恢復語法: 格式一:恢復到指定位置 mysqlbinlog --stop-position='操作id' 二進制文件名 | mysql -u用戶名 -p 格式二:從指定位置開始恢復 mysqlbinlog --start-postion='操作id' 二進制文件名 | mysql -u用戶名 -p
基於時間點恢復:跳過某個發生錯誤的時間點實現數據恢復
基於時間恢復語法: 格式一:從日誌開頭截止到某個時間點的恢復 mysqlbinlog --no-defaults --stop-datetime='年-月-日 小時:分鐘:秒' 二進制日誌 | mysql -u用戶名 -p 格式二:從某個時間點到日誌的結尾 mysqlbinlog --no-defaults --start-datetime='年-月-日 小時:分鐘:秒' 二進制日誌 | mysql -u用戶名 -p 格式三:從某個時間點到某個時間點 mysqlbinlog --no-defaults --start-datetime='年-月-日 小時:分鐘:秒' --stop-datetime='年-月-日 小時:分鐘:秒' 二進制日誌 | mysql -u用戶名 -p
增量備份恢復案例:
² 一般恢復案例
①編輯配置文件,開啓二進制日誌的功能
[root@nnv5 ~]# vim /etc/my.cnf //編輯數據庫配置文件 ----------------添加以下參數----------------------- log-bin=/usr/local/mysql/mysql-bin //開啓二進制日誌功能 [root@nnv5 ~]# systemctl restart mysqld //重啓mysql服務 [root@nnv5 ~]# ls /usr/local/mysql/ | grep mysql-bin //查看二進制日誌文件
②登錄數據庫,創建一個數據庫,在數據庫中創建一個表並錄入張三和李四的信息
[root@nnv5 ~]# mysql -uroot //登錄數據庫 mysql> create database client; //創建一個數據庫名爲client mysql> use client; //切換到client數據庫 mysql> create table xinxi(××× char(20),姓名 char(20),性別 char(20),用戶id char(20),資費 char(20)); //創建一個表設置字段 mysql> insert xinxi values ('000006','張三','男','016','61'); //在表中插入張三的信息 mysql> insert xinxi values ('000007','李四','男','017','91'); //在表中插入李四的信息
③爲了驗證二進制日誌的增量恢復功能,在插入兩條數據後對client數據庫進行一次完整的備份,然後生成新的二進制日誌文件
[root@nnv5 ~]# mkdir /mysql_bak //創建完整備份存放的目錄 [root@nnv5 ~]# mysqldump -uroot -p --databases client > /mysql_bak/client.sql //將client數據庫完整備份保存到mysql_bak目錄 [root@nnv5 mysql_bak]# mysqladmin -uroot -p flush-logs //生成新的二進制日誌文件 [root@nnv5 ~]# ls /usr/local/mysql/ | grep mysql-bin //查看二進制日誌文件
④繼續插入新的用戶數據並刷新二進制日誌文件進行增量備份,這樣在完整備份的基礎上新增加的操作備份插入王五和趙六的信息保存在000002二進制文件中
mysql> insert xinxi values ('000008','王五','女','018','23'); //在表中繼續插入王五的信息 mysql> insert xinxi values ('000009','趙六','男','019','37'); //在表中繼續插入趙六的信息 [root@nnv5 mysql_bak]# mysqladmin -uroot -p flush-logs //生成新的二進制文件 [root@nnv5 mysql_bak]# ls /usr/local/mysql/ | grep mysql-bin //查看二進制日誌文件
⑤模擬誤操作,把xinxi這個數據表刪除
mysql> drop table xinxi; //刪除xinxi這個表 mysql> select * from client.xinxi; //查看錶是否還存在
⑥恢復數據表信息,先進行完整備份恢復,然後在進行增量備份恢復
完整備份恢復
[root@nnv5 mysql_bak]# mysql -uroot -p < /mysql_bak/client.sql //恢復完整備份 mysql> select * from client.xinxi; //查看錶信息只有張三和李四的信息
增量備份一般恢復:在插入王五和趙六信息後重新生成了二進制文件,名爲000002,因爲這個二進制文件中保存了王五和趙六的信息
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢復000002二進制文件中的所有數據 mysql> select * from client.xinxi; //查看錶王五和趙六信息也恢復了
² 基於位置恢復
由於之前已經做過備份,就接前面的實驗接着操作模擬故障與數據恢復
①模擬誤操作,將xinxi表刪除
mysql> drop table xinxi; //刪除xinxi這個表 mysql> select * from client.xinxi; //查看錶是否還存在
②完整備份恢復
[root@nnv5 mysql_bak]# mysql -uroot -p < /mysql_bak/client.sql //恢復完整備份 mysql> select * from client.xinxi; //查看錶信息只有張三和李四的信息
③要基於位置或者時間恢復數據,必須先查看二進制文件的內容獲取到要恢復到的操作id或者要恢復到的時間點,可以使用“mysqlbinlog --no-defaults 二進制文件”查看二進制文件的具體內容
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults /usr/local/mysql/mysql-bin.000002 //查看000002二進制日誌文件的內容 --------------------------------------------------------------------------------------------------------- # at 203 #181214 0:43:07 server id 1 end_log_pos 337 CRC32 0x4209f33e Query thread_id=2 exec_time=0 error_code=0 use `client`/*!*/; SET TIMESTAMP=1544719387/*!*/; insert xinxi values ('000008','王五','女','018','23') /*!*/; # at 337 #181214 0:43:07 server id 1 end_log_pos 368 CRC32 0xf4cb4c7d Xid = 38 COMMIT/*!*/; # at 368 #181214 0:43:15 server id 1 end_log_pos 451 CRC32 0xa428e268 Query thread_id=2 exec_time=0 error_code=0 SET TIMESTAMP=1544719395/*!*/; BEGIN /*!*/; # at 451 #181214 0:43:15 server id 1 end_log_pos 585 CRC32 0xc3e48c8c Query thread_id=2 exec_time=0 error_code=0 SET TIMESTAMP=1544719395/*!*/; insert xinxi values ('000009','趙六','男','019','37') /*!*/; # at 585 #181214 0:43:15 server id 1 end_log_pos 616 CRC32 0xf05f2902 Xid = 39 COMMIT/*!*/; # at 616 #181214 0:45:59 server id 1 end_log_pos 663 CRC32 0xb3cc49ad Rotate to mysql-bin.000003 pos: 4 DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
④通過查看二進制文件內容可以看到每個操作前都有一個id或者時間點,例如在ID451之前插入了王五的信息
格式一:例如執行下面操作可以只將數據恢復到ID451,也就是說只恢復王五的信息,趙六的信息不恢復
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --stop-position='451' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢復操作ID451之前的所有數據 mysql> mysql> select * from xinxi; //查看xinxi表發現王五信息已經恢復了
格式二:如果執行下面操作是從ID451開始進行恢復,也就是說恢復id451之後的所有的數據,因此只會恢復趙六的數據,王五的數據就跳過了
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --start-position='451' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢復操作ID451之後的所有數據 mysql> mysql> select * from xinxi; //查看xinxi表發現王五信息已經恢復了
² 基於時間點恢復
由於之前已經做過備份,就接前面的實驗接着操作模擬故障與數據恢復
①模擬誤操作,將xinxi表刪除
mysql> drop table xinxi; //刪除xinxi這個表 mysql> select * from client.xinxi; //查看錶是否還存在
②完整備份恢復
[root@nnv5 mysql_bak]# mysql -uroot -p < /mysql_bak/client.sql //恢復完整備份 mysql> select * from client.xinxi; //查看錶信息只有張三和李四的信息
③使用“mysqlbinlog --no-defaults 二進制文件”查看二進制文件時間點
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults /usr/local/mysql/mysql-bin.000002 //查看000002二進制日誌文件的內容 --------------------------------------------------------------------------------------------------------- # at 203 #181214 0:43:07 server id 1 end_log_pos 337 CRC32 0x4209f33e Query thread_id=2 exec_time=0 error_code=0 use `client`/*!*/; SET TIMESTAMP=1544719387/*!*/; insert xinxi values ('000008','王五','女','018','23') /*!*/; # at 337 #181214 0:43:07 server id 1 end_log_pos 368 CRC32 0xf4cb4c7d Xid = 38 COMMIT/*!*/; # at 368 #181214 0:43:15 server id 1 end_log_pos 451 CRC32 0xa428e268 Query thread_id=2 exec_time=0 error_code=0 SET TIMESTAMP=1544719395/*!*/; BEGIN /*!*/; # at 451 #181214 0:43:15 server id 1 end_log_pos 585 CRC32 0xc3e48c8c Query thread_id=2 exec_time=0 error_code=0 SET TIMESTAMP=1544719395/*!*/; insert xinxi values ('000009','趙六','男','019','37') /*!*/; # at 585 #181214 0:43:15 server id 1 end_log_pos 616 CRC32 0xf05f2902 Xid = 39 COMMIT/*!*/; # at 616 #181214 0:45:59 server id 1 end_log_pos 663 CRC32 0xb3cc49ad Rotate to mysql-bin.000003 pos: 4 DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
④通過查看二進制文件內容可以看到每個操作前都有一個id或者時間點,例如在時間點181214 0:43:15之前插入了王五的信息
例如執行下面操作可以只將數據恢復到181214 0:43:15,也就是說只恢復王五的信息,趙六的信息不恢復
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --stop-datetime='2018-12-14 0:43:15' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢復操作時間點之前的所有數據 mysql> mysql> select * from xinxi; //查看xinxi表發現王五信息已經恢復了
如果執行下面操作是從181214 0:43:15這個時間點開始恢復以後的所有數據,因此只會恢復趙六的數據,王五的數據就跳過了
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --start-datetime='2018-12-14 0:43:15' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢復操作時間點之後的所有數據 mysql> mysql> select * from xinxi; //查看xinxi表發現趙六信息已經恢復了
如果執行以下操作是指恢復時間點#181214 0:43:07到#181214 0:45:59這個時間點之間的所有數據,如果前面或者時間點之後有數據則跳過不恢復
[root@nnv5 mysql_bak]# mysqlbinlog --no-defaults --start-datetime='2018-12-14 0:43:07' --stop-datetime='2018-12-14 0:45:49' /usr/local/mysql/mysql-bin.000002 | mysql -uroot -p //恢復時間點0:43:07到 0:45:49之間的所有數據 mysql> mysql> select * from xinxi; //查看xinxi表發現王五和趙六信息已經恢復了