1. 程式人生 > 實用技巧 >十八、Mysql之延時從庫

十八、Mysql之延時從庫

一、延時從庫的介紹

MySQL從5.6版本開始就支援主從延遲複製,這個功能主要解決的問題是,當主庫有邏輯的資料刪除或者錯誤更新時,所有的從庫都會進行錯誤的更新,從而導致資料庫的所有資料都異常,即使有定時的備份資料可以用於資料恢復,特別是資料庫的資料量很大時,恢復時間也會很長,在恢復期間,資料庫資料被刪除或者出現錯誤資料都會影響正常的訪問體驗。 而延遲複製就可以很好地解決這個問題。例如,可以設定某一個從庫和主庫的更新延遲1個小時,這樣當主庫資料出現問題以後,1個小時以內即可發現,可以對這個從庫進行無害恢復處理,使之依然是正確的完整的資料,這樣就省去了資料恢復佔用的時間,使用者體驗也會有所提高。

為什麼要有延時從?

資料庫故障?
物理損壞
主從複製非常擅長解決物理損壞.
邏輯損壞
普通主從複製沒辦法解決邏輯損壞

二、配置延時從庫

SQL執行緒延時:資料已經寫入從庫的relaylog中了,從庫的SQL執行緒"慢點"執行
一般企業建議3-6小時,具體看公司運維人員對於故障的反應時間

mysql>stop slave;
mysql>CHANGE MASTER TO MASTER_DELAY = 300;  #單位為秒
mysql>start slave;
mysql> show slave status \G
SQL_Delay: 300
SQL_Remaining_Delay: NULL

三、延時從庫應用

延時從庫主要用於主庫誤刪除資料,從庫可以在一段時間內恢復主庫刪除的資料。

四、延時從庫的實戰案例

1、延時從庫恢復的思路

1主1從,從庫延時5分鐘,主庫誤刪除1個庫
1. 5分鐘之內 偵測到誤刪除操作
2. 停從庫SQL執行緒
3. 擷取relaylog
起點 :停止SQL執行緒時,relay最後應用位置
檢視延時從庫的relay-log.info獲取
終點:誤刪除之前的position(GTID)
在從庫中show relaylog events in 'vm01-relay-bin.000002'來獲取
4. 恢復擷取的日誌到從庫
5. 從庫身份解除,替代主庫工作

2、實驗環境

OS: CentOS Linux release 7.6.1810 (Core)
mysql:mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz
mysql master: 3307
mysql slave:3308
主從部署省略

3、配置延時從庫3308

[root@vm01 ~]# mysql -S /data/3308/mysql.sock -p
Enter password: 
[(none)]>stop slave;
[(none)]>change master to master_delay=300;
[(none)]>start slave;
[(none)]>show slave status\G
......
SQL_Delay: 300
SQL_Remaining_Delay: NULL
......

4、故障模擬及恢復

在主庫3307上模擬故障

[root@vm01 ~]# mysql -S /data/3307/mysql.sock -p
Enter password: 
[(none)]>create database relay charset utf8;
[(none)]>use relay;
[relay]>create table t1 (id int);
[relay]>insert into t1 values(1);
[relay]>commit;
[relay]>select * from t1;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

[relay]>drop database relay;

[(none)]>show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |     1806 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

5、在從庫上恢復

5.1停止從庫SQL執行緒

[root@vm01 ~]# mysql -S /data/3308/mysql.sock -p
Enter password: 
[(none)]>show slave status\G
。。。。。。
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 1806
SQL_Delay: 300
SQL_Remaining_Delay: 123
。。。。。。
#可以發現主從庫的binlog已經同步,但是從庫的sql還沒有執行
#停止從庫的sql執行緒
[(none)]>stop slave sql_thread;

5.2. 找3308從庫relaylog的擷取起點和終點

relaylog的起點
方法一:
[root@vm01 ~]# cat /data/3308/data/relay-log.info
./vm01-relay-bin.000002
320
方法二:
[(none)]>show slave status\G
*************************** 1. row ***************************
。。。。。。
Relay_Log_File: vm01-relay-bin.000002
Relay_Log_Pos: 320
。。。。。。

relaylog的終點
[root@vm01 ~]# mysql -S /data/3308/mysql.sock -p
Enter password: 
[(none)]>show relaylog events in 'vm01-relay-bin.000002';
+-----------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name              | Pos | Event_type     | Server_id | End_log_pos | Info                                  |
+-----------------------+-----+----------------+-----------+-------------+---------------------------------------+
| vm01-relay-bin.000002 |   4 | Format_desc    |      3308 |         123 | Server ver: 5.7.20-log, Binlog ver: 4 |
| vm01-relay-bin.000002 | 123 | Previous_gtids |      3308 |         154 |                                       |
| vm01-relay-bin.000002 | 154 | Rotate         |      3307 |           0 | mysql-bin.000001;pos=1051             |
| vm01-relay-bin.000002 | 201 | Format_desc    |      3307 |           0 | Server ver: 5.7.20-log, Binlog ver: 4 |
| vm01-relay-bin.000002 | 320 | Anonymous_Gtid |      3307 |        1116 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| vm01-relay-bin.000002 | 385 | Query          |      3307 |        1226 | create database relay charset utf8    |
| vm01-relay-bin.000002 | 495 | Anonymous_Gtid |      3307 |        1291 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| vm01-relay-bin.000002 | 560 | Query          |      3307 |        1391 | use `relay`; create table t1 (id int) |
| vm01-relay-bin.000002 | 660 | Anonymous_Gtid |      3307 |        1456 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| vm01-relay-bin.000002 | 725 | Query          |      3307 |        1529 | BEGIN                                 |
| vm01-relay-bin.000002 | 798 | Table_map      |      3307 |        1575 | table_id: 281 (relay.t1)              |
| vm01-relay-bin.000002 | 844 | Write_rows     |      3307 |        1615 | table_id: 281 flags: STMT_END_F       |
| vm01-relay-bin.000002 | 884 | Xid            |      3307 |        1646 | COMMIT /* xid=927 */                  |
| vm01-relay-bin.000002 | 915 | Anonymous_Gtid |      3307 |        1711 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| vm01-relay-bin.000002 | 980 | Query          |      3307 |        1806 | drop database relay                   |
+-----------------------+-----+----------------+-----------+-------------+---------------------------------------+
15 rows in set (0.00 sec)

#pos為relaylog的起始位子
#End_log_pos為binlog的結束位子
#只需要看pos值即可
#看到relay的終點為pos=980

擷取relaylog

mysqlbinlog --start-position=320 --stop-position=980  /data/3308/data/vm01-relay-bin.000002>/tmp/relay.sql

5.3恢復從庫的relay

[root@vm01 ~]# mysql -S /data/3308/mysql.sock -p
Enter password: 
[relay]>source /tmp/relay.sql;
[relay]>select * from t1;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
#從庫資料恢復成功

5.4從庫身份解除

[root@vm01 ~]# mysql -S /data/3308/mysql.sock -p
Enter password: 
[relay]>stop slave;
[relay]>reset slave all;

5.5恢復業務

1、主從庫配置一樣,直接把從庫更改為主庫,主庫更改為從庫並重做主從
2、主從庫配置不一樣,從庫匯出資料給主庫恢復,重做主從