Entries Tagged with "mysql"

WP和MT的MySQL乱码问题解决方法

发表于 2006-02-06 23:00 | 分类: 菠萝菠萝蜜 | tags: , , | 发表评论

WordPress和MovableType是主流的Blog系统,而他们都用的是MySQL数据库,那么在MySQL4.1下,中文的WP和MT就会产生种种的乱码问题。

如前MySQL4.1乱码问题分析的,一个程序( PHP,CGI 等)与MySQL建立连接后,这个程序发送给MySQL的数据采用的是什么字符集,MySQL 是无从得知的。所以解决乱码问题的根本就是我们在程序中告诉MySQL采用的编码是什么,简单的就是在程序中加入这样的一个语句:

SET NAMES ‘utf8′

这个语句的效果等同于同时设定了

SET character_set_client=’utf8′
SET character_set_connection=’utf8′
SET character_set_results=’utf8′

为什么这么做?

我们安装MySQL4.1时按照默认配置,那么default-character-set= utf8。在MySQL Command Line Client下查看到的查看系统的字符集和排序方式的设定为:

mysql> SHOW VARIABLES LIKE ‘character_set_%’;
+————————–+—————————-+
| Variable_name            |            Value           |
+————————–+—————————-+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | utf8                       |
| character_set_results    | latin1                     |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+————————–+—————————-+
7 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE ‘collation_%’;
+———————-+——————-+
| Variable_name        |      Value        |
+———————-+——————-+
| collation_connection | latin1_swedish_ci |
| collation_database   | utf8_general_ci   |
| collation_server     | utf8_general_ci   |
+———————-+——————-+
3 rows in set (0.00 sec)

按照MySQL的存储机制,数据在传输的过程中就会在latin1和utf8两种编码之间互相转换,这样就很容易的变成了乱码。我们在程序中设置了SET NAMES ‘UTF8′,就等同于把所有的编码都设置为utf8,这样数据就没有了编码转换问题,也就没有了乱码问题了。

在WP和MT中的设置方法

那么具体在WordPress和MovableType中,怎么设定SET NAMES ‘UTF8′呢?

对于PHP的MySQL系统来说,这样的修改很简单:

找到wp-includes/wp-db.php

$this->dbh = @mysql_connect($dbhost,$dbuser,$dbpassword);

//加上下面这行

$this->query(”SET NAMES ‘utf8′”);

对于用Perl的MT系统来说,同样的修改方法是:

在 MT 目录下找到lib/MT/ObjectDriver/DBI/mysql.pm
加上以下粗体显示的那行

   sub init {
    my $driver = shift;
    $driver->SUPER::init(@_);
    my $cfg = $driver->cfg;
    my $dsn = ‘dbi:mysql:database=’ . $cfg->Database;
    $dsn .= ‘;hostname=’ . $cfg->DBHost if $cfg->DBHost;
    $dsn .= ‘;mysql_socket=’ . $cfg->DBSocket if $cfg->DBSocket;
    $dsn .= ‘;port=’ . $cfg->DBPort if $cfg->DBPort;
    $driver->{dbh} = DBI->connect($dsn, $cfg->DBUser, $cfg->DBPassword,
        { RaiseError => 0, PrintError => 0 })
        or return $driver->error(MT->translate(”Connection error: [_1]”,
             $DBI::errstr));
    $driver->{dbh}->do(”SET NAMES ‘utf8′”);     //加上这行
    $driver;

这样的Blog系统,数据在传输和存储的过程中,都不会出现乱码了。

ps:MT系统的修改方法感谢Pedro MeloZack 和 e-luck 的指点。也感谢xdanger最终在邮件中的帮助。

MySQL4.1的乱码问题

发表于 2006-02-06 22:44 | 分类: 菠萝菠萝蜜 | tags: | 发表评论

MySQL4.1的变化

MySQL为解决并控制不同层次的不同字符编码问题,在4.1以上版本对字符集的支持细化到四个层次:服务器(server)、数据库(database)、数据表(table)和连接(connection)。

MySQL通过以下三个方面来控制各个层次的字符编码:MySQL字符集(Character set)、MySQL连接校对(Collation,整理)以及站点编码。

编译 MySQL 时,指定了一个默认的字符集,这个字符集是 latin1;

安装 MySQL 时,可以在配置文件 (my.ini) 中指定一个默认的的字符集,如果没指定,这个值继承自编译时指定的;

启动 mysqld 时,可以在命令行参数中指定一个默认的的字符集,如果没指定,这个值继承自配置文件中的;

此时 character_set_server 被设定为这个默认的字符集;

当创建一个新的数据库时,除非明确指定,这个数据库的字符集被缺省设定为 character_set_server;
当选定了一个数据库时,character_set_database 被设定为这个数据库默认的字符集;

在这个数据库里创建一张表时,表默认的字符集被设定为 character_set_database,也就是这个数据库默认的字符集;

当在表内设置一栏时,除非明确指定,否则此栏缺省的字符集就是表默认的字符集;

这个字符集就是数据库中实际存储数据采用的字符集,mysqldump 出来的内容就是这个字符集下的;

简单的总结一下,如果什么地方都不修改,那么所有的数据库的所有表的所有栏位的都用 latin1 存储,不过我们如果安装 MySQL,一般都会选择多语言支持,也就是说,安装程序会自动在配置文件中把 default_character_set 设置为 UTF-8,这保证了缺省情况下,所有的数据库的所有表的所有栏位的都用 UTF-8 存储。

MySQL的存储机制

当一个程序( PHP,CGI 等)与MySQL建立连接后,这个程序发送给MySQL的数据采用的是什么字符集?MySQL 无从得知(它最多只能猜测),所以:

MySQL 4.1要求客户端必须指定这个字符集,也就是character_set_client;MySQL的怪异之处在于,得到的这个字符集并不立即转换为存储在数据库中的那个字符集,而是先转换为character_set_connection 变量指定的一个字符集;转换为character_set_connection的这个字符集之后,还要转换为数据库默认的字符集character_set_database 进行存储;当这个数据被输出时,又要转换为 character_set_results指定的字符集。

上面3个变量的作用是这样的,client表示客户端发送过来的字符集,results表示发送到客户端的字符集(这两个分开是因为发送过来和发送过去的不一定是同一个客户端),connection则在客户端和数据库起一个连接作用。

所以,因为MySQL4.1的支持细化到了四个层次,但是每个层次的设定并不是唯一,这样就造成了在数据的传输过程中有多次的编码转换,对于中文来说,就很容易的形成乱码了。