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

MySQL 以 UTF-8 存儲 GBK 輸出實踐:字符集分離連接參數實現零改造遷移

     編輯:MySQL 資料庫相關知識

場景痛點

龐大站點從 GB2312/GBK 遷移至 UTF-8,前端代碼改造成本極高。需實現數據層 UTF-8 存儲、應用層 GBK 讀寫,最小化前端變更。

核心原理:MySQL 4.1+ 連接層字符集轉換

MySQL 支持客戶端連接字符集獨立於列存儲字符集:

  • 存儲時:客戶端發送 GBK → 連接層轉 UTF-8 → 寫入 UTF-8 列
  • 讀取時:UTF-8 列 → 連接層轉 GBK → 客戶端接收 GBK

前提:列定義 CHARACTER SET utf8 COLLATE utf8_general_ci,且入庫數據必須是合法 UTF-8。

表結構定義


CREATE TABLE `t` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  INDEX (`g_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

PHP 連接封裝:雙模式切換


class DB {
    private $link, $db_name;

    // 寫入/UTF-8 操作模式
    function _select_db_utf() {
        mysql_select_db($this->db_name, $this->link);
        mysql_query("SET NAMES utf8", $this->link);
        mysql_query("SET CHARACTER SET utf8", $this->link);
        mysql_query("SET COLLATION_CONNECTION='utf8_general_ci'", $this->link);
        return true;
    }

    // 讀取/GBK 輸出模式
    function _select_db_gb() {
        mysql_select_db($this->db_name, $this->link);
        mysql_query("SET NAMES gbk", $this->link);
        mysql_query("SET CHARACTER SET gbk", $this->link);
        mysql_query("SET COLLATION_CONNECTION='gbk_chinese_ci'", $this->link);
        return true;
    }

    # 業務代碼中:
    # 寫入前調用 _select_db_utf()
    # 讀取前調用 _select_db_gb()
}

現代寫法:使用 mysqli::set_charset('utf8') / PDO::MYSQL_ATTR_INIT_COMMAND,棄用 mysql_* 函數。

四大前提條件

  1. MySQL 編譯包含 gbk、utf8 字符集(默認包含)。
  2. 入庫數據必須是合法 UTF-8(AJAX 提交天然 UTF-8,表單提交需轉碼)。
  3. 讀寫操作嚴格區分調用對應連接字符集方法。
  4. 前端頁面 Content-Type: text/html; charset=gbk 與輸出編碼一致。

PHP 轉碼函數對比(入庫前清洗)

函數字符集覆蓋自動識別性能典型用法
mb_convert_encoding最全支持(指定列表)較慢mb_convert_encoding($str, 'UTF-8', 'GBK,GB2312,BIG5')
iconv較少需指定源編碼較快iconv('GBK', 'UTF-8', $str)

建議:明確源編碼用 iconv,不確定編碼用 mbstring。無完美自動識別方案,源頭規範編碼最關鍵。

遷移路線圖

  1. 數據庫層:新建 UTF-8 表,歷史數據 iconv/mbstring 清洗導入。
  2. 應用層:封裝雙模式連接方法,逐模塊切換讀寫模式。
  3. 前端層:逐頁調整 charset 聲明,最終全站 UTF-8。
  4. 驗證:全鏈路編碼一致性測試,特別是特殊字符(繁體、生僻字、Emoji)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved