1

複数のセッションで次の PL/SQL を実行しました。

DECLARE
   x     NUMBER;
   y     NUMBER;
BEGIN
   x := 500;
   y := 0;
   WHILE (x > y)
   LOOP
       SET TRANSACTION 

       Select max(SERIAL_NO) INTO y from MY_TABLE;

       y := y + 1;

       insert into MY_TABLE S (S.SERIAL_NO, S.Request_id)
       values ((
                (select max(SERIAL_NO) from MY_TABLE) + 1
               )
              ,'B');

       Commit;

   END LOOP;
END;
/

テーブルにまだ重複したエントリがありますが、どうしてこうなったのでしょうか?

4

2 に答える 2

4

もちろん。Oracle には、read-commit トランザクション分離レベルがあります。

たとえば、次のように 2 つのセッションが実行されている場合:

Time  Session A                                 Session B
1     (Select max(SERIAL_NO) from MY_TABLE)+1
2                                               (Select max(SERIAL_NO) from MY_TABLE)+1
3     commit;

セッション A + B は SERIAL_NO に対して同じ値を参照するため、テーブルで SERIAL_NO の重複を取得します。

一意性を確保するためにシーケンスを使用する必要があります (または独自のセマフォを実装しますが、これはお勧めしません)。

あなたのSET TRANSACTIONステートメントにはいくつかのパラメーターがありませんが、これはとにかく役に立ちません (あなたが考えた場合SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;)

http://docs.oracle.com/cd/B19306_01/server.102/b14220/consist.htm#sthref1981も参照してください。シリアライズ可能な分離トランザクション レベルおよびデータの同時実行性と一貫性全般について説明しています。

于 2012-07-23T06:35:22.057 に答える
1

テーブル内で重複したくない場合は、UNIQUE CONSTRAINTS を使用してください。

于 2012-07-23T06:33:16.287 に答える