項目相關技術棧
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線程中的每次查詢使用相同的數據庫會話。(如果使用事務應該沒有這個問題)