背景
公司业务从.net迁移到java,上线后调下游的接口,有个别参数没传导致接口报错。为了快速修复问题,在insert操作之后,直接又根据主键查了一遍。
注:这一步操作其实是很low的,但是当时为了快速修复问题,又考虑到根据主键查询性能影响不大,又没有更深一步考虑最佳方案。
可是,就是这一步,让我一脚踩进了一个深坑,特此记录,以此警戒。
问题现象
修复的代码重新发布之后,问题解决了,可是没想到过了一会,下游的接口再次报错,原因还是少传了参数。
错误的表现,让我觉得线上有两套代码在运行,一套是老的代码,一套是新的代码。
由于运维在不久前的集成环境出现过两套代码同步运行的情况,期间排查问题的时候一度以为是运维发布的问题,浪费了大量时间。
问题定位
最后,加了一些日志,排除了运维发布的问题,发现就是根据主键查询这一步,有时候可以查到数据,有时候查不到数据。
于是,将排查范围缩小到了数据库层面,后来老同事指出项目数据库用主从做了读写分离。
上一步insert之后,马上select,如果从库还没来得及同步主库,就会查不到数据。
主从同步的延迟性,导致了这两行代码出现问题。
总结
- 尽量避免插入以后立马查询的low操作
- 在业务主流程,如果需要查数据库,最好强制性查插入的库
DbForceMaster.begin();
/*强制主库代码*/
DbForceMaster.end();
- 不要忙中出错