[pgsql-jp: 30195] Re: Serial型の列とトランザクション

Jun Kitamura kitamura @ zoozee.jp
2003年 6月 18日 (水) 23:45:22 JST


北村です。

> > 結果は先にも話したとおり、期待通りだった・・・わけです。汗
> > 期待通りだったのですが、理屈から言うと「同値が存在してしまう」
> > ハズなのに、ならない。実際、上のやり方で5回ほどやったのです
> > が、「欠番なし」「同値なし」で出来てしまいました。
> 
> なるほど.
> 余談ですが,こういう予備試験の結果が出てしまうのも(偶然であり
> 制御できないのでしょうけど)コワイものがありますね.

そうなんですよ・・・・。
私も書き方が変で、「期待していて、それを裏切られることを期待
していた」というのが正確なのです(笑。
サーバー1台(Pentium 200MHz、メモリ128MBかな?Gateway社の
P5-200って機種で、メモリだけ倍にしてたような)と端末2台、
10Base-T でハブも2000円くらいの家庭用のやつでした。
ネットワークの速度が遅いためか、PostgreSQLの処理能力が優秀な
のかわかりませんが、結果的に「欠番なし」「同値なし」になって
しまったんですよねぇ・・。
単テーブルの再帰的な外部参照制御や MVCC などが魅力で 
PostgreSQL を使い始めた経緯があるので、「欠番なし」「同値な
し」には「ならないハズ」なんですがねぇ。

これが「何でも隔離」の MS-SQL Server なら、何も気にせず、先
述の クエリ で「欠番なし」「同値なし」が実現可能ってわかるん
ですが(笑。(注:MS-SQL Server 6 時代の話なので今は違っている
かもしれません)。

とりあえず、欠番なし・同値無し をする時は、単文ではムリ、と
いうことで(・・・良いんですよね?汗)

サマリ
[Q] あるカラムで欠番なし・同値無しのセットを以下のような単文
で可能か?
insert tblA(a) values ((select max(t1.a) + 1 from tblA t1));
[A] 値が重複する可能性あり。MVCC により、同時に走ったトラン
ザクションからは max() が同値になるため。
欠番なし・同値無しのセットを作るには、
BEGIN;
 lock table tblA in share row exclusive mode;
 insert tblA(a) values ((select max(t1.a) + 1 from tblA t1));
COMMIT;
で行なう必要あり。
(ロックを獲得するモードは SHARE ROW EXCLUSIVE MODE であって
ますよね?間違っていたらご指摘おねがい>皆様)
空のテーブルから実行したい場合は、COALESCE(max(t1.a),0) + 1 
のように NULL 処理をする必要あり。毎回この関数が呼ばれるので
遅くなる気がします。ダミーを 1行、先に挿入しておくことをお勧
めします。

でわでわ。





pgsql-jp メーリングリストの案内