DIARIO DE CHINOS 华侨快报(国际刊号 ISSN 2530-1349) 新手帮助

西班牙华人网-华侨快报

电脑爱好电脑爱好
关注: 2贴子:242 排名: 55 
0 回复贴,2248 次查看
<返回列表

Discuz! 从 GBK 转换 UTF-8 编码全过程

网友
网友  发表于 2017-7-27 19:57:51
在 Discuz! 诞生之时,国内网站清一色以 GBK 编码为主流,很多老站长都选择了以在当时很成熟的 GBK 编码来建站。如今过了十几个年头,Unicode 已经成功统治了世界,如何把 Discuz! 从 GBK 转换到 UTF-8 成了困扰很多老论坛的难题。
3 [- J' u; Z  k. b3 ?% {+ V3 X! l, n+ l
SteamCN 论坛如今已经拥有十三年的历史,经历了 dvbbs、Discuz!、Discuz! X 三个阶段,是国内为数不多能完好保存十多年前附件和图片的论坛。今天在短短两小时的维护时间内,SteamCN 论坛成功从 GBK 编码完美转换到了 UTF-8(utf8mb4,支持 emoji &#128536;)。本文将记录转换所用的工具、脚本以及常见的坑,以供广大 Discuz! 站长参考。
$ ?1 F8 _, p3 h6 j: H0 d1 }) A5 }% B
本次转换工作得到了 DxGit Forker 群内 Coxxsgreenrock[微凡] 的帮助,非常感谢二位的指导!

: j6 i! q* g. q" u3 z+ B2 w3 ]& p) w* e: ?* i3 H  C
1. 准备工作# }3 R$ m5 q3 G, N
' j" H  A8 Z9 I4 J% f' J
不同的网站都有自己的不同之处,请务必先在测试环境内演练转换过程,然后再应用到线上正式服务器。$ f( Q: z0 Z& m1 U$ b% t
, e8 }/ P' |$ e+ e+ P- _$ c% T0 G3 C
1. 下载与自己当前 Discuz! 版本号相同的 UTF-8 安装包。本站为经过浅度定制的 Discuz! X3.3,以下教程以 Discuz! X3.3 为例来进行。如果你的网站经过深度定制,请人工将代码转换为 UTF-8 编码。
& a& t  k! D6 S9 a5 O. q* U: q+ p2. 准备测试数据库。将当前线上版本数据库完整拷贝一份作为测试数据库,我们将先以该数据库进行一次演练。
" ]. E/ E: g! o4 D' f0 z2 P& N3. 准备测试用 Web 服务器。将网站文件夹拷贝一份到测试 Web 服务器上。由于 data、uc_client/data、uc_server/data/avatar 这几个目录体积会比较大,可以忽略它们。
3 l' f" K: Z* b, d7 @% C6 o4. 编辑测试环境中的 config/config_global.php、config/config_ucenter.php、uc_server/data/config.inc.php,将数据库配置为测试数据库,并关闭 Discuz! 的一切内存缓存功能。5 X9 [1 W" N' b9 e$ s) o9 e
5. 确认测试环境的网站可以正常运行。+ ^) }$ J1 q9 W- Z8 q
3 Y4 m9 \/ x- D% i1 U
2. 转换数据库2 T5 m  \- k& T4 {; v3 L
* \, a+ p; r2 f
我们需要人工手动使用这条语句对数据库中的每一个表进行转换:
0 T# J, g% ?) f: Z5 x
  • ALTER TABLE `表名` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    9 e5 {) [" u+ f
+ V' j1 s+ L: e
[color=rgb(87, 186, 232) !important]复制代码
* E6 m# S7 q* Z6 _* ~* @
  s$ y7 H  x# h- A0 I. C

! s' ]0 {' [4 G; G务必将运行过的每一个语句记录下来中,方便最后在线上服务器部署。5 X0 Y1 q' l. Q
& h; I6 E, R. o& d
可能会遇到的问题:
$ i% {/ O: k0 a% J9 J
6 I: h4 c2 l8 u" a+ v  Q  {Q: 为什么这里不提供预先编写好的 SQL 呢?
' R+ x7 C" K( r/ UA: 因为每个网站的数据库差异很大,我们使用的 SQL 脚本(文末附件压缩包内 gbk-to-utf8mb4.sql)未必适合你的网站。这里需要人工对每一个数据表运行这个语句。! s4 @' E. f! K/ O
" h  u% ^+ g& {5 |/ V$ u; P
Q: 提示索引最大长度为 xxx,转换失败
& j2 j8 y7 a, p6 v1 _2 W* R' ^A: 调整索引涉及到的字段长度,保证不超过 xxx / 4。例如 pre_common_addon 这个表报错索引长度最大不能超过 1000,那么需要将 key 字段的类型从 varchar(255) 改为 varchar(200)。5 g, u; P7 {  w% n

# \; J: R5 s: j8 e& ]" s2 }* yQ: 提示用户名重复,转换失败$ e( e0 o# ?' A6 {9 U
A: 这是由于一些字符在 gbk_chinese_ci 排序规则下认为是不同的,但是在 utf8mb4_unicode_ci 排序规则下认为是相等的。例如全角英文字母与半角英文字母,在 gbk_chinene_ci 下认为 A != A,但是在 utf8mb4_unicode_ci 下认为 A == A。这时需要编辑 unique 索引,改为普通索引,然后重新转换,再将索引改回 unique 类型,此时会具体指出哪个用户名重复,请记录其 UID。如果数据量比较大,可以自行编写 SQL 寻找重复项。
% {4 F6 p0 A7 N; O对于重复的用户名,我们可以使用这个语句将该用户的用户名重置为 email:
) N; I4 Y  ~9 j1 s3 N% f& i
  • UPDATE `表名` SET `username` = email WHERE `表名`.`uid` = 上面记录的用户UID;
    ; ?) E1 x4 W9 w- O

4 l: b. w+ }9 F/ _2 r! ~3 M, j2 M2 H[color=rgb(87, 186, 232) !important]复制代码

" b* V; j: q) c, l
' ^5 W- I! B5 ]" }7 W
- i* \8 u# ~- O3. 上传 UTF-8 版本代码0 v1 N) l5 N' n' H% B; ^, H! B9 x
4 ]3 M5 C- W- q! M$ I- M
将准备阶段取得的 UTF-8 版本代码覆盖到测试服务器中(注意不要覆盖掉 config 文件)。
* j4 _  S: [: }# h1 P" B7 j  G编辑 config/config_global.php、config/config_ucenter.php、uc_server/data/config.inc.php,将其中 DBCHARSET 改为 utf8mb4,输出 CHARSET 改为 utf-8。
0 p: j5 d8 c/ i. @) d到此先不要打开网站测试效果!* u$ f6 M- M  p" T
8 |4 ?; z3 u' M4 e6 q3 S
4. 修复数据库
; K9 p+ j$ V8 _0 }! j- h' x- Z: }3 W* o
由于 Discuz! 大量使用了 PHP 的 serialize 方法来序列化对象存入数据库,而 serialize 方法序列化出来的结果和编码是相关的,因此需要修复数据库中以前使用 GBK 编码序列化的结果,使其能在 UTF-8 编码下反序列化出来。3 m0 I" c6 i( G- h7 y; S

3 {' d, M( x3 |. p: r3 U7 i: v扩展阅读) `) X4 N% Z& S/ |

) G+ [7 ?# H5 b7 t7 L9 L; t下载文末附件“脚本与工具.zip”,解压出来得到 migrate_db.php(出处,略做修改),编辑该文件结尾的数据表列表,确认这些表和字段都是在你数据库存在的。这个列表未必完善,建议手动检查一遍所有数据表,补充可能漏掉的数据表和字段。第 29 行指定了单次处理的数据条数,如果你的数据库性能比较差,建议降低该值。; \/ a6 Z! N, X- B: Q& S% n

, C& {& i5 W" ]将 migrate_db.php 上传到网站根目录,浏览器访问它,点击“Discuz! 序列化整理”开始修复。
+ A- ^, g  W7 d5 O& ~' U6 {% l* o) S; h; P0 I: U: m
5. 转换模板、插件编码0 z! `+ i2 r  S% T1 \

% }- J" V9 b7 `人工将你所有使用的模板、插件的编码转换为 UTF-8。注意不要漏掉 XML 文件。* X) x' X, ]) L8 q
如果你的模板、插件是从应用商店下载的,没有经过改动,建议登录后台进行卸载,在应用中心重新安装一遍。
. F; M/ x9 k9 t! y) @$ R( U: a
( v4 w1 d; n- W2 ^  W1 C6. 转换日志编码; Z1 a8 r$ s/ _" i

- i6 |; c) O+ r0 YDiscuz! 将运行日志记录在了 data/logs 目录下,如果你在准备阶段没有将这个目录复制到测试环境,可以在最终部署时再进行。
" l3 V" `/ o4 E5 t& }" S将该目录下的每个文件的编码转换为 UTF-8,重新上传覆盖原文件即可。
- Z4 [* H! e8 V& K: y/ H: _
; _& q4 S# k; \, N" [; i7. 更新缓存
; B/ ^+ j0 e; f9 W* q3 g. [! j0 u8 {% V: ~: J
登录后台,更新所有缓存(数据缓存、模板缓存、DIY模块分类缓存)。5 |. |& D% f+ U

  i2 J6 A2 H2 E( V7 b# n7 d" Q8. 检查问题
7 ^/ P9 w# v2 n! T; z0 K8 g4 A* p( x6 S6 Y" O
至此基本转换完成,需要仔细检查有无其他问题,重点检查插件、模板等是否工作正常。. v+ q9 a+ B" C( |3 M6 `0 ?( A

7 C& s- f  }& c8 _/ z: `$ n& C9. 在正式环境部署上线8 X2 W5 s. c  X

/ ]7 ~( _5 j! [# N一定要先阅读下面的 FAQ 再决定开始部署。
8 s/ n2 a( s2 R5 d8 z0 u8 [, ]5 ^! T2 {- H4 _5 {5 q, U
将以上步骤在正式服务器上重新操作一遍。需要注意将 config 中的数据库改为正式数据库,内存缓存无需关闭,在第 7 步更新缓存时要把内存缓存清空。2 w. b9 K# ^" h
" E( L4 C. H! S6 L
F.A.Q.
9 P% l$ a1 @2 U! s3 e4 n/ F; k6 v9 [& f2 A% s
Q: 转换数据库后,登录验证问答无法通过
# h3 G  C4 x: |/ l$ A! t7 y) JA: Discuz! 登录验证问答的加密算法为“substr(md5($answer.md5($questionid))”,结果与所用编码相关。可以参考这里修改代码,强制使用 GBK 来编码答案。: Y8 J6 X% v2 l" ]) ~

7 C% _" I) Q, ~! ?1 qQ: 转换模板后打开网站依旧乱码! }0 l# L7 c" u- \4 \- H. {
A: 请确认已经在后台更新缓存,如果依旧乱码,请 SSH 到服务器,运行 sync 命令。如果还不行,可以尝试修改乱码的模板(比如随便改一个字符),上传服务器,Discuz! 检测到文件变动后会重新刷新模板缓存,然后再将模板还原后上传。$ K5 d" W. x1 B( M7 u3 }. p

7 i/ j7 e$ O; c" w$ xQ: 站点统计内部分数据乱码' i) P4 Z+ {: _
A: 等到下一个更新时间数据刷新后就正常了7 [, Z8 y' G' u" y% e

9 ~# _3 s" c4 l( d5 nQ: 上传模板后 DIY 模块消失
4 P7 q& ^: E, _( c4 PA: 到 data/diy/template/模板名 下面寻找 .bak 文件,重新 diy,选择恢复这个文件即可。- V; D' G1 U# {
/ e, s  D; V! Q& R( }2 X0 L
Q: 部分论坛设置、插件设置行为诡异或设置丢失9 O7 v4 w. o& M+ T$ k: r
A: 很大可能是第 4 步修复数据库时,migrate_db.php 没有处理到相关数据表的字段。请仔细检查有无漏掉的数据表字段。# G* j! x* G3 ~3 W1 f! o
2 E! u, n1 {$ P1 `. x* t
Q: 如何方便地批量转换编码?5 \" J/ R6 J$ `1 l9 Z
A: 在 Linux 环境可以使用 iconv 命令(请稍微学习一下这条命令,使用很方便)。在 Windows 下可以使用 Codepage Converter 这个工具(已在附件提供)。! Q9 E; x& p& i8 s& `' ~% o

快速回帖 使用高级回帖 (可批量传图、还有插入视频等功能哦!)

您需要登录后才可以回帖 登录 | 注册

  • 发布信息免费
  • 发贴彩色标题
  • 签到额外经验值

如何快速提升等级,查看[积分规则]

活动中心

查看更多>>
最新热版
会员排行
©2009-2016 西班牙华人网 http://www.laicw.eu西班牙国家图书馆注册西中文化传媒促进会主办Powered byDiscuz!X3"世界华文媒体合作联盟"成员 ||
发帖 客服 微信 手机版 举报