theinfor


Mysql 数据库编码

Posted in tech by theinfor on the December 31st, 2006
转贴一篇文章,关于mysql数据库编码的问题:
来源:http://blog.jjgod.org/2005/07/31/a-mysql-41-story/#more-51
下面要写的是一篇非常无聊的东西,充斥了大量各式各样的编码、转换、客户端、服务器端、连接……呃,我自己都不愿意去看它,但想一想,写下来还是有点意义的,原因有四:

  1. MySQL 4.1 对多语言的支持有了很大变化 (这导致了问题的出现);
  2. 尽管大部分的地方 (包括个人使用和主机提供商),MySQL 3 仍然占主导地位;但 MySQL 4.1 是 MySQL 官方推荐的数据库,已经有主机提供商开始提供并将会越来越多;
  3. 许多 PHP 程序以 MySQL 作为默认的数据库管理软件,但它们一般不区分 MySQL 4.1 与 4.1 以下版本的区别,笼统地称“MySQL 3.xx.xx 以上版本”就满足安装需求了;
  4. 因为 latin1 在许多地方 (下边会详细描述具体是哪些地方) 作为默认的字符集,成功的蒙蔽了许多 PHP 程序的开发者和用户,掩盖了在中文等语言环境下会出现的问题;

简单的说,MySQL 自身的变化和使用 MySQL 的 PHP 程序对此忽略,导致了问题的出现和复杂化,而由于大部分用户使用的是英文,使这种问题不被重视。这里提到的 PHP 程序,主要就 WordPress 而言。

MySQL 4.1 字符集支持的原理

MySQL 4.1 对于字符集的指定可以细化到一台机器上安装的 MySQL,其中的一个数据库,其中的一张表,其中的一栏,应该用什么字符集。但是,传统的 Web 程序在创建数据库和数据表时并没有使用那么复杂的配置,它们用的是默认的配置,那么,默认的配置从何而来呢?

  1. 编译 MySQL 时,指定了一个默认的字符集,这个字符集是 latin1;
  2. 安装 MySQL 时,可以在配置文件 (my.ini) 中指定一个默认的的字符集,如果没指定,这个值继承自编译时指定的;
  3. 启动 mysqld 时,可以在命令行参数中指定一个默认的的字符集,如果没指定,这个值继承自配置文件中的;
  4. 此时 character_set_server 被设定为这个默认的字符集;
  5. 当创建一个新的数据库时,除非明确指定,这个数据库的字符集被缺省设定为 character_set_server
  6. 当选定了一个数据库时,character_set_database 被设定为这个数据库默认的字符集;
  7. 在这个数据库里创建一张表时,表默认的字符集被设定为 character_set_database,也就是这个数据库默认的字符集;
  8. 当在表内设置一栏时,除非明确指定,否则此栏缺省的字符集就是表默认的字符集;
  9. 这个字符集就是数据库中实际存储数据采用的字符集,mysqldump 出来的内容就是这个字符集下的;

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

当一个 PHP 程序与 MySQL 建立连接后,这个程序发送给 MySQL 的数据采用的是什么字符集?MySQL 无从得知 (它最多只能猜测),所以 MySQL 4.1 要求客户端必须指定这个字符集,也就是 character_set_client,MySQL 的怪异之处在于,得到的这个字符集并不立即转换为存储在数据库中的那个字符集,而是先转换为 character_set_connection 变量指定的一个字符集;这个 connection 层究竟有什么用我不大明白,但转换为 character_set_connection 的这个字符集之后,还要转换为数据库默认的字符集,也就是说要经过两次转换;当这个数据被输出时,又要由数据库默认的字符集转换为 character_set_results 指定的字符集。

一个典型的环境

典型的环境以我自己的电脑上安装的 MySQL 4.1 为例,我自己的电脑上安装着 Apache 2,PHP 5 和 WordPress 1.5.1.3,MySQL 配置文件中指定了 default_character_setutf8。于是问题出现了:

  1. WordPress 按照默认情况安装,所以所有的表都用 UTF-8 存储数据;
  2. WordPress 默认采用的浏览字符集是 UTF-8 (Options->Reading 中设置),因此所有 WP 页面的 meta 中会说明 charset 是 utf-8;
  3. 所以浏览器会以 utf-8 方式显示所有的 WP 页面;这样一来 Write 的所有 Post,和 Comment 都会以 UTF-8 格式从浏览器发送给 Apache,再由 Apache 交给 PHP;
  4. 所以 WP 从所有的表单中得到的数据都是 utf-8 编码的;WP 不加转换的直接把这些数据发送给 MySQL;
  5. MySQL 默认设置的 character_set_clientcharacter_set_connection 都是 latin1,此时怪异的事情发生了,实际上是 utf-8 格式的数据,被“当作 latin1”转换成……居然还是转换成 latin1,然后再由这个 latin1 转换成 utf-8,这么两次转换,有一部分 utf-8 的字符就丢失了,变成 ??,最后输出的时候 character_set_results 默认是 latin1,也就输出为奇怪的东西了。

最神奇的还不是这个,如果 WordPress 中设置以 GB2312 格式阅读,那么 WP 发送给 MySQL 的 GB2312 编码的数据,被“当作 latin1”转换后,存进数据库的是一种奇怪的格式 (真的是奇怪的格式,mysqldump 出来就能发现,无论当作 utf-8 还是当作 gb2312 来读都是乱码),但如果这种格式以 latin1 输出出来,居然又能变回 GB2312!

这会导致什么现象呢?WP 如果使用 MySQL 4.1 数据库,把编码改用 GB2312 就正常了,可惜,这种正常只是貌似正常。

如何解决问题

如果你已经不耐烦了 (几乎是肯定的),google 一下,会发现绝大部分的解答是,query 之前先执行一下:SET NAMES 'utf8',没错,这是解决方案,但本文的目的是说明,这为什么是解决方案。

要保证结果正确,必须保证数据表采用的格式是正确的,也就是说,至少能够存放所有的汉字,那么我们只有两种选择,gbk 或者 utf-8,下面讨论 utf-8 的情况。

因为配置文件设置的 default_character_set 是 utf8,数据表默认采用的就是 utf-8 建立的。这也应该是所有采用 MySQL 4.1 的主机提供商应该采用的配置。所以我们要保证的只是客户端与 MySQL 交互之间指定编码的正确。

这只有两种可能,客户端以 gb2312 格式发送数据,或者以 utf-8 格式发送数据。

如果以 gb2312 格式发送:

SET character_set_client='gb2312'
SET character_set_connection='utf8' 或者
SET character_set_connection='gb2312'

都是可以的,都能够保证数据在编码转换中不出现丢失,也就是保证存储入数据库的是正确的内容。

怎么保证取出的是正确的内容呢?考虑到绝大部分客户端 (包括 WP),发送数据的编码也就是它所希望收到数据的编码,所以:

SET character_set_results='gb2312'

可以保证取出给浏览器显示的格式就是 gb2312。

如果是第二种情况,客户端以 utf-8 格式发送 (WP 的默认情况),可以采用下述配置:

SET character_set_client='utf8'
SET character_set_connection='utf8'
SET character_set_results='utf8'

这个配置就等价于 SET NAMES 'utf8'

WP 应该作什么修改

还是那句话,客户端要发给数据库什么编码的数据,数据库是不可能确切知道的,只能让客户端自己说明白,所以,WP 是必须发送正确的 SET... 给 MySQL 的。怎么发送最合适呢?台湾的 pLog 同仁给出了一些建议

  1. 首先,测试服务器是否 >= 4.1,编译时是否加入了 UTF-8 支持;是则继续
  2. 然后测试数据库以什么格式存储 ($dbEncoding);
  3. SET NAMES $dbEncoding

对于第二点,WP 的情况是不同的,按照上面的典型配置,只要用 WP,肯定数据库是用 UTF-8 存储的,所以要根据用户设置的以 GB2312 还是 UTF-8 浏览来判断 (bloginfo('charset')),但这个值是要连接数据库以后才能得到的,所以效率最高的方式是连接数据库之后,根据这个配置设置一次 SET NAMES,而不必每次查询之前都设置一遍。

我的修改方式是这样的,在 wp_includes/wp-db.php 中增加:

function set_charset($charset)
{
// check mysql version first.
$serverVersion = mysql_get_server_info($this->dbh);
$version = explode('.', $serverVersion);
if ($version[0] < 4) return;

// check if utf8 support was compiled in
$result = mysql_query("SHOW CHARACTER SET like 'utf8'",
$this->dbh);
if (mysql_num_rows($result) < = 0) return;

if ($charset == 'utf-8' || $charset == 'UTF-8')
$charset = 'utf8';
@mysql_query("SET NAMES '$charset'", $this->dbh);
}

wp-settings.phprequire (ABSPATH . WPINC . '/vars.php'); 后增加:

$wpdb->set_charset(get_bloginfo('charset'));

.gmail is back!

Posted in tech by theinfor on the December 27th, 2006

I tried to create a new “.googlemail” account this morning, turn out the “.gmail” is available to use again. google must pay something for using this name again, but anyway, good news!

Client does not support authentication protocol requested

Posted in tech by theinfor on the December 27th, 2006
shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client
官方的说法是MySQL 4.1 and up uses an authentication protocol based on a password hashing algorithm that is incompatible with that used by older clients. …..


如果你升级mysql到4.1以上版本后遇到以上问题,请先确定你的mysql client 是4.1或者更高版本.(WINDOWS下有问题你就直接跳到下面看解决方法了,因为MYSQL 在WINDOWS是client和server一起装上了的)

请使用以下两种方法之一

其一:

mysql> SET PASSWORD FOR
-> 'some_user‘@’some_host‘ = OLD_PASSWORD(’newpwd‘);

其二:

mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd‘)
-> WHERE Host = ‘some_host‘ AND User = ‘some_user;
mysql> FLUSH PRIVILEGES;
上面红色的部分请按自己实际情况修改....
这样做后,连接就会正常了@!

A funny game and Merry Christmas!

Posted in tech by theinfor on the December 27th, 2006

Draw your line, send your guy and Merry Christmas!

This is really a funny game!

http://www.deviantart.com/deviation/40255643/

osCommerce .vs. css-flyout-header

Posted in tech by theinfor on the November 30th, 2006

osCommerceWhen css-flyout-header just doesn’t work in osCommerce, you might want to take a look at the “!DOCTYPE” declaration in file header!

A css-flyout-header which was developed for zen-cart originally was taken use of by me for a new osCommerce online shop www.acupuncture-direct.co.uk. However, after menu code included and .css file attached, the menu works fine in firfox, but just don’t get along with IE 7.0!

The problem is neither the .css file I used nor the menu code was included wrong, it was the “!doctype” declaration in header! The flyout menu module works in enviroment defined by “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”, after adding this line into “!doctype …” , everything works just fine!

New Yahoo Mail

Posted in tech by theinfor on the October 11th, 2006

Yahoo email just launched a new version. It’s now outlook and gmail like.

An interesting post from Read/WriteWeb

Posted in tech by theinfor on the May 28th, 2006

Firefox vs IEA post with a title “Firefox vs IE Smackdown!” really made me laugh out!

Just imagine Ben Goodger (Lead Engineer on Firefox who also works for Google) saying: “Now talks about designing and developing for IE – ‘we know it can be a little frustrating’. Discusses CSS issues and shows that IE7 has fixed all but one of the 25 bugs they identified ‘that drive developers crazy’” while Tony Chor (Group Program Manager of Microsoft’s Internet Explorer team) being present (seems like that) in a conference! I mean how funny is that!

Change Firefox Google Search Bar Default Settings

Posted in tech by theinfor on the May 10th, 2006

Firefox Google Search BarI’ve been thinking about to change firefox google search bar default searching zone from U.S to UK.

Now here is a solution:
Go to Firefox installation folder, for example C:\Program Files\Mozilla Firefox\, open the folder named “searchplugins”. Open “google.src” with your text editing tools, such as notepad, change the following code

action=”http://www.google.com/search”

to

action=”http://www.google.co.uk/search”

Then, you are done!

A battle between Google and eBay is coming?

Posted in tech by theinfor on the April 21st, 2006

According to ZDNet News, eBay is feeling pressure from Google because “After years of working closely with the search giant, eBay last year became alarmed as Google started assaulting its turf in multiple ways, including creation of a competing classified-advertising service,” the report said. So it turned to Microsoft and Yahoo, another two giants in IT industry, looking for a way to survive (everybody knows what google does all the time, so I dare not say eBay is going to win).
However, given the huge customer base and years of excellent reputation of eBay, Google still need time before it can really kick eBay’s ass. Well, at least I think so.

Can your Internet Exploer Pass A Spoofing Vulnerability Test?

Posted in tech by theinfor on the April 6th, 2006

A vulnerability in Internet Explorer has been discovered by Hai Nam Luke(I have no idea who this is). This vulnerability could be taken use to conduct phishing attacks. Luke supplies a link on website for testing purpose. Once open the page linked, an address “www.google.com” is shown in address bar of Internet Explore and contents of the page looks exactly like “Google”, however, the page changes seconds later into another one with the address of “Google” remain in the address bar, which means you could have been filling your credit card information or any other private information already if somebody else has built a fake website taking use of this vulnerability, and there is no way you can notice the spoofing.

Version of the Internet Explorer I’m using is 7, so I assume those old versions under 7 are all vulnerable.

Test link can be find here, and also method to solve the problem. Test it, fix it and be careful!

Next Page »