裏使用Postgres 9.6,我遵循了https://stackoverflow.com/a/40325406/435563建議做一個INSERT
或SELECT
並返回得到的ID策略:INSERT或SELECT策略總是返回一行?
with ins as (
insert into prop (prop_type, norm, hash, symbols)
values (
$1, $2, $3, $4
) on conflict (hash) do
update set prop_type = 'jargon' where false
returning id)
select id from ins
union all
select id from prop where hash = $3
不過,有時這種沒有返回。無論如何,我都會預料它會連續返回。我如何解決它以確保它始終返回一個ID?
注意,儘管沒有返回一行,但行似乎在檢查中存在。我相信這個問題可能與嘗試通過兩個會話同時添加相同的記錄有關。
問題的表被定義爲:
create table prop (
id serial primary key,
prop_type text not null references prop_type(name),
norm text not null,
hash text not null unique,
symbols jsonb
);
數據:
EDT DETAIL: parameters: $1 = 'jargon', $2 = 'j2', $3 = 'lXWkZSmoSE0mZ+n4xpWB', $4 = '[]'
如果我改變prop_type = 'jargon'
到prop_type = 'foo'
它的作品!即使給出where false
子句,如果表達式不會改變任何東西,看起來鎖也不會被採用。這真的需要依賴於我猜測一個不會排在行內的值嗎?還是有更好的方法來確保你獲得鎖定?
--- UPDATE ---
的總體情況是,應用程序嘗試使用連接池(...自動提交)保存向無環圖,並使用該查詢來獲取同時識別重複。 [事實證明,更聰明的是使用一個事務,只是序列化到一個連接。但是,當有爭這裏的行爲是奇數]
外鍵約束似乎並沒有影響到插入 - 如:
create table foo(i int unique, prop_id int references prop(id));
insert into foo values (1, 208);
insert into foo values (1, 208)
on conflict (i) do update set prop_id = 208 where false;
--> INSERT 0 0
insert into foo values (1, 208)
on conflict (i) do update set prop_id = -208 where false;
--> INSERT 0 0
注意一個與有效FK 208,其他無效-208。如果我使用完整模式將選擇連接到其中任何一個上,那麼在沒有爭用的情況下,它們都會按預期返回i = 1。
請發佈的數據樣本爲好,如果我不是弄錯它始終如果它返回一行,因此你甚至可以從XMIN告訴,XMAX已更新或插入 –
已添加數據。我想它與應用程序試圖保存一個複雜的數據結構,其中該葉片出現兩次,使用連接池相關。所以記錄被添加到兩個不同的連接中。 – shaunc
與您的更新我注意到哪裏更新不會發生錯誤 - 與該答案將不同:) –