织梦数据库迁移乱码怎么解决

织梦 DedeCMS 在换服务器或换数据库时,最让人崩溃的不是配置出错,而是中文全部变成 "????" 或 "娴嬭瘯" 这种乱码。这种问题一旦发生,往往不是改一处 charset 就能搞定,需要从导出、导入、连接三个层面一起处理。下面把根因和修复方案讲透。

一、乱码的根本原因

1. 导出编码与实际编码不一致

原数据库表是 latin1 字段存 utf8 内容(老版本织梦常见),phpMyAdmin 导出时按 utf8 解析,结果把已经是 utf8 的字节又当 latin1 重新编码一次,导致 "娴嬭瘯" 这类乱码。

2. 导入时 SQL 文件被另存为 GBK

用记事本编辑导出的 .sql 后保存,文件本身变成 GBK,但 SQL 里又写着 SET NAMES utf8,自然冲突。

3. MySQL 连接字符集未指定

新数据库默认连接字符集是 latin1,织梦读取时拿到的是按 latin1 解析的 utf8 字节。

4. 表结构字符集与字段字符集不一致

表是 utf8_general_ci,字段却是 latin1_swedish_ci,迁移后部分字段正常、部分乱码。

二、正确导出方法

方案 A:用 mysqldump 指定字符集

mysqldump -uroot -p --default-character-set=utf8 \
  dedecms > dedecms.sql

方案 B:处理 latin1 存 utf8 的特殊情况

如果原库实际是 latin1 字段存 utf8 内容,导出时强制按 latin1 读取,再导入到 utf8 库:

mysqldump -uroot -p --default-character-set=latin1 \
  --skip-set-charset dedecms > dedecms_latin1.sql

然后用文本编辑器(Notepad++/VSCode)打开 .sql,把里面的 latin1 全部替换为 utf8,再保存为 UTF-8 无 BOM 格式。

三、正确导入方法

先确保目标库本身的字符集是 utf8:

CREATE DATABASE dedecms DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

导入时同样指定 utf8:

mysql -uroot -p --default-character-set=utf8 dedecms < dedecms.sql

用 phpMyAdmin 导入时,在"字符集"下拉里选 utf-8,文件格式选"无 BOM"。

四、修改织梦连接字符集

打开 /data/common.inc.php,确认数据库配置:

$cfg_dblanguage='utf8';
$cfg_dbhost='localhost';
$cfg_dbname='dedecms';
$cfg_dbuser='root';
$cfg_dbpwd='password';
$cfg_dbprefix='dede_';
$cfg_db_character='utf8';
$cfg_db_collation='utf8_general_ci';

关键参数是 $cfg_dblanguage$cfg_db_character,必须同时为 utf8。

核心原则:导出、导入、连接三处字符集必须完全一致,任何一处不匹配都会乱码。

五、已有乱码数据的修复

如果数据已经导入且乱码,但原始 .sql 文件还保留,最稳的做法是 drop 整库后重新按上面方法导入,而不是尝试用 SQL 转换已乱码的内容。

如果原库还活着(未删除),直接从原库重新导出一次,按"导出 → 改字符集 → 导入"流程走一遍即可。

六、注意事项

1. 任何 .sql 文件都用 VSCode/Notepad++ 编辑,绝不用记事本,避免 BOM 问题。

2. MySQL 5.5+ 推荐用 utf8mb4,但织梦默认是 utf8,迁移时统一 utf8 即可,不必强行升级。

3. 备份时同时保留 .sql 和 .zip 两种格式,方便日后回滚。

4. 部分虚拟主机面板(如 DirectAdmin)导入有 50MB 限制,大库请用 BigDump 或分卷。

风险提醒:不要在已经乱码的库上反复执行 REPLACE、CONVERT 等转换操作,每转一次就损失一次信息,最终可能彻底无法还原。

解决织梦数据库迁移乱码,本质是让"导出编码=文件编码=导入编码=连接编码"四个值都对齐到 utf8。动手前先确认原库是 utf8 还是 latin1 存 utf8,再选择对应导出方式,最后务必在新库的 common.inc.php 里写明字符集。养成每次迁移都先做小批量测试导入、再用 dede_test 表校验中文显示的习惯,能避免一次性毁掉整站数据。