RDS Aurora PostgreSQL 15.2更新subscription_id字段异常求助
Aurora PostgreSQL 15.2 UPDATE返回结果与实际数据不符问题排查
问题描述
使用RDS Aurora PostgreSQL 15.2时出现异常:首次执行UPDATE语句可正常更新wallet表的subscription_id字段;第二次执行时,返回结果显示字段已更新为新值,但实际数据库中该字段被清空。两次请求的payload均包含有效的subscription_id(仅值不同),预期两次执行均应正常更新字段值。
表结构
CREATE TABLE IF NOT EXISTS "wallet" ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES "user" (id) ON DELETE CASCADE UNIQUE, customer_id VARCHAR(255) NOT NULL, subscription_id VARCHAR(255) DEFAULT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
执行的UPDATE代码
await client.query('UPDATE "wallet" SET subscription_id = $1, updated_at = CURRENT_TIMESTAMP WHERE user_id = $2 RETURNING *',[subscription_id, user_id])
执行返回结果
第一次执行返回:
response.rows[0] = {"id":1,"user_id":1,"customer_id":"cus_OJNfP0Mu1EYale","subscription_id":"sub_1NqZVsJw0oI6B3daTpPVYntu","created_at":"2023-07-25T20:50:51.531Z","updated_at":"2023-09-15T09:44:42.161Z"}
第二次执行返回:
response.rows[0] ={"id":1,"user_id":1,"customer_id":"cus_OJNfP0Mu1EYale","subscription_id":"sub_1NqZWBJw0oI6B3daGKkR98K1","created_at":"2023-07-25T20:50:51.531Z","updated_at":"2023-09-15T09:45:01.986Z"}
注:第二次执行后,实际数据库中subscription_id字段值被清空,与返回结果不一致。
排查方向
- 事务提交验证:确认第二次UPDATE所在的事务是否正常提交。若代码中存在事务控制逻辑,检查是否有未捕获的异常导致事务回滚,或者遗漏了commit操作。RETURNING返回的是事务内的快照值,若事务未提交,数据库不会持久化该变更。
- 触发器/规则检查:查询
wallet表是否存在UPDATE相关触发器:
若存在触发器,检查其函数逻辑是否在更新后将SELECT tgname, pg_get_triggerdef(t.oid) FROM pg_trigger t WHERE tgrelid = 'wallet'::regclass AND NOT tgisinternal;subscription_id重置为null。 - 参数绑定有效性:验证第二次执行时
subscription_id参数是否正确传入。可通过打印参数值、开启数据库SQL日志(设置log_statement = 'all')确认实际执行的SQL中$1参数的真实值。 - 读写分离与同步延迟:若使用Aurora读写分离架构,检查查询实际数据时是否访问了只读节点(数据未同步),需确保验证数据时直接访问主节点。
- 并发更新冲突:检查是否有其他会话或进程同时更新该条
user_id=1的记录,可通过查询pg_locks表查看锁定情况:SELECT * FROM pg_locks WHERE relation = 'wallet'::regclass AND pid != pg_backend_pid();
解决方案建议
- 手动执行验证:直接在数据库主节点执行第二次的UPDATE语句,随后查询字段值:
若手动执行结果正常,问题出在代码层面;若结果仍不符,需排查数据库端配置或触发器。UPDATE "wallet" SET subscription_id = 'sub_1NqZWBJw0oI6B3daGKkR98K1', updated_at = CURRENT_TIMESTAMP WHERE user_id = 1 RETURNING *; SELECT subscription_id FROM "wallet" WHERE user_id = 1; - 代码事务检查:梳理代码中的事务逻辑,确保UPDATE操作后事务正常提交,无异常回滚情况。
- 触发器逻辑排查:若存在触发器,仔细检查触发器函数的条件分支,确认是否存在针对第二次更新的异常处理逻辑导致字段被清空。
- 日志分析:开启数据库语句日志,记录所有执行的SQL,对比两次UPDATE的参数差异,定位问题根源。
内容的提问来源于stack exchange,提问作者talha_ah
相关产品推荐
相关产品推荐

