찾다
데이터 베이스MySQL 튜토리얼MySQL中文乱码问题的解决第1/2页

MySQL中文乱码问题的解决

转自:http://www.phpchina.cn/viewarticle.php?id=1584


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

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 程序在创建数据库和数据表时并没有使用那么复杂的配置,它们用的是默认的配置,那么,默认的配置从何而来呢?

简单的总结一下,如果什么地方都不修改,那么所有的数据库的所有表的所有栏位的都用 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',没错,这是解决方案,但本文的目的是说明,这为什么是解决方案。

要保证结果正确,必须保证数据表采用的格式是正确的,也就是说,至少能够存放所有的汉字,那么我们只有两种选择,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 同仁给出了一些建议:

首先,测试服务器是否 >= 4.1,编译时是否加入了 UTF-8 支持;是则继续
然后测试数据库以什么格式存储 ($dbEncoding);
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]
// check if utf8 support was compiled in
$result = mysql_query("SHOW CHARACTER SET like 'utf8'",
$this->dbh);
if (mysql_num_rows($result)
if ($charset == 'utf-8' || $charset == 'UTF-8')
$charset = 'utf8';
@mysql_query("SET NAMES '$charset'", $this->dbh);
}

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

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

http://www.phpchina.cn/viewarticle.php?id=1584

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
MySQL에 저장된 절차는 무엇입니까?MySQL에 저장된 절차는 무엇입니까?May 01, 2025 am 12:27 AM

저장된 절차는 성능을 향상시키고 복잡한 작업을 단순화하기 위해 MySQL에서 사전 컴파일 된 SQL 문입니다. 1. 성능 향상 : 첫 번째 편집 후 후속 통화를 다시 컴파일 할 필요가 없습니다. 2. 보안 향상 : 권한 제어를 통해 데이터 테이블 액세스를 제한합니다. 3. 복잡한 작업 단순화 : 여러 SQL 문을 결합하여 응용 프로그램 계층 로직을 단순화합니다.

쿼리 캐싱은 MySQL에서 어떻게 작동합니까?쿼리 캐싱은 MySQL에서 어떻게 작동합니까?May 01, 2025 am 12:26 AM

MySQL 쿼리 캐시의 작동 원리는 선택 쿼리 결과를 저장하는 것이며 동일한 쿼리가 다시 실행되면 캐시 된 결과가 직접 반환됩니다. 1) 쿼리 캐시는 데이터베이스 읽기 성능을 향상시키고 해시 값을 통해 캐시 된 결과를 찾습니다. 2) MySQL 구성 파일에서 간단한 구성, query_cache_type 및 query_cache_size를 설정합니다. 3) SQL_NO_CACHE 키워드를 사용하여 특정 쿼리의 캐시를 비활성화하십시오. 4) 고주파 업데이트 환경에서 쿼리 캐시는 성능 병목 현상을 유발할 수 있으며 매개 변수의 모니터링 및 조정을 통해 사용하기 위해 최적화해야합니다.

다른 관계형 데이터베이스를 통해 MySQL을 사용하면 어떤 장점이 있습니까?다른 관계형 데이터베이스를 통해 MySQL을 사용하면 어떤 장점이 있습니까?May 01, 2025 am 12:18 AM

MySQL이 다양한 프로젝트에서 널리 사용되는 이유에는 다음이 포함됩니다. 1. 고성능 및 확장 성, 여러 스토리지 엔진을 지원합니다. 2. 사용 및 유지 관리, 간단한 구성 및 풍부한 도구; 3. 많은 지역 사회 및 타사 도구 지원을 유치하는 풍부한 생태계; 4. 여러 운영 체제에 적합한 크로스 플랫폼 지원.

MySQL에서 데이터베이스 업그레이드를 어떻게 처리합니까?MySQL에서 데이터베이스 업그레이드를 어떻게 처리합니까?Apr 30, 2025 am 12:28 AM

MySQL 데이터베이스를 업그레이드하는 단계에는 다음이 포함됩니다. 1. 데이터베이스 백업, 2. 현재 MySQL 서비스 중지, 3. 새 버전의 MySQL 설치, 4. 새 버전의 MySQL 서비스 시작, 5. 데이터베이스 복구. 업그레이드 프로세스 중에 호환성 문제가 필요하며 Perconatoolkit과 같은 고급 도구를 테스트 및 최적화에 사용할 수 있습니다.

MySQL에 사용할 수있는 다른 백업 전략은 무엇입니까?MySQL에 사용할 수있는 다른 백업 전략은 무엇입니까?Apr 30, 2025 am 12:28 AM

MySQL 백업 정책에는 논리 백업, 물리적 백업, 증분 백업, 복제 기반 백업 및 클라우드 백업이 포함됩니다. 1. 논리 백업은 MySQLDump를 사용하여 데이터베이스 구조 및 데이터를 내보내며 소규모 데이터베이스 및 버전 마이그레이션에 적합합니다. 2. 물리적 백업은 데이터 파일을 복사하여 빠르고 포괄적이지만 데이터베이스 일관성이 필요합니다. 3. 증분 백업은 이진 로깅을 사용하여 변경 사항을 기록합니다. 이는 큰 데이터베이스에 적합합니다. 4. 복제 기반 백업은 서버에서 백업하여 생산 시스템에 미치는 영향을 줄입니다. 5. AmazonRDS와 같은 클라우드 백업은 자동화 솔루션을 제공하지만 비용과 제어를 고려해야합니다. 정책을 선택할 때 데이터베이스 크기, 가동 중지 시간 허용 오차, 복구 시간 및 복구 지점 목표를 고려해야합니다.

MySQL 클러스터링이란 무엇입니까?MySQL 클러스터링이란 무엇입니까?Apr 30, 2025 am 12:28 AM

mysqlclusteringenhancesdatabaserobustness andscalabilitydaturedingdataacrossmultiplenodes.itusesthendbenginefordatareplicationandfaulttolerance, highavailability를 보장합니다

MySQL의 성능을 위해 데이터베이스 스키마 설계를 어떻게 최적화합니까?MySQL의 성능을 위해 데이터베이스 스키마 설계를 어떻게 최적화합니까?Apr 30, 2025 am 12:27 AM

MySQL에서 데이터베이스 스키마 설계 최적화는 다음 단계를 통해 성능을 향상시킬 수 있습니다. 1. 인덱스 최적화 : 공통 쿼리 열에서 인덱스 생성, 쿼리의 오버 헤드 균형 및 업데이트 삽입. 2. 표 구조 최적화 : 정규화 또는 정상화를 통한 데이터 중복성을 줄이고 액세스 효율을 향상시킵니다. 3. 데이터 유형 선택 : 스토리지 공간을 줄이기 위해 Varchar 대신 Int와 같은 적절한 데이터 유형을 사용하십시오. 4. 분할 및 하위 테이블 : 대량 데이터 볼륨의 경우 파티션 및 하위 테이블을 사용하여 데이터를 분산시켜 쿼리 및 유지 보수 효율성을 향상시킵니다.

MySQL 성능을 어떻게 최적화 할 수 있습니까?MySQL 성능을 어떻게 최적화 할 수 있습니까?Apr 30, 2025 am 12:26 AM

tooptimizemysqlperformance, followthesesteps : 1) 구현 properIndexingToSpeedUpqueries, 2) useExplaintoAnalyzeanDoptimizeQueryPerformance, 3) AdvertServerConfigUrationSettingstingslikeInnodb_buffer_pool_sizeandmax_connections, 4) uspartOflEtOflEtOflestoI

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기