MySQL8 より、デフォルトでは無効な general_log に関する話
TL;DR
- 有効化すると、DB システムへよりパフォーマンスが求められる
- 「全クエリ」を「クエリ発行ごとに」ログへ記録するから
- すなわち、クエリ発行分の I/O 負荷が DB システムに上乗せされる
- なので、理由もなく本番適用をするのは避ける
実体験と記録経緯
本番稼働 MySQL8 サーバー の CPU 使用率が 70% だった(普段は 30% 前後)
原因調査のため general_log を有効化すると、CPU 使用率が 90% に上がった
当時そうなった理由を一部でも理解しておきたかった
general_log とは
「発行される全クエリ」を都度記録するログおよび設定値のこと。アプリ開発で例えると
「ログレベル関係なし(VERBOSE, DEBUG...)の全部盛りログ」である(あくまでイメージ)
記録されるもの
-
SELECT
,UPDATE
,INSERT
,DELETE
のデータ操作 -
BEGIN
,COMMIT
のトランザクション文 -
PREPARE
,EXECUTE
プリペアードステートメント -
SET
,SHOW
など、管理者が実行するステートメント - その他「クエリ」に該当するもの全て
を記録する。とにかく「出せるものを、一行一行全て」出す
general_log の例 (クリックで開閉)
2024-07-31T14:29:04.166514Z 8 Query BEGIN
2024-07-31T14:29:08.366769Z 8 Query SELECT * FROM users
2024-07-31T14:29:55.463541Z 8 Query SELECT * FROM users as u INNER JOIN user_profiles AS up ON u.profile_id = up.id
2024-07-31T14:29:59.079863Z 8 Query COMMIT
2024-07-31T14:31:55.079049Z 8 Query PREPARE statement_x FROM ...
2024-07-31T14:31:55.082580Z 8 Prepare SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse
2024-07-31T14:32:02.069460Z 8 Query SET @x = 3
2024-07-31T14:32:05.571490Z 8 Query SET @y = 4
2024-07-31T14:32:30.532325Z 8 Query EXECUTE statement_x USING @x, @y
2024-07-31T14:32:30.535364Z 8 Execute SELECT SQRT(POW(3,2) + POW(4,2)) AS hypotenuse
2024-07-31T14:32:51.108459Z 8 Query DEALLOCATE PREPARE statement_x
実装俯瞰
MySQL 実装より 「クエリ発行ごと」にログへ記録していることが分かる
つまり、general_log 有効化で DB へ追加負荷がかかることは予測できる
本番への適用はどうすべきか
私見では次に挙げるものが特にない限り、本番環境での有効化は推奨しない
- general_log をどう管理するかの具体的な計画・ポリシー
- 万が一の場合、追加負荷を賄えるだけの力
- ハードウェアのスペック
- 平たく言えば財力
- etc.