見えないエラーの原因とは? Amazon Aurora MySQL 2で発生したDatabase Collationによるmysqldumpコマンドがエラーメッセージなしで処理が終了する現象について
こんにちは。 DBRE チーム所属の @hoshino です
DBRE(Database Reliability Engineering)チームでは、横断組織としてデータベースに関する課題解決や、組織のアジリティとガバナンスのバランスを取るためのプラットフォーム開発などを行なっております。DBRE は比較的新しい概念で、DBRE という組織がある会社も少なく、あったとしても取り組んでいる内容や考え方が異なるような、発展途上の非常に面白い領域です。
弊社における DBRE チーム発足の背景やチームの役割については「KTC における DBRE の必要性」というテックブログをご覧ください。
この記事では、Amazon Aurora MySQL 2からAmazon Aurora MySQL 3への移行の際に mysqldump コマンドで発生したエラーメッセージなしで処理が終了する現象についてご紹介します。少しでも参考になれば幸いです。
エラーの原因
まずはエラーの原因について説明します。今回のエラーメッセージなしで処理が終了する現象は、Amazon Aurora MySQL 2のデータベースのトリガーに設定された照合順序が、MySQL 5系では未対応のutf8mb4_0900_ai_ci
だったため、mysqldump がそれを認識できなかったことが原因で発生しました。
原因が判明するまでの調査過程と解決方法を、以下で詳しく説明させていただきます。
発生した現象
Aurora MySQL 2からデータをエクスポートするために、mysqldump コマンドを直接実行しました際に、エラーメッセージが表示されないまま終了してしまう現象が発生しました。
コマンドの実行後に exit code を確認したところ、2(Internal Error)が返されました。エラーが発生していることはわかりましたが、具体的な原因を特定できない状況です。
$ mysqldump --defaults-extra-file=/tmp/sample.cnf > sample.sql
$ echo $?
2
原因調査
問題の原因を特定するために、以下を実施しました。
まず、別バージョンの mysqldump コマンドを実行した場合の挙動を確認しました。
今回、Aurora MySQL 2に対してMySQL 5.7系の mysqldump コマンドを使用しています。
$ mysqldump --version
mysqldump Ver 10.13 Distrib 5.7.40, for linux-glibc2.12 (x86_64)
試しにMySQL 8系の mysqldump コマンドでエクスポートを試みました。
$ mysqldump80 --version
mysqldump Ver 8.0.31 for Linux on x86_64 (MySQL Community Server - GPL)
$ mysqldump80 --defaults-extra-file=/tmp/sample.cnf > sample.sql
$ echo $?
0
結果は成功でした。このことから、MySQL のバージョン差異がエラーの原因である可能性が浮上しました。
さらに、mysqldump コマンド自体が内部でエラーを起こしている可能性を考え、さまざまなオプションを試してエラーメッセージの有無を確認しました。その結果、--skip-triggers
オプションを付与するとエラーが発生しないことが判明しました。
$ mysqldump --defaults-extra-file=/tmp/sample.cnf --skip-triggers > sample.sql
$ echo $?
0
この結果から、トリガーに関連する部分でエラーが起きていると推測されます。そこで、トリガーの設定を確認しました。
mysql> SHOW TRIGGERS FROM sample_database \G
*************************** 1. row ***************************
Trigger: sample_trigger
Event: UPDATE
Table: sample_table
Statement: BEGIN
SET NEW.`lock_version` = OLD.`lock_version` + 1;
END
Timing: BEFORE
Created: 2024-10-04 01:06:38.17
sql_mode: STRICT_TRANS_TABLES
Definer: sample-user@%
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_0900_ai_ci
*************************** 2. row ***************************
(以下省略)
ここで、データベースの照合順序(Collation)がutf8mb4_0900_ai_ci
になっていることに気付きました。これは MySQL 5系では認識されない照合順序です。
エラーが発生していたテーブルのトリガー定義をutf8mb4_general_ci
に修正し、再度 mysqldump コマンドを実行しました。
mysql> SHOW TRIGGERS FROM kinto_terms_tool \G
*************************** 1. row ***************************
Trigger: sample_trigger
Event: UPDATE
Table: sample_table
Statement: BEGIN
SET NEW.`lock_version` = OLD.`lock_version` + 1;
END
Timing: BEFORE
Created: 2024-10-04 01:06:38.17
sql_mode: STRICT_TRANS_TABLES
Definer: sample-user@%
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_general_ci
*************************** 2. row ***************************
(以下省略)
$ mysqldump --defaults-extra-file=/tmp/sample.cnf > sample.sql
$ echo $?
0
mysqldump が成功しました。MySQL 8系のコマンドで成功していた理由も、この照合順序の違いで説明できます。
この調査により、トリガーに設定されていたデータベースの照合順序が MySQL 5系では存在しないutf8mb4_0900_ai_ci
だったため、mysqldump が失敗していたことが判明しました。
Amazon Aurora MySQL 2 と MySQL 5.7 の関係について
Amazon Aurora MySQL 2は MySQL 5.7 をベースに構築されていますが、完全に同一というわけではありません。AWS は Aurora に独自の拡張機能を実装しており、その中には MySQL 8.0 の一部機能(今回問題となった utf8mb4_0900_ai_ci 照合順序など)も含まれています。
MySQL 5.7 にてutf8mb4_0900_ai_ci
を照合順序に指定しようとすると、以下のエラーが発生します。
mysql> ALTER DATABASE sample_database CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci'
一方、Aurora MySQL 2では同じコマンドが正常に実行されます。
mysql> ALTER DATABASE sample_database CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
Query OK, 1 row affected (0.03 sec)
mysql> SHOW CREATE DATABASE sample_database;
+------------------+---------------------------------------------------------------------------------------------------------+
| Database | Create Database |
+------------------+---------------------------------------------------------------------------------------------------------+
| sample_database | CREATE DATABASE `sample_database` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ |
+------------------+---------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
追加の調査
エラーの原因がトリガーのみなのか検証するために、他の MySQL のオブジェクトも調査します。
Aurora MySQL 2の環境でビュー(VIEW)の照合順序(Collation)をutf8mb4_0900_ai_ci
で作成し、そのダンプ時の挙動を確認しました。
CREATE VIEW customer_view AS
SELECT
customer_name COLLATE utf8mb4_0900_ai_ci AS sorted_name,
address
FROM
customers;
mysqldump コマンドを実行すると、エラーなく成功します。
$ mysqldump --defaults-extra-file=/tmp/sample.cnf > sample.sql
$ echo $?
0
次に、Aurora MySQL 2の環境でストアドプロシージャ(PROCEDURE)の場合も同様に確認しました。
DELIMITER //
CREATE PROCEDURE sample_procedure()
BEGIN
DECLARE customer_name VARCHAR(255);
-- 照合順序を指定した文字列操作
SET customer_name = (SELECT name COLLATE utf8mb4_0900_ai_ci FROM customers WHERE id = 1);
-- 照合順序を使用した比較
IF customer_name COLLATE utf8mb4_0900_ai_ci = 'sample' THEN
SELECT 'Match found!';
ELSE
SELECT 'No match.';
END IF;
END //
DELIMITER ;
こちらも問題なくダンプが成功します。
$ mysqldump --defaults-extra-file=/tmp/sample.cnf > sample.sql
$ echo $?
0
Aurora MySQL 2では、MySQL 5系には存在しない照合順序(Collation)utf8mb4_0900_ai_ci
を使用できます。
しかし、mysqldump コマンドが MySQL 5系 ベースの場合、この照合順序を認識できず、特にトリガーに関連する部分でエラーが発生することがわかりました。
ビューやストアドプロシージャでは問題が生じないことから、トリガーにおける照合順序の扱いが原因であると推測されます。
解決方法
今回の問題は、トリガーに設定されていたデータベースの照合順序がMySQL 5系では未対応のutf8mb4_0900_ai_ci
であったために発生していました。
エラーへの対応としてはデータベースの照合順序(Collation)をutf8mb4_general_ci
に変更し、トリガーを再設定しました。これにより、MySQL 5.7系の mysqldump コマンドでも照合順序を正しく認識できるようになり、エクスポートが正常に行えるようになりました。
ALTER DATABASE sample_database CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 必要に応じてトリガーを再作成
別の解決策として、MySQL 8.0系の mysqldump コマンドを使用する方法もあります。MySQL 8.0 系のクライアントはutf8mb4_0900_ai_ci
を認識できるため、データベースの照合順序を変更せずにエクスポートが可能です。
$ mysqldump80 --defaults-extra-file=/tmp/sample.cnf > sample.sql
$ echo $?
0
環境や他の依存関係の制約からクライアントのバージョンを簡単に変更できない場合もあります。
おわりに
今回の事例では、mysqldump コマンドがエラーメッセージを表示しないまま終了し、exit code を確認することで初めてエラーが発生していることに気付きました。このようなエラーメッセージなしで処理が終了する現象は、気付かないまま不完全なデータをエクスポート・インポートしてしまうリスクがあります。そのため、データベースのバックアップや移行をする際には、exit code を確認するなど、処理結果をチェックすることが重要です。
Aurora MySQL 2系はすでに EOL(End of Life)を迎えており、サポートが終了しています。まだ稼働している環境があり、移行を検討していることがあればお気をつけください。
関連記事 | Related Posts
Aurora MySQL でレコードが存在するのに SELECT すると Empty set が返ってくる事象を調査した話
Aurora MySQL におけるロック競合(ブロッキング)の原因を事後調査できる仕組みを作った話
Investigating Why Aurora MySQL Returns “Empty set” in Response to SELECT, Even Though Corresponding Records Exist
DBRE ガードレール構想の実現に向けた取り組みについて
What is the cause of invisible errors? Concerning the issue observed in Amazon Aurora MySQL 2, where the mysqldump command unexpectedly terminates without displaying an error message, attributed to the database collation.
データベースのパスワードを安全にローテーションする仕組みの導入
We are hiring!
【DBRE】DBRE G/東京・名古屋・大阪
DBREグループについてKINTO テクノロジーズにおける DBRE は横断組織です。自分たちのアウトプットがビジネスに反映されることによって価値提供されます。
【データエンジニア】データエンジニアリングG/名古屋・大阪
データ分析部について※データ分析部は、データエンジニアリングGが所属している部門です。KINTOにおいて開発系部門発足時から設置されているチームであり、それほど経営としても注力しているポジションです。