我有一個現有的表items
:如何回填此表格?
create table items (
id serial primary key,
name text
-- ... and other columns that aren't of relevance.
);
我想創建另一個表名爲item_documents
:
create table item_documents (
id serial primary key,
item_id integer unique foreign key items(id) on delete cascade,
document tsvector
-- ... and other computed columns.
);
的item_documents
表從items
表計算。每當插入,更新或刪除items
表時,都應重新計算相應的item_documents
記錄。爲了實現這一點,我將最終在items
表上創建觸發器,以便在插入/更新時重新計算item_documents
(這是我希望在完成此遷移後的位置)。
我面臨的主要問題是我想回填item_documents
表。 items
表格非常大。我想過只是做一個insert/select
:
insert into item_documents (item_id, document, ...)
select id, compute_document(id, name, ...), ... from items
這有一個明顯的問題:如果一個併發事務插入/更新items
表,也不會有相應的行item_documents
。
我的下一個解決方案是在之前添加觸發器做insert/select
。這會導致另一個問題:如果併發事務在insert/select
正在運行時通過觸發器插入/更新item_documents
,則該行由於唯一約束而被鎖定(這也會導致死鎖)。同樣,因爲insert/select
鎖定了item_documents
表中的行,所以它將阻止任何併發事務運行其觸發器。這是特別痛苦的,因爲insert/select
到item_documents
需要至少一分鐘運行(並且有很多併發事務)。
我的下一個解決方案是首先添加觸發器,但以較小的批次執行insert/select
並隨着時間的推移將其分散開。我可以承擔額外的時間,因爲使用item_documents
表的功能在回填完成之前未被使用。我的想法是,鎖定item_documents
只保留到批次完成。
這是確保表與減少鎖定同步的正確解決方案嗎?