首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

C# 操作 MySQL 中文亂碼徹底解決:編碼鏈路全鏈路鎖定、Connector/NET 參數、資料庫/表/欄位三層統一

     編輯:MySQL 綜合教學

前言:亂碼本質是編碼鏈路不一致,而非單點配置

C# → Connector/NET → TCP → MySQL Server → 儲存引擎 → 磁碟,任何一環編碼不一致即產生亂碼。網上流傳「UTF-8 萬能論」實為害,實測 UTF-8 在舊版 Connector/NET、MySQL 5.6-、特定 sql_mode 下頻發問題。本文提供全鏈路 GBK/utf8mb4 雙方案,含驗證腳本與避坑清單。

編碼鏈路五環鎖定法

環節配置點GBK 方案utf8mb4 方案(推薦新專案)
1. C# 字串.NET 內部 Unicode無需配置無需配置
2. Connector/NET連接字串 CharSetCharSet=gbkCharSet=utf8mb4
3. MySQL 連線層session 變數自動執行 SET NAMES gbk自動執行 SET NAMES utf8mb4
4. 資料庫/表/欄位CHARSET/COLLATECHARSET=gbk COLLATE=gbk_chinese_ciCHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
5. 作業系統/終端控制台編碼chcp 936chcp 65001

方案一:GBK 相容舊系統(MySQL 5.5/5.6、Connector/NET 6.x)

1. my.cnf 強制預設 GBK

[mysqld]
character_set_server=gbk
collation_server=gbk_chinese_ci
skip_character_set_client_handshake=1  # 強制忽略客戶端請求,統一 Server 端

2. 建庫建表指定 GBK

CREATE DATABASE `legacy_app` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
CREATE TABLE `users` (
  `name` VARCHAR(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci;

3. C# 連接字串

Server=127.0.0.1;Port=3306;Database=legacy_app;Uid=app;Pwd=pass;
CharSet=gbk;  // 關鍵
ConnectionReset=true;

方案二:utf8mb4 現代標準(MySQL 5.7+/8.0、Connector/NET 8.x+)

1. my.cnf 標準配置

[mysqld]
character_set_server=utf8mb4
collation_server=utf8mb4_general_ci
# 不開 skip_character_set_client_handshake,允許客戶端協商

2. 建庫建表 utf8mb4

CREATE DATABASE `modern_app` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE TABLE `users` (
  `name` VARCHAR(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

3. C# 連接字串

Server=127.0.0.1;Port=3306;Database=modern_app;Uid=app;Pwd=pass;
CharSet=utf8mb4;  // 關鍵
ConnectionReset=true;

驗證腳本:一鍵檢測全鏈路編碼

using (var conn = new MySqlConnection(connStr))
{
    conn.Open();
    // 1. 連線層協商結果
    using (var cmd = new MySqlCommand("SHOW VARIABLES LIKE 'character_set_%';", conn))
    using (var reader = cmd.ExecuteReader())
    {
        while (reader.Read())
            Console.WriteLine($"{reader.GetString(0)} = {reader.GetString(1)}");
    }
    
    // 2. 實測寫入讀取
    conn.Execute("DROP TABLE IF EXISTS encoding_test");
    conn.Execute("CREATE TABLE encoding_test (txt VARCHAR(100)) CHARSET=utf8mb4");
    conn.Execute("INSERT INTO encoding_test VALUES ('中文測試😀Emoji')");
    var result = conn.QuerySingle("SELECT txt FROM encoding_test");
    Console.WriteLine($"寫入讀取: {result}");
    Console.WriteLine($"十六進制: {BitConverter.ToString(Encoding.UTF8.GetBytes(result))}");
}

預期輸出(utf8mb4 方案):

character_set_client = utf8mb4
character_set_connection = utf8mb4
character_set_database = utf8mb4
character_set_results = utf8mb4
character_set_server = utf8mb4
寫入讀取: 中文測試😀Emoji
十六進制: E4-B8-AD-E6-96-87-E6-B8-AC-E8-A9-A6-F0-9F-98-80-45-6D-6F-6A-69

常見誤區與避坑

誤區真相正確做法
「資料庫設 UTF-8 就夠了」連線層未協商、Connector/NET CharSet 未設 → 亂碼五環全鎖定
「UTF-8 不支援 Emoji」MySQL utf8 實為 utf8mb3,需用 utf8mb4全鏈路 utf8mb4
「GBK 較省空間」中文 2 bytes vs utf8mb4 3-4 bytes,但 GBK 不支援 Emoji/生僻字/多語言新專案 utf8mb4,舊系統 GBK 相容
「Connector/NET 自動偵測」不會,必須顯式 CharSet連接字串強制指定
「SET NAMES 放在第一條 SQL」Connector/NET 連線建立時自動執行,手動執行會被覆蓋用 CharSet 參數

升級遷移:GBK → utf8mb4 零停機方案

  1. 雙寫期:應用層同時寫入 GBK 表與 utf8mb4 表(或用觸發器同步)
  2. 歷史資料轉換:ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;(鎖表,維護窗口執行)
  3. 切換連接字串 CharSet=utf8mb4,灰度發布驗證
  4. 下線 GBK 表、移除雙寫邏輯

結語

C# MySQL 中文亂碼不是玄學,是工程。建立「編碼鏈路五環鎖定」標準,將 CharSet、my.cnf、建表 DDL、驗證腳本納入專案模板、Code Review 清單、CI/CD 檢查。新專案直上 utf8mb4 全鏈路,舊系統 GBK 相容到退役。編碼治理,一勞永逸。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved