MySQL · 捉虫动态 · GTID下slave_net_timeout值太小问题

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 背景 官方 5.6 最新版本 5.6.24 有这样一个bugfix,当使用 GTID 协议进行复制,并且备库的 slave_net_timeout 值设置太小的话,备库的 slave io 线程会卡住,同时主库上的 binlog dump 线程数一直在涨,官方的bug地址 。 bug分析 首先

背景

官方 5.6 最新版本 5.6.24 有这样一个bugfix,当使用 GTID 协议进行复制,并且备库的 slave_net_timeout 值设置太小的话,备库的 slave io 线程会卡住,同时主库上的 binlog dump 线程数一直在涨,官方的bug地址 。

bug分析

首先说明下几个概念:
1. slave_net_timeout,这个变量控制备库 IO 线程的连接超时,如果IO线程在指定时间内没有从主库收到数据的话,就断开重连,默认值是3600秒;
2. heartbeat 事件,主库在dump线程空闲的时候(dump线程已经把所有binlog都发给备库了,主库还没有更新操作),就隔断时间发一个 heartbeat 给备库,以免备库超时断开,这个时间间隔是备库在 change master 时传过来的,在 rpl_slave.cc 中可以看到,默认取 min<float>(SLAVE_MAX_HEARTBEAT_PERIOD, (slave_net_timeout/2.0))
3. GTID 的 auto_position 协议,正是因为有了 GTID,才可以在 chang master 时不指定binlog坐标(filename, pos),但是主库dump线程在发给备库event的时候,还是需要从某个坐标开始的,只是这个过程通过 GTID 能自动搜出来罢了,关于如何找到要发送的第一个 binlog 可以看下之前的月报,找到后就需要从这个 binlog 开头开始扫描,找到第一个备库没有 GTID,然后开始发送。

问题的源头就出在 binlog 文件扫描上,官方 bug 的复现步骤中有这样一个条件,use 1GB binlog file size. stop slave at high binlog position (>800MB),就是说主库的 binlog 要比较大,并且备库 IO 线程要停在这个 binlog 比较靠后的位置。这样备库 start slave 连上的时候,主库的 dump 线程就要从这个 binlog 开头往后扫,找到开始发送 binlog 的位置,如果文件比较大的话,这个扫描时间就会比较长。heartbeat 事件是在主库空闲的时候才会发送的,在扫描过种中是不会检查要不要发 heartbeat 的,如果备库的 slave_net_timeout 设置比较小的话,超过时间还没收到一个事件,这时备库 IO 就会停下,然后重连。

IO 线程重连会导致另外一个问题,我们知道一个主库是可以拖多个备库的,但是对每个备库只能有一个连接,如果已经连上来的备库再发一个 dump 请求的话,主库就会把当前备库老的 IO 连接置为 killed,具体函数是 sql/rpl_master.cc 中的 kill_zombie_dump_threads,但这个 kill 只是置了标志位,还需要老的 dump 线程自己判断,然后退出。dump 线程 killed 状态检测只在切换 binlog 和空闲的时候,如果这个时候老的 dump 线程还在扫 binlog,即使已经是killed了也不会退出。而同时新的 dump 线程依然要从头扫 binlog,重复上面的过程,导致备库 IO 又超时重连,因此在主库上show processlist的话,会看到 dump 线程慢慢堆积起来。

下面的结果就是备库 slave_net_timeout 设置为10s的测试结果,可以看到相邻 dump 线程差不多间隔10s。

|  9 | root | localhost:46882 | NULL | Binlog Dump GTID |  159 | init  | NULL             |
| 10 | root | localhost:46929 | NULL | Binlog Dump GTID |  149 | init  | NULL             |
| 11 | root | localhost:46975 | NULL | Binlog Dump GTID |  138 | init  | NULL             |
| 12 | root | localhost:47023 | NULL | Binlog Dump GTID |  127 | init  | NULL             |
| 13 | root | localhost:47074 | NULL | Binlog Dump GTID |  115 | init  | NULL             |
| 14 | root | localhost:47143 | NULL | Binlog Dump GTID |  104 | init  | NULL             |
| 15 | root | localhost:47206 | NULL | Binlog Dump GTID |   93 | init  | NULL             |
| 16 | root | localhost:47255 | NULL | Binlog Dump GTID |   82 | init  | NULL             |
| 17 | root | localhost:47311 | NULL | Binlog Dump GTID |   71 | init  | NULL             |
| 18 | root | localhost:47362 | NULL | Binlog Dump GTID |   60 | init  | NULL             |
| 19 | root | localhost:47427 | NULL | Binlog Dump GTID |   49 | init  | NULL             |

如果在备库上 show slave status 的的话,会看到 IO 线程接收的 binlog 位点一直不更新,就像 hang 住了一样。

bug修复

出现这个问题是因为主库 dump 线程检测 heartbeat_period 和 thd->killed 的粒度太大,都是 binlog 文件级别的,因此官方的改法就是把两者的检测粒度降为event级别,dump 线程每 read 一个 event,都会检测是否该发送 heartbeat 了,同时 thd 的 killed 标志是否被置上,是的话就退出。
具体的patch可以看官方github

有了这个 patch 后,主库 dump 线程还是需要时间扫描binlog,备库的 IO 线程看起来依然像 hang 住一样,但是已经不会超时重连,主库的dump 线程也不会堆积。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
25天前
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
20 1
|
25天前
Mybatis+mysql动态分页查询数据案例——条件类(HouseCondition)
Mybatis+mysql动态分页查询数据案例——条件类(HouseCondition)
14 1
|
25天前
Mybatis+mysql动态分页查询数据案例——房屋信息的实现类(HouseDaoMybatisImpl)
Mybatis+mysql动态分页查询数据案例——房屋信息的实现类(HouseDaoMybatisImpl)
21 2
|
25天前
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
Mybatis+mysql动态分页查询数据案例——工具类(MybatisUtil.java)
15 1
|
25天前
|
Java 数据库连接 mybatis
Mybatis+mysql动态分页查询数据案例——Mybatis的配置文件(mybatis-config.xml)
Mybatis+mysql动态分页查询数据案例——Mybatis的配置文件(mybatis-config.xml)
14 1
|
25天前
Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)
Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)
14 1
|
25天前
Mybatis+mysql动态分页查询数据案例——房屋信息的接口(IHouseDao)
Mybatis+mysql动态分页查询数据案例——房屋信息的接口(IHouseDao)
12 1
|
10天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)
|
1月前
|
关系型数据库 MySQL 数据库连接
关于MySQL-ODBC的zip包安装方法
关于MySQL-ODBC的zip包安装方法
|
29天前
|
关系型数据库 MySQL 数据库
rds安装数据库客户端工具
安装阿里云RDS的数据库客户端涉及在本地安装对应类型(如MySQL、PostgreSQL)的客户端工具。对于MySQL,可选择MySQL Command-Line Client或图形化工具如Navicat,安装后输入RDS实例的连接参数进行连接。对于PostgreSQL,可以使用`psql`命令行工具或图形化客户端如PgAdmin。首先从阿里云控制台获取连接信息,然后按照官方文档安装客户端,最后配置客户端连接以确保遵循安全指引。
81 1

相关产品

  • 云数据库 RDS MySQL 版