本文記錄在 Linux 環境下從源碼編譯安裝 MySQL 5.1 (指定 GBK 字符集) 及 PHP 連接 MySQL 時中文亂碼的完整解決流程,涵蓋編譯參數、權限初始化、配置文件優化、Navicat 連接設置、PHP 代碼層面編碼統一等關鍵環節。
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.1.73.tar.gztar zxvf mysql-5.1.73.tar.gz && cd mysql-5.1.73groupadd mysql && useradd -r -g mysql -s /sbin/nologin mysql./configure \
--prefix=/usr/local/mysql \
--with-charset=gbk \
--with-collation=gbk_chinese_ci \
--with-extra-charsets=all \
--with-plugins=innobase,myisam \
--enable-thread-safe-client \
--enable-local-infileCharacter set 'gbk' is not a compiled character set,需在 make 時指定:make WITH_CHARSET=gbk WITH_COLLATION=gbk_chinese_ci WITH_EXTRA_CHARSETS=allmake && make installcp support-files/my-medium.cnf /etc/my.cnfsed -i 's#^datadir.*#datadir = /usr/local/mysql/var#' /etc/my.cnf/usr/local/mysql/bin/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/varchown -R mysql:mysql /usr/local/mysql /usr/local/mysql/varcp support-files/mysql.server /etc/init.d/mysqldchmod +x /etc/init.d/mysqld && chkconfig --add mysqld && chkconfig mysqld onservice mysqld start/usr/local/mysql/bin/mysqladmin -u root password 'NewPass123!'mysql -u root -p -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'NewPass123!' WITH GRANT OPTION; FLUSH PRIVILEGES;"亂碼本質是 **編碼不一致**:MySQL 存儲編碼 (GBK/UTF8) ≠ 連接字符集 ≠ PHP 頁面輸出編碼 ≠ 瀏覽器解碼編碼。任一環節不匹配即產生亂碼。
| 層級 | 設置點 | GBK 環境配置 | UTF-8 環境配置 (推薦) |
|---|---|---|---|
| 1. MySQL 服務端 | my.cnf / 建表語句 | default-character-set=gbk 建表: CHARSET=gbk | character-set-server=utf8mb4 collation-server=utf8mb4_general_ci |
| 2. 客戶端連接 | PHP 代碼 / PDO / mysqli | mysql_query("SET NAMES GBK"); | $pdo->exec("SET NAMES utf8mb4"); mysqli_set_charset($link, "utf8mb4"); |
| 3. 頁面輸出 | HTTP Header / HTML Meta | header("Content-Type: text/html; charset=gbk"); <meta charset="gbk"> | header("Content-Type: text/html; charset=utf-8"); <meta charset="utf-8"> |
<?php
// 1. 設置頁面輸出編碼 (最先執行)
header('Content-Type: text/html; charset=gbk');
// 2. 連接參數
$host = 'localhost:3306';
$user = 'root';
$pass = 'NewPass123!';
$dbname = 'test_db';
// 3. 建立連接 (mysqli 面向對象)
$mysqli = new mysqli($host, $user, $pass, $dbname);
if ($mysqli->connect_errno) {
die("Connect failed: " . $mysqli->connect_error);
}
// 4. 關鍵: 設置連接字符集 (必須在查詢前)
$mysqli->set_charset("gbk"); // 等同於 SET NAMES GBK
// 5. 執行查詢
$sql = "SELECT id, username, content FROM user_info";
$result = $mysqli->query($sql);
// 6. 輸出
echo "<table border='1'><tr><th>ID</th><th>用戶名</th><th>內容</th></tr>";
while ($row = $result->fetch_assoc()) {
echo "<tr><td>{$row['id']}</td><td>{$row['username']}</td><td>{$row['content']}</td></tr>";
}
echo "</table>";
$result->free();
$mysqli->close();
?>
原理:Navicat 默認自動檢測服務端字符集,但 MySQL 5.1 某些版本返回信息不準確,導致 Navicat 使用錯誤編碼發送/接收數據。手動指定可強制統一。
| 現象 | 可能原因 | 排查順序 |
|---|---|---|
| 存入正常, 讀出亂碼 (??? 或 ) | 連接字符集與存儲編碼不一致 | 檢查 SET NAMES / mysqli_set_charset / PDO::MYSQL_ATTR_INIT_COMMAND |
| 存入亂碼, 讀出正常 | 寫入時連接字符集錯誤 | 同上, 重點檢查 INSERT/UPDATE 前的字符集設置 |
| 中文變成亂碼字母 (如 涓婂竷) | UTF-8 數據被 GBK 解碼 | 統一全鏈路為 UTF-8 (推薦 utf8mb4) |
| Emoji 存入報錯 / 變 ?? | MySQL 字符集非 utf8mb4 | 修改表/庫/連接字符集為 utf8mb4 |
SET NAMES GBK。Content-Type: text/html; charset=xxx 權重高於 HTML <meta charset>。編碼問題無神秘之處,只有「不一致」。建立「服務端-連接-輸出」三層統一檢查清單,中文亂碼將不再是難題。