我叫張賀,貪財好色。一名合格的LINUX運維工程師,專注於LINUX的學習和研究,曾負責某中型企業的網站運維工作,愛好佛學和跑步。
個人博客:傳送陣
筆者微信:zhanghe15069028807
0、備份與恢復概述
系統版本 | mysql版本 | 安裝方式 |
---|---|---|
centos7 | 5.7.28 | 二進制安裝 |
數據庫要備份的內容:
dababase
數據文件binlog
日志文件my.cnf
配置文件
注:
1、所有的數據庫備份文件都應當放在非數據庫本地,而且建議備份多份。
2、僅備份沒啥用,我們備份的目的是為了恢復,能夠正常恢復才是最終目標,所以要經常進行恢復的演練,通常,恢復演練也是運維工作者的日常工作之一。
數據備份要考慮的因素:
- 數據的一致性
- 服務的可用性
數據庫的備份模式:
- 完全備份
- 增量備份:在上一次備份的基礎上,僅備份有變化的部分。
- 差異備份:在完全備份的基礎上,僅備份有變化的部分。
邏輯備份與物理備份的區別:
- 邏輯備份:備份的是SQL語句,效率較低,用於中小型企業。
- 物理備份:備份的具體的數據,效率較高,用於大型企業。
1、邏輯備份-完整備份與恢復
mysql
自帶邏輯備份工具mysqldump
,可以保證數據的一致性和服務的可用性。
>mysqldump -h 服務器 -u 用戶名 -p 密碼 數據庫名 > 備份文件.sql
//常用參數
-A,--all-databases #備份所有庫
-B,--databases #備份多個庫
--single-transaction #保證數據的一致性和服務的可用性
--master-data=1|2 #通常等於1,記錄binlog日志位置與文件名,追加至備份文件中
-F,--flush-logs #備份之前刷新日志
-E,--events #備份事件調度器代碼
--triggers #備份觸發器
-R,--routines #備份存儲過程和存儲函數
第一步:進入mysqld
創建一個數據庫test1
mysql -u root -p"cba-123"
mysql>create database test1;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test1 |
+--------------------+
創建好
test1
數據庫之后,我們就要開始全量備份了,備份之前要先開啟二進制日志。
第二步:在/etc/my.cnf
文件里面開啟二進制日志
vim /etc/my.cnf
[mysqld]
basedir=/soft/mysql
datadir=/soft/mysql/data
default_password_lifetime=0
server-id = 241 #id是做標識,隨便填寫
log-bin=/log/mysql/bin-log #設置二進制日志存放的位置
第三步:保證二進制日志文件的存在和權限
mkdir -p /log/mysql/ ; touch /log/mysql/bin-log ;
chown -R mysql:mysql /log/mysql/bin-log;
第四步:准備好全量備份好的文件存放的目錄和權限
mkdir /backup/mysql -p
chown -R mysql:mysql /backup/mysql/
第五步:重啟數據庫進行全量備份
/etc/init.d/mysqld restart
mysqldump -uroot -pcba-123
--all-databases
--single-transaction
--master-data=1
--flush-logs > /backup/mysql/$(date +%F%H)-mysql-all.sql
第六步:破壞數據庫,刪除數據表
/etc/init.d/mysqld stop
rm -rf /soft/mysql/data/*
第七步:向全量備份文件里面追加不記錄二進制日志的命令
sed -i '23a SET sql_log_bin=0;' /backup/mysql/2019-11-2810-mysql-all.sql
向全量備份文件里面追加不記錄二進制日志的命令的原因是因為我們在恢復的時候要重新執行一次
SQL
語句,這個語句沒有記錄的必要,如果記錄的話還可能會導致恢復失敗。
第八步:重啟初始化數據庫、啟動數據庫、並修改密碼
/soft/mysql/bin/mysqld --initialize --user=mysql --basedir=/soft/mysql --datadir=/soft/mysql/data
/etc/init.d/mysqld start
mysql -u root -p'U0ln8LE!ue=#'
mysql> ALTER USER USER() IDENTIFIED BY '123';
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
由於這是一個新的數據庫,里面只有默認的庫,並沒有
test1
數據庫。
第九步:導入全備的數據
mysql -u root -p'123' < /backup/mysql/2019-11-2810-mysql-all.sql
mysql -uroot -p123
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test1 |
+--------------------+
其實在數據庫內部也可以進行恢復,如下所示
mysql> set sql_log_bin=0;
mysql> source /backup/mysql/2019-11-2810-mysql-all.sql
導入之后當前的密碼會不變,當進入數據庫
flush privileges
之后,密碼又恢復到備份時的cba-123
了。
2、邏輯備份-增量備份與恢復
實戰案例1: 數據庫完整備份+數據庫增量備份
新建數據表, 進行全量備份, 隨着時間推移, 數據庫突然奔潰
(1)環境准備
//備份之前
mysql> create database bgx;
mysql> create table bgx.t1 (id int,name varchar(20));
mysql> insert into bgx.t1 values (1,"bgx1");
mysql> insert into bgx.t1 values (2,"bgx2");
mysql> select * from bgx.t1;
+------+------+
| id | name |
+------+------+
| 1 | bgx1 |
| 2 | bgx2 |
+------+------+
//基於當前狀態做一次全備
mysqldump -uroot -pcba-123 --all-databases --single-transaction --master-data=1 --flush-logs > /backup/mysql/$(date +%F%H)-mysql-all.sql
//進入數據庫,再插入一些數據
mysql> insert into bgx.t1 values (3,"bgx3");
mysql> insert into bgx.t1 values (5,"tt");
mysql> select * from bgx.t1;
+------+------+
| id | name |
+------+------+
| 1 | bgx1 |
| 2 | bgx2 |
| 3 | bgx3 |
| 5 | tt |
+------+------+
//模擬數據庫崩潰,重啟初始化,啟動數據庫,更改默認密碼
/etc/init.d/mysqld stop
rm -rf /soft/mysql/data/*
/soft/mysql/bin/mysqld --initialize --user=mysql --basedir=/soft/mysql --datadir=/soft/mysql/data
/etc/init.d/mysqld start
mysql -p'1=FuY==qhkjd'
mysql> ALTER USER USER() IDENTIFIED BY '123';
(2)恢復全量數據
[root@mysql02 ~]# sed -i "23aSET sql_log_bin=0;" /backup/mysql/2019-11-2810-mysql-all.sql
[root@mysql02 ~]# mysql -uroot -p'123' < /backup/mysql/2019-11-2810-mysql-all.sql
[root@mysql02 ~]# mysql -u root -p'123' -e "select * from bgx.t1"
+------+------+
| id | name |
+------+------+
| 1 | bgx1 |
| 2 | bgx2 |
+------+------+
(3)恢復增量備份
第一步:查看一下全量備份,備份到哪個點了,如下所示是154這個點,000001這個日志文件
[root@mysql02 ~]# sed -n '22p' /backup/mysql/2019-11-2810-mysql-all.sql
CHANGE MASTER TO MASTER_LOG_FILE='bin-log.000001', MASTER_LOG_POS=154;
全量僅備份到了154這個點,154后面的點全備文件里面就沒有了,需要去000002以后的二進制文件里面找
第二步:根據 MASTER_LOG_POS
恢復增量的數據
[root@mysql02 mysql]# pwd
/log/mysql
[root@mysql02 mysql]#mysqlbinlog --start-position=154 bin-log.000001 bin-log.000002 bin-log.000003 bin-log.000003 | mysql -uroot -p'123';
[root@mysql02 ~]# mysql -u root -p'123' -e "select * from bgx.t1"
+------+------+
| id | name |
+------+------+
| 1 | bgx1 |
| 2 | bgx2 |
| 3 | bgx3 |
| 5 | tt |
+------+------+
3、新來的開發妹子刪了庫!
上周,新來的開發妹子刪了庫,這件事不想再回憶了,以后打死也不會把數據庫的
root
權限輕易給別人了。今天把當時的場景用虛擬機還原一下,然后復現一下數據恢復的過程,就當是個總結吧!說多了都是淚啊~
(1)模擬環境准備
[root@mysql02 ~]# mysql -p'cba-123'
mysql> create database bgxdb;
mysql> use bgxdb;
mysql> create table t1 (id int,name varchar(20));
mysql> insert into t1 values (1,"ccr");
mysql> insert into t1 values (2,"tfr");
mysql> select * from t1;
+------+------+
| id | name |
+------+------+
| 1 | ccr |
| 2 | tfr |
+------+------+
(2)全備
[root@mysql02 ~]# mysqldump -uroot -pcba-123 --all-databases --single-transaction --master-data=1 --flush-logs > /backup/mysql/$(date +%F%H)-mysql-all.sql
(3)再次插入數據
[root@mysql02 ~]# mysql -p'cba-123';
mysql> insert into bgxdb.t1 values
-> (3,'tr1'),
-> (4,'zx'),
-> (5,'wq'),
-> (6,'tj'),
-> (7,'gwt');
mysql> select * from bgxdb.t1;
+------+------+
| id | name |
+------+------+
| 1 | ccr |
| 2 | tfr |
| 3 | tr1 |
| 4 | zx |
| 5 | wq |
| 6 | tj |
| 7 | gwt |
+------+------+
(4)開發妹子的誤操作
mysql> delete from bgxdb.t1 where id = '2';
mysql> drop database bgxdb;
(5)恢復全備
[root@mysql02 ~]# sed -i '23aSET sql_log_bin=0;' /backup/mysql/2019-11-2812-mysql-all.sql
[root@mysql02 ~]# mysql -u root -p'cba-123' < /backup/mysql/2019-11-2812-mysql-all.sql
[root@mysql02 ~]# mysql -u root -p'cba-123' -e "select * from bgxdb.t1"
+------+------+
| id | name |
+------+------+
| 1 | ccr |
| 2 | tfr |
+------+------+
(6)進一步小心地恢復,跳過DELETE
和DROP
語句
下面的操作就要小心翼翼了,不能一下子把二進制日志里面全備以后的操作全部恢復,一旦全部恢復了,那開發妹子的刪除操作也會恢復,我們只能跳過誤操作的地方。
[root@mysql02 ~]# sed -n '22p' /backup/mysql/2019-11-2812-mysql-all.sql
CHANGE MASTER TO MASTER_LOG_FILE='bin_log.000002', MASTER_LOG_POS=154;
[root@mysql02 ~]# ls /log/mysql/ #全備之后只有一個` bin_log.000002`二進程日志文件
[root@mysql02 ~]# mysqlbinlog --start-position=154 --stop-position=577
[root@mysql02 ~]# mysqlbinlog --start-position=670 --stop-position=701
[root@mysql02 ~]# mysql -uroot -p'cba-123' -e "select * from bgxdb.t1"
+------+------+
| id | name |
+------+------+
| 1 | ccr |
| 2 | tfr |
| 3 | tr1 |
| 4 | zx |
| 5 | wq |
| 6 | tj |
| 7 | gwt |
#被開發妹子刪除的數據終於恢復回來了
注:上述案例在全備之后僅產生了一個二進制日志,如果有多個呢?該如何操作?如下所示
mysqlbinlog --base64-output="decode-rows" -v bin_log.000001 bin_log.000002 > test3.sql