セッションの要約と登壇者の自己紹介

yoku0825氏(以下、yoku0825):「ぼくらが選んだ次のMySQL 8.0」の話をします。私たちは、次のMySQLを8.0.28にしました。みなさんには、それぞれ29や30や自分の使いたいバージョンについて調べてもらいたいのですが、量が膨大になるので、今いるバージョンから新しいほうに向かって調べていくのではなく、最新のものからこれはダメだというものまで遡って調べていくのがおすすめです。

パラメーターに現れない、いきなり挙動が変わるかもしれないものは「What Is New」のページか「Release Notes」のページに書いてあります。パラメーターとかのページだけでは見られないのでこのあたりはご注意ください。それから、パラメーターのデフォルト変更系は「MySQL Parameters」というサイトがあります。とても便利なので活用してください。

yoku0825と申します。とある企業でDBA(Database Administrator)をやっています。「オラクれない・ポスグれない・マイエスキューエる」。Twitter、ブログ、日本MySQLユーザ会のメーリングリストやMySQL CasualのSlackで活動しているピンクのお豆腐です。

今日はMySQLユーザ会としての登壇ですが、別にLINEをクビになったわけではありません。特に「LINEだからどういう」という話ではなく、「前の会社にいた時でもこんな話をしていただろうな」というような話をしているので、MySQLユーザ会名義です。LINEのMySQLに特化した細かい話を聞きたい方はこのあたりのリンクを踏んでもらうか、ググってもらえれば聞く機会はいくらでもあると思うのでそちらもよろしくお願いします。

「What Is New in MySQL 8.0」に書かれていること

(スライドを示して)MySQL 8.0 GAになったのは2018年4月20日。その時のバージョンは8.0.11です。2022年8月2日現在、最新版は8.0.30になりました。(※登壇当時)MySQLのドキュメントには「https://dev.mysql.com」の下にmysql-nutshellというHTMLがあります。ここは「What Is New in MySQL 8.0」というページです。

ここから8.0.xと、バージョンに言及して文字列を取り出して並べてみるとなんとこのとおり。普通、What Is Newは「このバージョンで何ができるようになりました」というマイナーバージョンアップの時にエントリーは現れないはずですが、このようになっています。

11はGAなので特に言及はありませんが、そこから15を除いて元気に。20からも、25を除いて元気に。30でも12ヶ所で何らかの「What Is New」の言及があり、31でもうすでに2つあるという謎状態になっています。

(スライドを示して)ちなみに5.7はこんなものです。バージョンに関して言及があるやつは、たぶん8.0の新機能を5.7にバックポートしたんだと思います。

このセッションは過去の自分に贈る1つのプラクティス

「メンテナンスリリースとは一体何だったのか」とずっと言い続けているのですが、そんな中でもバージョンアップはしなくてはいけなくて、とある書籍(※『MySQL徹底入門 第4版 MySQL8.0対応』)を開きました。

第6章の194ページあたりに「5.7と、それ以前の系列内ではアップグレードは不具合の修正に重点が置かれていたので、同一リリース系列内ではとりあえず最新バージョンを使っておけばよかった。致命的なバグがないかどうかだけを確認して一番後ろのバージョンを使えばよかったのですが、MySQL 8.0系列は同一リリース内でも非互換がある可能性がある。

それまでは『現在リリースされているバージョンの中で一番大きなものが一番バグ修正が進んでいるであろう』という感じだったのですが、8.0では新機能が追加されてしまうため、その機能やその周辺に新規バグが内在する可能性がある。バージョンアップはどうしようね。避けるのが望ましいかもしれません」というようなことが書いてあります。

これが書かれたのは2020年ぐらいだったと思いますが、「導入時点での最新バージョンを選んで動作確認をすること。回帰テストを作りましょう。それから、アップグレードをする時はクライアントのバージョンを先に上げること」ということが書いてあったのですが、肝心の次にどれを使うのか。

今いる会社では8.0.19を使っているのですが、8.0.19から8.0.29の間のどこにターゲットを置けばいいのかが一切合切書いていなかったんですね。第6章でした。担当したのは私でした。というわけでこのトークは、そうとしか書きようがなかった当時の自分への1つの調べ方・やり方の提示です。プロポーズです。

次のMySQL 8.0を探す旅に必要なもの

「ぼくらが選んだ次のMySQL 8.0」。今は8.0.19です。2020年1月13日。私が入社したのが2021年6月なので、それよりも1年半ぐらい前に決まって、検証されてそこからずっと塩漬けにされていたんでしょう。フリーズされてLTSとしてサポートされていたんでしょうね。

次に、致命的なバグを含んでおらず、バージョン番号が最大なものを探します。これを逆にやってしまうと読まなきゃいけない、探さなきゃいけないものの量が膨大になるので止めたほうがいいと思います。

探すために何を見ていくか。What Is New、MySQL Parameters、MySQL Bugs、最後にリリースノートを使った方法を紹介します。

(スライドを示して)What Is New in MySQL 8.0はこんな感じで、8.0.27ではmultifactor authenticationをサポートしましたよ、みたいなわからないことが書いてあります。CTRL+Fで「8.0.」までを入れると必ずマイナーバージョン付きのものが出てきます。なんと152ヶ所もあるらしいです。

これでひたすらポチポチ探していく。うちの会社の場合は、8.0.19からが先だったので「8.0.2」ぐらいまで打ち込んでもよかったのかもしれませんが、良い機会だったのでポチポチやりました。

次にMySQL Parameters。我らが日本MySQLユーザ会の代表、とみたさん(とみたまさひろ氏)が個人で作っているWebアプリケーションがあります。「MySQL」と名前が付いていますが公式ではありません。MySQLのパラメーターの名前、8.0.19の時の値、今のデフォルトの値、8.0.29の時のデフォルトの値が一発で出せます。ここのdiffのチェックボックスが一番便利です。

これでレプリカのパラレル並列数が変わったというのも一発で思い出すことができました。とても感謝しています。キーワードで、予約語やエラーコードの数が変わったとか、collationが増えた・減ったというのも対応してくれているので、とてもありがたいやつです。

それからお馴染みのMySQL Bugsですね。私は1日数回RSSでタイトルを全部チェックしていて、怪しそうなものがあればすぐにsubscribeするようにしています。例えばこれはCorruption in 8.0.29 related to instant DDLというものです。これは最終的にはAccess Deniedにはなっていませんが、クラッシュするようなものだとsubscribeしていようと容赦なく見られなくなります。

再現方法を試して再現した時にAffects Meというのを押すと、開発者の人たちにこのバグにどれくらいの関心が寄せられているかを伝えられるらしいです。

最後にリリースノートですね。これは毎回マイナーバージョンが上がる度にTwitterやMySQLユーザ会で斜め読みをしているので、今回特にまとめて読み直すようなことはしていないです。基本的にmysql-nutshellとMySQL Parameters、それから肌感覚で8.0.28を選んでいます。

何を見ていくのか?

どのあたりを見ていくのか、これは最初にまとめで出てきましたね。パラメーターに現れない、いきなり挙動が変わるかもしれないものはこの2ヶ所(What Is NewまたはRelease Notes)のどちらかに出てきます。トランザクションスケジューリングがFIFOからCATSに変更されたとか、HASH JOINの内部処理がリファクタされたとか、パラメーターには出てこないので、そんなところを見ていきます。

パラメーターのデフォルト変更系はMySQL Parameters。mysqldをDockerで起動して実物のデフォルトを見てくれるんだったかな。(スライドを示して)ここに書いてあるんですが、ドキュメントがたまに間違っていることがあるので、こっちが確実だと私は思っています。

それから、MySQL Bugsを毎日眺めています。INSTANT DROP COLUMN関連のバグが1日経たずに高確率でAccess Deniedになっているのを眺めてきました。

昔はレプリケーションのプロトコル圧縮、CHANGE MASTER TO master_compression_algorithm = 〇〇とやると、ソースレプリカ間の通信を圧縮して帯域を節約できるみたいな機能があったのですが、これをやるとIOスレッドがぶちぶち切れるというバグが一時期ありました。最近見なくなったということは直ったのかな。

それからTempTableストレージエンジン8.0で、いきなりデフォルトのTEMPORARY TABLEのストレージエンジンになりましたが、パフォーマンスIssue、結果不正、メモリ食いすぎ、その他諸々。8.0.11から先は毎週のように(バグが)バンバン上がってきていましたが、8.0.23を過ぎた頃にはぜんぜん見なくなりましたね。

「遅い」はたまにまだ見ます。「メモリストレージエンジンのほうが速い」はたまに見ますが、だいぶ枯れてきたんじゃないかなというのが、なんとなく肌感覚でわかるようになりました。

リリースノートにもBugs Fixedという項目があるのですが、正直量が多すぎるのと、最近はボカした言い回しが増えているので、このバージョンアップ先を探すという文脈で真面目に追うのはコスパが悪いです。

例えば昔「Crash」と書いてあったのが「Abnormal Exit」になって、最終的には「Unexpected Result」みたいな、クラッシュしているのかどうかがよくわからない言い回しになっています。最終的にはそこに書いてあるバグ番号からGitHubのコミット履歴を探す旅につながっているので、楽しいのは楽しいですがコスパが悪いので今回はやっていません。

8.0.21ぐらいまではどう考えても「バグ直線」だった

リリースノートに新機能がいっぱい出てくるのはおかしい感じがしていたので、ちょっと調べてみました。(スライドを示して)リリースノートの8.0.19から先、こっちが全体の行数です。w3m -T text/htmlで解釈させて単純に行数のカウントを取っています。どうやらあの長いリリースノートの9割ぐらいはバグを直しているみたいですね。

これはフッターとかも含んでいるので一概には言いきれませんが、未だに1,000行分のバグを直している気はします。とはいえ、ようやくこのあたりが減ってきてバグ曲線っぽくなってきましたね。バグ曲線はこうなるはずなんですけど、8.0.21ぐらいまではどう考えても「バグ直線」だったんですよね。ようやく収束してきそうな気もしますが、8.0.29以降がどうなるかなという感じもします。

例えば、7月にリリースされた8.0.30について7月中にレポートしても直るのはだいたい次の次です。今レポートした場合、「再現ケースがきちんと付いている・向こうでも再現できている・直す気がある」が揃ってようやく8.0.32ぐらいに直ると思います。致命的でない場合、さらにもうちょっと後ろに下がります。

クラッシュしない、結果が不正なわけでもない、ちょっと不便だとか、ここの表示がちょっとおかしいとか、そういうレベルだとさらに1世代以上後ろに下がると思います。これはたぶんコードフリーズの期間が関係しているんだと思いますが、出てすぐにレポートされるぐらいみんなが使っている機能であれば次の次ぐらいに直りますが、そうでない場合はもっと遅れます。

優先順位を付ける時の考え方

ここまで、そのあたりを見ながら優先順位を付けていきました。バグが埋まっているか埋まっていないかは、ソフトウェアなのでわかりません。埋まっているものと仮定して、どうやって回避できるかを主軸に今回のLTSを決めています。設定で回避できるものなのか、設定を変えれば昔と同じ動作に戻るのか、使おうと思うと動くものなのか、「オプティマイザーヒントが追加されました」というのはオプティマイザーヒントを自分で書かないと動かないので、あえて使おうと思わないと動かないもの。

あるいは特に何も意識しないと動くものなのか。INSTANT DROP COLUMNは自分でALGORITHM=INPLACEと書かない限り、勝手にINSTANT DROPになってしまうので、INSTANT DROP COLUMNはこっちのタイプ。当然こっちのほう(スライドで「使おうと思うと動くもの」を指して)が回避はしやすいですね。

よく使う機能なのか、使いたい人だけが使う機能なのか。HANDLERステートメントだったらバグがあってもほとんどの人は使わないので問題ないだろうし、かといってSELECTのORDER BYとかにバグがあれば、それはきっと致命的なインパクトを及ぼすのでLTSに採用するわけにはいきません。

ほかに、「みんなが使うクリティカルなバグは、2世代後の法則」を適用すると、8.0.28になったという話ですが、例えばReuing SSL Sessionsが8.0.29で入りました。仮に埋まっていたとしてもオプションでオフにできるので優先度は低めです。

Transaction Schedulingは8.0.21らしいです。ここは跨いじゃっているんですよね。オン/オフもなく、SQLシンタックスもへったくれもなくソースコードそのものがゴロッと変わっているのでもうこれは任せるしかない。この時点ではまだ前の会社にいましたが、8.0.21はしばらく跨ぎたくないというアレがありました。ちなみにこの間に廃止された機能は1つだけです。

8.0.28に決めた理由

TLSv1とTLSv1.1の廃止がありましたが、これもアプリケーション側のSSLライブラリを新しくすれば対応できるはずなので、問題にはならないだろうと思ってこれだけ一覧にしてきました。実際にはもっとあるはずです。

これは先ほど気づきましたが、Binlog Compressionがないんですよね。Binlog Compressionはデフォルトでオフだから素通りしたのか何なのかはわかりませんが、引っかかりそうだなと思って赤く塗ったのは避けようがないものです。

doublewrite bufferがibdata1から出ましたとか、あとはtransaction-safe CREATE TABLE .. SELECT..。今まではGTIDモードがオンだとCREATE TABLE AS SELECTはできずにエラーになっていたのですが、それができるようになりました。機能としてはうれしいですが、避けようがないという意味では避けようがないので赤く塗っています。なので、(スライドを示して)このあたりの8.0.21は2世代の法則でお漬物にしておきたい。

それから黄色く塗ってあるやつ。これもoptimizer_switch系ですね。デフォルトではオンになっていますが、その気になればオフにしてこのあたりを回避します。duplicate weed outという、凶悪なバグを持ったoptimizer_switchが昔いて、オプティマイザー周りで前の動作に戻せるというのはわりと私の中では大事なことです。

その他諸々、RENAME COLUMN .. ALGORITHM=INSTANT、嫌だなぁ。嫌な響きがしますね。このあたりを避けて8.0.28にしたのですが、要は私はこれが気に入らないんですよね。DROP COLUMN .. ALGORITHM=INSTANT、これだけがとてもピンチです。

今までのInnoDBのオンラインALTER TABLEは、並列書き込みをできるようにしているのですが、内側ではibdファイルをリビルドしていたんですね。ibdファイルのリビルドなしでDROP COLUMNをできるようにしようというのがこの意欲作です。

任意の場所からメタデータだけDROPできるということは、逆に任意の場所にメタデータだけをADDすることもできるだろう。結局やっていることは一緒なので、実体のないものにメタデータだけかぶせる。今までINSTANT ADD COLUMNは末尾にしかできなかったんですね。末尾にしかできないということは、(例えば)「ibdファイルをなめた時にテーブル定義上6個のカラムがあるはずです。ibdファイルを見た時に3つしかなかった場合、絶対に後ろの3つだけがINSTANT ADD COLUMNだ」という決まりがあったのですが、DROP COLUMNができるようになってしまったおかげで、逆にどこが抜けているかが数からだけじゃわからなくなったので、InnoDB REDOログの構造にも仕方なく手を入れたみたいです。

なので、8.0.29でこのあたりは相当変わっていて、Bugsを毎日見ているとAccess Deniedが積み上がっていくんですよ。たまたま再現方法が取れたやつを試してみるとやはり落ちるので、こいつは2世代じゃ済まないなと思います。

とにかく8.0.29だけは避けようとしました。(スライドを示して)この8.0.28の動作変更がちょっと大きいのですが、LOCK INSTANCE FOR BACKUPとか、RENAME COLUMNだったら大丈夫だろう。REDOに手は入っていないのでこのあたりは大丈夫であろうと。InnoDB Parallel DDLは念のためオフにしようというのを経て、8.0.28でよかろうとなって、これから検証とカナリアリリースが始まる予定となっています。

8.0.28に決めたあとにわかったこと

8.0.28に決めたあとに、XtraBackupが8.0.29対応のXtraBackupを出してきたのですが、このブログにやはりバグがあるよ、クラッシュリカバリに失敗するよと書いてありました。アップストリームのMySQLにはレポートしてパッチを送ってあると、(スライドを示して)バグ番号とそのリンクが載っているのですが、3つ全部がAccess Deniedだったので、まぁそういうことなんだろうなと思います。

(スライドを示して)こっちのリンクはPerconaのJIRAにつながっているので、ここから様子を探ることはできますが、やはり埋まっていました。

埋まっているなと思っていたら先週かな、8.0.30が出た時に(スライドを示して)ALGORITHM=INSTANT、instantry added columns、これは3個目でinstantry added columnsですね。

4個目でinstantry added columns、5個目でfield_phy_posという物理的に行の何番目にあるかを調べる関数にも何か埋まっていました。これもrec_get_instant_row_version_old()でinstantry added columnsがあります。

row versioningが必要になって、DROPとかを真ん中に追加するのを許してしまったおかげで、InnoDBがrow versioningをしないといけない。メタデータのバージョニングをしなきゃいけなくなって、そのあたりに何かが埋まっていました。

我ながら良い勘をしていたなと思うのですが、そんな理由で私たちは8.0.28を選びました。同じような検証をする時、何が増えた・何が減ったというのを昇順で調べていくのは大変なので、降順に調べていくのがおすすめです。パラメーターに出てこない、いきなり挙動が変わるかもしれないものはWhat Is Newです。

すでに8.0を使っているのにWhat Is Newを見るのは違和感があるかもしれませんが、やる前にもう一度目を通すのをおすすめします。リリースノートも見ておくといいんじゃないかなと思います。パラメーターのデフォルト系は、MySQL Parametersというとても便利なサイトがあります。

スライドをダウンロードすると、リンクがクリッカブルになっているはずなのでぜひご利用ください。

MySQLユーザ会からのお知らせ

広告です。MySQLユーザ会では、MySQLのリリースノートを読む勉強会を3ヶ月に1回開催しています。8.0.29版、8.0.28版、8.0.27版ぐらいから始めました。8.0.30も先週リリースされたので(※登壇当時)、今月か遅くても来月ぐらいには開催される気がします。日本MySQLユーザ会のconnpassで登録しておくとイベントが開催される時にメールが届きます。

ほかに、リリースノート勉強会ではありませんが、グダグダMySQLについてしゃべろうという会が今日公開されたのかな。「今夜も生でMySQL」というタイトルで3回目。よろしければこちらも参加をご検討ください。

長いMySQL坂を登り始めたばかり

ここからはおまけです。これは2019年11月なので2年半ぐらい前ですね。「未だ現役なPerl5.8 & MySQL4.0とどう戦うか?」。当時、他の会社にいた時に大変そうだなと思っていたものがつい最近手元に舞い込んで来ました。バージョン8.0の話をしておいてなんですが、バージョンが50パーセント減りました。4.0から8.0.28まで上がろうとすると、この長いMySQL坂を登っていくことになります。

これはおまけですね。まずMySQL5.7は2023年10月にExtended Supportで、マイナーバージョンアップされる期限があと1年ちょっとしかないんですね。Sustaining Supportという、オラクルDB的に、Sustaining Supportは何か意味がありそうな値なのですが、MySQLはGPLなので使うだけならGPLの下で無限に使い続けられるんですね。

というわけで、実質パッチが出るのはここまでだと考えると、ここがEOLなのであと1年半しかない。

これはMySQLがサポートしているプラットフォームですが、CentOS 7やUbuntuも、18.04しかMySQL5.7をサポートしていないんですね。最近のOSは8.0しかサポートをしていなくて、OSのサポート期間を考えるとそろそろ一気に4.0から8.0まで200パーセントの成長をしないといけないということがわかって、ガックリしているところです。

というわけで、私はまだ登り始めたばかりなので、この長いMySQL坂をという感じで私のセッションは終わりになります。質問や、もっとこうしたらいいんじゃない? というアイデアがあればぜひとも教えてください。どうもありがとうございました。

司会者:ありがとうございました。質問が1つ来ています。「現状MySQL8.0.xを使っていて、ここは今すぐ改善してほしいという点は何かありますか?」ということですが、いかがですか?

yoku0825:機能を増やしてくれるのはいいのですが、それは9.0のブランチを切ってからやってくださいと言いたいです(笑)。

司会者:ありがとうございます。