Postgresではファジーリードが発生、MySQLではファジーリードが発生しない(※ デフォルトの場合)
code:mysql
mysqlの分離レベルのデフォルトはREPEATABLE-READ。
mysql >select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.01 sec)
======
プロセスを視覚的に分かりやすくするためにpromptカスタマイズしておく。(やらんでもええけど)
プロセス1
mysql> prompt 1 >
=======
プロセス2
mysql> prompt 2 >
=======
1 >start transaction;
Query OK, 0 rows affected (0.00 sec)
======
2 >start transaction;
Query OK, 0 rows affected (0.00 sec)
=======
1 >select cash from users where id=1;
+------+
| cash |
+------+
| 100 |
+------+
1 row in set (0.01 sec)
========
2 >select cash from users where id=1;
+------+
| cash |
+------+
| 100 |
+------+
1 row in set (0.01 sec)
=======
1の方でupdateして、commitする。
1 >update users set cash=cash+100 where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
1 >select cash from users where id=1;
+------+
| cash |
+------+
| 200 |
+------+
1 row in set (0.00 sec)
1 >commit;
Query OK, 0 rows affected (0.01 sec)
======
だけど2の方ではまだ100で値がupdateされていない。つまりファジーリード発生していない。
2 >select cash from users where id=1;
+------+
| cash |
+------+
| 100 |
+------+
1 row in set (0.00 sec)
余談だけど、このトランザクション処理が cashに+100するもの であれば2の方で後からupdateするとロストアップデートが起こる。
=> 本来は300になって欲しいところが200になる。
MySQLのデフォルト REPEATABLE-READではファジーリードは起こらなかった。
ではPostgresでも同じことやってみよう。
code:Postgres
postgresのデフォルトトランザクションレベルは read committed 。
postgres=# SHOW TRANSACTION ISOLATION LEVEL;
transaction_isolation
-----------------------
read committed
(1 row)
ここではややこしいので プロセス1を 1=# , プロセス2を 2=# と表す。
1=# start transaction;
START TRANSACTION
=========
2=# start transaction;
START TRANSACTION
==========
1=# select cash from users where id=1;
cash
------
100
(1 row)
========
2=# select cash from users where id=1;
cash
------
100
(1 row)
=========
1の方でupdateしてcommitする。
1=# update users set cash=cash+100 where id=1;
UPDATE 1
1=# select cash from users where id=1;
cash
------
200
(1 row)
1=# commit;
COMMIT
========
2のトランザクションでも値が変わっている。つまりファジーリードが発生している! これは分離レベルがread committedだから。
postgres=# select cash from users where id=1;
cash
------
200
(1 row)
Postgresではファジーリードが発生した。