使用済みフラグが false の行を SELECT し、データを取得。
その後、使用済みフラグを立てるという処理を考える。
環境は PostgreSQL 7.2.1 を想定。
この問題は、SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
で単純にトランザクションレベルを上げても対処できない。
1: BEGIN;
2: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
3: SELECT id, data FROM table WHERE flag = FALSE;
4: ------ アプリケーションの処理 ------
5: UPDATE table SET flag = FALSE;
6: COMMIT;
これだと、3 の SELECT が終わった後に別のトランザクションが開始した場合、
更新予定の行も SELECT で読み込まれてしまう。
結果、同じ行を SELECT してしまい、その後 5 のUPDATE を発行しようとした時点で
SERIALIZABLE の分離チェックに引っかかり、2つ目のトランザクションはアボートしてしまう。
ERROR: Can't serialize access due to concurrent update
エラーを発生させずに処理を行うためには、更新トランザクションだけではなく
参照トランザクションもブロックしなければならない。
つまり、この問題はトランザクションレベルの設定では解決できない。
ACCESS EXCUSIVE MODE でロックすることで、SELECT 文自体もブロックされる。
1: BEGIN;
2: LOCK TABLE table IN ACCESS EXCLUSIVE MODE;
3: SELECT id, data FROM table WHERE flag = FALSE;
4: ------ アプリケーションの処理 ------
5: UPDATE table SET flag = FALSE;
6: COMMIT;
LOCK TABLE uniq_uri IN ACCESS EXCUSIVE MODE;
SELECT TOP 1 uri FROM uniq_uri WHERE digit = 5 AND last_update IS NULL;
COMMIT TRANSACTION;
http://www.postgresql.jp/document/pg732doc/user/mvcc.html
[pgsql-jp: 29112] 同時更新の制御2
http://ml.postgresql.jp/pipermail/pgsql-jp/2003-February/004 ...
その後、使用済みフラグを立てるという処理を考える。
環境は PostgreSQL 7.2.1 を想定。
この問題は、SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
で単純にトランザクションレベルを上げても対処できない。
1: BEGIN;
2: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
3: SELECT id, data FROM table WHERE flag = FALSE;
4: ------ アプリケーションの処理 ------
5: UPDATE table SET flag = FALSE;
6: COMMIT;
これだと、3 の SELECT が終わった後に別のトランザクションが開始した場合、
更新予定の行も SELECT で読み込まれてしまう。
結果、同じ行を SELECT してしまい、その後 5 のUPDATE を発行しようとした時点で
SERIALIZABLE の分離チェックに引っかかり、2つ目のトランザクションはアボートしてしまう。
ERROR: Can't serialize access due to concurrent update
エラーを発生させずに処理を行うためには、更新トランザクションだけではなく
参照トランザクションもブロックしなければならない。
つまり、この問題はトランザクションレベルの設定では解決できない。
- 解決するには、LOCK 文で行またはテーブルをロックする必要がある。
LOCK TABLE table IN ACCESS EXCLUSIVE MODE;ACCESS EXCUSIVE MODE でロックすることで、SELECT 文自体もブロックされる。
1: BEGIN;
2: LOCK TABLE table IN ACCESS EXCLUSIVE MODE;
3: SELECT id, data FROM table WHERE flag = FALSE;
4: ------ アプリケーションの処理 ------
5: UPDATE table SET flag = FALSE;
6: COMMIT;
- サンプル
BEGIN TRANSACTION;LOCK TABLE uniq_uri IN ACCESS EXCUSIVE MODE;
SELECT TOP 1 uri FROM uniq_uri WHERE digit = 5 AND last_update IS NULL;
COMMIT TRANSACTION;
- 参考:
PostgreSQL 7.3.2 ユーザガイド Chapter 9. 同時実行制御http://www.postgresql.jp/document/pg732doc/user/mvcc.html
[pgsql-jp: 29112] 同時更新の制御2
http://ml.postgresql.jp/pipermail/pgsql-jp/2003-February/004 ...
Unicode 関連モジュールやドキュメントがある。
http://homepage1.nifty.com/nomenclator/perl/
http://homepage1.nifty.com/nomenclator/perl/
以上の内容はhttp://sonic64.com//2003-05-29.htmlより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます
モバイルやる夫Viewer Ver0.14