应用执行UPDATE时收到cannot execute UPDATE in a read-only transaction,不能立即断定数据库权限不足。这个错误首先说明当前事务不允许写入。
先区分连接到了备用服务器,还是当前事务被设置为只读。这两种情况的处置完全不同。

先确定连接到了哪台实例
在报错的同一条应用连接中查询SELECT pg_is_in_recovery();、SHOW transaction_read_only;和SHOW default_transaction_read_only;,同时记录SELECT inet_server_addr(), inet_server_port();。连接池环境应尽量使用同一会话复核。
若pg_is_in_recovery()为true,这条连接位于恢复中的备库,不能用修改事务参数来获得正常写入能力。应检查应用写入流量是否被路由到主库。
事务只读与默认只读的差别
PostgreSQL文档说明,default_transaction_read_only决定新事务的默认模式;transaction_read_only反映当前事务的只读状态。应用的BEGIN READ ONLY或事务级设置也可能影响当前事务。
不要只看全局配置文件;会话参数、角色或数据库级设置以及应用框架的事务注解都可能改变新事务的行为。
按来源修正连接或事务
若写入请求误连备库,修正连接串、服务发现或读写分离路由,并检查故障切换后的主库地址。若主库上的应用主动开启只读事务,则在业务代码中为写入操作使用读写事务。
不要在备库上尝试关闭只读保护,也不要在未确认写入目标前批量重放失败请求。有些写入在错误前可能已由其他连接完成。
验证修复的范围
先在授权的测试事务中执行一条可回滚的写入验证,再回滚并检查应用同一连接池的写入路径。观察后续错误日志,同时确认只读查询仍按预期分流。
若单条SQL成功但应用继续报错,要检查连接池内是否仍保留旧连接,以及是否只有某个作业或框架事务被标为只读。
VPS上的恢复建议
跨实例部署数据库时,为读写端点建立清晰命名。萤光云和LightNode环境可用于独立演练连接切换;任何生产写入验证都应先确认备份与回滚范围。
FAQ
问:SHOW default_transaction_read_only为off,为什么仍报错?答:当前事务可能由应用显式设为只读,也可能连接到了备库;同时检查transaction_read_only与pg_is_in_recovery()。
温馨提示
温馨提示:故障切换期间不要仅凭主机名判断主备身份,连接池和代理可能暂时持有旧连接。


