在RDS MySQL实例进行切换类的运维操作时,应用程序与代理的连接会有短暂的断开,会对业务造成一定影响,您可以参考本文使用连接保持功能,保证连接不断开,提升产品可用性,降低运维成本。
关于RDS数据库代理的使用问题和更多相关信息,欢迎加入用户钉钉群(106730000316)进行咨询、反馈和交流 。
功能简介
RDS MySQL代理的连接保持功能,即在发生实例切换类的操作时,能保持应用程序与代理的连接不断开,用户通过代理地址访问数据库的应用程序不会收到连接断开的报错,如下图所示。


实现原理
数据库代理连接分为前端连接(代理与客户端的连接)和后端连接(代理与数据库的连接),在执行实例切换类操作时,能够在后端连接断开的情况下,保留前端连接,代理在此基础上实现了连接保持能力。
对于后端数据库是RDS MySQL的连接,连接保持的关键在于后端连接(代理与后端RDS MySQL连接)的连接状态恢复。
RDS MySQL的连接状态通常包括系统变量、用户变量、临时表、字符集编码、事务状态和Prepare语句状态信息等。本文将以set names utf8mb4作为连接状态为例介绍RDS MySQL连接保持的实现原理。
主动切换:
主动切换场景下,RDS MySQL数据库代理实现连接保持分为三个步骤:
包含主动切换的运维操作:
- 主动主备切换 
- 升级小版本 
- 修改重启类参数(修改参数时需重启实例) 
- 变更主实例配置 
- 开始切换:阻塞新的连接和新的请求 - 由于代理不具备事务保持能力,因此,对于不同状态的会话,采取不同的处理方式: - 阻塞期间事务活跃的会话:代理将放行请求到后端数据库主节点执行。 
- 阻塞期间新开启的事务的会话:代理将阻塞请求,客户端的现象是阻塞等待服务端回包。 
- 阻塞结束事务仍活跃的会话:客户端与代理的连接将会断开,后端数据库会对未提交的事务进行回滚。 
  
- 切换中:切换存量连接 - 切换过程中会修改存量连接的切换状态: - 无法保持的连接:代理会将整个连接断开。 
- 能够保持的连接:连接将会切换至新的数据库节点。 
- 连接池中原数据库主节点的连接:会被清理。 
  
- 切换完成:恢复连接 - 对于能成功保留的连接,代理与后端新的数据库主节点建立连接,并且恢复连接状态。  
故障切换:
当系统出现故障时,RDS实例会自动进行主备切换,提升一个备节点为主节点,这种切换是非预期的,称为故障切换(Failover)。
代理会缓存当前正在数据库上执行或将要转发的SQL语句。当数据库发生故障时,代理与后端数据库的连接将会断开。代理感知到数据库Failover后,不会立刻断开与客户端的连接,代理会将失败的读请求重新转发到可用的数据库节点,并且恢复连接状态。
对于失败的写请求,代理不能确定数据库是否写成功,因此故障切换时的会话保持不支持写请求。
开启连接保持
- 您可以在线体验(免费)基于连接保持功能的实例无感切换,实时观察实例性能变化与功能效果,详情请参见免费体验RDS MySQL数据库代理无感切换。 
- 2024年01月09日起,符合开启连接保持功能条件的RDS MySQL实例在开通数据库代理时,会默认开启连接保持功能。开启连接保持功能后,您可以随时关闭该功能。 
前提条件
主动切换的连接保持
RDS实例满足以下条件:
- 版本:MySQL 5.6或5.7或8.0 
- 系列:高可用系列、集群系列 
- 存储类型:云盘、高性能本地盘 
- 代理类型:通用型、独享型 
- 已开通数据库代理,且代理的内核版本不低于1.14.5_20231207。 
故障切换的连接保持
RDS实例满足以下条件:
- 版本:MySQL 5.6或5.7或8.0 
- 系列:高可用系列、集群系列 
- 存储类型:云盘、高性能本地盘 
- 代理类型:独享型 说明- 通用型数据库代理仅支持主动切换场景下的连接保持,独享型数据库代理支持主动切换和故障切换场景下的连接保持。 
- 已开通数据库代理,且代理的内核版本不低于2.9.1。 
开启步骤
- 访问RDS实例列表,在上方选择地域,然后单击目标实例ID。 
- 在左侧导航栏,单击数据库代理。 
- 在基本信息区域,单击连接保持右侧的开启。 说明- 若无连接保持字样,说明您的实例不符合连接保持的开通条件。 
使用连接保持
前提条件
- 已开通数据库代理。 
- 数据库代理已开启连接保持。 
操作步骤
- 访问RDS实例列表,在上方选择地域,然后单击目标实例ID。 
- 在左侧导航栏,单击数据库代理。 
- 根据业务需要配置目标代理连接地址的访问策略,详情请参见配置数据库代理连接地址访问策略。其中读写类型设置为读写(读写分离)。 
- 根据业务需要申请目标代理连接地址的内网/外网地址,详情请参见设置数据库代理连接地址。 
- 在应用程序中,使用目标代理连接地址的内网/外网地址与端口号进行数据库的连接。 
- 数据库实例进行切换的运维类操作时,数据库代理会自动实现连接保持功能,使用代理连接地址的应用程序与代理的连接不会断开。 
使用限制
在切换过程中,连接保持功能无法保持如下场景中的连接:
- MySQL服务端还没有完全返回包的连接。例如,100 MB的结果集,只返回了50 MB的结果集,剩余的结果集还在返回中。 
- 存在未提交的事务。 
- 连接上使用过change user语句。 
- 连接上使用过LOAD DATA语句。 
- 存在临时表。 
- 通过代理地址进行Binlog订阅的连接。 
- 不支持FOUND_ROWS、ROW_COUNT和LAST_INSERT_ID函数的调用,这些函数可以调用成功,但是无法保证调用结果的正确性。其中 - SELECT FOUND_ROWS()的用法MySQL官方已不推荐,建议您将- SELECT FOUND_ROWS()替换为- SELECT COUNT(*) FROM tb1进行查询,详情请参见FOUND_ROWS()。
注意事项
- 由于连接会重连,所以使用 - select connection_id()查询当前连接的thread id可能会变化。
- 由于连接会重连,所以 - show processlist或者SQL洞察中显示的IP地址和端口,可能会与客户端实际的IP地址和端口不一致。
- 如果连接上存在用户自定义的变量,连接能保持,但用户变量会失效。 
关闭连接保持
前提条件
实例已开启连接保持功能。
操作步骤
- 访问RDS实例列表,在上方选择地域,然后单击目标实例ID。 
- 在左侧导航栏,单击数据库代理。 
- 在基本信息区域,在连接保持右侧单击关闭。 
功能测试
本文仅对主动切换场景进行测试。
测试环境
- 测试用RDS MySQL实例如下: - MySQL 8.0版本、高可用系列。 
- 实例规格为8核16 GB独享型规格(mysql.x2.xlarge.2c)。 
 
- 测试工具:Sysbench 
- 测试数据如下: - 100张表,其中每张表包含40000行数据。 
- 并发线程数为128。 
 
测试方法
在不同运维场景下,测试RDS MySQL实例的连接保活率(即执行运维操作前后的连接保持比例)。
执行测试语句如下:
sysbench --db-driver=mysql --mysql-host=127.X.X.1 --mysql-port=3306 --mysql-user=username --mysql-password='' --tables=100 --table-size=40000 --threads=128 --mysql-db=sbtest --report-interval=5  --time=600 oltp_read_write run上述测试语句中的关键参数含义如下:
- db-driver:数据库引擎 
- mysql-host:数据库代理地址 
- tables:数据库中的表数量 
- table-size:每张表包含的记录条数 
- threads:并发线程数 
- time:测试时间,单位: 秒 
测试结果
在如下测试的运维场景中,RDS MySQL实例均能保持100%的连接保活率。
| 主动切换场景 | 保活率 | 
| 升级小版本 | 100% | 
| 主动主备切换 | 100% | 
| 变更主实例配置 | 100% | 
| 修改重启类参数 | 100% | 
相关API
| API | 描述 | 
| 修改RDS实例的数据库代理功能。 | |
| 查询RDS实例的数据库代理详情。 |