2016-04-07 6 views
0

私は現在、さまざまなアプリケーションの複数のユーザーを処理するプライマリpostgresデータベースを持っています。 AppOneとAppTwoがと同時に同時にのユーザーを追加したいと言うとき、並行性に関する問題の1つはそうです。PostgreSQLを使用して挿入時に行の一意のIDを生成

現在、AppOneは乱数(10桁の長さでなければなりません)を生成し、その値がデータベースに存在するかどうかをチェックし、存在しない場合はその値を持つユーザーをuser_url(URLに使用)という列です。

あなたがイメージを作成できるように、生成、チェック、または挿入の時間の間にAppTwoがユーザーを追加する要求を出したときに、私たちはユニークな値を繰り返すことができます。私は潜在的にpostgresトリガを使用してその問題を解決したい。

私はトランザクションを使用することができますが、私はデータベースを保持したくないことを知っていますが、私はむしろ関数とデータベース側でトリガーを介して一意の番号シーケンスを作成したいので、競合状態を心配する必要はありません。トリガーがそれを行うと、新しく追加されたユーザーに固有IDを含むデータがすべて取得されます。

だから理想的

CREATE OR REPLACE FUNCTION set_unique_number(...) RETURNS trigger AS $$ 
DECLARE 
    BEGIN 
    ....something here 
    RETURN new; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER insert_unique_url_id BEFORE INSERT ... PROCEDURE  
set_unique_number(...); 

それは番号を生成し、BEFORE INSERTのトリガーによって実行される行に挿入する関数であろう。私は間違っているかもしれません。

すべてのヘルプ/提案は有用

EDIT次のようになります。数字へのシーケンスがないように、私はそれをしたいです。このように人々は次のユーザーのURLを推測することができませんでした。

おかげ

+2

PostgreSQLでシーケンスジェネレータの使用を確認してください。オーバーヘッドと読み取りの一貫性のある環境で検証しようとする不確実性なしに、一意性を事実上保証できます。 –

答えて

0

なぜあなたはUUID-ossp拡張子を使用していませんか?ポストグラム自体からUUIDを生成することができます。

Heres a good tutorialこれらをプライマリキーとして使用する方法。

2

9,000,000,000は、誕生日の問題によって、すぐに衝突が発生することが保証されます。

advisory lockingを使用して同時挿入を許可しながらこの問題を回避することはできますか?あなたの手順は、(擬似コードで)次のようになります。あなたは、データベース内の90億行を持っていると思い際

while (true) { 
    start transaction; 
    bigint new_id = floor(random())*9000000000+1000000000; 
    if select pg_try_advisory_xact_lock(new_id) { 
    if select not exists id from url where id=new_id { 
     insert into url (id, ...) values (new_id, ...); 
     commit; 
     break; 
    } 
    } 
    commit; 
} 

この手順を終了することはありません。 Postgresのプロシージャはプロシージャ内で複数のトランザクションを許可しないため、外部で実装する必要があります。例外を使用して回避することは可能かもしれませんが、複雑になるでしょう。

関連する問題