mysql利用binlog恢復數據詳細例子


 

模擬數據恢復的案例

 

有些時候腦瓜就會短路,難免會出錯

場景:在生產環境中,我們搭建了mysql主從,備份操作都是在從備份數據庫上

前提:有最近一天或者最近的全備

          或者最近一天相關數據庫的備份

          最重要的是,二進制日志必須完整

服務器信息   角色 端口
192.168.1.21   mysql主     30136  
192.168.1.21       mysql從 30236

 

 

 

 

 

 

接下來,我們模擬下

案例一、update未加where條件,誤操作修改數據

全備命令: mysqldump -uroot -p123456  --single-transaction --set-gtid-purged=OFF --master-data=2 -A > all_database.sql

                   mysqldump -uroot -p123456  --single-transaction --set-gtid-purged=OFF --master-data=2  xcrm  > xcrm.sql

 

模擬災難現場

我這個是在k8s里面搭建了一個主從

kubectl get all -o wide

kubectl exec -it mysql-master-659958ff4f-l4sgt bash                #mysql主

 

mysql -uroot -p123456

mysql> show databases;

+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| xcrm |
+--------------------+
5 rows in set (0.00 sec)

 

mysql> use xcrm

mysql> create table edai_test like ding_cun;

mysql> insert into edai_test select * from  ding_cun;

比如凌晨全備是做到這里的

 命令:mysqldump -uroot -p123456  --single-transaction --set-gtid-purged=OFF --master-data=2 -A > all_database.sql

早上九點的時候,又有新的數據進來

mysql> insert into edai_test(nper,money) select nper,money from ding_cun;

110 rows in set (0.00 sec)

 

悲劇來了,上線中的sql,沒有檢查,where條件沒加,直接執行

mysql> update edai_test set money=0;
Query OK, 110 rows affected (0.07 sec)
Rows matched: 110 Changed: 110 Warnings: 0

糟糕,一不小心金額被我修改為0了,偶my嘎,

趕緊恢復,找出binlog點,根據之前的全備+binlog恢復

 

恢復步驟:

1.找出時間段

root@mysql-master-659958ff4f-l4sgt:~/backu1.p# cat all_database.sql |grep -i 'CHANGE MASTER TO MASTER_LOG_FILE'|head -n1

            -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=154;

mysql -uroot -p123456 -e "show binlog events in 'mysql-bin.000001'"|tail -n1000

找到了對應pos點:4326

 

2.mysql導入昨天晚上的備份數據,並且查看pos節點

mysql -uroot -p123456 < all_databases.sql

3.拷貝二進制日志文件到其他地方和二進制恢復

cp /var/lib/mysql/mysql-bin.000001 .

root@mysql-master-659958ff4f-l4sgt:~/backup#  mysqlbinlog  --start-position=154 --stop-position=4326 -d xcrm mysql-bin.000001|mysql -uroot -p123456 xcrm

好了,數據恢復

 

二、刪庫

其實刪除數據庫都是一樣的道理

比如我們的備份是還是昨天晚上的,但是今天下午清理數據,刪除無效的數據庫,誤刪了  

恢復步驟和原理都是差不多的,我就不演示了,簡單講解下

比如下午有新加了一些數據:

mysql> create table customers( id int not null auto_increment, name char(20) not null, age int not null, primary key(id)
)engine=InnoDB; Query OK, 0 rows affected (0.35 sec) mysql> insert into customers values(1,"wangbo","24"); Query OK, 1 row affected (0.07 sec) mysql> insert into customers values(2,"guohui","22"); Query OK, 1 row affected (0.12 sec) mysql> insert into customers values(3,"zhangheng","27"); Query OK, 1 row affected (0.06 sec) mysql> select * from customers; +----+-----------+-----+ | id | name | age | +----+-----------+-----+ | 1 | wangbo | 24 | | 2 | guohui | 22 | | 3 | zhangheng | 27 | +----+-----------+-----+ 3 rows in set (0.00 sec)
然后我一不小心把數據庫刪除了
mysql
> drop database xcrm; Query OK, 5 rows affected (0.40 sec)

 刪庫恢復步驟

到這里,如果是在生產環境,必須立刻做處理

1.立刻設置全局只讀

進入數據庫:set global read_only=1;   #普通權限的用戶只讀,不能寫數據

   mysql> show variables like '%read_only%';

此時普通用戶不能進行寫操作啦,比如下面
mysql -udemo -pdemo -P30136 -h192.168.1.21 xcrm mysql> select * from customers ; +----+-----------+-----+ | id | name | age | +----+-----------+-----+ | 1 | wangbo | 24 | | 2 | guohui | 22 | | 3 | zhangheng | 27 | +----+-----------+-----+ 3 rows in set (0.00 sec) mysql> delete from customers where id=3; ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement

 

2.找到最近備份文件和二進制日志點

root@mysql-master-659958ff4f-l4sgt:~/backup# mysql -uroot -p123456 -e "show binlog events in 'mysql-bin.000001'"|grep -i 'DROP DATABASE'

mysql: [Warning] Using a password on the command line interface can be insecure.
mysql-bin.000001 15035 Query 22 15127 drop database xcrm

  找到最近備份文件的最后pos位置

 root@mysql-master-659958ff4f-l4sgt:~/backup# cat all_database.sql |grep -i 'CHANGE MASTER TO MASTER_LOG_FILE'|head -n1

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=13871;

 3.進行恢復

先將今天凌晨備份的導進去

 mysql -uroot -p123456 < all_database.sql 

    13871   15035  

查看數據中間還相差很多數據,沒關系,再根據pos期間來恢復

mysqlbinlog  --start-position=13871   --stop-position=15035  -d xcrm mysql-bin.000001|mysql -uroot -p123456 xcrm

進入數據庫看看,數據是否正常
mysql -uroot -p123456 mysql> use xcrm 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> show tables; +------------------+ | Tables_in_xcrm | +------------------+ | customers | | ding_cun | | edai_app_version | | edai_test | +------------------+ 4 rows in set (0.00 sec) mysql> select * from customers; +----+-----------+-----+ | id | name | age | +----+-----------+-----+ | 1 | wangbo | 24 | | 2 | guohui | 22 | | 3 | zhangheng | 27 | +----+-----------+-----+ 3 rows in set (0.00 sec)

好了,沒問題,drop數據庫也可以恢復啦

 現在把全局鎖解開:

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

mysql> show variables like '%read_only%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_read_only | OFF |
| read_only | OFF |
| super_read_only | OFF |
| tx_read_only | OFF |
+------------------+-------+
4 rows in set (0.00 sec)

大家有沒有什么疑問?

 

 

再三強調:

在生產環境誤操作之后,應該立刻判斷這個表或者庫的重要性
1.如果是不常用的數據庫或者表,幾乎沒有數據更新,可以不用鎖庫,只讀
2.如果是很常用的數據庫或者表,必須處理,設置為只讀,如果更為嚴重,需要停止mysql服務器。目的就是防止有新的數據寫進來,數據混亂

   

另外呢,假如在生產環境誤操作了,比如,insert,delete,update等表的操作,利用mysql全備+binlog來恢復,時間成本很大,這種方式不是很好。

我們可以用python開發的一個工具:binlog2sql    (mysql閃回工具)

Mysql閃回工具之binlog2sql的原理及其使用

 


免責聲明!

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



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