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

MySQL Aurora写入后主节点立即读取数据不一致问题排查

问题分析:Aurora MySQL主实例写入后立即读取旧数据的原因

我有一个包含1个主实例(writer)和1个只读实例(reader)的Aurora MySQL集群。使用NodeJS的mysql2包操作数据库时,执行写入查询(如INSERT/UPDATE)并收到响应后,立即在主实例上执行SELECT查询,却读取到旧数据;但在写入与读取之间添加约1秒延迟就能正常获取新数据。示例代码如下:

await db.execute("UPDATE mytable SET emotion = 'frustrated' WHERE user = 'me'")
const result = await db.execute("SELECT emotion FROM mytable WHERE user = 'me'")
// result返回更新前的值,而非'frustrated'

可能的原因

1. 连接池路由错误,SELECT被转发到只读实例

你以为SELECT是在主实例执行,但mysql2连接池可能被配置了读写分离路由——写入请求走主实例,后续SELECT被自动路由到只读实例。Aurora只读实例同步主数据存在延迟(通常毫秒级,高负载下可能到1秒),因此会读到旧数据。

检查连接池配置,是否用了读写分离中间件、AWS RDS数据客户端,或者手动设置了路由规则,导致SELECT请求没绑定到主实例连接。

2. 事务隔离级别与自动提交配置问题

如果mysql2连接关闭了自动提交(autocommit),UPDATE执行后事务未立即提交:

  • 若SELECT用了当前连接,能看到未提交的修改;但如果SELECT用了连接池里的其他连接(未参与当前事务),就会读到旧数据。
  • 加上MySQL默认隔离级别是REPEATABLE READ,如果SELECT在新事务中执行,且事务快照是UPDATE提交前生成的,也会读到旧数据。

可以执行以下语句检查当前连接的autocommit状态:

const [rows] = await db.execute("SELECT @@autocommit");
console.log(rows);

3. Aurora主实例的一致性配置问题

Aurora MySQL默认提供会话级写后读一致性——同一会话中写入后立即读能看到最新数据,但如果写入和读取用了不同会话(连接池的不同连接),可能触发全局一致性延迟。

可以尝试在SELECT前加SQL提示强制读已提交隔离级别,或者在连接初始化时设置会话隔离级别:

/*+ READ_COMMITTED */ SELECT emotion FROM mytable WHERE user = 'me'
-- 或者连接初始化时执行
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED

4. mysql2的execute方法与连接复用问题

mysql2的execute方法会预编译SQL,连接池可能复用了状态未刷新的连接;如果连接存在未提交事务或会话状态不一致,也会导致读旧数据。

可以尝试用query方法替代execute测试,或者在UPDATE后显式提交事务(若autocommit关闭):

await db.query("UPDATE mytable SET emotion = 'frustrated' WHERE user = 'me'")
const result = await db.query("SELECT emotion FROM mytable WHERE user = 'me'")

5. Aurora存储层同步延迟(罕见)

Aurora的存储层是共享的,但主实例写入后,存储日志同步到查询层可能存在极短暂延迟(高负载下可能出现)。这种情况可以用FLUSH TABLES mytable;测试,但不建议生产环境使用,会影响性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:52:35