VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
データ型とデフォルトの違い
MariaDB 固有のスキーマオブジェクトがロードを失敗させる
CREATE SEQUENCE を使うスキーマは、MySQL にロードすると、どのテーブルも作成される前に即座に失敗します。mysqldump はシーケンスの定義をテーブルより先に書き込むためです。シーケンスを含む未修正のダンプをロードすると次のようになります。at line N の値はステートメントがダンプ内のどこにあるかを示すもので、ここに示す数値とは一致しません。
DROP SEQUENCE / CREATE SEQUENCE / DO SETVAL(...) のブロックを削除し、DEFAULT nextval(...) と書かれた列のデフォルトを、プレーンな AUTO_INCREMENT 列またはアプリケーションが割り当てる値に置き換えます。
INET6 型の列も、同じロードの後の方で、ローダーがその列を宣言するテーブルに到達した時点で同じように失敗します。これは、このガイドの中で、どのサーバーにロードするかによって文言が変わる唯一のエラーです。VillageSQL は型の名前を示します。その文法はその位置でカスタム型名を受け入れるため、解決できなかった型を報告するからです。
ERROR 1064 で、どちらも問題の行を示すため、修正はどちらでも同じです。ロードの前に列の型を VARCHAR(45)(テキスト形式の IPv6 アドレスに十分な長さ)に変更するか、移行先に拡張機能がインストールされていれば、それが提供する INET 型に変更します。
外部キー制約名がテーブル間で衝突する
MariaDB のmysqldump は、名前のない外部キー制約に、テーブルごとに 1 から始まるプレーンな整数の名前を自動で付けます。同じスキーマ内の 2 つのテーブルが、どちらも文字どおり 1 という名前の制約を持つことがあります。
CONSTRAINT 1“ のロードは次のエラーで失敗します。
CREATE TABLE で CONSTRAINT name を指定していなかった)場合にだけ起こります。ロードの前に、衝突する各制約を一意な名前、たとえば order_items_ibfk_1 と orders_ibfk_1 に変更します。
JSON 列はエラーなしに、別の型としてロードされる
上の 3 つの問題とは異なり、JSON 列はエラーも警告もなく MySQL にロードされます。MariaDB の JSON 列について、ダンプされた CREATE TABLE は次のようになります。
CHECK 制約と JSON_VALID() 関数をサポートしているため、このステートメントは書かれたとおりに実行されます。MySQL 側では、列は MySQL のネイティブな JSON 型ではなく、CHECK 制約付きの LONGTEXT になります。JSON_EXTRACT() と JSON_LENGTH() で読み戻すと、元のデータと同一の結果が得られるため、何も失われません。しかし、列の宣言された型は、新規の MySQL スキーマが使うものとは異なります。移行先でネイティブな JSON 型が必要なら、ロード後に列を変更します。
CHECK (json_valid(...)) 制約を列に付けたまま残します。ダンプはその制約に名前を付けていないため、CREATE TABLE の実行時にサーバーが products_chk_1 のような名前を付けました。ALTER の前からすでに存在しています。MySQL は型レベルですでに無効な JSON を拒否するため、ネイティブな JSON 列では無害ですが、LONGTEXT の定義から残った不要な制約です。クリーンなスキーマにしたい場合は削除します。
認証の違い
MariaDB と MySQL のクライアントは同じワイヤプロトコルを話し、一方から他方へのプレーンなパスワード認証による接続は動作します。引き継がれないのは、アカウントの定義そのものです。mysqldump はデフォルトでは mysql.user テーブルをダンプしないため、アカウントと権限は移行先で手作業で再作成する必要があり、そのための構文は異なります。
パスワード付きで作成された MariaDB のアカウントは、次のように表示されます。
caching_sha2_password プラグインを使う MySQL または VillageSQL では、同じステートメントは代わりに次のように表示されます。
SHOW CREATE USER ステートメントを MySQL にコピーしないでください。移行先で CREATE USER ... IDENTIFIED BY '<password>' によってアカウントを新規に作成し、サーバー自身のデフォルトプラグインを選ばせてから、GRANT ステートメントを再発行します。
セットアップしたばかりの MariaDB インストール(たとえば新規の Homebrew インストール)に対して移行をテストしていて、パスワードが正しいのに、パスワード付きの名前付きアカウントが「Access denied」で拒否される場合は、まず匿名アカウントを確認します。
''@'localhost' と ''@'<hostname>' が残っていることがあります。ホストの一致はユーザー名の一致より優先されるため、localhost に解決される接続は、名前付きアカウントより先に匿名アカウントに一致し、匿名アカウントはパスワードを期待しないため拒否されます。これは MariaDB 側のインストールの問題で、データとともに MySQL に引き継がれるものではありませんが、匿名アカウントを削除するまでは、移行元でのテストを混乱させることがあります。
移行の進め方
- スキーマとデータをダンプします。
mysqldumpを使います(MariaDB ホストでは通常 MariaDB 独自のmariadb-dumpへのシンボリックリンクです。mysqldump --versionを実行してどちらかを確認します)。 - ロードを試みる前に、ダンプから
CREATE SEQUENCE、INET6、およびRETURNINGを検索します。 この 3 つはいずれも、ロードがすでに途中まで進むまで有用なエラーを出しません。 - まずスクラッチ用のデータベースにロードを試みます。
CREATE SEQUENCEまたはINET6の失敗は、そのステートメントでスクリプト全体を中止します。そのため、ファイル内で先に定義されたテーブルはすでにロードされ、後に定義されたテーブルはロードされていません。半分ロードされたデータベースにパッチを当てるのではなく、ダンプを修正して新規のデータベースに再ロードします。 - 移行元のスキーマが名前のない外部キーに頼っていた場合は、外部キー制約名の衝突を確認します。
grep -o 'CONSTRAINT \[0-9]*`’ dump.sql` で見つかります。 - アカウントと権限を手作業で再作成します。
mysqldumpにはそれらが含まれず、CREATE USER/SHOW CREATE USERの構文は 2 つのサーバーで異なります。 - 行数を検証し、JSON 列を抜き取り検査します。
JSON列は黙ってLONGTEXTとしてロードされます。ネイティブなJSON列に変換するかどうかを決める前に、JSON_EXTRACT()でデータが往復することを確認します。
よくある質問
同じバージョン系統の MySQL を移行先とする場合、MariaDB の mysqldump ファイルに編集は必要ですか?
スキーマがシーケンス、INET6、RETURNING、または名前のない外部キーを使っていなければ、同じダンプは多くの場合、変更なしでロードされます。スキーマが「ただのテーブルとデータ」だから成功するだろうと仮定するのではなく、まずスクラッチ用のデータベースに対してロードをテストしてください。
ネイティブな MySQL の JSON 列は、MariaDB のダンプを通して正しく往復しますか?
値は正しく往復します。列の型は往復しません。MariaDB は JSON 列を CHECK 制約付きの LONGTEXT としてダンプし、それがそのまま MySQL にロードされます。後で明示的に ALTER TABLE ... MODIFY で列を JSON にしない限り、そのままです。
MySQL クライアントで MariaDB サーバーに、またはその逆に接続できますか?
はい、通常のパスワード認証による接続であれば可能です。どちらも同じワイヤプロトコルを使い、一方のライブラリでビルドされたクライアントは、パスワード付きのアカウントが存在しさえすれば、他方のサーバーのアカウントに対して認証できます。両者が分かれるのは、接続ではなく、各サーバーが受け入れる SQL です。トラブルシューティング
関連項目
- PostgreSQL から MySQL への移行 — 移行元が PostgreSQL の場合の同等のガイド
- MySQL のスキーママイグレーション — 移行に必要な DDL 変更の実行