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

西班牙华人网-华侨快报

电脑爱好电脑爱好
关注: 0贴子:195 排名: 57 
0 回复贴,530 次查看
<返回列表

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

网友
网友  发表于 2017-7-27 19:57:51
在 Discuz! 诞生之时,国内网站清一色以 GBK 编码为主流,很多老站长都选择了以在当时很成熟的 GBK 编码来建站。如今过了十几个年头,Unicode 已经成功统治了世界,如何把 Discuz! 从 GBK 转换到 UTF-8 成了困扰很多老论坛的难题。/ F+ a! G* \! J& F* I$ i
6 y# o0 u5 U/ O+ x0 @5 \5 D
SteamCN 论坛如今已经拥有十三年的历史,经历了 dvbbs、Discuz!、Discuz! X 三个阶段,是国内为数不多能完好保存十多年前附件和图片的论坛。今天在短短两小时的维护时间内,SteamCN 论坛成功从 GBK 编码完美转换到了 UTF-8(utf8mb4,支持 emoji &#128536;)。本文将记录转换所用的工具、脚本以及常见的坑,以供广大 Discuz! 站长参考。
1 E9 m9 X0 g' r% r5 `- l+ J( ]! f+ n1 E1 ~1 t( S
本次转换工作得到了 DxGit Forker 群内 Coxxsgreenrock[微凡] 的帮助,非常感谢二位的指导!

1 Y$ K& H2 s( e& u9 p1 I  {/ W7 v' N8 r
1. 准备工作" `# Z0 a9 n, E
; `' [% P  g" w% `; r
不同的网站都有自己的不同之处,请务必先在测试环境内演练转换过程,然后再应用到线上正式服务器。
0 K+ G# k! T( M# O7 m& r0 e- c$ D
+ I+ d9 O2 x6 a7 ?8 E1. 下载与自己当前 Discuz! 版本号相同的 UTF-8 安装包。本站为经过浅度定制的 Discuz! X3.3,以下教程以 Discuz! X3.3 为例来进行。如果你的网站经过深度定制,请人工将代码转换为 UTF-8 编码。! J( Z9 H$ P9 G. w# X
2. 准备测试数据库。将当前线上版本数据库完整拷贝一份作为测试数据库,我们将先以该数据库进行一次演练。2 b1 q9 k4 ?5 s& A
3. 准备测试用 Web 服务器。将网站文件夹拷贝一份到测试 Web 服务器上。由于 data、uc_client/data、uc_server/data/avatar 这几个目录体积会比较大,可以忽略它们。' Z* j$ v6 M9 Z
4. 编辑测试环境中的 config/config_global.php、config/config_ucenter.php、uc_server/data/config.inc.php,将数据库配置为测试数据库,并关闭 Discuz! 的一切内存缓存功能。
$ m$ V$ t) c& q! e0 J7 r: O5. 确认测试环境的网站可以正常运行。
8 C3 r+ i' r" g# K' l8 G4 v8 N8 A9 e; t; `& j  b# F4 }% W
2. 转换数据库
$ q. j0 w' r2 h; ^$ z# N/ F0 ?& a  }  F* F7 |# `& x
我们需要人工手动使用这条语句对数据库中的每一个表进行转换:
7 \- m# x2 \" r% F8 Q& h
  • ALTER TABLE `表名` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    6 [1 a! s4 q# i: c& H0 Y
& B+ a, p9 U% S
[color=rgb(87, 186, 232) !important]复制代码

# F* P# q, K4 W5 A5 G
. G& q  I, ?3 Z% e. l, e  _0 G; S5 T9 v2 k. r& r
务必将运行过的每一个语句记录下来中,方便最后在线上服务器部署。9 u1 q' t- f; l# Y  Q

- j6 c" K9 A0 A: S. d% ]0 P可能会遇到的问题:
/ F6 X5 U% \. R5 g
$ N8 K- L4 N) S1 `0 k" t! F& tQ: 为什么这里不提供预先编写好的 SQL 呢?2 P' q& n1 `9 i
A: 因为每个网站的数据库差异很大,我们使用的 SQL 脚本(文末附件压缩包内 gbk-to-utf8mb4.sql)未必适合你的网站。这里需要人工对每一个数据表运行这个语句。
9 q4 J0 X3 I3 {4 M0 G$ b, R
6 l. z! r+ q; b9 Y2 V8 nQ: 提示索引最大长度为 xxx,转换失败
2 u8 z2 c/ A0 `A: 调整索引涉及到的字段长度,保证不超过 xxx / 4。例如 pre_common_addon 这个表报错索引长度最大不能超过 1000,那么需要将 key 字段的类型从 varchar(255) 改为 varchar(200)。
" D3 C% K! Q- u
! }  ]; U: ^, N* y/ D+ tQ: 提示用户名重复,转换失败, M4 _4 E) R! ]# ^2 d, Y* a  G$ V
A: 这是由于一些字符在 gbk_chinese_ci 排序规则下认为是不同的,但是在 utf8mb4_unicode_ci 排序规则下认为是相等的。例如全角英文字母与半角英文字母,在 gbk_chinene_ci 下认为 A != A,但是在 utf8mb4_unicode_ci 下认为 A == A。这时需要编辑 unique 索引,改为普通索引,然后重新转换,再将索引改回 unique 类型,此时会具体指出哪个用户名重复,请记录其 UID。如果数据量比较大,可以自行编写 SQL 寻找重复项。
* F0 s  f  i. R9 T对于重复的用户名,我们可以使用这个语句将该用户的用户名重置为 email:" d- L! }3 C2 x8 G" K, g# `
  • UPDATE `表名` SET `username` = email WHERE `表名`.`uid` = 上面记录的用户UID;
    2 t4 m9 N/ K0 Y  h

. \9 X! ~! d) T$ z[color=rgb(87, 186, 232) !important]复制代码

' H. c; z, ?3 L9 Z9 f2 w
+ |* V8 b4 Z5 D; h- s, r! a$ o7 u9 r6 z3 C' K1 z
3. 上传 UTF-8 版本代码& k  g# [, i* G

. e4 I3 L- p* M" ~6 O将准备阶段取得的 UTF-8 版本代码覆盖到测试服务器中(注意不要覆盖掉 config 文件)。
( e5 Q. A- m( v) b& E# S" g编辑 config/config_global.php、config/config_ucenter.php、uc_server/data/config.inc.php,将其中 DBCHARSET 改为 utf8mb4,输出 CHARSET 改为 utf-8。
" F7 a" B; A2 E3 S5 o到此先不要打开网站测试效果!3 B9 V# A; Y; ]; ?, z2 J6 a# N

% ]. s, c  @9 l0 d6 ?* f& o5 ~4. 修复数据库
+ ~3 K$ V- A% k. o. P) z
! R) Z5 ?4 c9 j/ t0 R5 N1 F由于 Discuz! 大量使用了 PHP 的 serialize 方法来序列化对象存入数据库,而 serialize 方法序列化出来的结果和编码是相关的,因此需要修复数据库中以前使用 GBK 编码序列化的结果,使其能在 UTF-8 编码下反序列化出来。  B8 p; t- V& P' H
$ X5 T) S1 o! u5 f
扩展阅读
3 f% p, f+ \/ ?
# ~, u& d+ Q! Z1 h/ r& R下载文末附件“脚本与工具.zip”,解压出来得到 migrate_db.php(出处,略做修改),编辑该文件结尾的数据表列表,确认这些表和字段都是在你数据库存在的。这个列表未必完善,建议手动检查一遍所有数据表,补充可能漏掉的数据表和字段。第 29 行指定了单次处理的数据条数,如果你的数据库性能比较差,建议降低该值。. I6 a; r. k0 f* Z% h0 ]% K
0 Z+ Z" {3 {5 n7 f" y! g2 t6 y7 q
将 migrate_db.php 上传到网站根目录,浏览器访问它,点击“Discuz! 序列化整理”开始修复。1 Q+ r- H8 E6 L7 C! l( Z- G% i
8 V: P- R+ a, y7 C( ], b, p1 E, x
5. 转换模板、插件编码7 P' X6 [+ U  ^# x4 u3 m

; G7 G% \" d) M, W  N人工将你所有使用的模板、插件的编码转换为 UTF-8。注意不要漏掉 XML 文件。4 A2 m0 y6 y/ H
如果你的模板、插件是从应用商店下载的,没有经过改动,建议登录后台进行卸载,在应用中心重新安装一遍。
+ z6 d( E3 O' I0 s1 f. t: x' }/ z: q! H. C, Q5 L6 t
6. 转换日志编码1 y/ _7 D+ e8 \! P& U
3 O7 X9 z* [1 G# Z1 L
Discuz! 将运行日志记录在了 data/logs 目录下,如果你在准备阶段没有将这个目录复制到测试环境,可以在最终部署时再进行。
/ T2 ]& J7 c8 w4 {6 m2 z) `( k! ~将该目录下的每个文件的编码转换为 UTF-8,重新上传覆盖原文件即可。
; W0 A3 P/ M2 G" `7 \
! Y4 w) U8 w  P1 @8 _, c7. 更新缓存
- D8 Z) F7 p, A+ ?3 l0 R2 }# `2 y5 j1 i4 Q; `
登录后台,更新所有缓存(数据缓存、模板缓存、DIY模块分类缓存)。4 g' ?) y% D7 g
/ x- [; ~9 Z) d, n( g
8. 检查问题
' E+ t7 P; Q$ W$ X
0 Z; j$ D4 p, M3 `. t至此基本转换完成,需要仔细检查有无其他问题,重点检查插件、模板等是否工作正常。% ^$ v# z3 X0 q/ Z
7 s/ E" ^$ b7 m" R- s& [6 S7 N
9. 在正式环境部署上线
% [0 p: P( p7 {+ ^! p# _7 }+ I" R' {) G: f' R3 e$ Q
一定要先阅读下面的 FAQ 再决定开始部署。
- U. Y# p# h( l# R% t4 A4 z% g4 ]7 j5 }6 h& T( c, V) X
将以上步骤在正式服务器上重新操作一遍。需要注意将 config 中的数据库改为正式数据库,内存缓存无需关闭,在第 7 步更新缓存时要把内存缓存清空。
$ a* y: T, o% j! Y8 h: I1 F0 w
$ ]9 A6 _3 ?5 v. s1 ~; TF.A.Q.! ?3 q! V% Z5 z( e

( e# Q. _+ K% S9 K9 o' e: b4 HQ: 转换数据库后,登录验证问答无法通过# U5 o* L0 w' {. m
A: Discuz! 登录验证问答的加密算法为“substr(md5($answer.md5($questionid))”,结果与所用编码相关。可以参考这里修改代码,强制使用 GBK 来编码答案。, l" C3 f2 }1 u1 M8 Z: X5 o
: ]! c4 @8 Z7 h& }4 B
Q: 转换模板后打开网站依旧乱码9 @3 Y1 E; ?1 d( D
A: 请确认已经在后台更新缓存,如果依旧乱码,请 SSH 到服务器,运行 sync 命令。如果还不行,可以尝试修改乱码的模板(比如随便改一个字符),上传服务器,Discuz! 检测到文件变动后会重新刷新模板缓存,然后再将模板还原后上传。
) W; y# X. H& z) ]- c
* _2 \4 W, g& J: ~( i7 g8 NQ: 站点统计内部分数据乱码
. x8 @" f4 \+ i3 L5 Y4 l7 P- q0 Y5 hA: 等到下一个更新时间数据刷新后就正常了
! \  @9 b4 E" F: Q. N9 u& K" ]$ }4 z+ ^5 ?7 f
Q: 上传模板后 DIY 模块消失
/ r1 I. }3 ~4 XA: 到 data/diy/template/模板名 下面寻找 .bak 文件,重新 diy,选择恢复这个文件即可。
9 J0 ]& v  _1 }
5 J' }" j( Y0 P4 V* o! G; n+ \Q: 部分论坛设置、插件设置行为诡异或设置丢失3 d( y  ~" K  |
A: 很大可能是第 4 步修复数据库时,migrate_db.php 没有处理到相关数据表的字段。请仔细检查有无漏掉的数据表字段。0 d+ G& l) A6 r/ X$ I- d. ^
- A7 g6 S3 _$ L' L" w
Q: 如何方便地批量转换编码?
1 `) d) K6 j( M0 i9 T7 V# DA: 在 Linux 环境可以使用 iconv 命令(请稍微学习一下这条命令,使用很方便)。在 Windows 下可以使用 Codepage Converter 这个工具(已在附件提供)。
0 P* z! Y: S3 \6 M2 s

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

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

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

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

活动中心

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