1 缘由
前段时间在折腾discuz的PHP版本升级,据说PHP7比PHP5的性能提升了很多,于是新建了一个论坛镜像,将其中PHP版本从5.x升级了7.x版本,将原来跑PHP5的容器替换为PHP7的容器,docker在做升级软件的时候确实很方便,不会影响宿主机环境。从统计数据看,测试论坛的平均响应时间确实缩短了20%左右,效果不错。只是第二天有同事反馈,说论坛有用户发帖称自己的用户名变成乱码了。
2 查证
刚刚收到这个问题的时候,有点疑惑,看到这个用户名中有繁体字”誠“,想着可能是繁体字的问题,于是在测试环境中发了个帖子,帖子内容就是这个用户名,发现果然显示乱码了,查了下数据库表,发现存储的内容是截去了部分字节。接着用其他的几个繁体字测试了下,发现居然没有乱码,看来不是所有繁体字都会导致乱码。
一开始是比较困惑的,只是升级了PHP版本,按理不会引起这种BUG才对,这看起来是MySQL的编码设置的问题,也就是character_set_client, character_set_connection, character_set_result
这几个变量设置错误导致的。于是,就去查看discuz在新旧版本的PHP版本下数据库连接代码的不同的地方。最终发现discuz升级到PHP7以后,用的是source/class/db/db_driver_mysqli.php
下面的连接代码,这里与PHP5使用的source/class/db/db_driver_mysql.php
略有不同,PHP7用的新的 mysqli 库,PHP5用的是老的 mysql 库,两个库本身的功能是兼容的,但是数据库连接这里的编码设置发现了一些不同之处。
#PHP5采用的连接代码,dbcharset在我们系统中是GBK
$dbcharset = $dbcharset ? $dbcharset : $this->config[1]['dbcharset'];
$serverset = $dbcharset ? 'character_set_connection='.$dbcharset.
', character_set_results='.$dbcharset.', character_set_client=binary' : '';
$serverset && mysql_query("SET