📌

TiDB Serverless がバージョンアップしMySQL8.0互換性が向上したとのことで試してみた

に公開

TiDB Serverlessが従来の7.3系から7.5.2へバージョンアップしました。

これにより様々な改修が入っていますが、目玉はMySQL8.0互換性の向上のようです。

リリースノートはこちら。
https://docs.pingcap.com/ja/tidb/stable/release-7.5.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_databasecollation_connectionに異なる照合順序が使われている場合TiDB環境では照合順序を統一したうえで処理を行うようで、簡単なSQLですとエラーは出ませんでした。
https://docs.pingcap.com/tidb/stable/character-set-and-collation/#coercibility-values-of-collations-in-expressions

なおutf8mb4_general_ciutf8mb4_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