Open1
【第5話】やっと終わったと思ったら絵文字ファイル名でまた失敗した話 (draft)
2020年8月、緊急メンテでDNS切り替え成功。
全員が「もう終わった……」と安堵した。
……2ヶ月後、静かに地獄が始まった。
この記事は以下のシリーズの一部です
シリーズ一覧を見る
発覚:切り替えから約2ヶ月後(2020年10月頃)
- 若者向けサービスで「画像がno imageになる」クレームがポツポツ
- 調査 → ファイル名に絵文字(例:
sunset.jpg)が入っている画像だけタヒ
真の原因(最凶)
移行バッチで絵文字を力技で排除していた:
# 移行バッチの一部(当時のコード)
filename = original_filename.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
# → 絵文字は全部空文字に置換 → DBには空のfilenameが保存される
# → ActiveStorageがキー生成できず → 404 → no image画像に置き換え
さらに追い打ち:
-
filenameカラムはutf8(偽)→ そもそも絵文字保存不可 - 絵文字入りファイルは移行時に完全にデータが消滅していた
対応(18億レコードテーブルでの絶望作業)
- 旧環境のバックアップから絵文字入りファイル名を救出
-
filenameカラムをutf8→utf8mb4に変更(3日間ALTER) - 対象ファイルを特定 → 専用バッチで再attach(1件ずつ安全に)
-- 救出例(旧バックアップから)
SELECT old_id, original_filename
FROM old_images_backup
WHERE original_filename REGEXP '[x{1F300}-x{1F9FF}]';
教訓(血の文字)
- 絵文字を「力技で潰す」のは最悪の選択
- MySQLの
utf8は偽物(utf8mb4一択) - 移行プロジェクトは「切り替え成功=終わり」じゃない
- 「異常データは除外すればいい」と思ったら地獄を見る
最終話:「5年経って思うこと」
170TB・17億ファイルの画像移行で3回目の正直・2020年の全記録
第5話 完