ビューの変更はトランザクションセーフではない。

出典: MySQL Practice Wiki


説明

MySQLにおいてはトランザクションはストレージエンジンの階層で処理される。そしてビューはストレージエンジンの上位層で処理される。(実際にはベースとなっているテーブルへのマッピングをするだけである。)したがって、ビューの変更はトランザクションセーフではない。ビューを使ったトランザクションを実装する場合には注意が必要である。

動作例

例えば次のようなテーブルとビューを考える。

mysql> CREATE TABLE t1 (a BIGINT UNSIGNED NOT NULL PRIMARY KEY) ENGINE=InnoDB;
mysql> CREATE TABLE t2 LIKE t1;
mysql> CREATE VIEW v1 AS SELECT a FROM t1;

そしてトランザクションを開始する。

mysql> START TRANSACTION;
mysql> INSERT INTO v1 VALUES(1),(2),(3);

他のセッションからビューの定義を変更する。(参照するテーブルをt1からt2に変更。)

mysql> CREATE OR REPLACE VIEW v1 AS SELECT a FROM t2;

トランザクションを継続。

mysql> INSERT INTO v1 VALUES(4),(5),(6);
mysql> COMMIT;

そうすると以下のような結果になる。

mysql> SELECT * FROM t1;
+---+
| a |
+---+
| 1 | 
| 2 | 
| 3 | 
+---+
3 rows in set (0.00 sec)

mysql> SELECT * FROM t2;
+---+
| a |
+---+
| 4 | 
| 5 | 
| 6 | 
+---+
3 rows in set (0.00 sec)

対処

このような結果は望ましいものではない場合が多い。このような結果を回避するためには、ストレージエンジンの上位層での処理が必要となる。つまり、LOCK TABLESをするべきなのである。

mysql> LOCK TABLES t1 WRITE, t2 WRITE;
mysql> CREATE OR REPLACE VIEW v1 AS SELECT a FROM t2;
mysql> UNLOCK TABLES;
個人用ツール