主从延时问题的监控以及处理建议
监控方法:
方法一:确定有没有延时
Seconds_Behind_Master: 0(秒数)
方法二:
主库:
mysql> show master status ;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 | 151847 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
从库:
[root@db01 data]# mysql -S /tmp/mysql3308.sock -uroot -p123 -e "show slave status \G"|grep "Master_Log"
已经拿到的主库日志量(master.info):判断传输有没有延时
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 151847
已经执行的主库日志量(relay-log.info): 判断回放有没有延时
Relay_Master_Log_File: mysql-bin.000004
Exec_Master_Log_Pos: 141847
计算主从复制延时日志量。
导致延时的主要原因
外部因素
网络延时
主从硬件、参数等不一致
从库太多
主库压力太大
主库:
(1) binlog记录不及时。
mysql> select @@sync_binlog;
+---------------+
| @@sync_binlog |
+---------------+
| 1 |
+---------------+
参数说明:
1 : 每次事务提交都立即刷新binlog到磁盘。
0 : 由操作系统决定,什么刷新磁盘。
(2) DUMP线程串行工作。
大事务、并发事务高、DDL
解决办法:
5.6版本加入GTID复制模式,但手工配置。DUMP在传输日志时可以并发。
5.7版本GTID做了增强,不手工开启也自动维护匿名的GTID信息。
(3)怎么判断是主库导致的延时?
主库:
mysql> show master status ;
从库:
mysql -S /tmp/mysql3308.sock -uroot -p123 -e "show slave status \G"|grep "Master_Log"
从库方面
#IO线程:
从库IO比较慢。relay 落地慢。可以将realy放到 SSD
#SQL 线程: 串行回放。
主库可以并行事务,从库SQL线程串行回放。
所以:并发事务高、大事务、DDL
解决方法:
5.6 版本: 开启GTID后,可以多SQL线程,只能针对不同的库的事务进行并行SQL恢复。
5.7 版本: 做了增强,基于逻辑时钟的并行回放。MTS。
5.7 的从库并发配置方法。
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
#已经执行的主库日质量(relay-log.info): 判断回放有没有延时
Relay_Master_Log_File: mysql-bin.000004
Exec_Master_Log_Pos: 141847
过滤复制
7.1 主库实现
binlog_do_db 白名单
binlog_ignore_db 黑名单
说明: 是否记录binlog日志来控制过滤。
7.2 从库实现 ******
实现方法:
IO线程不做限制。
SQL线程回放时,选择性回放。
参数:
replicate_do_db=world
replicate_do_db=oldboy
replicate_ignore_db=
replicate_do_table=world.city
replicate_ignore_table=
replicate_wild_do_table=world.t*
replicate_wild_ignore_table=
配置方法:
方法一:
修改配置文件并重启
vim /data/3308/my.cnf
replicate_do_db=world
replicate_do_db=oldboy
systemctl restart mysqld3308
方法二:
STOP SLAVE SQL_THREAD;
CHANGE REPLICATION FILTER REPLICATE_DO_DB = (oldguo, oldboy);
START SLAVE SQL_THREAD;
延时从库的应用
配置方法:
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
思路 :
主库发生了逻辑损坏(DROP,truncate)时,可以使用延时从库快速恢复数据。
2小时延时
10:00 做的drop database A;
- 及时监控故障: 主库 10:05发现故障,从库此时8:05数据状态
- 立即将从库的SQL线程关闭。 需要对A业务挂维护页。
- 停止所有线程。
- 在延时从。恢复A库数据
手工模拟SQL线程工作,直到drop之前位置点。
SQL线程上次执行到的位置------》drop之前
relay.info ----> 分析drop位置点 —》 截取relaylog日志----》 source
故障模拟及恢复
故障模拟:
create database delaydb charset utf8mb4;
use delaydb;
create table t1(id int);
insert into t1 values(1),(2),(3);
commit;
drop database delaydb;
截取日志:
起点: SQL上次执行到的位置点,
Relay_Log_File: db01-relay-bin.000004
Relay_Log_Pos: 320
终点: drop 之前
db01-relay-bin.000004 | 1006 | Query | 7 | 152967 | drop databas
[root@db01 tmp]# mysqlbinlog --start-position=320 --stop-position=1006 /data/3309/data/db01-relay-bin.000004 >/tmp/bin.sql
mysql> reset slave all;
mysql> set sql_log_bin=0;
mysql> source /tmp/bin.sql;
mysql> set sql_log_bin=1;
mysql> show tables;
+-------------------+
| Tables_in_delaydb |
+-------------------+
| t1 |
+-------------------+
1 row in set (0.00 sec)
mysql> select * from t1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
GTID复制
清理环境
pkill mysqld
\rm -rf /data/mysql/data/*
\rm -rf /data/binlog/*
mkdir -p /data/mysql/data /data/binlog
chown -R mysql.mysql /data/*
准备配置文件
主库db01:
mv /etc/my.cnf /tmp
cat > /etc/my.cnf <<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/mysql/data
socket=/tmp/mysql.sock
server_id=51
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db01 [\\d]>
EOF
slave1(db02):
mv /etc/my.cnf /tmp
cat > /etc/my.cnf <<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/mysql/data
socket=/tmp/mysql.sock
server_id=52
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db02 [\\d]>
EOF
slave2(db03):
mv /etc/my.cnf /tmp
cat > /etc/my.cnf <<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/mysql/data
socket=/tmp/mysql.sock
server_id=53
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db03 [\\d]>
EOF
初始化数据
mysqld --initialize-insecure --user=mysql --basedir=/data/app/mysql --datadir=/data/mysql/data
启动数据库
/etc/init.d/mysqld start
9.5 构建主从:
master:51
slave:52,53
51:
grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
52\53:
change master to
master_host='10.0.0.51',
master_user='repl',
master_password='123' ,
MASTER_AUTO_POSITION=1;
start slave;