Postgresql

鎖定特定的選擇查詢,直到送出所有插入事務

  • January 2, 2022

我的數據庫中有一個僅插入表,其中包含時間序列數據。

當我的系統啟動時,我需要使用上個月的數據(每行包含一分鐘的數據)填充記憶體狀態,這意味著我首先進行選擇以獲取最新的行日期,然後從頭開始選擇所有行該日期的月份,直到日期本身。

之後,如果最後一行的 DateTime 不是目前 DateTime,我將啟動一個程序,該程序獲取歷史數據並將其插入數據庫,直到達到目前 DateTime。

我遇到的問題是,如果我正在執行的獲取歷史程序在對數據庫進行插入時崩潰,它將重新啟動,執行選擇以獲取最新行,並且最新行的可能性很小不是最後一個實際插入的數據(我猜可能是因為插入事務尚未完成或尚未由 PG 送出),這會破壞我的狀態並生成錯誤的數據。

所以,我的問題是,有什麼方法可以讓我的選擇從數據庫中獲取最新的行(以及選擇來獲取數據范圍)等待所有“待處理”的插入查詢之前送出檢索任何數據,以便我可以保證我真的會得到最新的行?

我不介意該解決方案是否會對性能產生一些影響,因為這些查詢僅在系統啟動期間執行一次。

謝謝您的幫助。

筆記:

如果我的解釋有點混亂,只是為了讓事情更清楚,假設我在表中有 rows AB並且C,現在系統正在插入 row D,但它崩潰了,但插入請求已發送到 PG,所以該行將D是插入。

在那之後,系統重新啟動並從應該是的表中請求最新數據D,但是由於該行(我猜)尚未送出,所以我得到的行是C.

我想要的是某種方式讓該選擇檢測到有一個正在進行的插入事務等待它完成然後檢索數據以保證我會得到D而不是C

您發現的統稱為悲觀鎖定或互斥(mutex)。為了讓它工作,我們需要選擇一個對象來鎖定。可以鎖定 DB ( select ... for update) 中的某些記錄,或者您可以要求 PostgreSQL 在表之外創建此類對象 ( pg_advisory_xact_lock())。

雖然pg_advisory_xact_lock()是一個有效的解決方案,但它特定於 PostgreSQL - 因此它應該被視為最後的手段。您應該想到的第一個解決方案是在現有表中查找我們可以鎖定的記錄。例如,在您的情況下,您似乎只附加數據,因此您可以使用select ... for update.

如果這不切實際(例如,因為桌子可能完全是空的),那麼是的 -pg_advisory_xact_lock()將是一個不錯的選擇。

引用自:https://dba.stackexchange.com/questions/305534