You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Aurora PostgreSQL读写分离时@Transactional(readOnly=true)引发延迟升高的最优配置问询

解决Aurora PG只读副本路由后的额外延迟问题

我之前在维护Spring Boot + Aurora PostgreSQL主从架构的服务时,遇到过和你完全一样的问题——用@Transactional(readOnly=true)路由到只读副本后,因为额外的SET SESSION CHARACTERISTICS语句导致延迟飙升。下面是我摸索出来的最优配置方案,核心思路是只做数据源路由,完全跳过连接的只读状态设置:

1. 调整自定义RoutingDataSource逻辑,去掉连接只读属性设置

你的自定义路由数据源可能在切换到只读节点后,会自动调用connection.setReadOnly(true),这正是触发JDBC驱动执行SET SESSION CHARACTERISTICS READ ONLY的根源。因为你只需要路由,不需要实际标记会话只读,所以要把这部分逻辑删掉:

public class CustomRoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        // 只负责判断路由键,不修改任何连接属性
        return TransactionSynchronizationManager.isCurrentTransactionReadOnly() 
            ? "reader" 
            : "writer";
    }

    // 确保父类不会自动设置连接只读(如果你的实现里有相关逻辑的话)
    @Override
    protected Connection doGetConnection(Object lookupKey) throws SQLException {
        Connection conn = super.doGetConnection(lookupKey);
        // 不要调用 conn.setReadOnly(...)!
        return conn;
    }
}

2. 配置Hikari连接池,彻底禁用只读会话设置

针对主、从数据源分别配置Hikari,重点给只读副本数据源加上两个关键配置,完全阻止JDBC驱动执行额外的SET语句:

主数据源(Writer)配置

spring.datasource.writer.url=jdbc:postgresql://your-aurora-writer-endpoint:5432/your-db
spring.datasource.writer.username=xxx
spring.datasource.writer.password=xxx
spring.datasource.writer.hikari.read-only=false
# 主数据源保持默认即可,不需要额外的readOnlyMode配置

只读数据源(Reader)配置

spring.datasource.reader.url=jdbc:postgresql://your-aurora-reader-endpoint:5432/your-db
spring.datasource.reader.username=xxx
spring.datasource.reader.password=xxx
# 核心1:告诉Hikari不要把连接标记为只读
spring.datasource.reader.hikari.read-only=false
# 核心2:告诉PG-JDBC驱动完全忽略只读属性的设置,不执行任何SET语句
spring.datasource.reader.hikari.data-source-properties.readOnlyMode=ignore

3. 禁用JOOQ的自动只读会话设置

JOOQ默认会根据@Transactional(readOnly=true)注解自动设置会话只读,这也会触发额外的数据库操作。你需要在JOOQ的配置里明确禁用这个行为:

@Bean
public DefaultConfiguration jooqConfiguration(DataSource dataSource, TransactionManager transactionManager) {
    DefaultConfiguration config = new DefaultConfiguration();
    config.set(dataSource);
    config.set(new SpringTransactionProvider(transactionManager));
    // 关键:禁用JOOQ自动设置只读会话
    config.set(new Settings().setExecuteReadOnly(false));
    return config;
}

4. 验证效果

配置完成后,你可以开启PG的日志或者用JDBC驱动的日志,确认不会再出现SET SESSION CHARACTERISTICS READ ONLY和SET SESSION CHARACTERISTICS READ WRITE语句。此时只读副本的查询延迟应该会和主节点基本一致——毕竟你只是把请求路由过去,没有额外的数据库往返开销了。

另外,你提到只读副本仅处理1%的流量,完全不用担心负载问题,这个配置方案不会带来任何额外的性能损耗。

内容的提问来源于stack exchange,提问作者frm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 06:12:40