LoginSignup
4
1

More than 3 years have passed since last update.

意外と意識されていないPostgreSQLのロックについて

Posted at

開発でPostgreSQLを利用することはよくありますよね。
しかし、ロックについてしっかり理解している人は少ないと思います。

PostgreSQLのロックの種類

まず、PostgreSQLのロックには以下のようなロックレベルがあります。

  • ACCESS SHARE
  • ROW SHARE
  • ROW EXCLUSIVE
  • SHARE UPDATE EXCLUSIVE
  • SHARE
  • SHARE ROW EXCLUSIVE
  • EXCLUSIVE
  • ACCESS EXCLUSIVE

それぞれについての詳しい内容は公式ドキュメントをご覧ください
https://www.postgresql.jp/document/12/html/explicit-locking.html

よく使うSQLだと例えば、
SELECT文はACCESS SHARE、INSERTやUPDATEはROW EXCLUSIVEにあたります。

競合するロック

ロックは以下の表の☓がの部分が競合します。

ACCESS SHARE ROW SHARE ROW EXCLUSIVE SHARE UPDATE EXCLUSIVE SHARE SHARE ROW EXCLUSIVE EXCLUSIVE ACCESS EXCLUSIVE
ACCESS SHARE X
ROW SHARE X X
ROW EXCLUSIVE X X X X
SHARE UPDATE EXCLUSIVE X X X X X
SHARE X X X X X X
SHARE ROW EXCLUSIVE X X X X X X
EXCLUSIVE X X X X X X X
ACCESS EXCLUSIVE X X X X X X X X

ACCESS EXCLUSIVEロック時に、ACCESS SHAREの実行はロックされ待ちが発生します。
しかし、ROW EXCLUSIVEロック時に、ACCESS SHAREの実行はロックされず実行することが可能です。

実際に実行してみる

競合なしパターン

BEGIN;

INSERT INTO hoge VALUES (1, 'hoge');

を実行して、ロック状況を見ると以下のようになります(pgAdminで確認してます。)
postgresql_lock_1.png
RowExclusiveLockでロックされているのがわかると思います。
この状態で以下を実行すると実行可能なことがわかります。
実行する際にはさきほど実行したのとは別のセッションでお願いします。

SELECT * FROM hoge LIMIT 1;

競合ありパターン

BEGIN;

TRUNCATE TABLE hoge;

を実行して、ロック状況を見ると以下のようになります。
postgresql_lock_2.png
こちらはAccessExclusiveLockになっているのがわかると思います。
この状態でさきほどと同じ以下のSQLを実行してみてください。

SELECT * FROM hoge LIMIT 1;

おそらくすぐに実行されないと思います。
この状態でロックかけてる側のセッションで

ROLLBACK;

を実行するとSELECTの結果も返ってくると思います。

まとめ

このように普段意外と意識していないかもしれませんが、しっかりとロックレベルがあります。
これを意識して開発するのは大事ですね。ロックレベルを意識的に上げたい場合などは明示的にロックをすることも可能なのでそのへんも意識していけるといいですね。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1