【MySQL】MyISAMからINNODBへの移行【ちゃんと調べてやってね】

【MySQL】MyISAMからINNODBへの移行【ちゃんと調べてやってね】Web開発者の備忘録MyISAMが並列書き込みに対し弱い事は前回お伝えした通りなのですが。
じゃあ ALTER TABLE 使って INNODB に変えればいいじゃん!と言って何も考えずに行うと痛い目に遭います。

MyISAMとINNODBで異なる点を理解する

よく言われている以下の点は皆さんご存知だと思います。
・テーブルロック、行ロック
・トランザクション機能が無い 、ある

前回の内容も、ロック機構の違いで大きく性能が変わったわけです。

ただ、これだけではMyISAMからINNODBに移行を躊躇する理由にはなりません。

アプリケーションエンジニアが意識すべき点

MySQLでMyISAMからInnoDBに乗り換える際に知らないとハマる、怖い話
こちらの記事がとても参考になります。

この中で特に私が移行に躊躇したのがこれ。
MySQLのInnoDBでもPRIMARY KEYの2カラム目以降にAUTO_INCREMENTを使いたい

プログラム変えて検証しないといけないので。。
※いや、やれば済む話なのですが・・

まあ、見ての通り、
1.function でオートインクリメントの代わりとなるものを作る
2.alter table でオートインクリメントを外す
3.insert SQL上で、オートインクリメントとなるカラムに対し、上記1.の関数で得られた値をセットするようSQLを直す
だけですけどね。

でも既に大量にデータとユーザを抱えている身としては、なかなか勇気がいるもんです(汗

ちなみに、オートインクリメントやPrimary key の定義を変える事なく、INNODBに変えようとすると、エラーが出ます。
メッセージは忘れましたが、INNODB ではサポートしていない構造だ、みたいな内容です。

データベース領域についても考えないとね

実際に MyISAMからINNODBへ移行するコマンドはこれ。

ALTER TABLE テーブル名 ENGINE= INNODB;

これだけです。

ですが、これをやる前に最低以下の事はチェックしましょう。

1.ディスクの空きが十分にあるか
2.テーブル単位にファイルを分割しなくてよいか

ディスクの空き

MyISAMに比べ、INNODBはディスクを食います。
理由は色々ありますが、人によってはMyISAMで使われている量の2~3倍はあった方がよい、と言っております。
※ちなみに、今回私が行った時は、2.0GBのテーブルが3.0GBくらいまで増えました。1.5倍ですね。
※細かくは言えませんが、レコード数は数万、1レコードあたりデータ容量がものすごくデカイ、というタイプなのでこの程度で済んだのかもしれません

ここで注意。
移行対象のテーブルが2.0GB、移行後が3.0GBになる(と推測)、移行前のディスク空きが2.0GBある場合。
移行前後の差分が3.0GB-2.0GB=1.0GBとなるから、移行後は空きが1.0GBになるだろう、という推測はあっておりますが、これだと失敗します。

MyISAMからINNODBへの移行時は、当然ですが一時的にMyISAMで確保された領域+INNODBで作り直すための領域が必要となります。
つまり

移行対象のテーブルが2.0GB、移行後が3.0GBになる(と推測した)場合。
一時的に、移行後の3.0GBの空きが最低限必要となります。

テーブル単位へファイルを分割

何を言っているかと言いますと。
デフォルトでは、INNODBはシステム全体で1つのファイルしか作らず、その中にいろんなデータベース、テーブル等を抱え込んでいる、という事。
データベースファイルがシステム全体で1つしか作られない、という事です。

それ自体はあまり気にすべき事項ではありませんが。
注意すべき点は、INNODBで使われるデータベースファイルは、決して小さく出来ない、という点。

データが増えた結果ディスクを圧迫したため、テーブルを消すなどしても、ファイルサイズは小さくならず、結果ディスクは圧迫されたままである、という点です。

データベースファイルを小さくしたい場合は、
1.mysqldump等で一度別ファイルにデータを退避させる。
2.全データベース、全テーブル等削除する(drop database , drop table等)。
3.mysqld を停止
4.データベースファイルを削除
5.mysqld を起動
6.上記1.でとったダンプファイルを使ってデータベースを再構築する

という、鬼の様な手順を踏んでいかないといけません。

ここで、この問題を少しでも緩和する策がこれ

「テーブル単位にデータベースファイルを作成する」

my.cnf ファイル等で、

innodb_file_per_table=1

を指定すること。

これを指定すれば、以後新たに作成されるテーブルについては、テーブル単位でデータベースファイルが作成されることになります。

このデータベースファイルが肥大してディスクを圧迫するようになった場合、次の手順でディスクの空きを調整する事が出来る様になります。

1.mysqldump等で該当テーブルのダンプファイルを作成
2.該当テーブルをdrop する
3.該当テーブルを create tableする
4.上記1.でとったダンプファイルでデータを戻す

システム全体へ影響を及ぼす事がなくなりますので、絶対にオススメします。

しかも、これは最初にINNODBを作る時に決めないといけない事なので、とても大事だと思います。

他にも色々あるんです

冒頭で紹介したページでは、メモリー等のチューニング、全文検索など色々書いてありますので、それらにつきましても十分考慮する必要があります。

ということで、色々めんどくて手を付けたくなかった部分なのですが。
少しでも参考になるかなー、と思い書いてみました。