[pgsql-jp: 27670] Re: テーブルの同時更新を防ぐには?

Tatsuo Ishii t-ishii @ sra.co.jp
2002年 10月 17日 (木) 22:28:10 JST


石井です.

> こんにちは。石田@苫小牧市と申します。
> > ------------------------------------------------------------
> > Aテーブルから今日の連番取得(日が変わると1に戻る)
> > ↓
> > PHP側で日付+連番の登録コード作成
> > (例)200201010001
> > ↓
> > Aテーブルに連番を+1して再登録
> > ↓
> > 作成した登録コード(プライマリキー)でBテーブルに新規登録
> > ------------------------------------------------------------
> > 
> > という流れなのですが、同時アクセステスト時に、
> > 数人一斉に「登録」ボタンを押すと、
> > ERROR: Cannot insert a duplicate key into a unique index.
> > と言うメッセージが表示されます。
> > これは既に登録しているプライマリキーで再度登録しようとしているため
> > だと思うのですが、複数人同時アクセス時にこのエラーを起こさせない
> > 良い方法は無いでしょうか?(なるべく上記の処理の流れを変えずに・・・)
> > biginやcommitなど試みたのですが、やはり結果は変わりません。
> 
> このようなケースでは、単に begin や select for update ではなく、
> 明示的にテーブルロックする必要があります。

> Aテーブルから今日の連番取得(日が変わると1に戻る)

のところが,

	Aテーブルの特定の1レコードにカウンタが入っていて,すべてのPHP
	アプリケーションはそのレコードを使う

という前提であれば,SELECT FOR UPDATEで行けると思いますよ.

BEGIN;
SELECT ... FROM A WHERE ... FOR UPDATE;
:
連番更新
:
UPDATE A SET ....;
INSERT INTO B ...;
COMMIT;

という感じ.

ただし,この方法は

SELECT ... FROM A WHERE ... FOR UPDATE;

のところで,ある1レコードのロックが競合するので,非常にアクセスが多い
ところでは性能が問題なるでしょう.その場合は,小山さんのおっしゃるよう
にSEQUENCEを使った方がいいですね.
--
Tatsuo Ishii



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