用戶反饋:下午 1 點後數據庫中文數據突然變亂碼。本文記錄完整排查過程:排除顯示層問題、定位 Binlog 中異常 UPDATE、追溯數據源頭字符集設置缺失,最終確認為 latin1 讀取導致中文丟失再寫回。
設置會話與客戶端均為 utf8:
SET NAMES utf8;
查詢亂碼數據,仍顯示亂碼。進一步用 HEX() 檢查底層存儲:
SELECT HEX(item_title) FROM promo_item WHERE promo_item_id = 500186324;
結果證明:存儲內容本身已損壞,非顯示層問題。
用戶確認數據插入時正常,UPDATE 後變亂碼。在 Binlog 中找到對應 UPDATE:
UPDATE promo_item SET item_title='乱码内容' WHERE promo_item_id=500186324;
Binlog 顯示該 SQL 以 latin1 方式寫入,SET 子句中中文已變亂碼。推測:應用先 LOAD 讀取數據,拼接成 UPDATE 再執行,讀取階段字符集錯誤導致中文損壞。
開啟全日誌,找到該連接執行的 SELECT:
SELECT `main_table`.* FROM `promo_item` AS `main_table` WHERE promo_item_id ='500186324'
該連接未執行任何字符集設置命令,直接查詢。MySQL 預設會話變量:
character_set_results = latin1
手動模擬:在 character_set_results=latin1 下執行上述 SELECT,中文確實顯示為問號。應用將這串問號拼接進 UPDATE,導致正確數據被覆蓋為亂碼。
character_set_results 為預設 latin1,無法正確表示中文,讀出亂碼。latin1 形式落盤。SET NAMES utf8mb4(或 utf8),確保 character_set_client/connection/results 一致。character_set_results 匹配。HEX() 檢查,早期發現存儲異常。Client (UTF-8) → character_set_client (UTF-8) → character_set_connection (UTF-8) + collation_connection → Server 內部處理 → character_set_results (UTF-8) → Client 顯示 (UTF-8)
任一環節不匹配,均可能導致亂碼。