ストレージエンジンをMyISAMからInnoDBへ切り替える際の注意
mroongaと間接的に関わる話として,
- 以下に該当するクエリを利用している
- INSERT IGNORE INTO ...
- INSERT INTO ... ON DUPLICATE KEY UPDATE ...
- LOAD DATA ... IGNORE INTO ...
- 行削除するケースがある
具体的にどのような挙動の違いがあるか,
-- テーブルを作成
CREATE TABLE test (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(10),
UNIQUE INDEX (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
IGNORE INTO文の動作の違い
INSERT IGNORE INTO ...
を用いて解説します。なお,INSERT INTO ... ON DUPLICATE KEY UPDATE ...
の挙動も同一です。
-- 1つめのレコードを入れます
mysql> INSERT IGNORE INTO test (name) VALUES('トマト');
Query OK, 1 row affected (0.00 sec)
-- 1件目なので,1が返ります
mysql> SELECT LAST_INSERT_ID()\G
*************************** 1. row ***************************
LAST_INSERT_ID(): 1
1 row in set (0.00 sec)
-- 重複のためスキップされるレコードを入れます
mysql> INSERT IGNORE INTO test (name) VALUES('トマト');
Query OK, 0 rows affected (0.00 sec)
-- 重複のため,1のままです
mysql> SELECT LAST_INSERT_ID()\G
*************************** 1. row ***************************
LAST_INSERT_ID(): 1
1 row in set (0.00 sec)
-- 重複とならないデータを追加します
mysql> INSERT IGNORE INTO test (name) VALUES('トマト2');
Query OK, 1 row affected (0.00 sec)
-- MyISAMではidが2となるのですが,InnoDBでは3となります
mysql> SELECT LAST_INSERT_ID()\G
*************************** 1. row ***************************
LAST_INSERT_ID(): 3
1 row in set (0.00 sec)
-- InnoDBのテーブル内容は以下の通りです
mysql> select * from test;
+----+------------+
| id | name |
+----+------------+
| 1 | トマト |
| 3 | トマト2 |
+----+------------+
2 rows in set (0.00 sec)
データを削除した時のプライマリキーの挙動の違い
InnoDBの場合,
具体例とともに解説します。
-- まずは1件目のデータを挿入します
mysql> INSERT INTO test (name) VALUES('トマト1');
Query OK, 1 row affected (0.02 sec)
-- 続けて2件目のデータを挿入します
mysql> INSERT INTO test (name) VALUES('トマト2');
Query OK, 1 row affected (0.02 sec)
-- 期待通り,idは2となりました
mysql> SELECT LAST_INSERT_ID()\G
*************************** 1. row ***************************
LAST_INSERT_ID(): 2
1 row in set (0.00 sec)
-- idが2のデータを削除します
mysql> DELETE FROM test WHERE name IN('トマト2');
Query OK, 1 row affected (0.03 sec)
-- 続けて3件目のデータを挿入します
mysql> INSERT INTO test (name) VALUES('トマト3');
Query OK, 1 row affected (0.03 sec)
-- 期待通り,idは3となりました
mysql> SELECT LAST_INSERT_ID()\G
*************************** 1. row ***************************
LAST_INSERT_ID(): 3
1 row in set (0.00 sec)
-- idが3のデータを削除します
mysql> DELETE FROM test WHERE name IN('トマト3');
Query OK, 1 row affected (0.02 sec)
-- ここで,MySQLを再起動し,再度接続後に以下の行を挿入します
mysql> INSERT INTO test (name) VALUES('トマト4');
Query OK, 1 row affected (0.03 sec)
-- 再起動により,MyISAMでは4となる一方,InnoDBでは2となりました
mysql> SELECT LAST_INSERT_ID()\G
*************************** 1. row ***************************
LAST_INSERT_ID(): 2
1 row in set (0.00 sec)
-- InnoDBのテーブル内容は以下の通りです
mysql> select * from test;
+----+------------+
| id | name |
+----+------------+
| 1 | トマト1 |
| 2 | トマト4 |
+----+------------+
2 rows in set (0.01 sec)
この挙動となる仕組みについては,
なお,COMMENT='engine "myisam"'
と指定することで,
その他,
パーティショニング
InnoDBラッパーモードそのものでは,
具体的な方法に関しては,
まとめと次回予告
今回はTritonnとmroongaそれぞれの紹介と移行時の要注意点,
次回は,
groongaの利用事例を寄稿しませんか
連載の目的は