延时从库是一种比较特殊的从库,是在主库执行完操作后几分钟或者几小时,从库再进行相应的操作,也能够人为的配置,一般的话多用在比较重要的架构中,可以一定程度上解决数据库的逻辑损坏。
为什么需要延时从库?
因为在主从环境下,主库和从库的操作一般情况下的话是很少会有延迟的,所以主从能解决物理层面的损坏,比如说主库的文件被删除,主库无法启动等等,都可以拿从库去进行恢复。但是在逻辑层面下却出现问题了,因为主库如果执行drop等操作,从库也会跟着执行,这种就叫逻辑损坏,无法有效的防止逻辑损坏,所以延时从库的概念就诞生了。
延时从库也是为了来解决主从复制逻辑损坏的这一问题的。如果说一个主从架构里面做了延时从库,主库数据被删除后,发现这个数据很重要,但是从库却要好几分钟,甚至几个小时后进行执行,现在就可以去这个延时从库把录入进去还未删除的数据给拿出来,恢复到主库中,这样就能有效的防止逻辑损坏。
延时从库配置延时的时间最好是6小时左右,如果发生问题,能有6个小时的反应时间,不致于到时候手忙脚乱,具体还是要看公司的反应时间。
从库配置内容
[t1]>stop slave;
Query OK, 0 rows affected (0.00 sec)
[t1]>change master to master_delay=30; 设置主库延时30秒
Query OK, 0 rows affected (0.01 sec)
[t1]>start slave ;
Query OK, 0 rows affected (0.00 sec)
[t1]>show slave status\G;
SQL_Delay: 30 延时30秒
SQL_Remaining_Delay: NULL 到达执行下一个SQL的时间还有多久
主库操作
[(none)]>create database delay1 charset utf8mb4;
Query OK, 1 row affected (0.00 sec)
[(none)]>show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 486 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
从库查看
表示创建库的操作将在27秒后进行执行,虽然需要27秒后执行,但是主库的日志其实已经到达从库了,只是延时了SQL_thread执行时间。
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 486
SQL_Delay: 30
SQL_Remaining_Delay: 27
(1)及时的去发现主库发生了逻辑层面的损坏。
(2)需要停止延时从库的SQL线程,防止它继续执行relaylog日志内的操作。
(3)线上生产项目如果是网站类,需要挂维护页或者提示用户正在进行维护中。
(4)需要通过relaylog日志去恢复数据,截取起点和终点,在从库中进行。
(5)日志起点即为stop slave时的relaylog位置点,因为stop后,SQL线程就停止执行日志。
(6)日志终点截取到逻辑损坏(drop)之前一条为止。
(7)截取的日志直接恢复到从库,检查从库数据是否有问题,没有问题的话替代主库进行工作。
准备好主从环境
开始模拟逻辑损坏的故障恢复
1、开启延时从库
[(none)]>change master to master_delay=300;
[(none)]>start slave ;
[(none)]>show slave status \G;
SQL_Delay: 300
2、故障模拟
主库:
[(none)]>create database delay charset utf8;
[(none)]>use delay;
[delay]>create table test(id int );
[delay]>insert into test values (1),(2),(3),(34);
[delay]>commit;
[delay]>drop database delay;
从库:
[(none)]>stop slave sql_thread; 停止SQL线程
一般的话300秒足够以上操作进行完成了,所以这边只设置了300秒,能更好的来演示模拟故障。
3、截取relaylog日志(从库)
起点:应为relaylog记录的position号
Relay_Log_File: hdfeng-relay-bin.000002
Relay_Log_Pos: 320
终点:查看relaylog的事件信息,看最后被误操作的内容
查看relaylog只需要关注开始的pos即可,后面的是master中的pos
[(none)]>show relaylog events in 'hdfeng-relay-bin.000002';
+-------------------------+-----+----------------+-----------+-------------+-----------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------------+-----+----------------+-----------+-------------+-----------------------------------------+
| hdfeng-relay-bin.000002 | 4 | Format_desc | 20 | 123 | Server ver: 5.7.20, Binlog ver: 4 |
| hdfeng-relay-bin.000002 | 123 | Previous_gtids | 20 | 154 | |
| hdfeng-relay-bin.000002 | 154 | Rotate | 10 | 0 | mysql-bin.000003;pos=486 |
| hdfeng-relay-bin.000002 | 201 | Format_desc | 10 | 0 | Server ver: 5.7.20-log, Binlog ver: 4 |
| hdfeng-relay-bin.000002 | 320 | Anonymous_Gtid | 10 | 551 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| hdfeng-relay-bin.000002 | 385 | Query | 10 | 661 | create database delay charset utf8 |
| hdfeng-relay-bin.000002 | 495 | Anonymous_Gtid | 10 | 726 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| hdfeng-relay-bin.000002 | 560 | Query | 10 | 828 | use `delay`; create table test(id int ) |
| hdfeng-relay-bin.000002 | 662 | Anonymous_Gtid | 10 | 893 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| hdfeng-relay-bin.000002 | 727 | Query | 10 | 966 | BEGIN |
| hdfeng-relay-bin.000002 | 800 | Table_map | 10 | 1014 | table_id: 220 (delay.test) |
| hdfeng-relay-bin.000002 | 848 | Write_rows | 10 | 1069 | table_id: 220 flags: STMT_END_F |
| hdfeng-relay-bin.000002 | 903 | Xid | 10 | 1100 | COMMIT /* xid=63 */ |
| hdfeng-relay-bin.000002 | 934 | Anonymous_Gtid | 10 | 1165 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| hdfeng-relay-bin.000002 | 999 | Query | 10 | 1260 | drop database delay |
+-------------------------+-----+----------------+-----------+-------------+-----------------------------------------+
15 rows in set (0.00 sec)
所以这次截取的日志应该是从320——999,因为999其实是drop操作的起点,drop操作是还没有做的。
[root@hdfeng mysql]# mysqlbinlog --start-position=320 --stop-position=999 /opt/mysql-replication/mysql3320/mysql/hdfeng-relay-bin.000002 >/tmp/relay.sql
截取完成!
4、进行relaylog的日志恢复(从库)
如果被误删除的数据库数量过大,则可以直接把从库更改为主库,这样不需要再把恢复的数据导到主库中去了,非常的方便。如果数据量比较小,则把从库的这个单个库备份到主库即可。
[root@hdfeng mysql]# mysql -uroot -p -S /opt/mysql-replication/mysql3320/mysql/mysql.sock
[(none)]>source /tmp/relay.sql;
[delay]>show tables;
+-----------------+
| Tables_in_delay |
+-----------------+
| test |
+-----------------+
1 row in set (0.00 sec)
[delay]>select * from test;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 34 |
+------+
4 rows in set (0.00 sec)
恢复成功!
如果需要把从库变成主库需要:
[delay]>stop slave;
[delay]>reset slave all;
然后在原来的主库进行change master to 操作,主从就更换完成了!