MySQL 乱码问题解决一例

发布于: 2010年11月20日

MySQL的编码问题和乱码问题对于新手来讲是一个麻团,剪不断,理还乱.

这次我碰到的问题是一个我大概5年前写的一个PHP小程序。那时还是一个初学Web程序的小菜鸟,几乎理所应当的犯了初学者该犯的所有错误。

想不到的是,5年中,那个小程序还一直被使用着。更想不到的是,我居然还有机会再次去维护它。

程序其实没有问题,中文输入和输出都很正常,只是PhpMyAdmin查看数据库,所有中文全是乱码。看看软件配置:

CentOS 4.1, Apache 2.0.53下运行的MySQL 4.1, PHP 5.2, PhpMyAdmin 2.6.1。 软件版本有点老,特别是PhpMyAdmin, 但是在公司内网,要升级软件可没那么容易。

仔细看了一下MySQL的编码,用命令: show variables like ‘char%’

1. mysql 命令行下直接使用:show variables like ‘char%’

character-set-client    latin1

character-set-connection    latin1

character-set-database    latin1

character-set-results    latin1

character-set-server    latin1

character-set-system    utf8

character-sets-dir    /usr/share/mysql/charsets/

这没啥意外的,毕竟是那帮的瑞典人弄出来的嘛,默认就是全是latin1。但命令行下的中文也是乱码,这个稍后再看。

2.  程序页面里使用 mysql_query(“show variables like ‘char%'”) 输出结果:

character-set-client    latin1

character-set-connection    latin1

character-set-database    latin1

character-set-results    latin1

character-set-server    latin1

character-set-system    utf8

character-sets-dir    /usr/share/mysql/charsets/

跟命令行下一样。这个也能理解,因为在程序里面没有对编码有个任何的改变。

3. 在PhpMyAdmin(版本2.6.1)的页面中使用mysql_query(“show variables like ‘char%'”) 输出结果:

character-set-client    utf8

character-set-connection    latin1

character-set-database    latin1

character-set-results    utf8

character-set-server    latin1

character-set-system    utf8

character-sets-dir    /usr/share/mysql/charsets/

其中两行不一致。

原因分析和解决:

我发现小程序网页页面使用的是gb2312编码。也就是说,程序交给数据库的是gb2312版本的字符编码,数据库当成了latin1的编码格式在存储,而PhpMyAdmin用utf8格式来提取和显示的。天哪,什么乱七八糟的。

小程序能正常显示中文的原因是,gb2312的编码,以latin1编码连接,存储,提取,所以存和取的过程中编码没有变,提取到网页上之后,又以gb2312的编码方式显示,一切正常。

那么我要做的是PhpMyAdmin也以这样的过程执行就好了。其实MySQL命令行下的满足了数据库部分的要求,是不是显示部分编码由问题呢?那就试试吧:

1.退出MySQL Client, 在Linux命令行下Locale一下。嗯,本地编码是zh_CN.utf8的。

2.于是执行: export LANG=zh_CN.gb2312

3.然后: mysql -h localhost -u user -p 连接到数据库,执行一条查询语句,果然中文显示正常了。

看来我的推断是正确的。现在的问题是如何让PhpMyAdmin也这样做:

1. 首先要把页面编码变成gb2312。 看起来要把PhpMyAdmin的语言改为English, 因为直接在中文版上改编码,显然会让网页上的正常中文字变为乱码。然后进入./lang 目录下,把english-utf8.inc.php文件顶部附近的下面一行:

$charset=utf8 改为 $charset=gb2312

因为任何编码都不会让英文变成乱码。刷新PhpMyAdmin的页面,然后查看页面html源码可以发现页面的charset由utf8变成了gb2312:

<meta http-equiv=content-type content=”text/html; charset=gb2312“>

2. 再次在PhpMyAdmin的页面中使用mysql_query(“show variables like ‘char%'”), 输出结果变成了:

character-set-client    gb2312

character-set-connection    latin1

character-set-database    latin1

character-set-results    gb2312

character-set-server    latin1

character-set-system    utf8

character-sets-dir    /usr/share/mysql/charsets/

看来character-set-client和character-set-results的编码跟页面编码是一致的。

3. 如何独立设置character-set-client和character-set-results呢?修改./libraries 的database_interface.lib.php文件,找到下边这一行:

$mysql-charset=$GLOBALS[‘mysql-charset-map’][$GLOBALS[‘charset’]];

改为:

$mysql-charset=”latin1″;

至此mysql_query(“show variables like ‘char%'”)输出的结果与程序页面一致,PhpMyAdmin也变查询出来的中文显示也没有乱码了。唯一的遗憾是PhpMyAdmin主页面显示的MySQL Charset: GB2312 Simpfilied Chinese(gb2312), 不过也无伤大雅了。

后记:

为了杜绝编码问题,以后一定要在程序开发的时候,在MySQL连接函数里面加上”SET NAMES UTF8″,这样至少也好转换一些。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理

浙ICP备18056264号-1