LoginSignup
22
25

More than 5 years have passed since last update.

Postgres の排他制御(行ロックとデッドロック)についてメモ

Last updated at Posted at 2014-10-27

背景

社内でデータベース研修が始まったため、いい機会なのでMacにPostgreSQLを入れて遊んでみました。
インストールはここを参照したら簡単でした。
研修はOracleの教科書で進んでいますがまあ基本的な概念は同じですね。

まとめてみると、どういうときにロック取得できないのかが意外と理解できてないことがわかりました。

行ロックの取得(select for update)

Transaction A

nsdb=# begin;
BEGIN
nsdb=# update hello set value = 'ngdesuyo' where num = 3;
UPDATE 1
nsdb=# update hello set value = 'ngdesuyo' where num = 2;
UPDATE 1

Transaction B

begin;
select * from hello where num = 2 for update;
-- ロックしようとしている行の変更がTransaction A でコミットされてないため、ここでwaitになる

Transaction A

nsdb=# commit;
COMMIT

Transaction B

-- select 結果が表示され、行ロックが取得される
 num |  value   
-----+----------
   2 | ngdesuyo
(1 row)

再度、行ロックの取得

Transaction A

nsdb=# begin;
BEGIN
nsdb=# update hello set value = 'ngdesutte' where num = 3;
UPDATE 1 -- ロックしてない行のupdate は通る
nsdb=# update hello set value = 'ngdesutte' where num = 2;
-- Transaction B がロックしているためwaitになる

デッドロック

上の状態で、下記のようにするとデッドロックします。
これは簡単な例なのでPostgresサーバが検出してくれました。

Transaction B

nsdb=# select * from hello where num = 3 for update;
ERROR:  deadlock detected
DETAIL:  Process 2930 waits for ShareLock on transaction 1021; blocked by process 2933.
Process 2933 waits for ShareLock on transaction 1020; blocked by process 2930.
HINT:  See server log for query details.

以上になります。

22
25
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
22
25