1、主从复制监控

主库监控

  1. #监控主库 Binlog Dump线程
  2. # 每个从库都有一行信息
  3. mysql -e "show processlist" | grep "Binlog Dump"
  4. #监控从库端口, UUID信息
  5. mysql -e "show slave hosts"

从库监控

show slave status\G

2、线程相关监控信息

2.1、主库相关监控信息

#主库连接信息、binlog位置信息 (master.info)
Master_Host: 127.0.0.1
Master_User: backup
Master_Port: 3316
Connect_Retry: 10
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 444

2.2、从库相关监控信息

#从库中relay-log的回放信息 (relay-log.info) 
Relay_Log_File: db01-relay-bin.000006
Relay_Log_Pos: 320
# relay-log 对应的 binlog位置点
Relay_Master_Log_File: mysql-bin.000001
Exec_Master_Log_Pos: 444

2.3、线程监控信息:主要用来排查主从故障

show slave status\G

#显示信息↓↓↓
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

#IO线程错误代码
Last_IO_Errno: 0

#IO线程完整报错
Last_IO_Error: 

#SQL线程错误代码
Last_SQL_Errno: 0

#SQL线程完整报错
Last_SQL_Error:

2.4、过滤复制相关信息

#默认情况是全库复制
Replicate_Do_DB: 
Replicate_Ignore_DB: 
Replicate_Do_Table: 
Replicate_Ignore_Table: 
Replicate_Wild_Do_Table: 
Replicate_Wild_Ignore_Table:

2.5、落后于主库的秒数

Seconds_Behind_Master: 0

2.6、延时从库状态信息

#人为配置的延迟复制信息
SQL_Delay: 0
SQL_Remaining_Delay: NULL

2.7、GTID复制信息

Retrieved_Gtid_Set: 
Executed_Gtid_Set: 
Auto_Position: 0

3、 日志文件 position相关信息

3.1、IO线程 已经获取到的主库BinLog的位置点 (master.info)

#作用: IO下次请求日志时, 起点位置
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 444

3.2、SQL线程 回放到的relay-log位置点 (relay-log.info)

Relay_Log_File: db01-relay-bin.000006
Relay_Log_Pos: 320

3.3、SQL线程 回放的realy-log位置点, 对应的主库BinLog的位置点 (relay-log.info)

#作用: 计算主从复制延时日志量
Relay_Master_Log_File: mysql-bin.000001
Exec_Master_Log_Pos: 600

4、主从复制故障分析

4.1、如何监控

mysql> show slave status\G
Slave_IO_Running: Yes     : IO线程工作状态: YES、NO、Connecting  
Slave_SQL_Running: Yes    : SQL线程工作状态: YES、NO
Last_IO_Errno: 0          : IO故障代码: 2003,1045,1040,1593,1236
Last_IO_Error:            : IO线程报错详细信息  
Last_SQL_Errno: 0         : SQL故障代码: 1008,1007
Last_SQL_Error:           : SQL线程报错详细信息

4.2、IO线程故障

4.2.1、连接主库失败 (连接错误)

#连接报错通过不会记录到错误日志
1. 连接信息错误: 网络、防火墙、最大连接数上线、主库宕机
2. 验证信息错误: IP、port、user、password、加密插件(native)

#连接错误排查方法 (登录主从复制用户)
mysql  -ubackup  -p123  -h 127.0.0.1  -P 3316

(1). 主库宕机

#主库
systemctl  stop   mysql

#从库
mysql> show slave status\G
Slave_IO_Running: Connecting
Last_IO_Errno: 2003
Last_IO_Error: error reconnecting to master 'backup@127.0.0.1:3316' - retry-time: 10 retries: 1 message: Can't connect to MySQL server on '127.0.0.1' (111)

#还原主从关系
主库
systemctl start mysql
从库
mysql> start slave;

(2). 模拟用户密码错误

Slave_IO_Running: Connecting
Last_IO_Errno: 1045
Last_IO_Error: error connecting to master 'backup@127.0.0.1:3316' - retry-time: 10 retries: 1 message: Access denied for user 'backup'@'localhost' (using password: YES)

(3). 模拟端口号错误

Slave_IO_Running: Connecting
Last_IO_Errno: 2003
Last_IO_Error: error connecting to master 'backup@127.0.0.1:3306' - retry-time: 10 retries: 2 message: Can't connect to MySQL server on '127.0.0.1' (111)

(4). 最大连接数上限

#主库
#mysql会为 root本地管理员用户预留一个连接
mysql> set global  max_connections=0;
max_connections=200

#从库
Slave_IO_Running: Connecting
Last_IO_Errno: 1040
Last_IO_Error: error connecting to master 'backup@127.0.0.1:3316' - retry-time: 10 retries: 1 message: Too many connections

#还原主从关系
主库
mysql> set global  max_connections=200;
vim  my.cnf
max_connections=200
从库
stop  slave;
start  slave;

4.3、请求二进制日志错误

报错现象: IO线程为No, 会记录错误日志
主库binlog损坏, 缺失
主从 server_id, server_uuid 相同

(1). 模拟主从server_id相同

1. 从库修改 server_id 与 主库相同
mysql> set global  server_id=3316;
# IO线程是长连接: 需要重启才会重新连接
mysql> stop slave;
mysql> start slave;

2. 从库报错信息
Slave_IO_Running: No
Last_IO_Errno: 13117
Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work 
(or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).

3. 解决方案
mysql> set global  server_id=3317;
mysql> stop slave;
mysql> start slave;

(2). 模拟主库binlog损坏

1. 主库
mysql> show master status;
mysql-bin.000004 |      156
#重置主库binlog日志
mysql> reset master;
mysql> show master status;
mysql-bin.000001 |      156

2. 从库
Relay_Master_Log_File: mysql-bin.000004
Exec_Master_Log_Pos: 156
Slave_IO_Running: No
Last_IO_Errno: 13114
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the first event 'mysql-bin.000004' at 156, the last event read from '/data/3316/logs/mysql-bin.000004' at 125, the last byte read from '/data/3316/logs/mysql-bin.000004' at 156.'

3. 解决办法: 数据一致, 停止主从关系, 清空主从同步信息, 重新做主从复制
主从数据处理一致
从库停止所有线程
mysql> stop slave;
将从库复制信息清空: relay-log、relay-log.info、master.info
mysql> reset  slave  all;
重新做主从
CHANGE MASTER TO
   MASTER_HOST='127.0.0.1',
   MASTER_PORT=3316,
   MASTER_USER='backup',
   MASTER_PASSWORD='123',
   MASTER_LOG_FILE='mysql-bin.000001',
   MASTER_LOG_POS=156,
   MASTER_CONNECT_RETRY=10;
mysql> start slave;
mysql> show slave status\G

4. 生产中要注意什么 (主从数据不一致时)
重构主从
(1). 备份恢复
(2). change  master  to  ...
(3). start  slave;

4.4、SQL线程故障

relay-log 损坏 (机率小)

#处理方法: 重构主从

方法一: 备份恢复: change  master  to  ... , start  slave;
#缺点: 简单、恢复时间长

方法二: 通过 slave  status\G; 找到SQL线程 当前 回放到什么位置了 
#前提: 主库binlog 完整
#缺点: 稍微复杂

Relay_Log_File: db01-relay-bin.000006
Relay_Log_Pos: 320
# relay-log 对应的 binlog位置点
Relay_Master_Log_File: mysql-bin.000001
Exec_Master_Log_Pos: 444

方式三: 重构主从
change  master  to  mysql-bin.000001 - 444

执行SQL出问题

场景一: 主从节点配置不一样: 平台、版本、配置参数、sql_mode

在生产中修改配置要同步进行, 减少差异

场景二: 修改的对象不存在 (库、表、用户)

原因: 从库被人为操作: 误删除了: 错误代码: 1108

模拟从库误删除
#从库
mysql> drop database  jjq;

#主库
mysql> drop database  jjq;

#从库
Last_SQL_Errno: 1008
Last_SQL_Error: Error 'Can't drop database 'jjq'; database doesn't exist' on query. Default database: 'jjq'. Query: 'drop database  jjq'

#解决方法
方式一: 主从数据恢复一致, 重构主从
方式二: 跳过错误
stop slave;
set global sql_slave_skip_counter = 1;
start slave;

创建的用户已存在 (库、表、用户、约束冲突)

原因: 从库被写入了: 错误代码: 1007

模拟从库被被写入:
#从库
mysql> create database db01  charset utf8mb4;

#主库
mysql> create database db01  charset utf8;

#从库
mysql> show slave status\G;
Slave_SQL_Running: No
Last_Errno: 1007
Last_Error: Error 'Can't create database 'db01'; database exists' on query. Default database: 'db01'. Query: 'create database db01  charset utf8'

解决办法: 
方式一: 停止主从同步线程, 手工删除从库 已存在的db01库, 启动主从同步
mysql> stop slave;
mysql> drop database db01;
mysql> start slave;

方式二: 跳过错误 (不推荐), 针对 1007 错误报错, 需要做评估是否跳过 (生产中以主库为准)
mysql> stop slave;
mysql> set global sql_slave_skip_counter = 1;
mysql> start slave;

4.5、常见错误代码

  • 1007:对象已存在
  • 1032:无法执行DML
  • 1062:主键冲突,或约束冲突

    4.5.1、解决办法

    部分场景可用

    mysql> stop slave;
    mysql> drop database db01;
    mysql> start slave;

    不推荐的方法

    vim my.cnf
    slave-skip-errors = all
    slave-skip-errors = 1032,1062,1007

    5、总结: 生产中规避SQL线程错误

  • 给开发人员从库查询权限, 读写分离中间件

  • 不适用双主结构, PXC、MGR替代双主结构
  • 半同步模式、增强半同步等、替代异步复制 (提高主从一致性问题)

    6、主从延时监控及原因

    6.1、监控方法

    方式一

    #不能完全相信此参数
    mysql -e "show slave status\G" | grep "Seconds_Behind_Master"
    Seconds_Behind_Master: 0  # 延迟秒数
    

    方式二

    ```

    通过pos对比

  1. 查看主库的日志量 show master status;

  2. 查看从库已经拿到的日志量 mysql -e “show slave status\G” | grep “Master_Log”

    已经拿到的主库的binlog日志量

    Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 156

  3. 查看从库已经执行到的日志量

    已经执行的binlog日志量

    Relay_Master_Log_File: mysql-bin.000002 Exec_Master_Log_Pos: 156

    <a name="0iTTf"></a>
    #### 方式三
    

    pt-heartbeat工具监控

    <a name="hqDtf"></a>
    ## 6.2、导致延时的主要原因
    <a name="5pTUG"></a>
    ### 6.2.1、外部因素
    
  4. 网络延时 (网卡绑定)
  5. 主从硬件设备, 配置文件参数不一致
  6. 从库太多
  7. 主库压力大
    <a name="zgeq8"></a>
    ### 6.2.2、主库导致的延迟
    <a name="rdZAE"></a>
    #### binlog 记录不及时
    
    mysql> select @@sync_binlog; 参数说明: 1: 每次事物提交都立即刷新binlog到磁盘 (数据安全) 0: 由操作系统确定, 什么时候刷新到磁盘 (提升性能) 大于1: 提交多少个事物, 刷新到磁盘

建议: 对主从实时性要求比较高时, 设置 sync_binlog=1

<a name="EqYu1"></a>
#### Binlog Dump 线程串行工作

串行工作模式: 保证执行顺序, 缺点: 对于并发事物没有全局唯一标识 大事物、并发事务高、DDL 并发事物 主从延时解决办法: GTID模式复制, Binlog Dump 在传输日志的时候可以支持并发 5.6 版本加入了GTID复制模式, 需要手工配置, Binlog Dump 在传输时可以并发 5.7 版本GTID做了增强, 没有开启GTID 也自动维护匿名GTID信息 大事务 主从延迟解决办法 将一个大事物, 拆分成多个小事务执行 例如: 更新 100w条数据, 分10次更新, 每次10w条 DDL操作 主从延时解决办法 停止主从同步、主库修改完、在从库手动执行、重新同步

<a name="wp4Dm"></a>
#### 怎么判断是主库导致的延迟

主库: mysql -e “show master status;” mysql-bin.000002 | 156

从库: mysql -e “show slave status\G” | grep “Master_Log” Relay_Master_Log_File: mysql-bin.000002 Exec_Master_Log_Pos: 156

<a name="YJ1Fn"></a>
### 6.2.3、从库导致主从延时的原因
<a name="OrfuO"></a>
#### 排查主从延迟方法

已经执行的主库日志量 (relay-log.info): 判断回放有没有延时 Relay_Master_Log_File: mysql-bin.000004 Exec_Master_Log_Pos: 141847

<a name="8sqqO"></a>
#### IO线程
从库IO比较慢, relay-log慢, 推荐将relay-log放到SSD上

relay_log_purge 线程会自动清理relaylog mysql> show variables like ‘%relay%’;

<a name="8qJUX"></a>
#### SQL 线程
主库可以并行事务,从库SQL线程串行回放。<br />所以:并发事务高、大事务、DDL
<a name="89GLn"></a>
### 6.2.4、解决方法
5.6 版本: 开启GTID后,可以多SQL线程,只能针对不同的库的事务进行并行SQL恢复<br />5.7 版本: 做了增强,基于逻辑时钟的并行回放 (MTS)<br />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

<a name="S92WK"></a>
# 7、降低主从复制延迟
参考博客: [https://www.jianshu.com/p/6f25002db226](https://www.jianshu.com/p/6f25002db226)

解决方法: 从库多线程并行复制

说明: 主库是默认多线程并行工作的, 5.5版本从库默认chuan’xing ```