2011-09-09 6 views
0

データベースにはユーザーのテーブルが含まれています。ユーザは、ユーザ名がデータベースに送信されるデータの一部(すなわち、関数を介して)の一部であるときは常にテーブルに追加され、ユーザ名はテーブル内で一意でなければならない。特定の関数呼び出しでは、1つのユーザー名が複数回表示されることもあります。volatile関数を呼び出す安定した関数:同時実行の問題

ユーザー名ごとに、既存のIDを取得するか、またはユーザーのテーブルにIDを挿入してIDを返します。

私が思い付いた解決策は、ユーザーテーブルから最初に選択しようとするSTABLE関数です。失敗した場合は、ユーザーのテーブルに挿入しようとするVOLATILEヘルパ関数を呼び出します。私はSTABLEを好むのは、関数の結果がトランザクションの残りの部分で同じになるためです。ユーザー名が複数回含まれている場合や、他の関数に渡された場合に最適化したいと思います。そのIDを探しています。

私の最初の関数のSTABLEは、(ヘルパー関数で例外を引き起こす)同時挿入が初期関数では見られないことを意味し、無限ループを引き起こしますか?

私は以下の定義を含んでいます。

CREATE SCHEMA orgnztn; 
CREATE TABLE orgnztn.tUsers (
    id serial NOT NULL, 
    usrid text NOT NULL, 
    PRIMARY KEY (id), 
    UNIQUE (usrid) 
); 

CREATE OR REPLACE FUNCTION orgnztn.getUserID (
    IN p_usrid    text 
) 
    RETURNS integer 
    LANGUAGE plpgsql 
    STABLE 
    CALLED ON NULL INPUT 
    SECURITY INVOKER 
    AS $$ 
     DECLARE 
      p_id integer; 
     BEGIN 
      IF p_usrid IS NULL THEN 
       RETURN NULL; 
      END IF; 
      p_usrid = upper(p_usrid); 
      LOOP 
       SELECT id INTO p_id 
        FROM orgnztn.tUsers 
        WHERE usrid = p_usrid 
        FETCH FIRST 1 ROWS ONLY; 
       IF found THEN 
        RETURN p_id; 
       END IF; 
       BEGIN 
        RETURN orgnztn.getUserID_helper(p_usrid); 
        EXCEPTION WHEN unique_violation THEN 
         -- loop 
       END; 
      END LOOP; 
     END; 
    $$; 
CREATE OR REPLACE FUNCTION orgnztn.getUserID_helper (
    IN p_usrid    text 
) 
    RETURNS integer 
    LANGUAGE plpgsql 
    VOLATILE 
    CALLED ON NULL INPUT 
    SECURITY INVOKER 
    AS $$ 
     DECLARE 
      p_id integer; 
     BEGIN 
      INSERT INTO orgnztn.tUsers (usrid) 
       VALUES (p_usrid) 
       RETURNING id INTO p_id; 
      RETURN p_id; 
     END; 
    $$; 

答えて

1

揮発性フラグまたは安定フラグは、並行性に関係しません。これらのフラグの主な用途は、クエリの最適化です。 REPEATABLE READまたはREAD COMMITEDレベルを使用するかどうかによって、トランザクション分離レベルから1つを選択して適切なソリューションを使用する必要があります。

実際には、関数getUserIDは他の揮発性関数を呼び出すため、volatileとマークする必要があります。 REPEATABLE READレベルを使用すると、無限ループが発生する可能性があります。

関連する問題