day09-02-主从原理及故障
5.主从复制原理 *****
5.1 主从复制中涉及的文件
主库:binlog
从库:
relaylog 中继日志
master.info 主库信息文件
relaylog.info relalog应用的信息
5.2 主从复制中涉及的线程
主库:
binlog_dump thread:DUMP_T
从库:
SLAVE_IO_THREAD: IO_T
SLAVE_SQL_THRED:SQL_T
5.3 主从复制工作原理 ********

1.从库执行change master to 命令(主库的链接信息+复制的起点)
2.从库会将以上信息记录到master.info
3.从库执行start slave,从库立即开启IO_T,SQL_T
4.从库IO_T,读取master.info文件中的信息,获取到IP,PORT,user,pass,binlog的位置信息。
5.从库IO_T链接主库,主库专门提供有一个DUMP_T线程,负责和IO_T进行交互。
6.IO_T请求根据binlog位置点信息(mysql-bin.000004.445),请求主库新的binlog
7.主库通过DUMP_T将最新的binlog网络传输至从库的IO_T
8.IO_T接收到新的binlog日志,存储到TCP/IP缓存,立即返回ACK给主库
9.IO_T将TCP/IP缓存转储到磁盘relaylog,并更新master.info(binlog信息)
10.SQL_T读取relay.info的信息,获取到上次已经应用过的relaylog的位置信息。
11.SQL_T会按照上次的位置点回放最新的relaylog,再次更新relay.info信息
小细节:
12.从库会根据(参数relay_log_purge=ON)自动定期删除应用过的relay-log
- 主库DUMP线程实时监控主库的binlog变化,如果有新变化,发信号通知从库,从库就再一次进行请求
补充说明:
主库一旦构建成功,主库当中发生新的变化,都会通过DUMP_T发送信号给IO_T,增强主从复制的实时性
5.4 主从复制监控****
命令:
show slave status \G
[root@mysql-node01 data]# mysql -uroot -p -S /data/3309/mysql.sock -e "show slave status\G"
Enter password:
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
\#主库有关的信息,来自master.info
Master_Host: 10.0.50.61
Master_User: repl
Master_Port: 3308
Connect_Retry: 10
----
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1039
----
\#从库relaylog应用信息有关的(relay.info)
Relay_Log_File: mysql-node01-relay-bin.000002
Relay_Log_Pos: 914
Relay_Master_Log_File: mysql-bin.000004
\# 从库线程运行状态(排错)
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
\# 从库同步线程状态不是"YES",还需要看这4个信息 + 从库的error-log
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
\# 过滤复制有关的信息:
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
\# 从库延时主库的时间(秒)
Seconds_Behind_Master: 0
\# 延时从库(防止误操作)
SQL_Delay: 0
SQL_Remaining_Delay: NULL
\# GTID复制有关的状态信息
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
[root@mysql-node01 data]#
5.5 主从复制故障*****
slave从库故障:
5.5.1 IO_Thread 线程故障:
1)链接主库 Connecting
网络,链接信息错误或变更了,防火墙,连接数上限
排查思路:
1.使用复制用户手工登陆
解决:
1.stop slave
2.reset slave all;
3.change master to ....
4.start slave
2)请求binlog
binlog 没开
binlog 损坏,不存在
reset master
(如果master做了reset master操作,会直接导致主从关系断裂,需要在slave节点按照master最新的binlog文件,重新执行
stop slave;
CHANGE MASTER TO
MASTER_HOST='master2.example.com',
MASTER_USER='replication',
MASTER_PASSWORD='password',
MASTER_PORT=3306,
MASTER_LOG_FILE='master2-bin.001',
MASTER_LOG_POS=4,
MASTER_CONNECT_RETRY=10;
start slave;
重新构建主从关系)
3)存储binlog到relaylog
relaylog 不能写入,也会报IO故障,检查relaylog权限
5.5.2 SQL_Thread 线程故障
SQL_Thread 作用就是在slave节点重新执行IO_Thread请求到的binlog信息
realy-log损坏
回放relay-log(执行SQL语句)
研究一条SQL语句为什么会执行失败?
insert delete update ---> t1 表不存在
create table db_name ---> db 已存在
约束冲突(主键,唯一键,非空....)
合理处理方法:
把握一个原则,一切以主库为准进行解决。
如果出现问题,在slave节点,找出故障语句,并进行反操作。
最直接稳妥办法,重新构建主从
官方给出处理方法(以从库为核心的处理方案):
方法一:(生产,看具体情况细节,前提是确认主从信息(库、表、表结构、字符集、数据,已完全一致)
stop slave;
set global sql_slave_skip_counter = 1;
#将同步指针向下移动一个,如果多次不同步,可以重复操作。
start slave;
方法二:(生产不推荐)
/etc/my.cnf
slave-skip-errors = 1032,1062,1007
常见错误代码:
1007:对象已存在
1032:无法执行DML
1062:主键冲突,或约束冲突
但是,以上操作有时是有风险的,最安全的做法就是重新构建主从。把握一个原则,一切以主库为主.
对于主键冲突问题:
Error 'Duplicate entry '20663' for key 'PRIMARY'' on query
先校验 主从 之间 重复主键数据行的信息,然后以master为准,把slave 节点上主键对应的数据行进行update,然后再跳过这个报错,再start slave
第三方对比表差异工具:
pt-table-checker 对比差异
pt-table-sync 同步
故障演示:
slave 新建db:
mysql> select @@port;
+--------+
| @@port |
+--------+
| 3309 |
+--------+
1 row in set (0.00 sec)
mysql>
mysql> create database db_test;
Query OK, 1 row affected (0.00 sec)
mysql>
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db_test |
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
mysql>
master节点也建立db:
mysql> select @@port;
+--------+
| @@port |
+--------+
| 3308 |
+--------+
1 row in set (0.00 sec)
mysql> create database db_test charset utf8mb4;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db_test |
| mysql |
| performance_schema |
| sys |
+--------------------+
6 rows in set (0.00 sec)
mysql>
mysql> use db_test
Database changed
mysql>
mysql> create table t1(id int);
Query OK, 0 rows affected (0.01 sec)
mysql>
从库查看db_test.t1
mysql> select @@port;
+--------+
| @@port |
+--------+
| 3309 |
+--------+
1 row in set (0.00 sec)
mysql> use db_test
Database changed
mysql> show tables;
Empty set (0.00 sec)
mysql>
从库检查 同步状态:
mysql> show slave status\G
*************************** 1. row ***************************
......
Slave_IO_Running: Yes
Slave_SQL_Running: No
......
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1007
Last_SQL_Error: Error 'Can't create database 'db_test'; database exists' on query. Default database: 'db_test'. Query: 'create database db_test charset utf8mb4'
......
可以看到,slave节点SQL_Thread报错,提示不能创建db_test,查询db_test已存在。
在主从关系中,slave一切数据信息以master为准。
解决:
1)停止slave
2)删除已经创建的db_test
3)重新开启主从
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql>
mysql> drop database db_test;
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> show slave status \G
......
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
......
mysql>
为了很大程度避免SQL线程故障
1)从库只读
mysql> show variables like '%read_only%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| read_only | OFF |
| super_read_only | OFF |
+-----------------------+-------+
5 rows in set (0.00 sec)
mysql>
2)使用读写分离中间件
atlas
mycat
ProxySQL
MaxScale
5.6 主从延时监控及原因*****
5.6.1 主库方面原因
1)binlog写入不及时
sync_binlog=1 #有可能这个参数影响的,1为最优。
2)默认情况下,DUMP_T是串行传输binlog
DUMP_T 是按照事件的方式,传输二进制日志到slave节点IO_T线程
在并发事务量大时,或者大事务,由于dump_t是串行工作的,导致传送binlog较慢。
如何解决?
使用并行传输,前提:
必须使用GTID,使用group commit方式,可以支持dump_t并行
mysql> show variables like '%group_commit%';
+-----------------------------------------+-------+
| Variable_name | Value |
+-----------------------------------------+-------+
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
+-----------------------------------------+-------+
2 rows in set (0.01 sec)
mysql>
必须开启双“一”参数
3)主库极其繁忙
满语句,锁等待,从库个数比较多,网络延时
5.6.2 从库方面原因
1)传统复制(Classic)中,
如果主库并发事务量很大,或者出现大事务
由于是单SQL线程,导致不管传的日志有多少,只能一次执行一个事务。
5.6 版本,有了GTID,可以实现多SQL线程,但只能基于不同库的事务进行并发回放。
# 从库的并发工作线程参数
mysql> show variables like '%worker%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| slave_parallel_workers | 0 |
+------------------------+-------+
1 row in set (0.00 sec)
mysql>
5.7 版本中,有了增强GTID,在SQL方面,提供了基于逻辑时钟(logical_clock),binlog加入了seq_no机制,
真正实现了基于事务级别的并发回放,这种技术我们把它称之为MTS(enhanced multi-threaded slave)
1) 主从硬件差异太大
2) 主从参数配置不一样
3) 从库和主库索引不一样
4) 主从版本有差异
主从延时的监控
Seconds_Behind_Master: 0
主库方面原因的监控:
主库:
mysql> show master status\G
*************************** 1. row ***************************
File: mysql-bin.000004
Position: 1391
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
mysql>
从库:
mysql> show slave status\G
*************************** 1. row ***************************
......
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1391
......
mysql>
对比主从读取主库binlog进度,看是否在同一position进行判断。
从库方面原因:
查看从库拿了多少日志:
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1391
执行了多少日志:
Relay_Log_File: mysql-node01-relay-bin.000003
Relay_Log_Pos: 320
binlog 和 relay-log 对应关系查看:
# 最准确,最直观:
[root@mysql-node01 data]# cat relay-log.info
7
./mysql-node01-relay-bin.000003
320
mysql-bin.000004
1391
0
0
1
## mysql-node01-relay-bin.000003 : 320
## 对应 mysql-bin.000004 :1391
[root@mysql-node01 data]#
#第二种方法:
mysql> show slave status\G
......
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 1391
......
Exec_Master_Log_Pos: 1391
Relay_Log_Space: 1646
......
mysql>
# Read_Master_Log_Pos 表示slave从master读取binlog日志的位置。
# Exec_Master_Log_Pos 表示slave执行binlog日志的位置。
# Read_Master_Log_Pos 与 Exec_Master_Log_Pos 相等,则证明从库无延迟。
# Exec_Master_Log_Pos 小于 Read_Master_Log_Pos 较多,说明slave的SQL执行线程繁忙,有阻塞,压力大。
# Exec_Master_Log_Pos 卡在哪个位置,就通过查看relaylog内容,定位对应的事件以及语句。
# 可以查看relay-log具体内容
mysql> show relaylog events in 'mysql-node01-relay-bin.000003';
+-------------------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+-------------------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql-node01-relay-bin.000003 | 4 | Format_desc | 3309 | 123 | Server ver: 5.7.26-log, Binlog ver: 4 |
| mysql-node01-relay-bin.000003 | 123 | Previous_gtids | 3309 | 154 | |
| mysql-node01-relay-bin.000003 | 154 | Rotate | 3308 | 0 | mysql-bin.000004;pos=1391 |
| mysql-node01-relay-bin.000003 | 201 | Format_desc | 3308 | 0 | Server ver: 5.7.26-log, Binlog ver: 4 |
+-------------------------------+-----+----------------+-----------+-------------+---------------------------------------+
4 rows in set (0.00 sec)
mysql>
MySQL延迟追平
stop slave;
set global innodb_flush_log_at_trx_commit=2;
set global sync_binlog=0;
set global slave_parallel_type=LOGICAL_CLOCK;
set global binlog_transaction_dependency_tracking=COMMIT_ORDER;
set global slave_parallel_workers=8;
set global slave_preserve_commit_order=0;
start slave;
# 待追平以后
stop slave;
set global innodb_flush_log_at_trx_commit=1;
set global sync_binlog=1;
start slave;
如果库经常有延迟,写入较大
主库和从库都要做以下设置
stop slave;
set global binlog_transaction_dependency_tracking=COMMIT_ORDER;
set global binlog_group_commit_sync_delay=0;
set global binlog_group_comit_sync_no_delay_count=0;
set global slave_parallel_type=LOGICAL_CLOCK;
set global transaction_write_set_extraction=XXHASH64;
set global binlog_transaction_dependency_tracking=WRITESET;
set global slave_parallel_workers=8;
set global slave_preserve_commit_order=0;
start slave;
# 配置文件添加
binlog_group_commit_sync_delay=0
binlog_group_commit_sync_no_delay_count=0
slave_parallel_type=logical_clock
transaction_write_set_extraction=XXHASH64
binlog_transaction_dependency_tracking=WRITESET
slave_parallel_workers=8 -----注意节点CPU核数
SLAVE_PRESERVE_COMMIT_ORDER=0
#
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~