Amazon RDS に MySQL のデータを移行しようとしたら Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes と怒られた話

はじめに

最近、お仕事で AWS に触る機会が出てきました。

触ると言っても AWS の機能をフル活用して、ってレベルではなくて。
Web として EC2 にインスタンスを立てて、DB として RDS を使って、といったくらいのものです。

起きたエラー

現在進行系で国内産クラウドを使っているのを AWS に切り替えよう、という動きの中で触ることになったのですが、このときに以下のエラーメッセージが表示され、困りました。

SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

国内産クラウドでは、AWS でいうところの EC2 的なサービスでサーバを立て、MySQL を入れて運用していました。

ここで培っていたデータを Amazon RDS に移行しようと CREATE TABLE したときに発生したエラーです。

原因

結論から述べると、MySQL文字コードutf8mb4 になっていたのが原因でした。

エラーメッセージを読み解くと、以下のようになります。

Syntax error or access violation

シンタックスエラーかアクセス違反、ということですね。

過去に利用した実績のある CREATE TABLE のクエリだったので 🤔 という感じです。

1071 Specified key was too long; max key length is 767 bytes

MySQL のインデクスサイズが最大 767 bytes である制約に当たってしまった、と思われます。

これも実績あるクエリ、ということで謎に思えたのですが、エラーメッセージでググって出てきた以下の記事に助けられました 🙏

qiita.com

上記の記事は Laravel で、私の使うシステムは Symfony という違いはありましたが、原因だろうと思われるインデクスの type は varchar(255) である点は同じでした。

そこで、Amazon RDS の設定値を確認、そしてビンゴ。

文字コード関連の設定値が utf8mb4 になっていました。

varchar(255) を 4bytes で保存すると 767bytes を超えてしまいますので、上記の記事と同じ現象ということですね。

解消方法の検討

対処法はいくつかあるのですが、私は Amazon RDS の設定値を書き換えることにしました。

インデクスの対象となるカラムのサイズを変えたり、インデクスの最大サイズを変更したり、最初に CREATE DATABASE する際の文字コード指定でも良いのですけれど、今回の主目的はデータ移行。

前の DATABASE で utf8 を使っていたので、それに合わせるのが適当だと判断しました。

解消

というわけで、Amazon RDS の設定画面から、パラメータグループを開きます。

パラメータの数が多いので、絞り込むために character_set と入力すると、目的のパラメータが出てきます。

f:id:h-yamashita:20190226133346p:plain

ここで utf8mb4 になっている設定を utf8 に書き換えます。

f:id:h-yamashita:20190226133518p:plain

この変更を保存。

RDS を再起動して、もう一度 CREATE DATABASE からやり直すと、文字コードutf8 で構築し直されました。

f:id:h-yamashita:20190226133635p:plain

あとは、先ほどコケた CREATE TABLE を流し、エラーが出なくなったのを確認して、完了です。

おわりに

Amazon RDS ですと、普通に MySQL で構築したときと違って設定値が my.cnf で管理されなくなるので、こうした設定値の差異は起きてしまいやすいかもしれませんね。

今回のエラーで、少しだけ詳しくなれた気がするので、良い経験になりました。