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

使用Go Aurora SDK偶连至只读实例的问题排查求助

解决Lambda中Go连接Serverless Aurora的只读模式错误问题

核心原因

Serverless Aurora缩容至0再恢复后,集群的读写端点映射会重置;同时Lambda执行环境的容器复用会导致RDS Data API客户端被缓存,旧客户端可能仍指向只读实例,而默认SDK配置没有自动处理这种路由切换的情况。

解决方案

1. 避免复用RDS Data客户端

Lambda容器复用会让全局的客户端实例长期存在,缓存旧的集群路由信息。将客户端创建逻辑放到每次查询的函数内部,确保每次请求使用全新的客户端:

func runWriteQuery(ctx context.Context, clusterARN, secretARN, dbName, sql string) error {
    region := "eu-west-2"
    cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(region))
    if err != nil {
        return err
    }
    // 每次查询创建新客户端
    auroraClient := rdsdata.NewFromConfig(cfg)

    input := &rdsdata.ExecuteStatementInput{
        ResourceArn:     &clusterARN,
        SecretArn:       &secretARN,
        Database:        &dbName,
        Sql:             &sql,
        FormatRecordsAs: types.RecordsFormatTypeJson,
    }

    _, err = auroraClient.ExecuteStatement(ctx, input)
    return err
}

2. 针对只读错误添加重试机制

当遇到错误代码1836的只读异常时,触发重试,让SDK重新路由到可用的读写实例:

import (
    "context"
    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/rdsdata"
    "github.com/aws/aws-sdk-go-v2/service/rdsdata/types"
    "github.com/aws/smithy-go"
)

func createRetryEnabledConfig(ctx context.Context) (aws.Config, error) {
    cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("eu-west-2"))
    if err != nil {
        return aws.Config{}, err
    }

    // 自定义重试逻辑,匹配只读错误
    cfg.Retryer = aws.RetryerFunc(func(ctx context.Context, attempt int, err error) (aws.RetryToken, bool) {
        if apiErr, ok := err.(smithy.APIError); ok {
            if apiErr.ErrorCode() == "DatabaseErrorException" {
                if dbErr, ok := apiErr.(*types.DatabaseErrorException); ok && dbErr.ErrorCode == "1836" {
                    // 允许重试该只读错误
                    return nil, true
                }
            }
        }
        // 其他错误使用默认重试规则
        return aws.NoRetryToken, false
    })

    return cfg, nil
}

// 使用带重试的客户端执行查询
func executeWithRetry(ctx context.Context, clusterARN, secretARN, dbName, sql string) error {
    cfg, err := createRetryEnabledConfig(ctx)
    if err != nil {
        return err
    }
    auroraClient := rdsdata.NewFromConfig(cfg)

    input := &rdsdata.ExecuteStatementInput{
        ResourceArn:     &clusterARN,
        SecretArn:       &secretARN,
        Database:        &dbName,
        Sql:             &sql,
        FormatRecordsAs: types.RecordsFormatTypeJson,
    }

    _, err = auroraClient.ExecuteStatement(ctx, input)
    return err
}

3. 可选:指定读写实例ARN(不推荐)

如果集群有固定的读写实例,可以直接将ResourceArn设置为读写实例的ARN,跳过集群路由。但此方案会丢失集群自动故障转移的能力,仅适用于读写实例固定不变的场景:

input := &rdsdata.ExecuteStatementInput{
    ResourceArn:     &writerInstanceARN, // 替换为你的读写实例ARN
    SecretArn:       &auroraSecretsStoreARN,
    Database:        &auroraDatabaseName,
    Sql:             &sqlStatement,
    FormatRecordsAs: types.RecordsFormatTypeJson,
}

最优实践

结合每次请求创建新客户端和只读错误重试,既能解决Lambda容器复用导致的缓存问题,又能应对集群恢复后的路由切换,是最稳定的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:28:12