Category: "MySQL, Oracle, データベース" , Tags: InnoDB, MyISAM, MySQL, oracle, トランザクション
しゃちょーです。
しばらく宣伝が続いたので、DB Tracklayer開発中に気づいたちょっとおかしな感じのする話をしてみます。
MySQLでMyISAMとInnoDBが混在するトランザクションについて
やっぱり今回もOracleから来た人向けの話。
Oracleの場合に(というか普通)トランザクションを考慮する時というのは、
一連の作業を一つの決定で処理したい時、またはすべき時に
トランザクション中で一連の処理を行って、CommitまたはRoolbackするように処理を考える。
普通トランザクションとはこんな感じじゃないのかな。
とりあえず今回の話では、トランザクションのレベルの話とかロック関係の話は置いておいていただくとしてだ。
トランザクションは明示的に開始と終了を行いたいのであって
気にする必要があるのは、暗黙のうちにトランザクションが終了する物はないかということくらいか。(レベルとかロックの話とかは別ね)
暗黙のうちにトランザクションが終了するステートメントを把握しておかないで
トランザクション中にtruncateとか書いちゃった日には、
そこまでの処理は全てcommitされて、とても悲しい結果を見ることになる。
そこさえ把握していれば別に何ら扱いにくい、という物でもない。(レベルとかロックの話とかは別ね)
上記のように扱えるのはOracleがスキーマに対してエンジンが1つだから。
私が知らないだけかもしれないが、通常Oracleを操作する上で、DBエンジンとかストレージエンジンとか意識することはないはず。
対してMySQLは、テーブル単位でストレージエンジンを設定可能なのだが
これはスキーマ(データベース)の中にエンジンが混在する可能性があると言うこと。
実際そういう場合はDBの物理設計でエンジンごとに別スキーマにすべき、
と個人的には思うが、そんな物理設計が無いとは限らない。
では、たとえばMyISAMとInnoDBのテーブルが混在した処理を1つのトランザクションの中で行った場合どうなるのか?
う…即答できない…
ということで、答えられないのは悔しいから実験!
下記SQLをステップ実行した際に別セッションから見た状態で実験
① create table test1 ( col1 int ) engine=InnoDB;
② create table test2 ( col1 int ) engine=MyISAM;
③ start transaction;
④ insert into test1 values (11);
⑤ insert into test2 values (21);
⑥ commit;
① mysql> create table test1 ( col1 int ) engine=InnoDB;
Query OK, 0 rows affected (0.05 sec)
mysql> show create table test1;
+——-+——————————————————————————————-+
| Table | Create Table |
+——-+——————————————————————————————-+
| test1 | CREATE TABLE `test1` (
`col1` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+——-+——————————————————————————————-+
1 row in set (0.00 sec)
② mysql> create table test2 ( col1 int ) engine=MyISAM;
Query OK, 0 rows affected (0.05 sec)
mysql> show create table test2;
+——-+——————————————————————————————-+
| Table | Create Table |
+——-+——————————————————————————————-+
| test2 | CREATE TABLE `test2` (
`col1` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
+——-+——————————————————————————————-+
1 row in set (0.00 sec)
③ mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
④ mysql> insert into test1 values (11);
Query OK, 1 row affected (0.01 sec)
・実行後同じセッションで確認
mysql> select * from test1;
+——+
| col1 |
+——+
| 11 |
+——+
1 row in set (0.00 sec)
・別セッションで確認
mysql> select * from test1;
Empty set (0.01 sec)
⑤ mysql> insert into test2 values (21);
Query OK, 1 row affected (0.00 sec)
・実行後同じセッションで確認
mysql> select * from test1;
+——+
| col1 |
+——+
| 11 |
+——+
1 row in set (0.00 sec)
mysql> select * from test2;
+——+
| col1 |
+——+
| 21 |
+——+
1 row in set (0.00 sec)
・別セッションで確認
mysql> select * from test1;
Empty set (0.00 sec)
mysql> select * from test2;
+——+
| col1 |
+——+
| 21 |
+——+
1 row in set (0.00 sec)
・上記から、InnoDBのテーブルはトランザクション継続中で
MyISAMのテーブルはトランザクション中でも勝手にcommitされる(というかその概念がないのだな)
MyISAMテーブルのデータが確定しても、トランザクションは確定および中断しない。
⑥ mysql> commit;
Query OK, 0 rows affected (0.04 sec)
・同じセッションで確認
mysql> select * from test1;
+——+
| col1 |
+——+
| 11 |
+——+
1 row in set (0.00 sec)
mysql> select * from test2;
+——+
| col1 |
+——+
| 21 |
+——+
1 row in set (0.00 sec)
・別セッションで確認
mysql> select * from test1;
+——+
| col1 |
+——+
| 11 |
+——+
1 row in set (0.00 sec)
mysql> select * from test2;
+——+
| col1 |
+——+
| 21 |
+——+
1 row in set (0.00 sec)
・上記から、トランザクションは⑤で中断されなかったことがわかる。
・ということで私が考える結論
・エンジンの混在は気にせずともよい。
・トランザクションをサポートしないエンジンに対してトランザクションを発行しても
意味がないだけで、別に害もない、なので気にしない(そういう操作を明示的にする人の勝手)。
まあ予想通りの結果でしたが、確信が持てなかったので実験してみて正解でした。
本質的なところにはまた後日踏み込んでみるとしましょう。
今日はこの辺で。
では、また。


