查询方法标了 readOnly,里面顺手做了一次更新,直接报 Connection is read-only. Queries leading to data modification are not allowed。日志里能对上时间点,这种反而好排。

只读事务把连接设成只读并改了自动提交方式,驱动层直接拦住写语句,Hibernate 也会跳过脏检查。这一点先确认清楚,后面就不用反复试。

@Transactional(readOnly = true)
# 写操作移到另一个 @Transactional 方法里

「只读事务」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。偶发问题先统计频率,一小时几次和一天一次,查法完全不同。

改完顺手把文档补一句,省得下次自己重新推一遍。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

处理上按这个顺序:把写操作拆到独立的事务方法;只读方法里不要混入任何更新;确认注解不是从接口或父类带下来的。

结果对不对很好判断,读接口只返回数据,更新走独立方法后不再抛只读异常。

作者 9823189