マルチスレッド アプリケーションで使用される postgreql 接続プールがあり、いくつかのレコードを大きなテーブルに永続的に挿入します。したがって、10 個のデータベース接続があり、同じ関数を実行して、レコードを挿入するとします。
問題は、結果として 10 個のレコードが挿入されていることです。一方、トランザクションのみが互いのレコードを確認できる場合、挿入されるのは 2 ~ 3 個のレコードのみである必要があります (関数は、日付に従ってレコードを挿入しないという決定を下します)。最後に見つかったレコード)。
func の実行期間中は、テーブルをロックする余裕がありません。新しいレコードが並列トランザクションで作成されているにもかかわらず、データベースが新しいレコードにすぐにルールを適用するようにさまざまな手法を試しましたが、まだ成功していません。
だから、私はどんな助けやアイデアにもとても感謝しています!
より具体的には、コードは次のとおりです。
schm.events ( evtime TIMESTAMP, ref_id INTEGER, param INTEGER, type INTEGER);
レコード フィルタ ルール:
BEGIN
select count(*) into nCnt
from events e
where e.ref_id = ref_id and e.param = param and e.type = type
and e.evtime between (evtime - interval '10 seconds') and (evtime + interval '10 seconds')
if nCnt = 0 then
insert into schm.events values (evtime, ref_id, param, type);
end if;
END;
更新 (コメントの長さは残念ながら十分ではありません)
独自のインデックス ソリューションを本番環境に適用しました。結果はかなり受け入れられるものですが、当初の目標は達成されていません。問題は、一意のハッシュでは、連続する hash_codes を持つ 2 つのレコード間の間隔を制御できないことです。
コードは次のとおりです。
CREATE TABLE schm.events_hash (
hash_code bigint NOT NULL
);
CREATE UNIQUE INDEX ui_events_hash_hash_code ON its.events_hash
USING btree (hash_code);
--generate the hash codes data by partioning(splitting) evtime in 10 sec intervals:
INSERT into schm.events_hash
select distinct ( cast( trunc( extract(epoch from evtime) / 10 ) || cast( ref_id as TEXT) || cast( type as TEXT ) || cast( param as TEXT ) as bigint) )
from schm.events;
--and then in a concurrently executed function I insert sequentially:
begin
INSERT into schm.events_hash values ( cast( trunc( extract(epoch from evtime) / 10 ) || cast( ref_id as TEXT) || cast( type as TEXT ) || cast( param as TEXT ) as bigint) );
insert into schm.events values (evtime, ref_id, param, type);
end;
その場合、evtime がハッシュで決定された間隔内にある場合、1 つのレコードのみが挿入されます。場合によっては、決定された異なる間隔を参照しているが、互いに近い (60 秒未満の間隔) レコードをスキップできます。
insert into schm.events values ( '2013-07-22 19:32:37', '123', '10', '20' ); --inserted, test ok, (trunc( extract(epoch from cast('2013-07-22 19:32:37' as timestamp)) / 10 ) = 137450715 )
insert into schm.events values ( '2013-07-22 19:32:39', '123', '10', '20' ); --filtered out, test ok, (trunc( extract(epoch from cast('2013-07-22 19:32:39' as timestamp)) / 10 ) = 137450715 )
insert into schm.events values ( '2013-07-22 19:32:41', '123', '10', '20' ); --inserted, test fail, (trunc( extract(epoch from cast('2013-07-22 19:32:41' as timestamp)) / 10 ) = 137450716 )
最初の目標を達成するためにハッシュ関数を変更する方法があるに違いないと思いますが、まだ見つけていません。おそらく、postgresql 自体によってトランザクションから実行されるいくつかのテーブル制約式があるのでしょうか?