「Migrating Meta to MySQL 8.0」まとめ

yamaguchi naoto
8 min readSep 5, 2023

だいぶ時間が経ってしまったんですが、去年末に「MySQLテクノロジーセミナー スペシャルエディション “Facebook & MySQL”」に参加してきました。

そのセミナーで「FacebookにおけるMySQL 5.6から8.0へのバージョンアップ」(Migrating Facebook to MySQL 8.0)の発表がありました。

そこで改めて、同じ内容のPercona Live 2022での発表を見たり、Metaの公式Blogを読んでまとめてみることにしました。

あとセミナー時のtogetterも見返しました。

Percona Live

公式Blog

Timeline

Metaは5.6から8.0に上げました。

5.6から5.7に上げるのは大変だったそうで、いきなり8.0にあげる決断をしたそうです。(後述のパッチを5.7に当て直すのが辛かったらしい)

MetaのMySQLは InnoDBとRocksDBの2つのストレージエンジンを搭載していて、その都合もあった模様です。

5.6には数多くのパッチを当てたそうで、それを8.0にポートするということから始まったそう。

Patch

開始時には 1,700 を超えるパッチがありましたが、それらをいくつかの主要なカテゴリに整理したそうです。(スプレッドシートにまとめたっぽい)

精査して8.0に備わったものは移植する必要がなかったり、InnoDBとMyRocksに関連する機能が移植されたりした模様です。

これらすべての機能の移植を完了するまでに数年かかり、最後に到達するまでに、2,300 を超えるパッチを評価し、そのうち 1,500 を 8.0 に移植したそうです。

Row Based Replication

8.0にするにあたって、RBRの使用を標準化することに決めたようです。これによりMyRocksの移植作業も簡素化されたそうです。 すべてRBRだったわけではなく一部SBRが残っていて、簡単には変換できなかったそうです。

また主キーが無かったり、カーディナリティの高いカラムが無いテーブルが多数あった模様です。こういうテーブルはレプリケーションが遅延します。

ただ最終的にすべてSBRからRBRに移行できたそうです。

Automation Validation

8.0 の移行プロセスのほとんどは、自動化インフラストラクチャへの投資とアプリケーションクエリを使用した mysqld サーバーのテストと検証でした。

E2E Integration Test

まずは5.6 と 8.0 の両方で実行されるE2Eの自動化テストを開発したようです。両方で実行して結果を突き合わせているようです。

Percona Live抜粋

そこで色々な課題が出で対応したようです。

  • エラーログのフォーマットが変更されたこと
  • utf8mb4のデフォルトcollationの変更(utf8mb4_general_ci)
  • エラーコードが変更されたこと
  • etc

Shadow Test

透過的に移行したいため、本番トラフィックをキャプチャしてテストインスタンスに再生するShadow testフレームワークを構築していました。

5.6で実行してrelay logから8.0に投げてエラーになったら記録するようです。

Percona Live抜粋

8.0から返されるエラーをログに記したところ、ここでも色々なエラーが発生したようです。

  • 予約語が増えたこと
  • REGEXP の非互換性
  • JSONの非互換性(JSONはおそらくカスタム)

Data Correctness

(ここはちょっと正しくまとめられてるか怪しいです)

次はデータの整合性です。GTIDベースのスナップショットから5.6と8.0でデータが一致しているかどうか確認したようです。図だとchecksumで比較してました。

また同じところまでGTIDを進めて、前述のShadow testのpluginを用いて、取得結果が一致しているかも見たようです。

Percona Live抜粋

Migration

実際のMigrationは下記の動画がわかりやすいです。

  1. mysqldump を使用してロジカルダンプ取って8.0レプリカを作成。これらのセカンダリは、アプリケーションの読み取りトラフィックを処理しません。
  2. 8.0 セカンダリで読み取りトラフィックを有効にします。
  3. 8.0 インスタンスをプライマリに昇格できるようにします。
  4. 読み取りトラフィックに対して 5.6 インスタンスを無効にします。
  5. すべての 5.6 インスタンスを削除します。

Monitoring

主に下記を監視したようです。

  • Slow Query Logs
  • Query Traffic Statistics (行の読み取り数など)
  • Replication Traffic Statistics(書き込みのスループットなど)
  • Client Errors
  • CoreDump Statistics

Production Pains

Lock Wait Timeout

とあるテーブルでPrimary KeyとUnique Keyの両方を持ってる時、5.7でlockの仕方が変わったのでLock wait timeoutが多発したのがあったようです。これは分離レベルをRRからRCに変えて対応したようです。

Performance Schema

もともと5.6でオフにしてたが、デフォルトの Performance_schemaの設定では、すべてのインストゥルメントが有効になり、大量のメモリが消費されていたようです。8.0ではオフにしたものの、仕様上ある程度は裏側で動くようでCPUが10%ぐらいもっていかれたようです。

その他

  • Skip-Scanの問題
  • binlog indexのmutex競合
  • 一時テーブルのクエリのクラッシュ
  • etc

感想

移行の規模感に圧倒されました。

MySQLに対してめちゃくちゃパッチを送ってるので偉いと思ったのですが、最終的にそれが移行のハードルになったりしてて序盤から大変そうでした。togetterにもまとめられてましたが、Auroraが独自機能から離れてるように最近見えていますが、独自機能を維持するのは大変なのかなと自分も思いました。

また移行ツールへの投資が結構行われていたようですが、Perconaがサポートに入っていた手前、Perconaが提供しているツールで満たせなかったのかなとかは気になりました。(GTIDベースのbinlogがあったはずなので)

最後に今回色々調べてみて、アプローチやプラクティスなど色々勉強になりました。

関連リンク

--

--