TiDB Serverless がバージョンアップしMySQL8.0互換性が向上したとのことで試してみた
TiDB Serverlessが従来の7.3系から7.5.2へバージョンアップしました。
これにより様々な改修が入っていますが、目玉はMySQL8.0互換性の向上のようです。
リリースノートはこちら。
MySQL 8.0 では、デフォルトの文字セットは utf8mb4 で、 utf8mb4 のデフォルトの照合順序はutf8mb4_0900_ai_ciです。TiDB v7.4.0 でこれに対するサポートが追加されたことで、MySQL 8.0 との互換性が向上し、デフォルトの照合順序を持つ MySQL 8.0 データベースからの移行とレプリケーションがよりスムーズになりました。
7.4の時点でMySQL8.0との互換性を持つutf8mb4_0900_ai_ci
サポートがリリースされていたようですが、今回Serverlessが7.3系から7.5.2になったことでサポートされた、という関係性のようです。
今日はこの照合順序による違いを見ていきたいと思います。
3つの照合順序変数
TiDB Serverlessは3つの照合順序を管理する変数が存在しています。
SHOW VARIABLES LIKE 'collation_%';
3つの違いですが以下の役割のようです。
collation_server:サーバー全体の初期値。Create Database時にデータベースに設定が反映される
collation_database:collation_server
から引き継がれたデータベースの初期値。明示的に指定しない場合、テーブルが値を引き継ぐ。
collation_connection:接続の際にリテラル
に対して優先的に使われる照合順序
リテラルとは以下のSQLでいうabc
の部分です。
SELECT * FROM test_table WHERE val = 'abc';
一方比較対象となるval
カラムはcollation_databaseと同じ照合順序を持ちます。先ほどの設定値ですとカラムが保有する照合順序であるcollation_database
とリテラルで使われる照合順序であるcollation_connection
が異なっているため、予期しないエラーが出るケースがあります。
例えば以下のようなSQLはエラーとなります。
SELECT * FROM (
SELECT 'test' COLLATE utf8mb4_general_ci AS val
) AS t1
JOIN (
SELECT 'test' COLLATE utf8mb4_bin AS val
) AS t2
ON t1.val = t2.val;
Illegal mix of collations (utf8mb4_general_ci,EXPLICIT) and (utf8mb4_bin,EXPLICIT) for operation '='
ただしテストしたところcollation_database
とcollation_connection
に異なる照合順序が使われている場合TiDB環境では照合順序を統一したうえで処理を行うようで、簡単なSQLですとエラーは出ませんでした。
なおutf8mb4_general_ci
とutf8mb4_bin
では以下ような結果の異なりがあります。
SELECT * FROM test_table ORDER BY val COLLATE utf8mb4_general_ci;
abc
ABC
Abc
SELECT * FROM test_table ORDER BY val COLLATE utf8mb4_bin;
ABC
Abc
abc
SELECT * FROM test_table ORDER BY val;
を実行した場合、リテラルが存在しませんから、collation_connection
の照合順序は採用されず、collation_database
の設定が採用されるため私の環境ですとutf8mb4_bin;
と同じ結果となります。
ABC
Abc
abc
以下を実行することでテーブルの実行順を変更させることが可能です。
ALTER TABLE test_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
SELECT * FROM test_table ORDER BY val;
abc
ABC
Abc
utf8mb4_0900_ai_ci
さて改めて今回のアナウンスの中に含まれている utf8mb4_0900_ai_ci
を見ていきます。
先ほど操作した2つ、utf8mb4_bin
はバイナリ順(大文字小文字やアクセントも区別する)、
utf8mb4_general_ci
は MySQL 独自の簡易辞書順(大文字小文字は区別しないが、アクセントは一部区別される)でした。
一方で utf8mb4_0900_ai_ci
は Unicode 9.0 に準拠した照合順であり、より多言語に対応した正確な文字比較や並び順が可能です。アルファベット以外の漢字や記号なども正確に扱える点で、特に国際化対応の場面においては有力な選択肢となります。
アルファベットや数字以外を取り扱う際、高精度なデータ照合が必要な場合MySQL8.0以降でよく使われる照合順のようですので、MySQL8.0からの移行がやりやすくなったようです。
Discussion