読者です 読者をやめる 読者になる 読者になる

山下寛人オフィシャルブログ

オイシックス株式会社 執行役員 システム本部長 山下寛人の公式ブログです。

Oracleのロック

データベースのロックはデータの整合性を保つ上で非常に重要です。データが壊れて不具合が起こったとき、山のようなデータの中から要因を特定していくのは非常に困難です。

一方でロックはうまく使わないと逆に障害になります。今までも何度トラブルが起こったことか。ロックしたまま解放しないと他のスレッドが待ち状態になっていっぱいになりシステムがダウンします。ロックはできるだけ最小限にしたいものです。安易にテーブルロックを乱発するとデッドロックが起こりやすくなったりロック待ちで止まったりしやすくなります。

Oracleの場合データの更新時には自動的に行ロックがかかります。あるセッションが行をアップデートしてコミットするまでに別のセッションが同じ行をアップデートするとそのセッションは待ち状態になります。読み取りについては更新前の値が返ります。

データの更新はしないが他のセッションの更新を待たせたい場合の行ロックをするにはselect~for updateを使います。普通のselect文の最後にfor updateをつけます。これで他のセッションからの更新はロック待ちにすることができます。この場合についても読み取りについては更新前の値が返ります。

では読み取りをロック待ちにさせたいときはどうするか?Oracleではそういうロックはありません。コミットがされるまでは更新前の値がちゃんと返るので読み取りロックしなくてよいということだそうです。

主キーが連番になっている場合、新しい行の主キーの値を計算するときにselectでmax値を取ってきたりします。読み取りロックがないと値がバッティングしてしまいそうです。こういう場合はシーケンスを使います。Oracleのシーケンスでは取得するたびに違う値になることが保証されています。