电脑技术学习

MySQL数据库乱码问题及解决方法

dn001

有人要问,为什么都要改成utf8呢?改成GB2312不行吗?

解释如下:

我也不想改成utf8,只是phpmyadmin2.6在mysql4.1的时候只会用utf8,连其他页面的charset也都是utf8,改成gb2312一定会乱码,我们只能凑phpmyadmin了。

只有在mysql3.23的时候,phpmyadmin才会多一个gb2312的页面charset,这时候是正常的。

3.将以前的mysql3的库文件导入mysql4.1的库

有两种情况:

一是从phpmyadmin上导入,这时候你要注意的是在选择库文件的页面左下脚有个“文件的字符集:,默认是utf8,要改成gb2312,否则导进去乱码;

二是在linux下导入,这时候你需要先在库文件的头部加一行:

SET NAMES 'gb2312'; 注意最后也是;号,别漏了。

然后执行mysql -u用户名 -p密码 xxx.sql > 库名

导入完成以后再用phpmyadmin打开看,里面的中文字就是正确的。

4.从mysql4.1里导出库文件

一.用phpmyadmin导出

导出倒是问题不大,如果phpmyadmin的浏览页面里显示的中文是正常的,那么导出肯定也是正常的

二.在linux上导出

如果用mysqldump导出出现了乱码也没有关系,可以运行iconv来转换一下

iconv -c -f UTF-8 -t GB2312 库文件名 > 新的gb2312的库文件名

综上所述,你要注意:

1。尽量在需要导入的库文件的开头加入SET NAMES 'gb2312';告诉mysql你要导入的是一个gb2312的文件;

2。可能你需要这个:

SET NAMES 'utf8';

在登陆到mysql后用,把character的一些默认参数改到utf8上,有时可以减少一些困扰,不过也不是必须的。

在mysql上使用:

SHOW VARIABLES LIKE 'character_set_%';

用来查看当前的状态。

3.如果出现乱码也不要怕,一是你要注意留存原有的备份,二是用iconv来进行转化。

在正常使用之前注意做导入导出的测试,确保万无一失。

下面再说明一下,网上很多朋友说Mysql4.1的只能升,不能降. 这是不正确的. 同样使用mysqldump 导出数据库时加一个 --compatible 的参数.也千万不能忘了--default-character-set=这个设定字符集的参数.

示范: mysqldump -uroot -pPassword --compatible=mysql40 --default-character-set=gb2312 discuz>d:discuz.sql

ok 这样导出来的文件,就可以在Mysql4.0.X和Mysql.3.2.X版本中使用了.

Linux下 Mysql 5 中文乱码的彻底解决及应用的一些注意事项

一. 自从mysql4.1开始,mysql对中文的支持问题是比较烦人的,怎么弄都乱码,如今mysql5 据说是mysql的新纪元,但从官方下载安装的mysql5仍存在乱码现象,这里就是针对此现象做的讨论:

建议最好是下载mysql的源码进行编译,这是由于官方编译的mysql的默认支持编码是latin字符集,所以中文字符在数据库里查看的时候看到的是乱码。编译MySQL时使用withcharset=编码,可以方便地把mysql编译成该编码形式,这样MySQL就会直接支持中文查找和排序,-- with-extra-charsets参数指定其它可用的字符集。

下载并解压源码包,打开INSTALL-SOURCE,这里介绍了linux下详细的安装方法,所以大家所要注意的只是下面的configure指令:

groupadd mysql

useradd -g mysql mysql

./configure --with-charset=gbk --with-collation=gbk_chinese_ci --with-extra-charsets=gb2312,big5,utf8,binary,ascii --prefix=/usr/local/mysql

make

make install

cp support-files/my-medium.cnf /etc/my.cnf

cd /usr/local/mysql

bin/mysql_install_db --user=mysql

chown -R root .

chown -R mysql var

chgrp -R mysql .

bin/mysqld_safe --user=mysql &

bin/mysql

mysql> show variables;

你可以看到全局的字符集参数全是gbk,gb2312字集应该包含在gbk里,所以不讨论。

进行和平常mysql4.0一样的php操作,你会发现仍然出现中文乱码现象。

这里要说明的是:从mysql 4.1开始,必需在mysql数据库连接后对应用的字符集做出说明,否则非英文字母的文字存取都无法解释变成?号。

解决方法就是要适应新版mysql的要求:

在连接mysql数据库后执行set character set 字符集,该指令在最新版的mysql 5如果默认字集和存储相符可以免设:

set character set gbk;

在php里应该是这么写:mysql_query("set character set gbk");

指令大小写均可

phpwind和discuz是广泛应用的国产php论坛,大量的朋友在应用它,了解了以上步骤,你也可以对论坛源码进行很小的修改,安全地把数据库升级到mysql5:

找到include/db_mysql.php,修改function connect(...){.....}

在选择数据库mysql_select_db($dbname);后面加上一句mysql_query('set character set gbk');存盘。

二. 文件的导入导出:如果存入非gbk字符,这时候你需要先在导入文件的头部加一行: SET NAMES '字符集'; 并注意最后也是;号,别漏了。

文件导入和导出执行

mysql -u用户名 -p密码 数据库名

mysqldump -u用户名 -p密码 数据库名>data.sql

如果用mysqldump导出数据出现了乱码也没有关系,可以运行iconv来转换一下:

iconv -c -f utf8 -t gbk 库文件名>新的gbk的库文件名

综上所述,你要注意:

1。尽量在需要导入的库文件的开头加入set names 'gbk';告诉mysql你要导入的是一个gbk的文件;

2。在mysql上使用 show variables;或show variables like 'character_set_%'; 用来查看当前的字集状态。

3。如果出现乱码也不要怕,其一是你要注意留存原有的备份,其二是用iconv来进行转化。

#PHP连接问题:

由于MySQL 4.1版本开始密码的hash算法改变,所以连接数据库时可能会出现Client does not support authentication protocol问题

此问题在mysql 5中不存在,mysql 5不需要以下的设置。

可以通过一下两种方法解决数据库用户密码不符问题:

其一: 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'

PHP输出的其它乱码问题:

如果将mysql编译为默认编码gbk的话,又会造成非gbk数据直接导入显示为乱码,比如部份utf8存储的字符,如果你大部份数据是utf8字集,当然得把mysql编译为默认编码utf8才合适。

Mysql 4.1.x出来以后,引入了collation (校勘)的概念,终于有办法让mysql同时支持多种编码的数据库了,所以PHP要用以下SQL语句来创建utf-8编码的数据库:

Create DATABASE `mytest` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

但是仅仅是将数据库的校勘改为utf-8是不够的,还必须在连接了mysql数据库之后用这个语句来设置:set names 'utf8';才能在php程序里得到正确编码的字符,并将其显示在web页面里。

mysql_query("set names 'utf8'",$connection);

下面再说明一下,网上很多朋友说Mysql4.1的只能升,不能降. 这是不正确的. 同样使用mysqldump 导出数据库时加一个 --compatible 的参数.也千万不能忘了--default-character-set=这个设定字符集的参数。

示范: mysqldump -uroot -pPassword --compatible=mysql40 --default-character-set=gb2312 discuz>d:discuz.sql

ok 这样导出来的文件,就可以在Mysql4.0.X和Mysql.3.2.X版本中使用了.

下面要写的是一篇非常无聊的东西,充斥了大量各式各样的编码、转换、客户端、服务器端、连接……呃,我自己都不愿意去看它,但想一想,写下来还是有点意义的,原因有四:

MySQL 4.1 对多语言的支持有了很大变化 (这导致了问题的出现);

尽管大部分的地方 (包括个人使用和主机提供商),MySQL 3 仍然占主导地位;但 MySQL 4.1 是 MySQL 官方推荐的数据库,已经有主机提供商开始提供并将会越来越多;

许多 PHP 程序以 MySQL 作为默认的数据库管理软件,但它们一般不区分 MySQL 4.1 与 4.1 以下版本的区别,笼统地称“MySQL 3.xx.xx 以上版本就满足安装需求了;

因为 latin1 在许多地方 (下边会详细描述具体是哪些地方) 作为默认的字符集,成功的蒙蔽了许多 PHP 程序的开发者和用户,掩盖了在中文等语言环境下会出现的问题;

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

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

编译 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 存储。

当一个 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_set 为 utf8。于是问题出现了:

WordPress 按照默认情况安装,所以所有的表都用 UTF-8 存储数据;

WordPress 默认采用的浏览字符集是 UTF-8 (Options->Reading 中设置),因此所有 WP 页面的 meta 中会说明 charset 是 utf-8;

所以浏览器会以 utf-8 方式显示所有的 WP 页面;这样一来 Write 的所有 Post,和 Comment 都会以 UTF-8 格式从浏览器发送给 Apache,再由 Apache 交给 PHP;

所以 WP 从所有的表单中得到的数据都是 utf-8 编码的;WP 不加转换的直接把这些数据发送给 MySQL;

MySQL 默认设置的 character_set_client 和 character_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',没错,这是解决方案,但本文的目的是说明,这为什么是解决方案。