Azureにはマネージドデータベースとして、MySQL・MariaDB・PostgreSQL・CosmosDB・SQL Serverなど様々な選択肢が用意されています。
管理画面からちょこっと操作するだけで簡単にDBを作ることができ、手動でやるとたいへん面倒なバックアップ・レプリケーション・スケーリングなどの設定もいとも簡単に行うことができます。
私はこれを使い始めてから、手動でデータベースを作ることがなくなりました。
ところがMicrosoftは先日、Azure Database for MariaDBの提供をやめると発表しました。
2025/09/19に終了します。
サポートはしないけど一応動くとかではなく、完全に動かなくなるみたいです。
従って、MariaDBを使っている場合はそれまでにサービスを閉じるか別のデータベースに移行しなければなりません。
移行先としてはドキュメントでもお勧めされているAzure Database for MySQL フレキシブルサーバーが最適でしょう。
そもそもMariaDBはMySQLのforkだから互換性が高く、というかこれまで互換性で引っかかったことがないです。
専門家に言わせれば違うのでしょうが、個人的には全く同じ使い方で支障が出たことはないですね。
だからきっと移行しても安心です。
Azure Database Migration Service
AzureにはDatabase Migration Serviceというサービスが存在します。
これを使えばデータベースAからデータベースBへとデータを簡単に移行したり、さらには異なる種類のDB間でもレプリケーションすら行えてしまうという優れもののサービスです。
そんなわけで、さっそくこれを使って移行しようとしたわけですよ。
は??????????????????????????????????????????
お前の都合で移行するんだからマイグレーションくらい用意しとけ!!!!!!!!
手動でマイグレーションする
Azure Database for MariaDBのドキュメントにおいて、移行方法の説明へのリンクがはってあります。
ところがこのマイグレーションガイド、全面英語なうえに全てコマンドラインの手動マイグレーションであり、さらにはそのまま打つと動かないところがあったりして色々苦労したので記録しておきます。
マイグレーションを実行するサーバを用意
移行元のMariaDBでも移行先のMySQLでもなく、それ以外にもう一台マイグレーション用のサーバが必要です。
MySQL Shellというクライアントを使うので、そいつをインストールするためのサーバを用意します。
まあなんか適当にVMでも立てればいいよ。
もしくはMySQL ShellはWindows用もあるので、ローカルマシンで動かしてかまわない規模のサービスであればこっちのほうが手っ取り早いかもしれません。
もちろんサーバからは、MariaDBとMySQL両方に対して3306ポートが通っている必要があります。
MySQL Shellのインストール手順。
su -
# mysql-community-releaseの存在確認
yum repolist all | grep mysql
# mysql-community-releaseが既にインストールされていた場合は削除しないといけないらしい
yum remove mysql-community-release
# リポジトリを追加
wget https://dev.mysql.com/get/mysql80-community-release-el8-8.noarch.rpm
yum install mysql80-community-release-el8-8.noarch.rpm
# MySQL Shellをインストール
yum install mysql-shell
# インストール確認
mysqlsh --version
# mysqlsh Ver 8.0.34 for Linux on x86_64
suするな?
うるせえ知るか。
MariaDBのバイナリログが有効か確認する
とりあえずMariaDBでバイナリログが有効になっているかを確認しましょう。
SHOW VARIABLES LIKE 'log_bin';
これがオフだった場合、MariaDBはバイナリログを保存していません。
バイナリログはINSERTとかUPDATEとかALTERとかのSQLを保存しているログです。
従ってこれがないとレプリケーションすることができないため、まずは有効にする必要があります。
でもAzure管理画面では、直接これを有効にする方法が何故かないんですよね。
『レプリケーション』 → 『レプリカの追加』を実行するとバイナリログが有効になります。
有効にさえしてしまえばレプリケーション自体は不要なのですぐに停止・削除してかまいません。
あとついでに、『接続のセキュリティ』の項目から『SSL接続を強制する』を無効にしておくと後で楽になります。
MariaDBからバックアップ
現在のデータを、MariaDBからマイグレーション用サーバにバックアップします。
# バックアップ用ディレクトリを用意
mkdir /path/to/tmp
cd /path/to/tmp
# MariaDBにログイン
mysqlsh --uri [ユーザ名]@[サーバ]:3306
# バックアップコマンド
util.dumpInstance("/path/to/tmp/mariadbbackup", {threads: 16, showProgress: true, users:false})
実際のログインコマンドはmysqlsh --uri username@sample.mariadb.database.azure.com:3306
みたいなかんじになります。
これでMariaDBのデータがマイグレーションサーバの/path/to/tmp/mariadbbackup
ディレクトリに保存されました。
なおユーザ名に@
が入っていた場合は%40
に書き替えましょう。
でないとユーザ名とサーバの区切りと誤認識されて動きません。
またmysqlsh上では、コマンドの最後に半角スペース等があるとエラーになります。
大抵の言語は末尾スペースとか無視してくれるのですが、mysqlshはそんな融通を利かせてはくれないようです。
util.dumpInstance
は第二引数で様々なパラメータに対応しているのですが、今回はドキュメントに従っただけなのでthreadsが何なのか、どうしてusersはfalseにするのか、などはよくわかりません。
またバックアップ対象のスキーマを指定していないのですが、自分で作ったスキーマだけがバックアップされました。
sys
とかinformation_schema
とかのシステム用は自動的に対象外にされるようです。
特定のスキーマだけをバックアップするコマンドとかもありますが、今回は不要だったので調べていません。
バックアップ位置を確認する
せっかく保存したバックアップファイルですが、どこまでのデータが入っているかわからないと、あとでレプリケーションするときに困ります。
@.json
というファイルに、その情報が記録されています。
cat /path/to/tmp/mariadbbackup/@.json
"binlogFile": "mysql-bin.999999",
"binlogPosition": 12345,
binlogFile
とbinlogPosition
の値をメモしておきましょう。
MySQLにリストア
今度は移行先のMySQLで作業します。
# MySQLにログイン
mysqlsh --uri [ユーザ名]@[サーバ]:3306
# リストアコマンド
util.loadDump("/path/to/tmp/mariadbbackup", {threads: 16, showProgress: true, ignoreVersion: true})
ドキュメントにはignoreVersion
がありませんが、これを指定しないとエラーになりました。
ERROR: Destination MySQL version is newer than the one where the dump was created.
Loading dumps from different major MySQL versions is not fully supported and may not work.
Enable the 'ignoreVersion' option to load anyway.
Util.loadDump: MySQL version mismatch (MYSQLSH 53011)
移行先のメジャーバージョンが移行元より新しいのでエラーになったということでした。
でも移行元はMariaDB10.2で、移行先はMySQL8.0だったのですが、これでも移行先のほうが新しいと判定するんですね。
ignoreVersion
はバージョンの違いを無視してリストアするオプションです。
つまりこれを指定すると、バージョンの違いによって互換性の問題が発生する可能性があるということです。
ということでバージョン違いによる差があるか調査してみたところ、移行前にはあったINT(1)
とかの(1)
が飛んでINT
になっていました。
これはMySQLの仕様なので回避方法はありませんし、そもそもあれ桁数ではないのでほぼ無意味な項目であり、消えた方がすっきりですね。
レプリケーション実行
単純にバックアップした時点のDBをリストアするだけでよいならここで終わりですが、毎秒アクセスが来るようなDBであれば、限りなく最新の状態を保ったまま移行する必要があります。
ということでレプリケーションの出番です。
# MySQLにログイン
mysqlsh --uri [ユーザ名]@[サーバ]:3306
# 使用言語をSQLにする
\sql
# レプリケーション設定
CALL mysql.az_replication_change_master('MariaDBのサーバ', 'ユーザ名', 'パスワード', 3306, 'mysql-bin.999999', 12345, '');
# レプリケーション開始
CALL mysql.az_replication_start;
# ステータス確認
SHOW SLAVE STATUS;
レプリケーション設定の第5引数はbinlogFile
、第6引数はbinlogPosition
で、どこの時点からレプリケーションを始めるかの設定です。
従って、ここには先ほどメモした値を入力します。
誤った値を入れるとデータが正しくならないので注意しましょう。
mysql.az_replication_start
後、レプリケーションがうまくいかなかったらerror connecting to master
みたいなエラーが発生します。
メッセージに従って対処する必要があります。
私はSSLでひっかかりました。
第7引数の''は、MariaDBへの接続にSSLが必須である場合に証明書を指定します。
のはずなんだけど、なんかフルパスで指定してもSSL connection error: SSL_CTX_set_default_verify_paths failed
とか言われて解決できなかったんですよね。
よくわからないし面倒だったので、単にAzure管理画面からMariaDBへのアクセスにSSLが必須のチェックを外しました。
どうせ移行が終わったらDB自体すぐ止めるからまあ別にいいでしょ。
全てのエラーが解消されたのち、レプリケーションコマンドを打つとSlave_IO_State
がWaiting for source to send event
になります。
これでもうレプリケーションが始まっているはずなので、MariaDBになんか突っ込んでMySQL側に反映されるか確認するとよいでしょう。
ただレプリケーション開始直後はデータが追い付いていないので、同期が終わるまでしばらく待機する必要があります。
具体的にはSeconds_Behind_Master
の値が0になるまで待ちます。
アプリケーションのDB向き先変更
最後にアプリケーションをデプロイします。
これは単にアプリケーションのDSNをMariaDBからMySQLに変更するだけです。
そういえばユーザは移行しなかったので、別途作成する必要があります。
適当にGRANTしておきましょう。
レプリケーション停止
MySQL側にインサートとかを行ってレプリケーションに矛盾が生じたら、その時点でレプリケーションは勝手に止まるみたいです。
ただ判定がいまいちわからないので、手動で停止したほうがより安全だと思います。
これもマイグレーションガイドに載ってないんだよな。
# MySQLにログインして実行
CALL mysql.az_replication_stop;
これでレプリケーションが停止しました。
最後にMariaDBとマイグレーションサーバを削除して、移行は完了です。
感想
Azure側都合で対応を取りやめるんだからマイグレーションくらい用意してくれよ。
Azure Database Migration Serviceは、このあたりのコマンドをAzure管理画面上でできるようにしてあるだけだと思うんですよね。
しかしこれがもう驚くほど便利であり、3TBの高負荷MySQLを手動マイグレーションして死にかけていたのが画面上でぽちぽちするだけでできるようになったときはもう本当に感動感謝感激雨霰でしたよ。
だからもっと対応データベース増やしてくれ。