在RDS MySQL实例进行切换类的运维操作时,应用程序与代理的连接会有短暂的断开,会对业务造成一定影响,您可以参考本文使用连接保持功能,保证连接不断开,提升产品可用性,降低运维成本。
功能简介
RDS MySQL代理的连接保持功能,即在发生实例切换类的操作时,能保持应用程序与代理的连接不断开,用户通过代理地址访问数据库的应用程序不会收到连接断开的报错,如下图所示。
实现原理
数据库代理连接分为前端连接(代理与客户端的连接)和后端连接(代理与数据库的连接),在执行实例切换类操作时,能够在后端连接断开的情况下,保留前端连接,代理在此基础上实现了连接保持能力。
对于后端数据库是RDS MySQL的连接,连接保持的关键在于后端连接(代理与后端RDS MySQL连接)的连接状态恢复。
RDS MySQL的连接状态通常包括系统变量、用户变量、临时表、字符集编码、事务状态和Prepare语句状态信息等。本文将以set names utf8mb4作为连接状态为例介绍RDS MySQL连接保持的实现原理。
主动切换:
主动切换场景下,RDS MySQL数据库代理实现连接保持分为三个步骤:
包含主动切换的运维操作:
主动主备切换
升级小版本
修改重启类参数(修改参数时需重启实例)
变更主实例配置
开始切换:阻塞新的连接和新的请求
由于代理不具备事务保持能力,因此,对于不同状态的会话,采取不同的处理方式:
阻塞期间事务活跃的会话:代理将放行请求到后端数据库主节点执行。
阻塞期间新开启的事务的会话:代理将阻塞请求,客户端的现象是阻塞等待服务端回包。
阻塞结束事务仍活跃的会话:客户端与代理的连接将会断开,后端数据库会对未提交的事务进行回滚。
切换中:切换存量连接
切换过程中会修改存量连接的切换状态:
无法保持的连接:代理会将整个连接断开。
能够保持的连接:连接将会切换至新的数据库节点。
连接池中原数据库主节点的连接:会被清理。
切换完成:恢复连接
对于能成功保留的连接,代理与后端新的数据库主节点建立连接,并且恢复连接状态。
故障切换:
当系统出现故障时,RDS实例会自动进行主备切换,提升一个备节点为主节点,这种切换是非预期的,称为故障切换(Failover)。
代理会缓存当前正在数据库上执行或将要转发的SQL语句。当数据库发生故障时,代理与后端数据库的连接将会断开。代理感知到数据库Failover后,不会立刻断开与客户端的连接,代理会将失败的读请求重新转发到可用的数据库节点,并且恢复连接状态。
对于失败的写请求,代理不能确定数据库是否写成功,因此故障切换时的会话保持不支持写请求。
开启连接保持
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实例的数据库代理详情。 |