图解LAMP开发的乱码问题(前篇)

作为LAMP的开发人员,估计或多或少都遇到过MySQL的乱码问题。就算是老鸟,有时候也会被它给郁闷。这篇文章,将从底层机制解释乱码出现的原因,并给出解决方案。(如果你只想知道,怎么解决问题,只用看完前两端就可以了)。

解决方案:

  1. 确定出现乱码的列(数据表中的字段)的编码,记为X
  2. 在你每次连接数据库的时候使用:”SET NAMES `X`”
  3. 确保你的写入页面和显示页面(通常是php script )有相同的编码。


比较典型的情况是:

数据库中列字段的编码是`latin1`(或者是utf8GBK),那么在你连接数据库的地方加上”SET NAMES `latin1`” (或者是utf8GBK)。然后保证你的写入页面add.php, list.php编码一致(比如都是GB2312utf8)。

在这个过程中,数据库MySQL有三个重要的环境变量

  1. character_set_client
  2. character_set_connection
  3. character_set_result

图解:下图给出了,一个INSERT的请求可能经过怎样的编码转换,才最终被存入数据库的。

mysql charset

过程详细分析:

  1. MySQL收到客户端的一个请求“494E5345525460E79A8460”(字符在传输过程中都是二进制编码的,这里用十六进制表示)。MySQL会按照”character_set_client“来解析这个字符串。例如“494E5345525460E79A8460”如果按照UTF8编码解释为”INSERT …``”。
  2. MySQL内部处理会将以上的SQL字符串转码为character_set_connection。例如,如果character_set_connection等于’utf8’、’gbk’、’latin1’,以上的串将会被转码为:
    utf8:494E5345525460E79A8460
    gbk:494E5345525460B5C460
    latin1:494E53455254603F3F60
  3. 内部处理后(比如相关函数操作),将存入数据库之前,会将存入的数据转码为对应字段的列编码(Column Character Set)。比如列编码可能为’utf8’、’gbk’、’latin1’,那么最终存入的数据库的`的`可能是:E79A84、B5C4、3F3F。(如果存入的是3F3F,很抱歉,肯定是乱码)

参考文章:

  1. http://dev.mysql.com/doc/refman/5.0/en/charset-connection.html
  2. 编码查询:http://orczhou.com/charset/charset.php

つづく

In:

2 responses to “图解LAMP开发的乱码问题(前篇)”

  1. 页面乱了乱了!

  2. orczhou

    貌似某个插件除了问题 调试ing

Leave a Reply

Your email address will not be published. Required fields are marked *