Monday, November 19, 2007

Cygwin 环境下安装 Gtk2

这里的 Gtk2 是指 Perl 的 Gtk2 模块,Cygwin 环境下通过 CPAN 是无法直接安装的,需要修改了 Makefile.PL 之后手动安装。
--- Makefile.PL 2006/11/06 00:35:44 1.1
+++ Makefile.PL 2006/11/06 10:24:38
@@ -331,10 +331,6 @@

# this probably needs to go into ExtUtils::Depends.
sub find_extra_libs {
- # right now we need this terrible hack only for windows.
- # unfortunately, this code doesn't work on cygwin. :-/
- return "" unless $^O eq "MSWin32";
-
# win32 does not allow unresolved symbols in libraries, but
# Gtk2 uses on symbols in the dll created for Glib.
# so, we have to break all this nice abstraction and encapsulation
@@ -346,10 +342,19 @@
my $retstring = "";

use File::Find;
- find (sub {
- $retstring .= " ".$File::Find::name
- if /Glib.lib/i;
- }, @INC);
+
+ if ($^O eq "MSWin32") {
+ find (sub {
+ $retstring .= " ".$File::Find::name
+ if /Glib\.lib/i;
+ }, @INC);
+ } elsif ($^O eq "cygwin") {
+ find (sub {
+ $retstring .= " -L".$File::Find::dir
+ if /libGlib\.dll\.a/i;
+ }, @INC);
+ $retstring .= " -lGlib.dll" if ($retstring ne "");
+ }

return $retstring;
}

这是 Dirk Froemberg 向 Torsten Schoenfeld 提交的 patch,到现在为止还没有被合并进 source。

参考链接:
http://bugzilla.gnome.org

Friday, November 09, 2007

寻找被占用的硬盘空间

收到系统邮件报警,有个分区的空间使用率已经超过90%
[root@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda7 4.9G 4.3G 267M 94% /
/dev/sda1 99M 17M 77M 18% /boot
/dev/sda2 43G 8.8G 32G 22% /data
none 1.9G 0 1.9G 0% /dev/shm
/dev/sda6 4.9G 43M 4.6G 1% /home
/dev/sda5 4.9G 1.8G 2.8G 39% /usr
/dev/sda3 4.9G 1.5G 3.2G 31% /var

[root@localhost ~]# du -h -x --max-depth=1 /
8.0K /opt
2.0K /boot
5.7M /bin
4.0K /data
0 /proc
144M /lib
8.0K /initrd
11M /etc
8.0K /mnt
0 /sys
8.0K /selinux
2.2M /tmp
42M /root
8.0K /var
8.0K /srv
16K /lost+found
17M /sbin
16K /media
8.0K /usr
0 /dev
8.0K /misc
8.0K /home
4.2G /

[root@localhost ~]# ls -al /
total 174
drwxr-xr-x 24 root root 4096 Aug 16 01:23 .
drwxr-xr-x 24 root root 4096 Aug 16 01:23 ..
-rw-r--r-- 1 root root 0 Aug 16 01:23 .autofsck
drwxr-xr-x 2 root root 4096 Aug 23 04:02 bin
drwxr-xr-x 4 root root 1024 Aug 15 19:12 boot
drwxr-xr-x 5 root root 4096 Sep 20 16:41 data
drwxr-xr-x 9 root root 6540 Aug 16 01:23 dev
drwxr-xr-x 67 root root 4096 Nov 9 14:42 etc
drwxr-xr-x 9 root root 4096 Nov 9 14:42 home
drwxr-xr-x 2 root root 4096 Feb 22 2005 initrd
drwxr-xr-x 12 root root 4096 Oct 26 04:03 lib
drwx------ 2 root root 16384 Aug 16 03:43 lost+found
drwxr-xr-x 4 root root 4096 Aug 16 01:23 media
drwxr-xr-x 2 root root 4096 May 3 2007 misc
drwxr-xr-x 2 root root 4096 Aug 15 18:48 mnt
drwxr-xr-x 2 root root 4096 Sep 20 17:07 opt
dr-xr-xr-x 420 root root 0 Aug 16 10:22 proc
drwxr-x--- 6 root root 4096 Nov 9 14:42 root
drwxr-xr-x 2 root root 12288 Aug 23 04:02 sbin
drwxr-xr-x 2 root root 4096 Aug 15 18:43 selinux
drwxr-xr-x 2 root root 4096 Feb 22 2005 srv
drwxr-xr-x 9 root root 0 Aug 16 10:22 sys
drwxrwxrwt 4 root root 4096 Nov 9 22:36 tmp
drwxr-xr-x 16 root root 4096 Aug 15 18:45 usr
drwxr-xr-x 22 root root 4096 Aug 21 16:32 var

找来找去,找不到吃掉空间的文件,还是经过好友指点,学到了这个命令:
[root@localhost~]# lsof | grep deleted
logswatch 14767 zimbra 1w REG 8,7 1830440 384006 /tmp/logswatch.out (deleted)
logswatch 14767 zimbra 2w REG 8,7 1830440 384006 /tmp/logswatch.out (deleted)
......

意为列出已被删除,但仍被进程占用中的文件。然后就是处理(杀掉?)掉相关进程,释放文件,空间就回来了。

Thursday, September 27, 2007

MySQL Users Conference Japan 2007 講演資料公開

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

MySQL Users Conference Japan 2007 参加登録者の方へ

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

この度は、悪天候の中、MySQL Users Conference Japan 2007にたくさんの方にお越しいただき、誠にありがとうございました。カンファレンス資料を公開致しました。
http://www.mysql-ucj2007.jp/session/index.html

見逃してしまったセッション、もう一度見たいセッションがございましたら、ぜひお早めにダウンロードをお勧めいたします。10月31日まで公開しております。なお、都合により非公開の資料もございます。予めご了承ください。

次回 MySQL カンファレンスに対するご要望をお持ちの方は、ucj@mysql.com までお知らせください。


MySQL Enterprise にご興味のある方は、下記サイトでご紹介しております。
http://www-jp.mysql.com/products/enterprise/
MySQL Enterprise 30日トライアルも実施中です。

購入に関するお問い合わせは、03-5918-7507 までご連絡ください。

この度は、MySQL カンファレンスへのご登録およびご来場、ありがどうございました。

MySQL 株式会社

Thursday, September 20, 2007

Update your HTML::Parser

An example of using HTML::FillInForm
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
...

after fill the form...
<!--DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
...

The declaration was changed which could cause problem in IE. It was fixed in 3.56 released in 2007.01.12.

Tuesday, September 11, 2007

MySQL Users Conference Japan 2007 - 1

今天是大会第一天,由于路线选择错误,我花了近两小时才抵达会场,台场真的是好远啊。

迟到了一小时,所以错过了 E11(MySQL 高可用性解决方案简介 by Jimmy Guerrero)。

所以就从 J12(使用 DRBD 和 heartbeat 搭建高可用性 MySQL by Patrick Bolduan of MTV Japan)开始了。介绍了一个的案例,2 个 MySQL Master 节点,heartbeat 管理共享的 Virtual IP 以及 MySQL 实例,DRBD 实现数据同步。
这个方案的优点在于不需要人工干预就能实现 failover,M/S Replication 架构如果不考虑事后重建 Slave 这档子事儿的话也算是可以自动化的。缺点是,2 个数据库节点只能用其中 1 个,稍微有些浪费资源。关于 DRBD,一个问题是它本身有开销,会导致 MySQL 性能有一定程度的下降,另一个问题是在数据量大到某种程度后,安全性并不是非常可靠,Patrick 介绍他们测试下来,50GB 左右还是安全的。我对 DRBD 几乎没什么了解,找时间看看。

接下来是 E13(MySQL Performance Tuning and Benckmark by Colin Charles of MySQL AB)。介绍了一下 Tuning 和 Benckmark 的方向和若干工具,因为多数内容都有所了解,基本没有留下笔记。Peter 的 mysqlperformanceblog 大家都说不错,值得常去逛逛。

最后是 E14(面向 Web 2.0 的 MySQL 架构 by Brian Aker)。讲的内容面比较广,这里就略了,有时间以后再补上。Brian 重点推荐了一下 EC2,记一下。

参考链接:MySQL Users Conference Japan 2007

Friday, September 07, 2007

Debug JavaScript in Internet Explorer

经常被提到的一个话题,才知道还有这些东西。

Microsoft Script Debugger
非常、非常弱的一个工具,只是聊胜于无。安装之后,要改一下 IE 的设置
unchecking Tools / Internet Options... / Advanced / Disable script debugging (Internet Explorer).

然后重启 IE 就可以在 View->Script Debugger 就可以调用了。在中断处呼出窗口后,能做的事情非常有限,还算有用的是 View->Command Window,输入变量或者表达式可以得到值。

Microsoft Script Editor
一个很像 Visual Studio 的脚本调试工具,但却是 Microsoft Office 的组件,如果你已安装,那么其路径应该是 %ProgramFiles%/Microsoft Office/OFFICE11/MSE7.exe。
它可以单独启动去绑定指定进程,也可以从 IE 呼出,不过这个需要安装 Microsoft Script Debugger,然后在调试窗口打开前有个弹窗可以选 Debugger 还是 Editor。
界面友好,功能也还可以,大家不妨试试。

其他还有重型武器 Visual Studio,好像是有组件调试 JavaScript 的,我没玩过,就不乱说了。

参考链接:
http://www.jonathanboutelle.com/mt/archives/2006/01/howto_debug_jav.html
http://erik.eae.net/archives/2005/07/04/21.49.50/

Sunday, September 02, 2007

Patch for Jcode-2.06

Bug report: http://rt.cpan.org/Public/Bug/Display.html?id=29049

Bug detail:
1. According to RFC1522 as the document mentioned, I'm afraid it would be better to set $lf as \r\n instead of \n, which could cause some MTA like qmail working improperly.

2. The optional parameter $lf is not used in the function, although the document says it is.

Archive patched: Jcode-2.06-patched.tar.gz

Tuesday, August 28, 2007

不好用的 Cygwin 的 vi

一直以为 Cygwin 的 vi 特别不好用,特别是在输入模式(i)下,小键盘的表现很奇怪。
其实,是自己太菜了,在主目录下建一个 vi 的配置文件就万事OK了。
islue@localhost ~
$ locate vimrc
/usr/share/vim/vim71/vimrc_example.vim

islue@localhost ~
$ cp /usr/share/vim/vim71/vimrc_example.vim .vimrc

Monday, August 20, 2007

alternative solution of port forward

ssh的port forward很方便又很不方便,如果网关代理服务器支持nc命令的话,试试这个。
[localhost ~]$ cat .ssh/config
Host 192.168.0.100
ProxyCommand ssh 192.168.0.1 "nc %h %p"

192.168.0.100: 内网目标服务器
192.168.0.1: 网关代理服务器

Wednesday, May 23, 2007

小发现

观察 df 的输出
[localhost ~]$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 2.0G 1.3G 623M 68% /
/dev/sda3 6.9G 3.2G 3.4G 49% /usr/local
/dev/sda8 2.0G 118M 1.8G 7% /usr/local/tmp

以比较明显的第二行为例,可以发现
Size > Used + Avail

原因是系统为特权用户保留了一部分空间。所以,Avail 的含义其实是非特权用户的可用空间,并且可能为负。

然后呢,在使用一些工具时就要注意了,比如 HotSaNIC,它生成的磁盘容量使用图表中的 free 是不同于 df 的 Avail 的。

HotSaNIC.free = df.Size - df.Used

在磁盘空间快耗尽的时候,不要被它麻痹了。

Thursday, May 17, 2007

MySQL Community Server 5.0.41 is released

其中,我最关注的 bug fixed 是这个:

Loading data using LOAD DATA INFILE may not replicate correctly (due to character set incompatibilities) if the character_set_database variable is set before the data is loaded. (Bug#15126)

摔过跟头,自然印象深刻。

Sunday, April 15, 2007

删除文件或文件夹时出错

无法删除 i-am-a-sample: 文件正在被另一个人或程序使用。
关闭任何可能使用这个文件的程序,重新试一次。

相信大多数人都见过这个错误消息,而且有时候对于“任何可能使用这个文件的程序”会很困惑,最后只能重启电脑。在一次忍无可忍的经历后,我终于决定去找一个第三方软件来帮我解决这个问题。也许是 old 了,但还是推荐一下:unlocker,它能帮你找出“任何可能使用这个文件的程序”。

Thursday, April 05, 2007

谷歌拼音输入法

解脱了,总算用上了一款还算顺手的输入法。

自己一直是用紫光的,也久仰搜狗大名,无奈工作环境是日文操作系统,谁也不顶。还是 Google 好,赞一个。

Sunday, March 25, 2007

PuTTYcyg

PuTTYcgy,一个 PuTTY 的改版,可使用 PuTTY 作为本地 Cygwin 终端。

在这之前,我有两个选择。
Cygwin 的自带终端。缺点,主要是复制粘贴不方便,要同时用到鼠标和键盘。
Cygwin 的 X Term。缺点,本地要起 X Server,开销比较大。

说明一下 putty 的快捷方式的创建方法。

首先,打开 putty,修改好各项设置后保存,假设 Session 名为 cygwin。
然后,再创建一个 putty 的快捷方式,把“目标”设置为
\path\to\putty.exe -load "cygwin"

顺便提一下,hoekey 是个创建键盘快捷方式的好工具。

参考链接:
PuTTY - How can I create a Windows shortcut to start a particular saved session directly?

Wednesday, March 07, 2007

MySQL 子查询一例

到目前为止,MySQL 还不能支持这样的操作,子查询的 FROM 字句和更新/删除对象不能使用同一张表。
mysql> DELETE FROM tab1 WHERE col1 = ( SELECT MAX( col1 ) FROM tab1 );
ERROR 1093 (HY000): You can't specify target table 'tab1' for update in FROM clause

针对“同一张表”这个限制,撇开效率不谈,多数情况下都可以通过临时表来变通解决,像这样
DELETE FROM tab1
WHERE col1 = (
SELECT MAX( col1 )
FROM (
SELECT * FROM tab1
) AS t
);

参考链接:
MySQL 5.0 Reference Manual - Subquery Errors

Tuesday, March 06, 2007

Cygwin 环境设置

一、使用和当前 Windows 登录用户不同的用户名

打开 /etc/passwd,找到标示当前 Windows 登录用户,即“自己”,的那行,修改用户名,即第一项。

二、自定义 HOME 环境

打开 /etc/passwd,找到标示“自己”的那行,修改 HOME 目录。
也可以通过设置名为 HOME 的 Windows 环境变量来实现,此设定优先级更高。但主要缺点是 ssh 命令只认 /etc/passwd,经常使用 ssh 的话还是得绕回来修改 /etc/passwd。

三、自定义 HOME 文件夹

1. 使用 ln 命令创建软链接
2. 使用 mount 命令或者直接修改注册表,举个例子
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Cygnus Solutions\Cygwin\mounts v2\/home]
"flags"=dword:0000000a
"native"="D:\\home"

参考链接:
Cygwin FAQ No.13 My Windows logon name has a space in it, will this cause problems?
Cygwin FAQ No.14 My HOME environment variable is not what I want.
Cygwin User's Guide - The Cygwin Mount Table

Friday, March 02, 2007

Unknown HZ value!

Unknown HZ value! (0) Assume 100.

在 uptime 超过若干时间之后(我的遭遇是 248 天),使用 uptime, w, top 时会出现上述错误信息。直接原因是 procps 中的 libproc 在计算 HZ 不能时(其实我没有明白什么意思),打印出了一个无用警告。而这个据说是因为某个内核级 bug,也就是说取决于你用的 OS。

我的环境:
islue@localhost:~$ cat /etc/issue
Debian GNU/\s 3.0 \n \l

islue@localhost:~$ uname -a
Linux localhost 2.4.18 #1 SMP Fri Mar 11 18:50:01 JST 2005 i686 unknown

解决方案有,重启服务器,或者修改 proc/sysinfo.c 重新编译安装。
基本是无害的,随它去也无妨。

参考网址:
http://lists.debian.org/

Tuesday, February 13, 2007

靠,又被迫降级!

软件:FlashGet
版本:1.81 -> 1.73

新版本默认行为太暴力了,线程数多到泛滥,而且不容易设置。我原来的设置为 3 线程,最小分段尺寸 1MB。出于使用习惯,选择了降级,没有转投他处。

不在沉默中爆发(FlashGet),就在沉默中死亡(NetAnts),这年头,搞什么啊?

为什么说“又”?看这里

Sunday, February 04, 2007

在 DreamHost 虚拟主机上部署 Catalyst 应用

在虚拟主机上部署 Catalyst 应用的前提是用户可以自己安装 CPAN 模块,DreamHost 提供了 shell 环境,所以就完全没问题了。

如何在非 root 环境下安装 CPAN 模块,请参考 Catalyst Wiki 中的相关文章

好,在安装完 Catalyst 之后呢,那么就万事具备,只欠东风了。
虚拟主机,Catalyst 自带的 httpd 肯定是不能用的;没有 apache 的控制权限,mod_perl 也上不了;剩下还有 cgi 和 fastcgi 方式,还用想吗?当然用 fastcgi 咯~

下面就以 fastcgi 方式为例,分享一下我的一些经验。

一、部署环境
[hostname ~]$ ls -1
MyApp/ # 项目名
example.com/ # 域名

二、apache 环境
[hostname ~]$ ls -a1 example.com
.htaccess
script -> /home/islue/MyApp/script/
static -> /home/islue/MyApp/root/static/

软链接的意义很好理解,不罗嗦了,然后来看一下 .htaccess 文件。
[hostname ~]$ cat example.com/.htaccess
AddHandler fastcgi-script .pl

RewriteEngine On

# 避免屏蔽 DreamHost 提供的 Site Statistics 功能
RewriteCond %{REQUEST_URI} ^/stats/(.*)$ [OR]
RewriteCond %{REQUEST_URI} ^/failed_auth.html$
RewriteRule ^.*$ - [L]

# fastcgi 工作模式
RewriteCond %{REQUEST_URI} !^/script/myapp_fastcgi.pl
RewriteRule ^(.*)$ script/myapp_fastcgi.pl/$1 [PT,L]

很容易理解吧,也不罗嗦了。

三、定制 myapp_fastcgi.pl
[hostname ~]$ cat MyApp/script/myapp_fastcgi.pl
...

BEGIN {
$ENV{CATALYST_ENGINE} ||= 'FastCGI';
unshift @INC, qw(
/home/islue/local/lib/perl/5.8
/home/islue/local/lib/perl/5.8.4
/home/islue/local/lib/perl5
/home/islue/local/lib/perl5/i386-linux-thread-multi
/home/islue/local/share/perl/5.8
/home/islue/local/share/perl/5.8.4
);
$SIG{'TERM'} = 'IGNORE';
}

...

我原以为,修改过了 .bashrc 之后,应该不需要再用 use lib 了,但是数次实践下来,不在 myapp_fastcgi.pl 里声明用户的 lib 还真不行。要是哪位知道这里的道道,记得告诉我啊。

至于为什么要 IGNORE TERM,故事是这样的,很久很久以前,世界和平,大家都过着男耕女织的生活,不用在意什么,MyApp 也能跑得欢快。

突然有一天,电闪雷鸣,大雨瓢泼,MyApp 就再也跑不起来了,访问站点能看到的只有 Internal Server (500) 错误,翻开史册,书上如是说:
[Mon Jan 29 06:13:13 2007] [error] [client 210.151.136.180] FastCGI: comm with (dynamic) server "/home/islue/example.com/script/myapp_fastcgi.pl" aborted: (first read) idle timeout (60 sec)
[Mon Jan 29 06:13:13 2007] [error] [client 210.151.136.180] FastCGI: incomplete headers (0 bytes) received from server "/home/islue/example.com/script/myapp_fastcgi.pl"

在无数次 ps 之后,总算看到 myapp_fastcgi.pl 的身影一闪而过。是他杀,我惊醒!真相只有一个,下面公布凶手的自白书。
Dreamhost regularly kills off sleeping processes with a proc watch script. This will kill your dispatch.fcgi processes, leading to Error 500s from time to time. You'll need to make dispatch.fcgi ignore all TERM requests by changing how it responds to them.

说笑啦,上面这段是 DreamHost 客服给我的回复。IGNORE TERM 之后,世界又太平了。

四、应用启动方式

启动应用的方法就是访问站点。如果需要重启,杀掉所有 myapp_fastcgi.pl 即可,如果 IGNORE TERM 了的话,需要 kill -9。

Saturday, February 03, 2007

公告:Save You More(暂名)上线

一个提供横向实时比较各网上书店指定图书价格服务的站点。
http://sym.noticpan.org/

核心服务已经成形,拿出来晒晒先。

Saturday, January 20, 2007

ssh-agent 简介

ssh-agent 是一个保管私钥的程序。然后的故事呢是这样的,ssh-agent 在一个 X-session 或者一个 login session 的一开始启动,所有其他窗口以及程序都会作为 ssh-agent 的客户端启动。
以上译自 ssh-agent 的在线手册(man)。

按我的理解来说,ssh-agent 就是一个管理私钥的代理,受管理的私钥通过 ssh-add 来添加,所有 ssh-agent 的客户端都可以共享使用这些私钥。

用处一,不用重复输入密码。

用 ssh-add 添加私钥时,如果私钥有密码的话,照例会被要求输入一次密码,在这之后 ssh-agent 可直接使用该私钥,无需再次密码认证。

用处二,不用到处部署私钥。

假设我有私钥分别可以登录同一内网的主机 A 和主机 B,出于一些原因,不能直接登录 B。我可以通过在 A 上部署私钥或者设置 PortForwarding 来登录 B,也可以转发认证代理连接在 A 上面使用 ssh-agent 管理的私钥登录 B。

以 cygwin 环境为例,描述一下操作流程

islue@localhost $ ssh-agent bash --login -i

通过 ssh-agent 启动 bash,或者说把 bash 挂到 ssh-agent 下面

islue@localhost $ ssh-add

添加私钥,如果跳过第一步直接添加私钥,也就是说当前的 shell 并没有挂在 ssh-agent 下面,则会收到这样的错误信息

Could not open a connection to your authentication agent.

接下来登录主机 A

islue@localhost $ ssh -A HOST_A

-A 的作用就是启用转发认证代理连接

islue@HOST_A $ ssh HOST_B
islue@HOST_B $

从主机 A 上顺利登录主机 B,完毕。

更多内容请参阅 ssh 和 ssh-agent 的在线手册。

用好 MySQL 字符集

我们都知道,MySQL 支持 30 多种字符集,其中包括了我们常用的 gb2312、gbk 和 uft8 等字符集。

在很多简单应用场合下,字符集设置是可有可无的。把后台存储的视为裸数据(raw data),存入的数据可以被原封不动地取出,对于前端的处理及应用,通常是不会有问题的。

当然,不设置正确的字符集,在实际应用中也有诸多不便之处。假设情况是这样的:

前端应用:GB2312
后端存储:latin1

那么大概会得到这样的结果:

字符终端(GB2312环境):正确
phpMyAdmin:乱码
MySQL Query Browser:乱码

如果你是个完全无视 GUI 管理工具的开发者,那么无视字符集设置就是了。

设置合适的字符集,我觉得主要是可以获得 GUI 管理工具强大支持。除此以外,其实用处并不是很多,以我的使用经验为例,只是用来做文本排序。

那么以 Perl 为例,说说我的经验,怎样使用合适的字符集,情况如下

前端应用:GB2312
后端存储:utf8

设置字符集可以分为四个环节:
客户端 <-> 前端 <-> 连接 <-> 后端

客户端,这里指浏览器。当前输出内容编码为 GB2312,所以应该在 HTML 头部加入如下语句:

<meta http-equiv="Content-Type" content="text/html; charset=GB2312">

通常,即使没有上述语句,多数浏览器也能“猜”出正确编码,这是题外话,不深入了。

前端,这里指数据处理程序。因为后端存储是 utf8,所以在这里需要把数据从 GB2312 转为 UTF8,就绪。

use Encode;
Encode::from_to( $data, 'euc-cn', 'utf8' );

连接,这里指由程序创建的数据库连接。通常我们这样连接数据库:

use DBI;
my $dbh = DBI->connect('dbi:mysql:database=test;host=localhost', $user, $password);

为了加入字符集信息,需要在连接后执行下面的命令:

$dbh->do('SET NAMES utf8');

声明了输入输出使用的都是 utf8 字符集。要保证建立连接后,首先执行字符集声明。

这在某些自动重连的情况下可能会失效,我推荐用读取配置文件的方式声明连接字符集。

首先,在配置文件 /etc/my.cnf 中加入字符集设置

[client]
default-character-set=utf8

然后,连接语句相应地改为

my $dbh = DBI->connect('dbi:mysql:database=test;host=localhost;mysql_read_default_file=/etc/my.cnf', $user, $password);

或者
my $dbh = DBI->connect('dbi:mysql:database=test;host=localhost;mysql_read_default_file=/etc/my.cnf;mysql_read_default_group=client', $user, $password);

这样保证了创建连接前就能读取到字符集设置。

后端,这里指 MySQL 数据库。在建表或数据库时,声明字符集

CREATE TABLE (
...
) CHARSET utf8;

以上就是各环节字符集的设置,一些描述乃属经验记忆,难免会有错漏,还望海涵。更多请参阅 MySQL 参考手册相关章节