-
延时从库主从复制解决逻辑损坏
主从复制功能解决了物理损坏(比如把1台服务器砸了)没事,
那么逻辑损坏怎么办呢?
什么是延时,比如,主库删除文件1小时后同步到从库,
慢点传送日志,或者从库sql线程延时,执行语句
SQL线程进行延时设置
延时从库前提,设置主从复制
以多实例为例
3307为主库
3308,3309从库
从库 关闭binlog
mysql> set sql_log_bin=0;
-
主库全备设置主从用户
grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
[root@db01 3307]#mysqldump -S /data/3307/mysql.sock -A -R --triggers --master-data=2 --single-transaction > /backup/full3307.sql
3307主库查看pos起点和binlog
[root@db01 ~]#sed -n '22p' /backup/full3307.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=120;
-
3308,3309设置从库
change master to
master_host='10.0.0.51',
MASTER_PORT=3307,
master_user='repl',
master_log_file='mysql-bin.000006',
master_password='123',
MASTER_LOG_POS=4,
master_connect_retry=10;
-
开启从库
start slave;
-
从库设置延时
mysql> stop slave; #停止从库
mysql> change master to master_delay = 60; #延时69秒
mysql> change master to master_delay = 0; #关闭延时
mysql> start slave;
-
从库查看状态
mysql> show slave statusG
SQL_Delay: 60
-
结论
此时主库有任何插入,删除等操作都是60秒后同步到从库
-
利用延时从库恢复数据
-
企业案例
主库删除了db库,从库会在3600秒后,执行删库操作,我要阻止这一切,怎么用延时从库恢复数据呢?
-
处理思路:
停止SQL线程,如果不停止,总有一个时候会同步到从库,
为了严谨,如果后续还有数据从主库复制过来,之关闭sql线程就可以,不让sql线程执行任何操作
- 关闭SQL线程
mysql> stop slave sql_thread;
- 起始点分析
sql线程上次的结束点保存在relay-log.info里,所以relay-log.info就是恢复点
-
结束点分析
我们手动模仿sql线程工作,阻止sql线程执行到drop.因此 结束点就是到drop之前的操作,我要让从库数据状态达到删除之前的状态,还缺什么呢?对于从库来讲是这后半个小时之内的日志,从库是基于relay.log恢复的,从库截取relay.log 到误删除之前的点,relay-log里是从库从主库里收过来的事件,所以,结束点就在relay-log里
-
延时从库恢复数据
主库3307
有以下数据库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| aaaa |
| binlog |
| mysql |
| performance_schema |
| test |
| world |
+--------------------+
-
主库插入数据
mysql> use aaaa;
mysql> create table t1 select * from mysql.user;
mysql> create table t2 select * from mysql.user;
-
从库3308,3309 3309开启延时从库
mysql> stop slave;
mysql> change master to master_delay=180;
mysql> start slave;
-
主库再插入数据
mysql> create table t3 select * from mysql.user;
mysql> create table t4 select * from mysql.user;
-
3307主库删除aaa库
mysql> drop database aaaa;
-
查看aaa库删库了
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| binlog |
| mysql |
| performance_schema |
| test |
| world |
+--------------------+
-
3309从库关闭sql线程
mysql> stop slave sql_thread;
-
此时3307和3308库的aaa表都已经删除了.3309的aaa库还在
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| binlog |
| mysql |
| performance_schema |
| test |
| world |
+--------------------+
-
利用3309的延时从库,把3309的aaa库恢复到主库
-
截取起点
-
relay-log.info里保存了 从库的上次sql线程执行的位置,那么这个点就是起点,
[root@db01 ~]#cat /data/3309/data/relay-log.info
7
./db01-relay-bin.000002
283
mysql-bin.000004
1355285
180
0
1
-
截取终点
终点在relaylog里drop aaaa之前
show relaylog events in 'db01-relay-bin.000002'
或者
[root@db01 ~]#mysqlbinlog --base64-output=decode-rows -vvv /data/3309/data/db01-relay-bin.000002
### @42='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### @43=1 /* ENUM(1 byte) meta=63233 nullable=0 is_null=0 */
# at 7284
#190312 23:23:50 server id 3307 end_log_pos 1362317 CRC32 0x2caf9cff Xid = 5808
COMMIT/*!*/;
# at 7315
#190312 23:24:00 server id 3307 end_log_pos 1362409 CRC32 0xe14bd3b2 Query thread_id=8 exec_time=0 error_code=0
SET TIMESTAMP=1552404240/*!*/;
drop database aaaa
/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
-
截取relaylog
[root@db01 ~]#mysqlbinlog --start-position=283 --stop-position=7284 /data/3309/data/db01-relay-bin.000002 > /tmp/aaaarelaylog.sql
-
恢复relaylog.sql
取消3307从库身份
mysql> stop slave;
mysql> reset salve all;
-
3307主库恢复数据
mysql> source /tmp/aaaarelaylog.sql;
-
报错,是因为截取的relaylog里没有创建aaaa表的语句,relaylog到时间自动删除了一些东西
ERROR 1049 (42000): Unknown database 'aaaa'
Query OK, 0 rows affected (0.00 sec)
ERROR 1046 (3D000): No database selected
ERROR 1146 (42S02): Table 'aaaa.t3' doesn't exist
-
添加aaaa库
mysql> create database aaaa;
mysql> source /tmp/aaaarelaylog.sql;
-
数据都回来了
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| aaaa |
| binlog |
| mysql |
| performance_schema |
| test |
| world |
+--------------------+
7 rows in set (0.00 sec)
mysql> use aaaa;
Database changed
mysql> show tables;
+----------------+
| Tables_in_aaaa |
+----------------+
| t3 |
| t4 |
+----------------+
-
延时从库600秒, 删库10分钟之前有人插入数据,任务是恢复10分钟之前插入的数据
-
模拟有人插入数据
mysql> use test;
mysql> create table t1111 select * from mysql.user;
mysql> create table t2222 select * from mysql.user;
-
删库
mysql> drop database test;
test库没了
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| aaaa |
| binlog |
| mysql |
| performance_schema |
| world |
+--------------------+
由于3309开启了延时从库600秒,此时对于3309这个库来说,test库之前就存在, 只是个空库,别人写的数据,数据还没写到库里,只存到了relaylog里,因此我们要从relaylog里截取10分钟之前写入的数据
-
从库截取relaylog起点
[root@db01 ~]#cat /data/3309/data/relay-log.info
7
./db01-relay-bin.000002
283
mysql-bin.000004
1376814
600
0
1
-
截取relaylog结束点
[root@db01 ~]#mysqlbinlog --base64-output=decode-rows /data/3309/data/db01-relay-bin.000002
# at 6382
#190313 0:01:31 server id 3307 end_log_pos 1383082 CRC32 0x506ff15a Table_map: `test`.`t2222` mapped to number 129
# at 6551
#190313 0:01:31 server id 3307 end_log_pos 1383827 CRC32 0x66414a9d Write_rows: table id 129 flags: STMT_END_F
# at 7296
#190313 0:01:31 server id 3307 end_log_pos 1383858 CRC32 0xd1274362 Xid = 5948
COMMIT/*!*/;
# at 7327
#190313 0:02:12 server id 3307 end_log_pos 1383950 CRC32 0x599faa44 Query thread_id=11 exec_time=0 error_code=0
SET TIMESTAMP=1552406532/*!*/;
drop database test
-
导出 relaylog 10分钟之前别人写入的数据
[root@db01 ~]#mysqlbinlog --start-position=283 --stop-position=7296 /data/3309/data/db01-relay-bin.000002 > /tmp/incrtestelaylog.sql
-
备份3309从库里的 test库,此时是个空库
[root@db01 ~]#mysqldump -S /data/3309/mysql.sock -B test > /tmp/test.sql
-
3307主库导入test库
mysql> source /tmp/test.sql;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| aaaa |
| binlog |
| mysql |
| performance_schema |
| test |
| world |
-
导入数据,数据都回来了
mysql> source /tmp/incrtestelaylog.sql
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1111 |
| t2222 |
+----------------+