DB2 テーブルをロックせずにSELECTする方法 with ur;

菱田直哉
DB2でSELECTするとき、「with ur」を必ずつけろって言われたんだけどなんで?

モリー
それは、コミット前のものも確認してねってことじゃない?

菱田直哉
なんか、ロックがどうのこうのって言ってたよ。何も付けないSELECT文じゃダメなの?

モリー
ダメなときと大丈夫なときがあるね。

インデックスがあるなしでのロックが変わる

SELECT *
FROM TABLE
WHERE EMPNO = ‘000310’;

単純な Where文でも検索対象の対象の列にIndexが張ってあるかないかで
ロック対象が全く異なる。

インデックスがあればオプティマイザはインデックスキャンを選び行ロック(row-level locking == IS)を行う。
インデックスがなければ表全体を検索しなければならず、このときは表ロック(table level lock == S)がかかる。
参考:デッドロックの公式見解

菱田直哉
普通の検索だと、行ロックか表ロックのどちらかがかかっちゃうんだ!

モリー
そう。だからただ検索するためには、「with ur」は有効だね。

モリー
でも、他のトランザクションがコミット前の更新も見えちゃうよ?いいの?
菱田直哉
どういうこと?
モリー
例えば、わたしが間違ったデータを追加して、ロールバックする予定なんだけど、そっちで検索したら見えちゃうってこと。
菱田直哉
それは困るね。間違ったデータは見たくないな。ちゃんとデータベースにコミットされているものだけ見たい。
モリー
それならこうだね。

結果表が読み取り専用であることを明示するには、「SELECT … FOR READ ONLY(またはFETCH ONLY)」を使用します。

菱田直哉
じゃあ「with ur」って何者?

DB2では、UR(Uncommitted Read:非コミット読み取り)、CS(Cursor Stability:カーソル固定)、RS(Read Stability:読み取り固定)、RR(Repeatable Read:反復可能読み取り)がサポートされています。例えば「SELECT * FROM STAFF WITH UR」とすると、非コミット読み取り(最小限のロック)を使用してSELECTが実行されます。
DB2チューニング・ベストプラクティス

菱田直哉
ロックをかけないって目的と、最小限ロックでコミット前の状態も取得できるものは違うんだね。

結論:DB2 テーブルをロックせずにSELECTする方法
select * from TABLE_NAME for read only;

菱田直哉
次からはread onlyを使おっと。