2

簡短故事: 我有一個分區postgres數據庫和一個表來跟蹤分區和觸發器。觸發器需要更改分區表上的約束(它們的valid_date [daterange]根據另一個分區的valid_date而改變),並且最好能夠刪除表,但是這是由於觸發鏈正在使用這些表而導致的錯誤。帶觸發器的Postgres分區管理。問題修改表

cannot ALTER TABLE "core_geometryrecord_8_2" because it is 
    being used by active queries in this session 

FULL問題: 我給我的模式和觸發架構的情況下進行徹底的解釋是需要或有人想知道爲什麼我覺得對於一個「令人費解」的必要性系統,儘管它可能沒有必要。

我正在重構幾何數據的大型數據庫,以便使用起來更加方便快捷。舊系統具有保持相關幾何形狀的「幾何圖表」(美國的I.E.縣)。數據應該真正按「date_valid」和「geometrytable_id」分組。

我們決定在date_valid(日期範圍)和geometrytable_id(外鍵)上使用帶有約束的postgres分區。

因爲日期很敏感,並且需要大量的記錄以保持正確,所以我試着用管理大部分數據庫的觸發器(我已經知道我需要分區表的插入觸發器,所以爲什麼不)。

我設計了一組觸發器來管理分區列表,並在插入或刪除幾何時執行所有記錄。這是他們做的。

  • 在插入分區列表表中創建分區表並應用約束。如果對於與新的重疊的日期(呼叫更新觸發器)存在分區有效,請對其進行修改。如果有一個分區在此日期之後有效,則修剪新的分區結束日期以開始下一個分區的日期(保持連續的時間軸)。
  • 從分區列表中刪除時,刪除分區表。重新計算已刪除分區(如果有)的partition_list條目的日期範圍(Call Update Trigger)以使日期連續。
  • 在更新分區列表表中,DROP OLD DATE CONSTRAINT,將分區表中所有行的date_valid更改爲分區的新date_valid值,然後使用新日期創建DATE CONSTRAINT(約束條件是項目具有完全相同date_valid作爲分區)。
  • 在插入到geometryrecord(分區表)中時,找到應該使用的分區,或INSERT插入分區列表表(TRIGGERS ON INSERT)。將NEW插入正確的分區。
  • 從geometryrecord刪除時,如果分區表現在爲空,請從分區列表表(CALLS DELETE TRIGGER)中刪除分區條目。

如果我試圖以任何方式改變表格,只要我在鏈條中的任何觸發器上觸摸它,它就會一直生氣。如果我直接插入到該表中,分區列表表格的觸發器可以很好地工作,但從幾何表(即調用同一個觸發器)中刪除即使它正在做的只是一個select(查看分區表是否爲空),也會彈出。插入到分區幾何表中也會導致問題,因爲我必須刪除約束才能更改行的date_valid。

必須有一種方法可以做到這一點,我只是不明白。 (我還必須刪除表格,使其更加被動'標記爲由cron作業刪除',因爲我無法從源自我要刪除的表格的觸發器調用中刪除表格)。

任何建議將非常受歡迎。我無法相信沒有人需要做這樣的事情,所以我假設我只是不知道自己在做什麼:)。

+1

你是從觸發器內部做DDL的嗎? – wildplasser

+0

哇,我想我剛剛瞭解DDL和DML之間的區別(主要是有差異)。是的,我需要在觸發器內進行修改或刪除。 –

回答

1

因此,經過深入研究和試驗,我想出了我需要的東西,並認爲我會記錄我的發現。

這裏是一個如何基本的Postgres劃分爲有興趣的工作文檔頁面:http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html

關鍵的一點知道的是,對於每一個分區,你必須設置指定什麼可以在該分區中找到的約束(拆分id使得每個表中只有200,000條記錄只需要每個表一個約束)。這使得它在查詢主表時很快就會根據所有子表的約束來檢查請求。只有查詢落在表約束範圍內的表纔會被進一步查詢。如果你這樣做,只有一個表被真正查詢。

,從而爲我所學到的:

首先,我不認爲這是不可能的從自己的觸發器刪除表。我的解決方案只是爲了讓它通過其他一些機制(比如稍後放下的表格)。這個問題在Cron作業運行之前一直存在。由於從自己的觸發器更改表也是不可能的,所以表格仍然是一個分區,只是標記爲稍後丟棄。如果你的分區正確,這可能不會造成任何問題。在我的情況下,可能有兩個分區重疊(一個標記爲丟棄,另一個應該在那裏)。這樣做的副作用是查詢指定可能在這兩個表中的任何一個表中的內容都會觸發這兩個表。這對我來說很好,直到Cron工作到來,所以我很好,但有些情況可能不適用於這個問題。其次,我意識到改變他們沒有寫入的表的插入工作正常,但是觸發相同觸發鏈的刪除和更新失敗,因爲表被會話使用。我認爲這是一件瘋狂的事情,但真正的問題是,我在日期和外鍵上進行了分區,但是被記錄的ID刪除。這導致postgres檢查所有表的所有約束,這使得它無法瞭解要使用哪個表,因此只檢查了所有表。爲了讓刪除工作,我所要做的只是指定我分區的信息,以便知道要查找的表,而不是掃描整個表來查找ID。

TLDR如果您在一些任意(一組)列上分區postgres表,請確保您通過提供分區的列來刪除或更新記錄,以便postgres可以知道要查找的表以及不必掃描整個設備。