避免固定 RDS 代理
当数据库请求不依赖于先前请求的状态信息时,多路复用效率更高。在这种情况下,RDS Proxy 可以在每个事务结束时重用连接。此类状态信息的示例包括可通过 SET
或 SELECT
语句更改的大多数变量和配置参数。默认情况下,客户端连接上的 SQL 事务可以在底层数据库连接之间多路复用。
与代理的连接可以进入一种称为固定的状态。固定连接后,每个后续事务将使用相同的底层数据库连接,直到会话结束。在会话结束之前,其他客户端连接也不能重用该数据库连接。客户端连接断开时,会话结束。
当 RDS Proxy 检测到不适合其他会话的会话状态更改时,它会自动将客户端连接固定到特定的数据库连接。固定降低了连接重用的有效性。如果您的所有连接或几乎所有连接都遇到固定,请考虑修改应用程序代码或工作负载,以减少导致固定的条件。
例如,您的应用程序更改了会话变量或配置参数。在这种情况下,后面的语句可能依赖于新变量或参数来生效。因此,当 RDS 代理处理更改会话变量或配置设置的请求时,它会将该会话固定到数据库连接。这样,会话状态对于同一会话中的所有后续事务仍然有效。
对于某些数据库引擎,此规则并不适用于您可以设置的全部参数。RDS 代理会跟踪某些语句和变量。因此,在您修改这些内容时,RDS 代理不会固定会话。在这种情况下,RDS 代理仅将连接重用于具有相同设置值的其他会话。有关 RDS 代理针对数据库引擎跟踪的内容的详细信息,请参阅以下内容:
RDS 代理针对 RDS for SQL Server 数据库跟踪的内容
以下是 RDS 代理跟踪的 SQL Server 语句:
USE
SET ANSI_NULLS
SET ANSI_PADDING
SET ANSI_WARNINGS
SET ARITHABORT
SET CONCAT_NULL_YIELDS_NULL
SET CURSOR_CLOSE_ON_COMMIT
SET DATEFIRST
SET DATEFORMAT
SET LANGUAGE
SET LOCK_TIMEOUT
SET NUMERIC_ROUNDABORT
SET QUOTED_IDENTIFIER
SET TEXTSIZE
SET TRANSACTION ISOLATION LEVEL
RDS 代理针对 RDS for MariaDB 数据库和 RDS for MySQL 数据库跟踪的内容
以下是 RDS 代理跟踪的 MariaDB 和 MySQL 语句:
DROP DATABASE
DROP SCHEMA
USE
以下是 RDS 代理跟踪的 MySQL 和 MariaDB 变量:
AUTOCOMMIT
AUTO_INCREMENT_INCREMENT
CHARACTER SET (or CHAR SET)
CHARACTER_SET_CLIENT
CHARACTER_SET_DATABASE
CHARACTER_SET_FILESYSTEM
CHARACTER_SET_CONNECTION
CHARACTER_SET_RESULTS
CHARACTER_SET_SERVER
COLLATION_CONNECTION
COLLATION_DATABASE
COLLATION_SERVER
INTERACTIVE_TIMEOUT
NAMES
NET_WRITE_TIMEOUT
QUERY_CACHE_TYPE
SESSION_TRACK_SCHEMA
SQL_MODE
TIME_ZONE
TRANSACTION_ISOLATION (or TX_ISOLATION)
TRANSACTION_READ_ONLY (or TX_READ_ONLY)
WAIT_TIMEOUT
最大限度地减少固定
RDS 代理的性能优化包括尝试通过最小化固定来最大化事务级别连接重用(多路复用)。
您可以执行以下步骤以最大限度地减少固定:
-
避免可能导致固定的不必要的数据库请求。
-
在所有连接中一致地设置变量和配置设置。这样,后续会话更有可能重用具有这些特定设置的连接。
但是,对于 PostgreSQL 设置,变量会导致会话固定。
-
对于 MySQL 引擎系列数据库,可将会话固定筛选条件应用于代理。您可以免除某些类型的操作,使其不固定会话(如果您知道这样做不会影响应用程序的正确操作)。
-
通过监控 Amazon CloudWatch 指标
DatabaseConnectionsCurrentlySessionPinned
来查看固定的发生频率。有关该指标和其他 CloudWatch 指标的信息,请参阅 使用 Amazon CloudWatch 监控 RDS Proxy 指标。 -
如果您使用
SET
语句为每个客户端连接执行相同的初始化,则可以在保留事务级别多路复用的同时执行此操作。在这种情况下,您将设置初始会话状态的语句移动到由代理使用的初始化查询中。该属性是一个字符串,包含一个或多个 SQL 语句(用分号分隔)。例如,您可以为设置特定配置参数的代理定义初始化查询。然后,每当为该代理设置新连接时,RDS Proxy 都会应用这些设置。您可以从应用程序代码中删除相应的
SET
语句,这样,它们就不会干扰事务级别多路复用。有关代理的固定发生频率的指标,请参阅 使用 Amazon CloudWatch 监控 RDS Proxy 指标。
导致对所有引擎系列进行固定的条件
对于以下情况(其中多路复用可能会导致意外行为),代理将会话固定到当前连接:
文本大小大于 16 KB 的任何语句都会导致代理固定会话。
导致对 RDS for Microsoft SQL Server 进行固定的条件
对于 RDS for SQL Server,以下交互也会导致固定:
使用多个活动的结果集(MARS)。有关 MARS 的信息,请参阅 SQL Server
文档。 使用分布式事务协调器(DTC)通信。
创建临时表、事务、游标或预准备语句。
使用以下
SET
语句:SET ANSI_DEFAULTS
SET ANSI_NULL_DFLT
SET ARITHIGNORE
SET DEADLOCK_PRIORITY
SET FIPS_FLAGGER
SET FMTONLY
SET FORCEPLAN
SET IDENTITY_INSERT
SET NOCOUNT
SET NOEXEC
SET OFFSETS
SET PARSEONLY
SET QUERY_GOVERNOR_COST_LIMIT
SET REMOTE_PROC_TRANSACTIONS
SET ROWCOUNT
SET SHOWPLAN_ALL
、SHOWPLAN_TEXT
和SHOWPLAN_XML
SET STATISTICS
SET XACT_ABORT
导致对 RDS for MariaDB 和 RDS for MySQL 进行固定的条件
对于 MariaDB 和 MySQL,以下交互也会导致固定:
-
显式表锁定语句
LOCK TABLE
、LOCK TABLES
或FLUSH TABLES WITH READ LOCK
会导致代理固定会话。 -
通过使用
GET_LOCK
创建命名锁会导致代理固定会话。 -
设置用户变量或系统变量(有些例外)会导致代理固定会话。如果这种情况过多地减少了连接重用,则选择让
SET
操作不导致固定。有关如何通过设置会话固定筛选条件属性来执行此操作的信息,请参阅创建 RDS 代理和修改 RDS 代理。 -
创建临时表会导致代理固定会话。这样,无论事务边界如何,临时表的内容都会在整个会话期间保留。
-
调用函数
ROW_COUNT
、FOUND_ROWS
和LAST_INSERT_ID
有时会导致固定。 -
预编译语句会导致代理固定会话。无论预编译语句使用 SQL 文本还是二进制协议,这项规则都适用。
-
使用 SET LOCAL 时,RDS 代理无法固定连接。
-
调用存储过程和存储函数不会导致固定。RDS 代理不会检测此类调用导致的任何会话状态更改。如果您希望跨事务持久保持存储例程中的会话状态,请确保您的应用程序不会更改该状态。例如,RDS 代理目前与创建跨所有事务持久存在的临时表的存储过程不兼容。
如果您拥有关于应用程序行为的专业知识,则可以跳过某些应用程序语句的固定行为。为此,请在创建代理时选择会话固定筛选条件选项。当前,您可以选择退出会话固定,以设置会话变量和配置设置。
导致对 RDS for PostgreSQL 进行固定的条件
对于 PostgreSQL,以下交互也会导致固定:
-
使用
SET
命令。 -
使用
PREPARE
、DISCARD
、DEALLOCATE
、或EXECUTE
命令管理准备好的语句。 -
创建临时序列、表或视图。
-
声明游标。
-
丢弃会话状态。
-
监听通知频道。
-
加载库模块,如
auto_explain
。 -
使用函数操作序列,例如
nextval
和setval
。 -
使用函数与锁定交互,例如
pg_advisory_lock
和pg_try_advisory_lock
。注意
RDS 代理未锁定事务级咨询锁,特别是
pg_advisory_xact_lock
、pg_advisory_xact_lock_shared
、pg_try_advisory_xact_lock
和pg_try_advisory_xact_lock_shared
。 -
设置参数或将参数重置为其默认值。具体而言,就是使用
SET
和set_config
命令为会话变量分配默认值。 -
调用存储过程和存储函数不会导致固定。RDS 代理不会检测此类调用导致的任何会话状态更改。如果您希望跨事务持久保持存储例程中的会话状态,请确保您的应用程序不会更改该状态。例如,RDS 代理目前与创建跨所有事务持久存在的临时表的存储过程不兼容。