PostgreSQL トランザクション分離レベル v9.6 2017/7

Serializable (直列化)
※ 一つのトランザクションだけが更新系SQLを実行できる。

Case1
Transaction 1
testdb=# BEGIN; 
BEGIN
testdb=# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET
testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    1 | A
    2 | B
    3 | C
(3 行)
/* 左右同じ結果が返る。 */



testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    1 | A
    2 | B
    3 | C
(3 行)
/* 右のコミット前のアップデートは左に反映されない。 */

testdb=# UPDATE test_table_2 SET col2='F' WHERE col1= 1;
/* 右のトランザクション待ちとなる */

ERROR:  could not serialize access due to concurrent update
/* 強制的にROLLBACKされる。 */
Transaction 2
testdb=# BEGIN;
BEGIN
testdb=# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    1 | A
    2 | B
    3 | C
(3 行)

testdb=# UPDATE test_table_2 SET col2='D' WHERE col1= 1;
UPDATE 1

testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    2 | B
    3 | C
    1 | D
(3 行)




testdb=# COMMIT;
COMMIT

※ 先に更新したトランザクションがコミット → 後から更新したトランザクションはキャンセル。

Case2
Transaction 1
testdb=# BEGIN; 
BEGIN
testdb=# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET
testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    1 | A
    2 | B
    3 | C
(3 行)
/* 左右同じ結果が返る。 */



testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    1 | A
    2 | B
    3 | C
(3 行)
/* 右のコミット前のアップデートは左に反映されない。 */

testdb=# UPDATE test_table_2 SET col2='F' WHERE col1= 1;
/* 右のトランザクション待ちとなる */

UPDATE1
/* UPDATE成功 */
testdb=# COMMIT;
COMMIT
Transaction 2
testdb=# BEGIN;
BEGIN
testdb=# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    1 | A
    2 | B
    3 | C
(3 行)

testdb=# UPDATE test_table_2 SET col2='D' WHERE col1= 1;
UPDATE 1

testdb=# SELECT * FROM test_table_2;
 col1 | col2
------+------
    2 | B
    3 | C
    1 | D
(3 行)




testdb=# ROLLBACK;
ROLLBACK



※ 先に更新したトランザクションがロールバック → 後から更新したトランザクションが反映される。