首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 存儲過程字符集陷阱:character_set_server 僅讀啟動值的解決方案

     編輯:MySQL 資料庫相關知識

問題現象

  • 表/欄字符集 = utf8mb4
  • 系統預設 character_set_server = latin1
  • 存儲過程參數無法指定字符集
  • 調用存儲過程寫入中文 → 亂碼 (雙重編碼或截斷)

根因分析

  1. 存儲過程創建時,MySQL 讀取全域變數 character_set_server 的啟動時值 作為該過程的「字符集上下文」。
  2. 運行時 SET GLOBAL character_set_server = utf8mb4 **不影響** 已存在的存儲過程。
  3. 參數傳遞、變數賦值、字串字面量均按此上下文編碼/解碼。

解決方案:配置文件固化,重啟生效

# my.cnf (Linux) / my.ini (Windows)
[mysqld]
# 方案 1:標準參數 (5.7+ 推薦)
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# 方案 2:兼容舊參數 (5.6 及以下)
default-character-set = utf8mb4

必須重啟 MySQL 服務 使存儲過程捕獲新的啟動值。

驗證步驟

-- 1. 確認全域變數
SHOW VARIABLES LIKE 'character_set_server';
-- 應顯示 utf8mb4

-- 2. 重新創建存儲過程 (關鍵!舊過程不會自動更新字符集上下文)
DROP PROCEDURE IF EXISTS sp_test;
CREATE PROCEDURE sp_test(IN p_name VARCHAR(50))
BEGIN
  INSERT INTO t_test (name) VALUES (p_name);
END;

-- 3. 測試調用
CALL sp_test('測試中文');
SELECT * FROM t_test;  -- 應正常顯示中文

完整字符集配置清單 (生產建議)

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4'  -- 針對非超級用戶連線自動設定
skip-character-set-client-handshake  -- 強制忽略客戶端字符集請求,統一用服務端設定

避坑指南

誤區正確做法
運行時 SET GLOBAL character_set_server = utf8mb4 以為能修好存儲過程只影響新連線的會話變數,存儲過程讀的是啟動值,**必須重啟**
以為 SET NAMES utf8mb4 在存儲過程內有效存儲過程內無會話上下文,參數編碼已在創建時固化
只改配置文件不重啟配置文件僅供下次啟動讀取
存儲過程參數用 VARCHAR(100) CHARACTER SET utf8mb4**語法不支援**,參數不允許指定字符集

MySQL 8.0 改進

  • 預設 character_set_server = utf8mb4,問題大幅減少。
  • 支援 SET PERSIST character_set_server = utf8mb4 持久化到 mysqld-auto.cnf,重啟自動生效 (但存儲過程仍需重建)。
  • 建議統一使用 utf8mb4 + utf8mb4_0900_ai_ci (8.0 預設校對)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved