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 である制約に当たってしまった、と思われます。
これも実績あるクエリ、ということで謎に思えたのですが、エラーメッセージでググって出てきた以下の記事に助けられました 🙏
上記の記事は Laravel で、私の使うシステムは Symfony という違いはありましたが、原因だろうと思われるインデクスの type は varchar(255)
である点は同じでした。
そこで、Amazon RDS の設定値を確認、そしてビンゴ。
文字コード関連の設定値が utf8mb4
になっていました。
varchar(255)
を 4bytes で保存すると 767bytes を超えてしまいますので、上記の記事と同じ現象ということですね。
解消方法の検討
対処法はいくつかあるのですが、私は Amazon RDS の設定値を書き換えることにしました。
インデクスの対象となるカラムのサイズを変えたり、インデクスの最大サイズを変更したり、最初に CREATE DATABASE する際の文字コード指定でも良いのですけれど、今回の主目的はデータ移行。
前の DATABASE で utf8
を使っていたので、それに合わせるのが適当だと判断しました。
解消
というわけで、Amazon RDS の設定画面から、パラメータグループを開きます。
パラメータの数が多いので、絞り込むために character_set
と入力すると、目的のパラメータが出てきます。
ここで utf8mb4
になっている設定を utf8
に書き換えます。
この変更を保存。
RDS を再起動して、もう一度 CREATE DATABASE からやり直すと、文字コードが utf8
で構築し直されました。
あとは、先ほどコケた CREATE TABLE を流し、エラーが出なくなったのを確認して、完了です。
おわりに
Amazon RDS ですと、普通に MySQL で構築したときと違って設定値が my.cnf で管理されなくなるので、こうした設定値の差異は起きてしまいやすいかもしれませんね。
今回のエラーで、少しだけ詳しくなれた気がするので、良い経験になりました。