项目相关技术栈
springboot
hikari连接池+pgbouncer+postgresql数据库
背景
为了优化一个任务执行的速度,我将任务的sql中部分语句抽出生成临时表(create temp table tempqw as xxxxxxxxx),再和其他表关联,提高查询速度。测试,没有问题,上线观察日志却发现偶发如下报错,报错信息如下:
relation "tempqw" does not exist
推测
临时表消失,只能有两种原因:
1. 被删除了(可能是数据库某些机制或者我的程序中删除的)
2. 创建临时表和使用临时表不在同一个数据库会话中
检查
首先检索springboot程序代码的日志,发现在使用前并没有drop临时表,排除程序删除临时表。
postgresql中的临时表分为会话级和事务级,在会话级临时表中,数据可以存在于整个会话的生命周期中,在事务级临时表中的数据只能存在于事务的生命周期中。
我在此处创建的是会话级别的临时表,是不能跨会话的。所以检查创建临时表和使用临时表的sql语句,是否为一个java线程,结果也是同一个线程,讲道理是一个会话啊,至此有点懵逼。
于是找了postgersql的日志:
根据数据库日志,发现虽然程序是同一个java线程,但是sql执行过程中突然换了一个数据库会话,由于pg临时表是会话隔离的,所以就自然而然的报错了。
总结
使用了线程池,不能保证同一个java线程中的每次查询使用相同的数据库会话。(如果使用事务应该没有这个问题)