Aurora MySQL Version3(MySQL8.0)にアップグレードしたら、ある特定のクエリだけ照合順序エラーになった話とその解決策

メディア統括本部 サービスリライアビリティグループ(SRG)の鬼海雄太(@fat47)です。
#SRG(Service Reliability Group)は、主に弊社メディアサービスのインフラ周りを横断的にサポートしており、既存サービスの改善や新規立ち上げ、OSS貢献などを行っているグループです。
本記事は、Aurora MySQL version3にアップグレード後の、特定クエリだけが照合順序エラーが出たという事象についてまとめている記事になります
なにかの役に立てば幸いです。
 

Aurora MySQL Version3にアップグレード後、特定クエリだけエラー


Aurora MySQL Version3にアップグレード後、ある特定のGoアプリケーションでだけエラーが出るようになりました。
その時のエラーログに出力されていたのは下記のエラーです。
、つまり異なる照合順序(Collation)の組み合わせによるエラーです。
utf8mb4_general_ciとutf8mb4_0900_ai_ciを比較しようとしてエラーになっていることがわかります。

照合順序とMySQL8.0


MySQL5.7でのデフォルトの照合順序はでした。
これがMySQL8.0からに変更されています。
 
今回エラーが出ていたテーブルとカラムでは、MySQL5.7との互換性を重視し、を指定していました。
 
しかし、なぜを指定して使っているだけのはずなのに、エラー文にはが出現しているのでしょうか。

エラーの原因


今回のGoのコードではgo-sql-driver/mysql v1.8.1を利用しAurora(MySQL)に接続していました。
エラーになったコードのSQLクエリでは、以下のようなSQLのユーザー定義変数を利用し、カラムの値と比較するような処理を行っていました。
(クエリのサンプル)
 
go-sql-driver/mysqlの接続オプションではcharset=utf8mb4だけを指定していました。
go-sql-driver/mysqlでCOLLATION未指定の場合のデフォルト値は、 となっています。これは内部的にはと同一となります。
しかし、文字セットである だけを指定していると、
が実行されます。
SET NAMES による文字コード指定だけが実行されると、MySQLの仕様上システムのデフォルトのCOLLATIONが設定されてしまいます。
つまり、MySQL5.7では がセットされますが、
 
MySQL8.0の環境では、がセットされてしまいます。
 
つまり今回のエラーでは、実際のカラムに設定されているCollationがであるが、ユーザー定義変数にはデフォルトのがセットされてしまい、その2つを比較するような処理をおこなっていたため、異なる照合順序によるエラーが出ていました。
 
このgo-sql-driver/mysqlのcollationの話は、今年8月に開催されたMySQLユーザー会のイベントのLTで@mita2 さんが話されており、以下のブログに詳細な検証が載せられていますのでご参照ください。

再現検証


テスト用テーブルの作成

テストデータ100件INSERT

go-sql-driverをつかったGoの再現コード

 
実行するとエラーになる

解決策


go-sql-driver/mysqlの接続オプションで、どちらかの修正を適用することで解決できます。
  • 何も指定しない
  • charsetとcollation両方指定する
※go-sql-driver/mysqlのv1.8.0未満のバージョンだと、両方指定すると意図しないcollationが指定される挙動をするので1.8.0以上に上げましょう。詳しくは前述の@mita2さんのブログを参照してください。

終わりに


急にエラーが出て焦りましたが、ちょうどMySQLユーザー会のLTで聞いていた話をすぐに思い出すことができて助かりました。
イベントに積極的に参加して情報を集めておくのは重要だなぁと感じた出来事でした!
 
SRG では一緒に働く仲間を募集しています。 ご興味ありましたらぜひこちらからご連絡ください。
 
このエントリーをはてなブックマークに追加