トランザクション

トランザクション関連コマンド

psql -U sample sample
sample=> select id,name from addressbook;
   id   |   name  
--------+---------------
   1    |  鈴木 太郎  
   2    |  ああ ああ   
   3    |  いい いい   
   4    | うう うう   
 (4 rows)

sample=> begin;
BEGIN

sample=> update addressbook
sample=> set name='んん んん' where id = '4';
UPDATE 1
sample=> select id,name from addressbook;
   id   |   name  
--------+---------------
   1    |  鈴木 太郎  
   2    |  ああ ああ   
   3    |  いい いい   
   4    |  んん んん  
 (4 rows)


(この時点で他の PC から addressbook を参照すると commit してないので古いデータを表示する)

sample=> commit;
COMMIT

トランザクション隔離レベル

複数のトランザクションが同時実行され、ほぼ同時に同じデータにアクセスした場合、3種類の問題が

問題 内容
ダーティリード 同時に実行されている他のトランザクションによりデータが更新され、まだコミットしていないデータを読み込んでしまう
反復不能読み取り 同じ検索を2回行ったときに、間に他のトランザクションがデータを更新もしくは削除してしまう
ファントムリード 検索条件を満たす問合せを2回実行する間に、別のトランザクションによってその条件を満たす新しい行が挿入されてしまう

これを回避する4種類の隔離レベル (SQLの規格)

  • READ UNCOMMITTED (低)
  • READ COMMITTED → PostgreSQL でサポート
  • REPEATABLE READ
  • SERIAZABLE (高) → PostgreSQL でサポート

隔離レベルが高いほど、問題の発生を防げるが、エラーになってトランザクション自体を実行できないこともある。

隔離レベル READ COMMITTED に設定

(BEGIN;の後でする)
select=> show transaction_isolation;
 transaction_isolation
----------------------
 read committed
(1 row)

select=> の状態で show transaction_isolation で隔離レベルを確認できる。

隔離レベルを READ COMMITTED にしている状態で、別のPCからデータベースを更新すると、更新された状態が参照される。

隔離レベル serializable に設定

(BEGIN;の後でする)
select=> SET transaction_isolation = 'serializable';
SET

隔離レベルを serializable に変更する。
隔離レベルを serializable にしている状態で、別のPCからデータベースを更新しても、更新された状態を参照できない。