第28节 从库Seconds_Behind_Master延迟总结

本文总结了引起MySQL主从复制延迟的各种原因,包括大事务、大表DDL、不当的键索引使用、不合理参数设置、从库binlog记录、长期未提交事务、InnoDB行锁及MDL锁等问题,并通过具体测试案例解析延迟现象。

注意:本文是《深入理解MySQL主从原理 32节》的第28节


到这里本系列已经接近尾声了,是时候对常见引起主从延迟的情形进行一个总结了。我想如果我一开始就把这些情形拿出来也许大家对具体的原因不是那么清楚,但是经过本系列的学习,我相信当我说起这些情形的时候大家都很清楚它的原因了。当然如果还有其他造成延迟的情形也欢迎大家一起讨论。

一、总结

有了前面的知识我们就能够从本质上了解造成延迟的可能有哪些,我先来总结一下这些可能,我将其分为两类:

(1)第一类:

这一类延迟情况可能造成服务器有较高的负载,可能是CPU/IO的负载。因为从库在实际执行Event,如果我们服务器的负载比较高应该考虑这几种情况,关于如何查看线程的负载可以参考29节。

  • 大事务造成的延迟,其延迟会不会从0开始增加,而是直接从主库执行了多久开始。比如主库执行这个事务花费的20秒,要么延迟就会从20开始,可以自己细心观察一下很容易看到。这是因为Query Event中没有准确的执行时间,这个在上一节的计算公式中详细描述过了 ,可以参考第8节和第27节。

  • 大表DDL造成的延迟,其延迟会从0开始增加,因为Query Event记录了准确的执行时间。这个在上一节的计算公式中也详细描述过了,可以参考第8节和第27节。

  • 表没有合理的使用主键或者唯一键造成的延迟。这种情况不要以为设置slave_rows_search_algorithms参数为 INDEX_SCAN,HASH_SCAN就可以完全解决问题,原因我们在第24节进行了描述。

  • 由于参数sync_relay_log,sync_master_info,sync_relay_log_info不合理导致,特别是sync_relay_log会极大的影响从库的性能。原因我们在第26节进行过描述,因为sync_relay_log设置为1会导致大量relay log刷盘操作。

  • 是否从库开启了记录binary log功能即log_slave_updates参数开启,如果不是必要可以关闭掉。这种情况我遇到很多次了。

(2)第二类:

这一类延迟情况往往不会造成服务器有较高的负载。它们要么没有实际的执行Event,要么就是做了特殊的操作造成的。

  • 长期未提交的事务可能造成延迟瞬间增加,因为GTID_EVENT和XID_EVENT是提交时间其他Event是命令发起的时间。这个我们在第27节中举例描述过了。

  • Innodb层的行锁造成的延迟,这种是在从库有修改操作并且和SQL线程修改的数据有冲突的情况下造成的,因为我们前面23节说过SQL线程执行Event也会开启事务和获取行锁,下面我们进行测试。

  • MySQL层的MDL LOCK造成的延迟,这种情况可能是由于SQL线程执行某些DDL操作但是从库上做了锁表操作造成,原因我们已经在23节描述过了,下面我们进行测试。

  • MTS中不合理的设置参数slave_checkpoint_period参数导致,这个在第27节已经测试过了。

  • 在从库运行期间手动改大了从库服务器时间,这个也在第27节已经测试过了。

更多主从同步相关可以参考我的《深入理解MySQL主从原理 32节》专栏:

KTA2LA6$`_9Z0B2~P)FULPL.png

二、相关测试

因为上面的延迟情形很多我们都已经测试和讲述过了。下面我们测试锁造成的延迟情形。

(1)Innodb层的行锁造成的延迟

这个很容测试,我只要先在从库做一个事务和SQL线程修改的数据相同即可以出现,大概测试如下:

从库:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from tmpk;
Query OK, 4 rows affected (0.00 sec)
不要提交
主库执行同样的语句
mysql> delete from tmpk;
Query OK, 4 rows affected (0.30 sec)

这个时候你会观察到延迟如下:

image.png

如果查看sys.innodb_lock_waits能看到如下的结果:

image.png

当然如果查看INNODB_TRX也可以观察到事务的存在,这里就不截图了,大家可以自己试试。

(2)MySQL层的MDL LOCK造成的延迟

这种情况也非常容易测试,我们只需要开启一个事务做一个select,然后主库对同样的表做DDL就可以出现如下:

从库:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> 
mysql> 
mysql> select * from tkkk limit 1;
+------+------+------+
| a    | b    | c    |
+------+------+------+
|    3 |    3 |  100 |
+------+------+------+
1 row in set (0.00 sec)
不要提交,表上MDL LOCK就不会释放
主库执行语句:
mysql> alter table tmpk add testc int ;
Query OK, 0 rows affected (1.14 sec)
Records: 0  Duplicates: 0  Warnings: 0

这个时候你将会看到如下的信息:

image.png

我们可以通过state看到这是等待MDL lock获取而导致的延迟,关于MDL lock的详情可以参考我的文章:

http://blog.itpub.net/7728585/viewspace-2143093/

三、总结

通过整个系列,我们应该清楚了Seconds_Behind_Master计算的方法,同时如果出现了延迟,我们首先查看从库是否有负载,根据是否有负载进行区别对待,注意这里的负载一定要使用 top -H查看io/sql/woker线程的负载。我曾不止一次的遇到朋友问我延迟问题,当我问他负载如何的时候他告诉我负载不高啊整体负载也就不到2,这里我们应该注意的是对于一个线程只能使用到一个CPU核,虽然整体负载不到2但是可能io/sql/worker线程已经跑满了,实际上负载已经很高了,我们来看下面的这个截图就是sql线程负载高的截图如下:

image.png

这个截图我们发现虽然整体负载不高在1多一点,但是Lwp号20092的线程已经跑满了,这个线程就是我们的sql线程,这个时候出现延迟是很可能的,这个截图正是来自一个没有合理使用主键或者唯一键造成的延迟的案例,案例如下:

https://www.jianshu.com/p/56e8ca2223a0

我们查看CPU负载应该使用 top -H去查看,查看io负载可以使用iotop,iostat等工具。我需要强调一下看MySQL负载的时候我们必须用 线程的眼光去看,第29节将让你获得这种能力。

到这里整个系列接近尾声,大家会发现主从的原理的还是比较复杂的,这可能颠覆了以前我们的认知,以前我们认为主从无非就是搭建起来能跑同时知道有io/sql线程就可以了(这确实很简单)。整个系列结论很简单,我们无非就是想配置出安全高效的从库同时知道延迟是怎么导致的,出现延迟后我们如何处理,我自认为本系列还是将这些问题讲解得很清楚了。当然如果本系列的原理部分都能够理解得很好,那么工作中解决主从问题一定会更加得心应手。


第28节结束

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7728585/viewspace-2655672/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7728585/viewspace-2655672/

<think>我们正在处理MySQL主从同步中Seconds_Behind_Master为NULL的问题。根据之前的上下文,虽然Slave_IO_Running和Slave_SQL_Running都是Yes,但数据未同步,且现在Seconds_Behind_Master为NULL,这通常表示复制出现了严重错误。 根据引用[1]和引用[2]的内容,Seconds_Behind_Master的计算方式是通过比较从的SQL线程当前正在执行的事件的时间戳与从的当前时间戳的差值。如果为NULL,通常意味着复制进程出现了问题,无法计算延迟。 以下是针对Seconds_Behind_Master为NULL的排查步骤和解决方法: 1. **检查错误信息**:在`SHOW SLAVE STATUS\G`的输出中,查看`Last_IO_Error`和`Last_SQL_Error`字段,这些字段会提供具体的错误信息。 2. **检查复制线程状态**:确认`Slave_IO_Running`和`Slave_SQL_Running`的状态。虽然用户说都是Yes,但在某些情况下,其中一个线程可能会在运行中出错而停止,但状态可能还未更新。另外,注意`Slave_SQL_Running_State`字段的状态描述。 3. **常见错误及解决**: - **主键冲突(1062错误)**:从上插入了一条主键已经存在的记录。解决方法:根据业务需求,跳过错误或者手动修复数据。 - **表结构不一致**:主和从的表结构不同,导致从无法应用SQL线程的事件。解决方法:确保表结构一致。 - **行不存在(1032错误)**:从上删除或更新一条不存在的记录。解决方法:手动修复数据。 - **权限问题**:复制用户权限不足。解决方法:授予足够的权限。 - **网络问题**:网络中断导致IO线程无法获取主的binlog。解决方法:检查网络连接。 4. **跳过错误**(谨慎使用,仅适用于可以跳过错误且不影响数据一致性的情况): ```sql STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; -- 跳过一个事件 START SLAVE; ``` 或者指定跳过特定错误码(在配置文件中设置): ```ini slave_skip_errors = 1062,1032 ``` 5. **重新配置复制**:如果以上方法无效,可以考虑重新配置复制链路(注意:需要重新同步数据): - 在主上执行`SHOW MASTER STATUS`记录binlog位置。 - 在从上停止复制,然后重置复制状态: ```sql STOP SLAVE; RESET SLAVE ALL; -- 清除所有复制信息 ``` - 重新配置复制: ```sql CHANGE MASTER TO ... -- 根据主状态重新设置 START SLAVE; ``` 6. **使用GTID模式**(如果启用了GTID):在GTID模式下,重新配置复制可以避免手动指定binlog位置,但需要确保数据一致性。 7. **数据一致性校验**:使用如`pt-table-checksum`和`pt-table-sync`工具来检查和修复主从不一致。 8. **查看错误日志**:MySQL的错误日志通常包含更详细的信息,查看错误日志有助于定位问题。 注意:在操作之前,务必备份数据,尤其是生产环境。 下面是一个具体的排查流程: **步骤1:查看从复制状态** ```sql SHOW SLAVE STATUS\G ``` 重点关注以下字段: - Slave_IO_Running: Yes - Slave_SQL_Running: Yes - Seconds_Behind_Master: NULL - Last_IO_Errno: 0 - Last_IO_Error: - Last_SQL_Errno: 0 - Last_SQL_Error: - Slave_SQL_Running_State: 如果`Last_IO_Error`或`Last_SQL_Error`不为空,则根据错误信息处理。 **步骤2:检查Slave_SQL_Running_State** 如果该状态显示为`Waiting for the next event`,则可能表示IO线程正常,但SQL线程没有工作。或者显示`Waiting for dependent transaction to commit`等,可能表示存在多线程复制的问题。 **步骤3:检查错误日志** 在从服务器上查看MySQL错误日志,通常位于`/var/log/mysql/error.log`或MySQL数据目录下。 **步骤4:尝试重启复制线程** ```sql STOP SLAVE; START SLAVE; ``` 然后再次检查状态。 **步骤5:如果SQL线程因错误停止** 如果发现`Slave_SQL_Running`变为No,则根据错误号处理。例如,遇到1062错误(主键冲突),可以跳过该事件(使用`SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1`)或者手动修复数据。 **步骤6:考虑重新同步** 如果问题无法解决,且数据不一致,可能需要重新同步从。可以使用mysqldump导出主数据,然后导入从,并重新设置复制位置。 注意:在重新同步期间,主数据会继续变化,所以需要确保在导出数据时记录准确的binlog位置(使用`--master-data`参数)。 总结:Seconds_Behind_Master为NULL通常表示复制出现了错误,需要根据具体的错误信息进行解决。常见原因包括复制错误、网络中断、主重启、从重启后无法连接到主等。 如果以上步骤无法解决,请提供具体的错误信息以便进一步分析。 相关问题: 1. 如何解决MySQL主从同步中的1062主键冲突错误? 2. 如何重新同步MySQL主从数据库? 3. 如何跳过MySQL复制中的错误事件? 4. MySQL复制中GTID模式有什么优势? 5. 如何使用pt-table-checksum检查主从数据一致性?</think>### MySQL主从同步异常:Seconds_Behind_Master为NULL的解决方法 当MySQL主从同步中`Seconds_Behind_Master`显示为**NULL**时,表示复制进程出现严重错误,无法计算延迟时间。以下是系统化的排查和解决方案: --- #### 一、核心原因分析 1. **SQL线程异常停止**: - SQL线程无法执行中继日志中的事件 - 常见于数据冲突、表结构不一致等场景 2. **IO线程连接中断**: - 无法从主获取binlog事件 - 网络故障或权限问题导致[^1] 3. **系统时间不同步**: - 主从服务器时间差异过大 - 导致时间戳计算失效(计算公式:`从系统时间 - 事件时间戳`)[^1][^2] 4. **关键进程崩溃**: - `Slave_SQL_Running`或`Slave_IO_Running`状态异常 - 虽显示为"Yes"但实际已停止工作 --- #### 二、诊断步骤 ```sql SHOW SLAVE STATUS\G ``` 重点关注以下字段: | **字段** | **正常值** | **异常处理** | |------------------------|------------------|-------------------------------| | `Slave_IO_Running` | `Yes` | 检查网络/主binlog权限 | | `Slave_SQL_Running` | `Yes` | 查看`Last_SQL_Error` | | `Last_IO_Errno` | `0` | 根据错误代码修复 | | `Last_SQL_Errno` | `0` | 解决数据冲突或表结构不一致 | | `Relay_Log_Pos` | 持续增长 | 检查磁盘空间/文件权限 | --- #### 三、解决方案 ##### 1. 修复SQL线程错误(最常见) ```sql -- 查看具体错误 SHOW SLAVE STATUS\G -- 观察Last_SQL_Error字段 -- 跳过单个错误(谨慎使用) STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE; -- 修复后验证 SELECT SLEEP(5); SHOW SLAVE STATUS\G -- 检查Seconds_Behind_Master ``` ##### 2. 处理主从不一致 ```bash # 主生成一致性快照 mysqldump --single-transaction --master-data=2 -uroot dbname > dump.sql # 从导入并重置复制 STOP SLAVE; SOURCE dump.sql; RESET SLAVE; CHANGE MASTER TO ... # 使用主SHOW MASTER STATUS的位置 START SLAVE; ``` ##### 3. 修复时间不同步 ```bash # 在所有服务器执行 sudo timedatectl set-ntp yes sudo systemctl restart mysqld ``` ##### 4. 网络与权限修复 ```sql -- 主检查复制用户权限 SHOW GRANTS FOR 'repl'@'slave_ip'; -- 从测试连接 mysql -h master_ip -u repl -p -e "SHOW DATABASES;" ``` ##### 5. 终极重建方案 ```sql -- 从执行 STOP SLAVE; RESET SLAVE ALL; -- 彻底清除复制信息 -- 重新配置 CHANGE MASTER TO MASTER_HOST='master_ip', MASTER_USER='repl', MASTER_PASSWORD='password', MASTER_AUTO_POSITION=1; -- 使用GTID模式更可靠 START SLAVE; ``` --- #### 四、预防措施 1. **启用GTID复制**: ```ini [mysqld] gtid_mode=ON enforce_gtid_consistency=ON ``` 2. **定期校验数据**: ```bash pt-table-checksum --replicate=test.checksums h=master_ip ``` 3. **监控配置**: - 设置告警:`Seconds_Behind_Master > 60 OR NULL` - 监控`Slave_SQL_Running_State`状态 > ⚠️ **重要提示**:操作前务必备份数据!跳过错误可能导致数据不一致。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值