MySQL 8.0 でクエリキャッシュは非推奨になる
MySQL 8.0 でクエリキャッシュは非推奨になることが発表されました
参照:MySQL 8.0: Retiring Support for the Query Cache
そこで、MySQL でクエリキャッシュを利用されている方は、クエリキャッシュを使わないようにアプリケーションを変更するか、下記に紹介する ProxySQL の様なソリューションの利用を検討する必要があります
ProxySQL はクエリキャッシュに対応している
ProxySQL はクエリキャッシュに対応しているソリューションで、ProxySQL のサイトにクエリキャッシュを有効にした状態でのベンチマーク結果も公開されています
Scaling with ProxySQL Query Cache
今回紹介する ProxySQL の構成
構成は前回紹介させていただいている、こちらの記事 中にあるシングルプライマリの構成で、更新は特定のノード、参照は全ノードにバランシングする構成です
ProxySQL には下記に示すような特性がある
ProxySQL は接続ユーザやクエリによりバックエンドを切り替えられる
ProxySQL は mysql_query_rules というテーブルに情報を登録することで、バックエンドのホストグループを切り替える機能があります
切り替え条件としては、接続ユーザ名、スキーマ、クエリパターン等により接続するホストグループを切り替えることができます
この条件は複数種類組み合わせ・設定が可能です
一例として、
- reader ユーザで接続し、SELECT で始まるクエリは、ホストグループ 1 に接続する
- writer ユーザで接続し、SELECT で始まるクエリは、ホストグループ 0 に接続する
- reader ユーザで接続し、mysql スキーマへの SELECT で始まるクエリは、ホストグループ 0 に接続する
- reader ユーザで接続し、SELECT で始まり、FOR UPDATE で終わるクエリは、ホストグループ 0 に接続する
- INSERT で始まるクエリは、ホストグループ 0 に接続する
- DELETE で始まるクエリは、ホストグループ 0 に接続する
の様な設定することが可能です
その際のクエリは正規表現を用いて設定可能ですが、あまり複雑・大量に設定すると ProxySQL の負荷が上がってしまいます
ProxySQL のクエリキャッシュ
ProxySQL のクエリキャッシュは上記のクエリ分散機能に TTL を設定することで実現されています
そのため、たとえ同じクエリであっても reader ユーザで接続した場合はキャッシュするが、 writer ユーザで接続した場合はキャッシュしないといったことが起こりますし、mysql_query_rules に別々にクエリ条件が登録されていれば、独立してキャッシュされます
よって、
- reader ユーザでデータを SELECT する(キャッシュされる)
- writer ユーザで同じクエリを実行する(キャッシュされない)
- reader ユーザでデータを SELECT する(1.でキャッシュされた情報が返却される)
- writer ユーザで同じクエリを実行する(最新のデータが返却される)
- 設定した TTL 秒経過後に再度 SELECT する(キャッシュが破棄されているので、最新のデータが返却され、新たにキャッシュされる)
の様な動作となります
キャッシュするクエリ条件を単純にしない
添付の動画は上の reader ユーザでキャッシュされている様子を紹介するものです
- 最初は writer、reader の両ユーザとも最新の日時を取得できています
- 40 秒頃にクエリ振り分けルールを登録しています
TTL はまだ未設定の為、クエリはキャッシュされていません - 1分05秒ごろに TTL の値を 10,000 マイクロ秒に設定しています
少し反映まで時間がかかっていますが、1分20秒ごろに reader ユーザのクエリでキャッシュが返却されるようになります - 1分45秒ごろに TTL の値を NULL に設定し、クエリキャッシュを無効にしています
こちらも反映に少し時間がかかっていますが、reader ユーザのクエリキャッシュが無効になり、最新の日時を取得できるようになります
以上の様に単純なクエリ条件(安直な条件)を設定してしまうと、意図しないキャッシュ結果を取得してしまうことになってしまいます
しかも、クエリ自体はエラーになりませんので、発覚が遅れてしまいます
結論
ProxySQL でクエリキャッシュを使う場合
- 更新のほぼ存在しないマスタテーブルへの利用
- 最新のデータを取得しなくても良いワークロードでの利用の場合
の様な限定的な利用になると思われます
ちなみに、キャッシュを使用しているユーザ・スキーマで更新処理を行った場合、MySQLのクエリーキャッシュだとキャッシュは破棄され最新のデータが返却されますが、ProxySQL のキャッシュは破棄されず TTL マイクロ秒後に更新されたデータが返却されるようになります