一、MASTER TO MASTER_DELAY延迟复制
便于数据恢复,设置从库延迟主库1个小时
方案优点:没有万一,都能快速恢复数据
潜在不足:资源利用率有点低,为了保证数据的安全性,多了2台延时从,降低了从库利用率
【提高从库效率】
1小时延时从也不是完全没有用,对于一些“允许延时”的业务,可以使用1小时延时从,例如:
(1)运营后台,产品后台
(2)BI进行数据同步
(3)研发进行数据抽样,调研
但需要注意的是,毕竟这是从库,只能够提供“只读”服务哟。
【总结】
保证数据的安全性是DBA第一要务,需要进行:
(1)全量备份+增量备份,并定期进行恢复演练,但该方案恢复时间较久,对系统可用性影响大
(2)1小时延时从,双份1小时延时从能极大加速数据库恢复时间
(3)个人建议1小时延时从足够,后台只读服务可以连1小时延时从,提高资源利用率
主从复制功能解决了物理损坏(比如把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;
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 status\G
SQL_Delay: 60
此时主库有任何插入,删除等操作都是60秒后同步到从库
主库删除了db库,从库会在3600秒后,执行删库操作,我要阻止这一切,怎么用延时从库恢复数据呢?
停止SQL线程,如果不停止,总有一个时候会同步到从库,
为了严谨,如果后续还有数据从主库复制过来,之关闭sql线程就可以,不让sql线程执行任何操作
3、关闭SQL线程
mysql> stop slave sql_thread;
4、起始点分析
sql线程上次的结束点保存在relay-log.info里,所以relay-log.info就是恢复点
5、结束点分析
我们手动模仿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;
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;
mysql> drop database aaaa;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| binlog |
| mysql |
| performance_schema |
| test |
| world |
+--------------------+
mysql> stop slave sql_thread;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| binlog |
| mysql |
| performance_schema |
| test |
| world |
7、 利用3309的延时从库,把3309的aaa库恢复到主库
7.1 截取起点
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
2、截取终点
终点在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 |
+----------------+