<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[[实践OK]mysql连接字符串乱码之mysql连接通道中的字符集和校验规则---来源：淘宝团队，[转]深入Mysql字符集设置，比阿里巴巴技术团队的更形像 。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Wed, 12 Nov 2008 08:13:01 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	https://www.cnblogs.com/wcwen1990/p/6917109.html<br/><textarea name="code" class="php" rows="15" cols="100">
早期项目中存在一些前端输入（Web/ 接口REST参数）均以UTF8格式输入，而通过PHP在Mysql里set names latin1（character_set_client、character_set_connection、character_set_results均是Latin1）写入数据和显示UTF8数据。
经实践发现：其存入的数据在入库时是UTF8格式的占用了过多空间且对数据表字段长度大小和输入长度并不相等，尽管UTF8占空间，但现在磁盘很便宜，加上国际化GBK的编码逐步很少被采用：
一）如果character_set_client和character_set_results 一般情况下要一致，因为一个表示客户端发送的数据格式，另一个表示客户端接受的数据格式为了避免造成数据丢失，需让 character_set_connection的字符编码大于 character_set_client的字符编码.(MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection；)，如果由 character_set_connection的字符编码小于character_set_client的编码，就会出现信息丢失，及时数据库的存储编码是UTF8（character_set_database=utf8 ），已经丢失，也就会出现查询出来时出现问号情况，ASCII码十六进制A63 3F ?。
二）对于Mysql旧版本的默认latin情况，里面尽管传入了UTF8，也能正常的显示和插入（character_set_client&#124; latin1(中文你utf8是3个字节，也就是来自前端网页的UTF8的你字，而latin1是按照单个字节解析的，虽然进行了转换，但不会导致二进制内容的变化，但实际上mysqlServer根据Client配置（character_set_client）认为我输入了3个latin1字符；还好是UTF8前端，如果客户端是GBK，直接收到一个3字节的UTF8的编码会为是1个gbk字符和一个西欧字符) -&gt; character_set_connection &#124; latin1-&gt;），但本质上是以UTF8的方式存入磁盘时是6个字符（ character_set_database&nbsp;&nbsp; &#124; utf8 ），而出来时又被Latin1转回为3个字符后被UTF8看成1个汉字也就是你字，而如果这个Lation1不这样6字节变3字节，也就是（character_set_results 的值由latin1变UTF8后）UTF8后，则6个字符以UTF8直接穿透到显示层了，会在SecureCRT（设置UTF8输出显示）看到UTF8是6个字符认为是两个汉字，也就成了我们认为的乱码！！！
结论：
一）统一采用UTF8的编码，包括：
1）PHP文件用UTF8且无BOM头输出。
2）REST参数浏览器输出Header和接口参数也传UTF8。
3）Mysql尽可能采用严格模式，一定程序上防止一些编码问题和长度问题（https://blog.csdn.net/fdipzone/article/details/50616247）。
</textarea><br/><br/><br/>最后谈严格模式：Mysql尽可能采用严格模式，一定程序上防止一些编码问题和长度问题（https://blog.csdn.net/fdipzone/article/details/50616247）。<br/>set global sql_mode=&#039;&#039;; #这种方法修改，当前会话失效后，这个修改就没意义了，建议修改配置文件的方式修改，修改后，不需要重启mysql服务，立即生效，检查是否生效，执行sql ，select @@sql_mode;<br/><br/><br/>show create table t;<br/>CREATE TABLE `t` (<br/>&nbsp;&nbsp;`c` varchar(255) DEFAULT NULL<br/>) ENGINE=InnoDB DEFAULT CHARSET=utf8 <br/><br/>show variables like &quot;%char%&quot;;<br/>set names gbk;<br/><br/>mysql&gt; select c ,hex(c) from t;<br/>+------+--------+<br/>&#124; c&nbsp;&nbsp;&nbsp;&nbsp;&#124; hex(c) &#124;<br/>+------+--------+<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>&#124; 东&nbsp;&nbsp;&nbsp;&nbsp; &#124; E4B89C &#124;<br/>+------+--------+<br/>8 rows in set (0.00 sec)<br/><br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php
&nbsp;&nbsp;var_dump(bin2hex(&quot;东&quot;));
&nbsp;&nbsp;$dsn = &quot;mysql:host=localhost;dbname=t&quot;;
&nbsp;&nbsp;$db = new PDO($dsn, &#039;root&#039;, &#039;******);
&nbsp;&nbsp;//$db-&gt;query(&#039;set names utf8&#039;);
&nbsp;&nbsp;$db-&gt;query(&#039;set names gbk&#039;);
&nbsp;&nbsp;//插入
&nbsp;&nbsp;try&#123;
&nbsp;&nbsp;&nbsp;&nbsp;$count = $db-&gt;exec(&quot;insert into t set c=&#039;东&#039;&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;var_dump($count);
&nbsp;&nbsp;&#125;catch(Exception $e)&#123;
&nbsp;&nbsp;&nbsp;&nbsp;print $e-&gt;getMessage();
&nbsp;&nbsp;&#125;
&nbsp;&nbsp;$rs = $db-&gt;query(&quot;select c,hex(c) as hex from t&quot;);
&nbsp;&nbsp;$result_arr = $rs-&gt;fetchAll();
&nbsp;&nbsp;foreach($result_arr as $key=&gt;$value)&#123;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;var_dump(bin2hex($value[0]));
&nbsp;&nbsp;
&nbsp;&nbsp;&#125;
&nbsp;&nbsp;print_r($result_arr);

?&gt;
</textarea><br/>php igbk.php <br/>string(4) &quot;b6ab&quot;<br/>int(1)<br/>string(4) &quot;b6ab&quot;<br/>string(4) &quot;b6ab&quot;<br/>Array<br/>(<br/>&nbsp;&nbsp;&nbsp;&nbsp;[0] =&gt; Array<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[c] =&gt; 东<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[0] =&gt; 东<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[hex] =&gt; E4B89C<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[1] =&gt; E4B89C<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br/><br/>说明三个问题：<br/>1)咱们在显示一个字符时，在SecureCRT里配置的character encoding只是显示，并不像Mysql的set names utf8里的三个参数（character_set_client character_set_connection character_set_results ）有由一个字符转向另一个字符集的功效，要想显示正常，则只需要对转出来的结果进行匹配即可显示正常。bin2hex(&quot;东&quot;)<br/><br/>三条：<br/>一）如果character_set_client和character_set_results 一般情况下要一致，因为一个表示客户端发送的数据格式，另一个表示客户端接受的数据格式为了避免造成数据丢失，需让 character_set_connection的字符编码 大于 character_set_client的字符编码.(MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection；)<br/>二）对于Mysql旧版本的默认latin情况，里面尽管传入了UTF8，也能正常的显示和插入（character_set_client&#124; latin1(中文你utf8是3个字节，也就是来自前端网页的UTF8的你字，而latin1是按照单个字节解析的，虽然进行了转换，但不会导致二进制内容的变化，但实际上mysql客户端认为我输入了3个latin1字符；还好是UTF8前端，如果客户端是GBK，直接收到一个3字节的UTF8的编码会为是1个gbk字符和一个西欧字符) -&gt; character_set_connection &#124; latin1-&gt;），但本质上是以UTF8的方式存入磁盘时是6个字符（ character_set_database&nbsp;&nbsp; &#124; utf8 ），而出来时又被Latin1转回为3个字符后被UTF8看成1个汉字也就是你字，而如果这个Lation1不这样6字节变3字节，也就是（character_set_results 的值由latin1变UTF8后）UTF8后，则6个字符以UTF8直接穿透到显示层了，会在SecureCRT（设置UTF8输出显示）看到UTF8是6个字符认为是两个汉字，也就成了我们认为的乱码！！！归结于：由于latin1 是一种非常宽松的编码方式，任何一种编码方式得到的文本，用 latin1 进行解码，都不会发生解码失败——当然，解码得到的结果自然也就是理所当然的“乱码”。<br/>实践如下,实践证明输出与character_set_results的编码有关，当set character_set_results是latin1时会转为输入时的UTF8的三个字符，而set character_set_results=&quot;utf8&quot;时，则它输出了存入Mysqld数据库的6个字节的UTF8直接输出，前端认为是两个字也就显示出来了ä¸œ，也就是把C3A4C2B8C593以SecureCRT配置的前端输出经过UTF8解码显示，就是乱码了。<br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php
&nbsp;&nbsp;echo &quot;utf8编码的东字节序：&quot;;
&nbsp;&nbsp;var_dump(bin2hex(&quot;东&quot;));
&nbsp;&nbsp;$dsn = &quot;mysql:host=localhost;dbname=t&quot;;
&nbsp;&nbsp;$db = new PDO($dsn, &#039;root&#039;, &#039;*****&#039;);
&nbsp;&nbsp;$db-&gt;query(&#039;set names latin1&#039;);
&nbsp;&nbsp;//$db-&gt;query(&#039;set names utf8&#039;);
&nbsp;&nbsp; //$db-&gt;query(&#039;set character_set_results=&quot;latin1&quot;&#039;);
&nbsp;&nbsp; //$db-&gt;query(&#039;set character_set_results=&quot;utf8&quot;&#039;);
&nbsp;&nbsp;//插入
&nbsp;&nbsp;try&#123;
&nbsp;&nbsp;&nbsp;&nbsp;$count = $db-&gt;exec(&quot;insert into t set c=&#039;东&#039;&quot;);
&nbsp;&nbsp;&#125;catch(Exception $e)&#123;
&nbsp;&nbsp;&nbsp;&nbsp;print $e-&gt;getMessage();
&nbsp;&nbsp;&#125;


&nbsp;&nbsp;$rs = $db-&gt;query(&quot;select c,hex(c) as hex from t&quot;);
&nbsp;&nbsp;$result_arr = $rs-&gt;fetchAll();
&nbsp;&nbsp;foreach($result_arr as $key=&gt;$value)&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;经过set names latin1后，主要是character_set_results=latin1的结果又还回来了，通过utf8显示刚好又显示回来了：&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;var_dump(bin2hex($value[0]));
&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;回头看数据库：select c ,hex(c) from t ;&#92;n&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;hex(c)=C3A4C2B8C593 ,也就DB文件里存的UTF8的C3A4C2B8C593经过latin1转换时又回到了e4b89c。（UTF8的六个字节，转成了Latin1的三个字节，这三个字节就是用户输入的UTF8的东字对应的e4b89c，让SecureCRT的配Character encoding后按UTF8一显示，也就成了东字。）&quot;;
&nbsp;&nbsp;
&nbsp;&nbsp;&#125;
&nbsp;&nbsp;print_r($result_arr);

?&gt;

</textarea><br/>这个在Mysql里可通过设置set names latin1;并且secureCRT的Character encoding设置为utf8就能正常显示，本质上：<br/>mysql&gt; select c ,hex(c) from t;<br/>+--------+--------------+<br/>&#124; c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; hex(c)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/>+--------+--------------+<br/>&#124; 东 （这里面的输出是将 hex(c)里的内容C3A4C2B8C593 经过character_set_results=latin1编码后显示，这个显示正常不正常是由SecureCRT的输出时是GB2312，还是UTF8，这儿输出本来是latin1，但是被SecureCRT按utf8显示后就是 三个字节的东字！！！ ）&nbsp;&nbsp; &#124; C3A4C2B8C593 &#124;<br/>+--------+--------------+<br/><br/><br/>核心内容：输出的那个Lation1变UTF8（set&nbsp;&nbsp;character_set_results=utf8）后，反而乱码的原因是如下：<br/><textarea name="code" class="php" rows="15" cols="100">
&lt;?php&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;echo &quot;utf8编码的东字节序：&quot;;
&nbsp;&nbsp;var_dump(bin2hex(&quot;东&quot;));
&nbsp;&nbsp;$dsn = &quot;mysql:host=localhost;dbname=t&quot;;
&nbsp;&nbsp;$db = new PDO($dsn, &#039;root&#039;, &#039;*****&#039;);
$db-&gt;query(&#039;set&nbsp;&nbsp;character_set_results=utf8&#039;);
$rs = $db-&gt;query(&quot;select c,hex(c) as hex from t&quot;);
&nbsp;&nbsp;$result_arr = $rs-&gt;fetchAll();
&nbsp;&nbsp;foreach($result_arr as $key=&gt;$value)&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;经过set names latin1后，主要是character_set_results=latin1的结果又还回来了，通过utf8显示刚好又显示&gt;回来了：&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var_dump(bin2hex($value[0]));&nbsp;&nbsp;&nbsp;&nbsp;#string(12) &quot;c3a4c2b8c593&quot; ，看这儿，和数据一样的，是6个字节，没有像Lation一样转成三个字节刚好碰Utf8转成正常的东字的三个字节。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;回头看数据库：select c ,hex(c) from t ;&#92;n&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;hex(c)=C3A4C2B8C593 ,也就DB文件里存的UTF8的C3A4C2B8C593经过latin1转换时又回到了e4b89c。（UTF8的六个
字节，转成了Latin1的三个字节，这三个字节就是用户输入的UTF8的东字对应的e4b89c，让SecureCRT的配Character encoding后
按UTF8一显示，也就成了东字。）&quot;;

&nbsp;&nbsp;&#125;
</textarea><br/><br/><br/><textarea name="code" class="php" rows="15" cols="100">
思考一下2：为什么接收到的还是正确的utf8编码。
这是因为mysql服务器从将数据从“列”的编码（utf8）转换为latin1了，而列存储的数据并不是真正的utf8的中文“你”对应的&quot;0xe4 0xbd 0xa0&quot;，
而是后面抓包看到的“c3a4 c2bd c2a0”（6个字节），mysql服务器将utf8的c3a4转换为latin1的0xe4，c2bd转换为0xbd， c2a0转换为0xa0

思考一下3：为什么latin1显示了正确的utf8字符。
因为mysql客户端收到了mysql服务器转换后的&quot;0xe4 0xbd 0xa0&quot;，并把这个数据当做latin1的3个字符处理，然后抛给终端（我的是SecureCRT），
SecureCRT又把这三个latin1当做uft8处理，结果中文的“你”就显示出来了。

思考一下4：为什么连接的字符集和数据库的字符集设置成一样了，接收的数据反而不是utf8了。（请与latin1接收数据包对比）
字符集都一样的情况下，整个流程中不需要进行编码转换，直接将存储的“c3a4 c2bd c2a0”返回给客户端

思考一下5：为什么连接的字符集和数据库的字符集设置成一样了，显示反而乱码了。
参考思考4，客户端收到数据后也直接抛给终端显示，终端认为是两个utf8字符，并且找到了对应字符并显示，但我们看不懂，所以知道是乱码了，但这两个字符显示并没有错，如果真正找不到字符，可能会显示问号或者字符集规定的缺省符号。
</textarea><br/><br/><br/>From:https://edu.aliyun.com/a/15790 <br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;基础学习：关于前面提到的字节和位的一个关系的一个基础知识：位：&quot;位(bit)&quot;是电子计算机中最小的数据单位。每一位的状态只能是0或1。字节：8个二进制位构成1个&quot;字节(Byte)&quot;，它是存储空间的基本计量单位。1个字节可以储存1个英文字母或者半个汉字，换句话说，1个汉字占据2个字节的存储空间。即1个字节等于8个比特（1Byte=8bit）。八位二进制数最小为00000000，最大为11111111（0XFF，全是1，也就是两个F（十进制是255 ），C3的对应的十进制195，A4对应十进制是164）；通常1个字节可以存入一个ASCII码，“c3a4 c2bd c2a0”（6个字节） ，ASCII码用十六进制表示的，C3、a4等等，http://ascii.911cha.com/。<br/><br/>三）对于2的这种情况是在升级时可全部改为UTF8的编码的，是可以根据 mysqldump 时加上 --default-character-set=latin1,导出正常的Utf8编码的中文且显示正常的字符，但是加了这 个后，记得修改里面的set names latin1,为set names utf8, 而在程序代码里连接时也加上set names utf8,黄冶是default-character-set=utf8就能正常显示。（mysqldump -h 127.0.0.1 -P 3306 -u username --default-character-set=latin1 -p databasename &gt; dumpfile.txt）<br/>=========================================================================================<br/>[转]深入Mysql字符集设置，比阿里巴巴技术团队的更形像，有图：<br/>https://blog.csdn.net/haiross/article/details/51273630&nbsp;&nbsp;(请道因为UTF8插入时如果存的是比它小的，可能转时出现问题，而没法恢复，因为存入时就坏了：插入数据将经过utf8=&gt;utf8=&gt;latin1的字符集转换，若原始数据中含有/u0000~/u00ff范围以外的Unicode字符，会因为无法在latin1字符集中表示而被转换为“?”(0x3F)符号，以后查询时不管连接字符集设置如何都无法恢复其内容了。而以latin1入到Utf8后，会导致字符数变多，也就是存储空间会因为中文的UTF8是3个及以上（文章里提到的3个字节变成6个字节），占用了更多磁盘，插入操作的数据将经过latin1（character_set_client）=&gt;latin1（character_set_connection）=&gt;utf8（character_set_results）的字符集转换过程，这一过程中每个插入的汉字都会从原始的3个字节变成6个字节保存； )<br/>阿里云大学谈到了其乱码的本质一样的用你的UTF8作描述的文字版：https://edu.aliyun.com/a/15790<br/>MySQL的几个character_set变量的说明：https://www.linuxidc.com/Linux/2017-04/143263.htm<br/>MySQL抓包工具：MySQL Sniffer【转】：<br/>https://www.cnblogs.com/zhoujinyi/p/6497231.html<br/>利用tcpdump对mysql进行抓包操作技巧_Mysql：<br/>https://edu.aliyun.com/a/15214<br/><br/>特殊变量之character_set_system：character_set_system是个只读数据不能更改。也没多少改的意义，他是元数据的编码，相信不会有人用中文做数据库名和字段名之类的吧，这个字段和具体存储的数据无关。<br/>mysql&gt; show variables like &#039;%char%&#039;;<br/>+--------------------------+-----------------------------------------------------+<br/>&#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; 说明&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>+--------------------------+-----------------------------------------------------+<br/>&#124; character_set_client&nbsp;&nbsp; &#124; 客户端字符集&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_connection &#124; 当前连接字符集&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/>&#124; character_set_database&nbsp;&nbsp;&#124; 数据库字符集&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_filesystem &#124; 文件系统字符集，不要修改，使用binary即可 &#124;<br/>&#124; character_set_results&nbsp;&nbsp;&#124; 返回结果集字符集&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/>&#124; character_set_server&nbsp;&nbsp; &#124; 服务器默认字符集，当数据库、表、列没有设置时，如Show create table里的中文表字段批注&nbsp;&nbsp; &#124;<br/>&#124;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;&nbsp;&nbsp; 默认使用此字符集&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_system&nbsp;&nbsp; &#124; 固定为utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>+--------------------------+-----------------------------------------------------+<br/>&#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/>+--------------------------+-----------------------------------------------------+<br/>&#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_connection &#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_database&nbsp;&nbsp; &#124; utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_filesystem &#124; binary&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>&#124; character_set_server&nbsp;&nbsp;&nbsp;&nbsp; &#124; utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/><br/><br/>------------------------而latin1是按照单个字节解析的，虽然进行了转换，但不会导致二进制内容的变化！-------------------------------------------<br/>这里首先需要解释的是，我想应该就是连接通道的含义了。那什么是连接通道呢？<br/>背景：这种理解其实是早期程序员以PHP为例通常觉得数据存为简体中文比教少占空间，utf8中文占用大于等于三，由unicode字符集决定的，其实现在看来用utf8都不是啥大事，磁盘很便宜。再就是早期mysql默认就是拉丁字符集合。<br/>导致出现想转为utf8的，首先导出时候得指定字符集为拉丁，假如不加指定以拉丁导出其默认是utf8，往往那个建表结构的comment注释是utf8，出现评论正常，数据库内容中文乱码，用file xxx.sql检查的确是一个utf8的sql文件。<br/>如果MySQL服务器上的字符集是 latin1 的，mysqldump 出来的中文都是乱码！一个简单的办法是加上默认字符集选项，如：<br/>mysqldump -h 127.0.0.1 -P 3306 -u username --default-character-set=latin1 -p databasename &gt; dumpfile.txt&nbsp;&nbsp;＃character_set_connection、character_set_client、character_set_results三个字符集一次性被设置为latin1了。character_set_client、character_set_connection、character_set_results这3个参数值是由客户端每次连接进来设置的，和服务器端没关系。我们登陆进mysql后，执行 set names utf8; 实际就是同时修改上面的这3个参数值的。From:MySQL的几个character_set变量的说明，https://www.linuxidc.com/Linux/2017-04/143263.htm。<br/>有些网站在开发时，并没有正确指定编码，採用了预设的 latin1 ，并且将 big5 的中文资料直接储存。这种情况如果直接用 mysqldump 直接匯出，结果可能是一堆乱码，必须加上 --default-character-set=latin1 让匯出的资料保持正常的 big5 编码。<br/>mysqldump -u USER -p DBNAME --default-character-set=latin1 &gt; DBNAME.sql<br/>如果在匯出备份资料时，忘记加上参数，產生的乱码资料，用 iconv 可以救回部分(以下指令示范假设匯出档為错误编码的utf8)，参数 &quot;-c&quot; 表示忽略无法转码的字元。<br/>iconv -c -f utf8 -t latin1 DBNAME.sql &gt; DBNAME.big5.sql<br/>对于 big5 编码的匯出档，也可以用 iconv 转换成 utf8 格式。<br/>iconv -c -f big5 -t utf8 DBNAME.sql &gt; DBNAME.utf8.sql<br/>再进行编码格式设定的替换。<br/>perl -pi -e &#039;s/big5/utf8/g&#039; DBNAME.utf8.sql<br/>旧的Mysql默认选项：<br/>mysql&gt; show variables like &quot;%set%&quot;; <br/>+--------------------------+----------------------------+<br/>&#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#124;<br/>+--------------------------+----------------------------+<br/>&#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/>&#124; character_set_connection &#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/>&#124; character_set_database&nbsp;&nbsp; &#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/>&#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#124;<br/><br/><br/>从源码编译mysql的时候，通过编译参数进行设置<br/>编译的时候如果指定了-DDEFAULT_CHARSET和-DDEFAULT_COLLATION，那么：<br/>创建database、table时，会将其作为默认的字符集/字符序。<br/>client连接server时，会将其作为默认的字符集/字符序。（不用单独SET NAMES）<br/>shell&gt; cmake . -DDEFAULT_CHARSET=utf8 &#92;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -DDEFAULT_COLLATION=utf8_general_ci<br/>RPM打包：<br/>cmake . &#92;<br/>...<br/>-DDEFAULT_CHARSET=utf8 &#92;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>...<br/>make %&#123;?_smp_mflags&#125;<br/>=============================================================================<br/><br/>搞成utf8的编码，怎么办？分三步：<br/>1）mysqldump default-character-set=latin databse table &gt; /tmp/utf8format.sql #本质上是存在数据库里面的编码就是latin，指定以Latin字符编码给导出到一个utf8文件里面。<br/>2）在导出文件里面因为1加入了指定导出编码了，于是文件里面sql语句有一个set names latin，把这个改成set names utf8。此时用less看无论建表结构的评论注释还是表里内容均显示正常，中文不乱码。<br/>3）在导入数据的mysqlserver的my.cnf设置尽可能全utf8，如果不设置因为2在sql文件建立表和插入数据前加入设置编码了，直接mysql导入即可。保证全是utf8后，PHP的连接字符串编码也是UTF8即可。<br/><br/>所谓连接通道，就是客户端和服务器端保持连接的一个通道，它是逻辑上的一个概念。客户端通过连接通道发送sql语句到服务器端，服务端执行，将结果再通过连接通道返回至客户端。the connection is the pass when you connect to the server.<br/><br/>这个过程中，有几个临界点（逻辑上概念），是我们需要注意的，mysql也就在这几个临界点上做了文章。<br/><br/>1、当语句离开客户端的时候：<br/>从客户端出来的，包括sql语句本身（这里里面就包含字符串和关键字等了），以及character_set_client系统变量。为什么要包含这个变量呢？这个变量的作用说明2点，也是它的作用：一是表示该语句中的字符集是使用character_set_client指定的字符集编码的，二是通过此系统变量来告诉服务器所发送来的语句中的字符集编码。<br/>2、当服务器端接受到客户端的语句的时候：<br/>mysql会使用character_set_connection/collation_connection指定的字符集以及校验规则，将客户端的字符串，做一个从character_set_client到character_set_connection的转换。<br/>3、当服务器处理好结果以后，在把结果传给客户端前：<br/>mysql会先将结果转换成character_set_results指定的字符集，然后传回给客户端。<br/><br/><br/>当字符串在mysql服务器的时候，最终以什么格式存储到mysql数据库中，这个是受到具体的数据表级别、列级别字符集设置的控制了。<br/><br/>从上面的介绍中，我们就知道和连接通道相关几个参数了，他们分别是character_set_client/connection/results，可以如下查看：<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+-------------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+-------------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_database&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; .........................&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+-------------------+<br/>8 rows in set (0.00 sec)<br/><br/>mysql&gt; show variables like &#039;colla%&#039;;<br/>+----------------------+-------------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+----------------------+-------------------+<br/>&amp;#124; collation_connection &amp;#124; latin1_swedish_ci &amp;#124;<br/>&amp;#124; collation_database&nbsp;&nbsp; &amp;#124; gbk_bin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; collation_server&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; latin1_swedish_ci &amp;#124;<br/>+----------------------+-------------------+<br/>3 rows in set (0.00 sec)<br/>下面我们来做个实验，来证明一下这个结果：<br/>首先保证character_set_connection与character_set_results以及底层存储字符集的一致性，看看character_set_client的效果。<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+------------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+------------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_database&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; .........................&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+------------------+<br/>8 rows in set (0.00 sec)<br/><br/>mysql&gt; create table t (a varchar(10));&nbsp;&nbsp;--&nbsp;&nbsp;这里没有指定字符集，就默认使用了database的字符集gbk了<br/>Query OK, 0 rows affected (0.08 sec)<br/><br/>mysql&gt; insert into t values(&#039;中国&#039;);<br/>Query OK, 1 row affected (0.00 sec)<br/><br/>mysql&gt; select * from t;<br/>+-------+<br/>&amp;#124; a&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+-------+<br/>&amp;#124; ???ú &amp;#124;<br/>+-------+<br/>1 row in set (0.00 sec)<br/>由此可以看到由于latin1与gbk对汉字的编码方式不一样（或者说latin1根本就不能正确编码汉字），在这个collection过程中，从character_set_client到character_set_connection转换时，就把你输入的好好的汉字转换成乱码了。那么，如果让过程不发生转换呢？<br/><br/>mysql&gt; set character_set_client=gbk;<br/>Query OK, 0 rows affected (0.00 sec)<br/><br/>mysql&gt; insert into t values(&#039;人民&#039;);<br/>Query OK, 1 row affected (0.02 sec)<br/><br/>mysql&gt; select * from t;<br/>+-------+<br/>&amp;#124; a&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+-------+<br/>&amp;#124; ???ú &amp;#124;<br/>&amp;#124; 人民&nbsp;&nbsp;&amp;#124;<br/>+-------+<br/>2 rows in set (0.00 sec)<br/>可见，这里是能正确存储和显示的，很简单，因为任何转换都没有发生，当然就不会出现乱码了。<br/><br/>接着做实验，我们让character_set_connection发生变化：<br/><br/>mysql&gt; set character_set_connection=latin1;<br/>Query OK, 0 rows affected (0.00 sec)<br/><br/>mysql&gt; insert into t values (&#039;共和国&#039;);<br/>Query OK, 1 row affected (0.00 sec)<br/><br/>mysql&gt; select * from t;<br/>+-------+<br/>&amp;#124; a&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+-------+<br/>&amp;#124; ???ú &amp;#124;<br/>&amp;#124; 人民&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; ???&nbsp;&nbsp; &amp;#124;<br/>+-------+<br/>3 rows in set (0.00 sec)<br/>可见，这里character_set_client=gbk,character_set_connection=latin1,character_set_database=gbk。首先，client到connection过程中，汉字被转换成乱码（这个过程可能就会丢失信息）；然后存储数据的时候，又从connection到存储的字符集（gbk）发生一次转换，乱码被转换成“更”乱码。这里如果connection与client的字符集有种包容性关系的话，如character_set_client=gbk, character_set_connection=utf8,character_set_results=gbk,底层存储也是gbk编码，由于utf8“兼容”所有的字符集，故在转换过程中不会发生信息丢失，查询的时候也不会是乱码，如下：<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+-----------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+-----------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; utf8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_database&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; .........................&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+-----------------+<br/>8 rows in set (0.00 sec)<br/><br/>mysql&gt; create table t (a varchar(10)) charset=gbk;<br/>Query OK, 0 rows affected (0.05 sec)<br/><br/>mysql&gt; insert into t values(&#039;中国&#039;);<br/>Query OK, 1 row affected (0.00 sec)<br/><br/>mysql&gt; select * from t;<br/>+------+<br/>&amp;#124; a&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+------+<br/>&amp;#124; 中国 &amp;#124;<br/>+------+<br/>1 rows in set (0.00 sec)<br/>我来解释一下这个过程，假设“中国”的gbk编码是1234，而utf8的编码是4321，utf8的编码为1234的假设是“淘宝”。client的“中国”的编码1234进入connection，仍然是1234（但实际上它的含义已经发生变化为“淘宝”），存储的时候connection的1234编码到表存储也是1234，刚好正确表达了“中国”的意思，查询返回时，由于results也是gbk，所以不发生转换，正确显示。很显然，如果results又是一种与gbk不兼容的字符集如latin1，查询又会出问题，如下：<br/><br/>mysql&gt; set character_set_results=latin1;<br/>Query OK, 0 rows affected (0.00 sec)<br/><br/>mysql&gt; select * from t;<br/>+------+<br/>&amp;#124; a&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+------+<br/>&amp;#124; ??&nbsp;&nbsp; &amp;#124;<br/>+------+<br/>1 rows in set (0.00 sec)<br/>当我们改变底层存储的字符集的时候，会怎样？请看如下实验：<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+---------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+---------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_database&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; .........................&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+---------------+<br/>8 rows in set (0.01 sec)<br/><br/>mysql&gt; create table t (a varchar(10)) charset=latin1;<br/>Query OK, 0 rows affected (0.05 sec)<br/><br/>mysql&gt; insert into t values(&#039;淘宝&#039;);<br/>Query OK, 1 row affected, 1 warning (0.02 sec)<br/><br/>mysql&gt; select * from t;<br/>+------+<br/>&amp;#124; a&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+------+<br/>&amp;#124; ??&nbsp;&nbsp; &amp;#124;<br/>+------+<br/>1 row in set (0.00 sec)<br/>很显然，由于latin1字符集无法存储汉字，故出现乱码。<br/>下面，我们只改变results字符集，看看效果如何：<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+----------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+----------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_database&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; .........................&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+----------------+<br/>8 rows in set (0.00 sec)<br/><br/>mysql&gt; create table t (a varchar(10)) charset=gbk;<br/>Query OK, 0 rows affected (0.08 sec)<br/><br/>mysql&gt; insert into t values(&#039;淘宝&#039;);<br/>Query OK, 1 row affected (0.00 sec)<br/><br/>mysql&gt; select * from t;<br/>+------+<br/>&amp;#124; a&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+------+<br/>&amp;#124; ??&nbsp;&nbsp; &amp;#124;<br/>+------+<br/>1 row in set (0.00 sec)<br/>很显然，底层为gbk编码的字符串转换成latin1的字符集的字符，变成乱码，传给客户端，再次转换成gbk字符集，变成“更”乱码，故显示乱码。<br/><br/>下面，我再介绍几个“简约”命令。<br/>SET NAMES ‘x’，(SET NAMES ‘charset_name’ COLLATE ‘collation_name’)相当于：<br/><br/>SET character_set_client = x;<br/>SET character_set_results = x;<br/>SET character_set_connection = x;<br/><br/>实验如下：<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+----------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+----------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; .........................&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+----------------+<br/>8 rows in set (0.00 sec)<br/><br/>mysql&gt; set names &#039;ascii&#039;;<br/>Query OK, 0 rows affected (0.00 sec)<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+----------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+----------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; ascii&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; ascii&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; ascii&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; .........................&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+----------------+<br/>SET CHARACTER SET ‘x’,相当于：<br/><br/>SET character_set_client = x;<br/>SET character_set_results = x;<br/>SET collation_connection = @@collation_database;<br/><br/>这里collation_connection = @@collation_database的意思就是把collation_connection的设置的collation_database的值，由于collation肯定能确定character set，故其又相当于多做了个设置：把character_set_connetion设置成character_set_database的值。请看如下实验：<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+-------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+-------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; character_set_database&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; latin1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>&amp;#124; .......................&nbsp;&nbsp;&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+-------------+<br/>8 rows in set (0.00 sec)<br/><br/>mysql&gt; show variables like &#039;collat%&#039;;<br/>+----------------------+-------------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+----------------------+-------------------+<br/>&amp;#124; collation_connection &amp;#124; latin1_swedish_ci &amp;#124;<br/>&amp;#124; collation_database&nbsp;&nbsp; &amp;#124; gbk_bin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; collation_server&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; latin1_swedish_ci &amp;#124;<br/>+----------------------+-------------------+<br/>3 rows in set (0.00 sec)<br/><br/>mysql&gt; set character set &#039;ascii&#039;;<br/>Query OK, 0 rows affected (0.00 sec)<br/><br/>mysql&gt; show variables like &#039;char%&#039;;<br/>+--------------------------+-------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+--------------------------+-------------+<br/>&amp;#124; character_set_client&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; ascii&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_connection &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_database&nbsp;&nbsp; &amp;#124; gbk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; character_set_results&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; ascii&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; .......................&nbsp;&nbsp;&amp;#124; ......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124;<br/>+--------------------------+-------------+<br/>8 rows in set (0.00 sec)<br/><br/>mysql&gt; show variables like &#039;collat%&#039;;<br/>+----------------------+-------------------+<br/>&amp;#124; Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;#124; Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>+----------------------+-------------------+<br/>&amp;#124; collation_connection &amp;#124; gbk_bin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; collation_database&nbsp;&nbsp; &amp;#124; gbk_bin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124;<br/>&amp;#124; collation_server&nbsp;&nbsp;&nbsp;&nbsp; &amp;#124; latin1_swedish_ci &amp;#124;<br/>+----------------------+-------------------+<br/>3 rows in set (0.00 sec)<br/>通过以上的介绍，所以为了防止出现乱码，我们可以把character_set_client,character_set_connection,character_set_database,character_set_results设置成同样的值，把collation_connection和collation_database也设置成同样的值，这样就“一劳永逸”了。程序连接mysql的时候，一般都会显示设置character_set_client的值，如java连接中，一般都有如下的一段代码来显示设置这个值：<br/><br/>jdbc:mysql://10.1.6.174:3306/notify?connectTimeout=1000&amp;characterEncoding=utf8<br/>转：<br/>http://rdc.taobao.com/blog/dba/html/184_mysql_connect_charset_collation.html<br/><br/><br/>作者：叶金荣（Email:imysql@gmail.com），来源：http://imysql.cn，转载请注明作者和出处，并且不能用于商业用途，违者必究。<br/><br/>首先,这片文章纯粹是我的个人经验之谈,适用于我常见的环境及项目中.<br/>个人建议,数据库字符集尽量使用utf8(HTML页面对应的是utf-8),以使你的数据能很顺利的实现迁移,因为utf8字符集是目前最适合于实现多种不同字符集之间的转换的字符集,尽管你在命令行工具上可能无法正确查看数据库中的内容,我依然强烈建议使用utf8作为默认字符集.<br/>接下来是完整的一个例子：<br/>1.创建数据库表<br/>mysql&gt;CREATE DATABASE IF NOT EXISTS my_db default charset utf8 COLLATE utf8_general_ci;<br/>#注意后面这句话 &quot;COLLATE utf8_general_ci&quot;,大致意思是在排序时根据utf8校验集来排序<br/>#那么在这个数据库下创建的所有数据表的默认字符集都会是utf8了<br/><br/>mysql&gt;create table my_table (name varchar(20) not null default &#039;&#039;)engine=MyISAM default charset utf8 default charset utf8;<br/>#这句话就是创建一个表了,制定默认字符集为utf8<br/><br/>2.写数据<br/>例子1是通过php直接插入数据:<br/>a.php<br/>&lt;?php<br/>mysql_connect(&#039;localhost&#039;,&#039;user&#039;,&#039;password&#039;);<br/>mysql_select_db(&#039;my_db&#039;);<br/><br/>//请注意,这步很关键,如果没有这步,所有的数据读写都会不正确的<br/>//它的作用是设置本次数据库联接过程中,数据传输的默认字符集<br/>//其他编程语言/接口也类似，例如 .net/c#/odbc<br/>//jdbc则设置连接字符串为类似&quot;jdbc:mysql://localhost/db?user=user&amp;password=123456&amp;useUnicode=true&amp;characterEncoding=UTF-8&quot;<br/>mysql_query(&quot;set names utf8;&quot;);<br/><br/>//必须将gb2312(本地编码)转换成utf-8,也可以使用iconv()函数<br/>mysql_query(mb_convet_encoding(&quot;insert into my_table values(&#039;测试&#039;);&quot;, &quot;utf-8&quot;, &quot;gb2312&quot;));<br/>?&gt;<br/><br/>例子是通过页面提交插入数据2:<br/>b.php<br/>&lt;?php<br/>//输出本页编码为utf-8<br/>header(&quot;content-type:text/html; charset=utf-8&quot;);<br/><br/>mysql_connect(&#039;localhost&#039;,&#039;user&#039;,&#039;password&#039;);<br/>mysql_select_db(&#039;my_db&#039;);<br/><br/>if(isset($_REQUEST[&#039;name&#039;))<br/>&#123;<br/>//由于上面已经指定本页字符集为utf-8了,因此无需转换编码<br/>mysql_query(sprintf(&quot;insert into my_table values(&#039;%s&#039;);&quot;, $_REQUEST[&#039;name&#039;]));<br/>&#125;<br/><br/>$q = mysql_query(&quot;select * from my_table&quot;);<br/>while($r = mysql_fetch_row($q))<br/>&#123;<br/>print_r($r);<br/>&#125;<br/>?&gt;<br/><br/>&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;<br/>&lt;form action=&quot;&quot; method=&quot;post&quot;&gt;<br/>&lt;input type=&quot;text&quot; name=&quot;name&quot; value=&quot;&quot;&gt;<br/>&lt;input type=&quot;submit&quot; value=&#039;submit&#039;&gt;<br/>&lt;/form&gt;<br/><br/>自此,使用utf8字符集的完整的例子结束了.<br/>如果你想使用gb2312编码,那么建议你使用latin1作为数据表的默认字符集,这样就能直接用中文在命令行工具中插入数据,并且可以直接显示出来.而不要使用gb2312或者gbk等字符集,如果担心查询排序等问题,可以使用binary属性约束,例如:<br/>create table my_table ( name varchar(20) binary not null default &#039;&#039;)engine=MyISAM default charset utf8 default charset latin1;<br/><br/>附1：旧数据升级办法<br/>以原来的字符集为latin1为例，升级成为utf8的字符集。原来的表: old_table (default charset=latin1)，新表：new_table(default charset=utf8)。<br/>第一步：导出旧数据<br/>mysqldump --default-character-set=latin1 -hlocalhost -uroot -B my_db --tables old_table &gt; old.sql<br/>第二步：转换编码(类似unix/linux环境下)<br/>iconv -t utf-8 -f gb2312 -c old.sql &gt; new.sql<br/>或者可以去掉 -f 参数，让iconv自动判断原来的字符集<br/>iconv -t utf-8 -c old.sql &gt; new.sql<br/>在这里，假定原来的数据默认是gb2312编码。<br/>第三步：导入<br/>修改old.sql，在插入/更新语句开始之前，增加一条sql语句： &quot;SET NAMES utf8;&quot;，保存。<br/>mysql -hlocalhost -uroot my_db &lt; new.sql<br/>大功告成！！<br/><br/>附2：支持查看utf8字符集的MySQL客户端有<br/>1.) MySQL-Front，据说这个项目已经被MySQL AB勒令停止了，不知为何，如果国内还有不少破解版可以下载（不代表我推荐使用破解版 :-P）。<br/>2.) Navicat，另一款非常不错的MySQL客户端，汉化版刚出来，还邀请我试用过，总的来说还是不错的，不过也需要付费。<br/>3.) PhpMyAdmin，开源的php项目，非常好。<br/>4.) Linux下的终端工具（Linux terminal），把终端的字符集设置为utf8，连接到MySQL之后，执行 SET NAMES UTF8; 也能读写utf8数据了。<br/><br/>附3：直接使用MySQL提供的 ALTER 语法转换字符集<br/>这对广大非utf8又想转成utf8的用户来说，是个天大的喜讯，我也是在学习MySQL手册是才发现的。具体用法如下：<br/>ALTER TABLE OLD_TABLE CONVERT TO CHARACTER SET charset_name [COLLATE collation_name];<br/>转换之前，记得要先备份旧表，以防万一。更多详情请查看相关版本的MySQL手册。下面是一个实际的例子：<br/>ALTER TABLE `t_yejr` CONVERT TO CHARACTER SET UTF8;<br/>这个方法应该是从MySQL 4.1才开始提供的，大家可以检查一下自己的版本是否支持，如果不支持，只好按照上面提到的转换了。enjoy it!!!<br/><br/>http://www.sun023.com/post/108.html<br/><br/><br/>再摘录自同事的一点更简洁明了的看法：<br/>&nbsp;&nbsp; 在web开发中，经常会遇到中文显示为乱码的情况。这里简单总结一下在遇到这种问题时分析和解决的思路。 <br/><br/> <br/><br/>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不论数据库是何种编码，只要在取出数据时设置的编码和存入数据时设置的编码一致，就不会出现乱码现象。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mysql数据字符集分成四个级别：服务器级、数据库级、表级和连接级。通过status命令可以看到自己的mysql的这些设置。前三者主要控制数据在服务器端的存储。这些数据集的设置有从上至下的包含关系，也就是说，如果表没有做特设的字符集设置，则会继承数据库级的设置。而连接级字符集主要是用于客户端和服务器端的数据交互。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;执行sql语句时数据的流转路径是这样的， <br/><br/>信息输入路径：Client –&gt; Connection -&gt; Server<br/><br/>信息输出路径：Server -&gt; Connection -&gt; Client <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;和连接相关的几个设置有character_set_client、character_set_connection和character_set_results。比如执行一个sql查询，服务器端会以character_set_client设置的字符集接受这个查询，而后根据转换成character_set_connection设置的字符集，处理完成后，以character_set_results字符集将结果返回。要更改连接时的字符集可以执行命令 <br/><br/>SET NAMES &#039;charset_name&#039;; <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;它等价于执行了下面三个命令 <br/><br/>mysql&gt; SET character_set_client = x;<br/><br/>mysql&gt; SET character_set_results = x;<br/><br/>mysql&gt; SET character_set_connection = x; <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;也不需要每次启动客户端时都进行这几个操作，可以在mysql语句或者选项文件中添加一个--default-character-set=的选项设置。比如你想以gbk格式查询数据库，可以设置此选项为gbk。 <br/><br/> <br/><br/>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果网站支持多语言，可以选用utf-8编码，如果只在国内使用，则没有必要。如果网站使用了utf-8编码，则数据库，以及网页提交的数据都要使用utf8。 <br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;说没有必要，是从各种编码占有的字节长度的考虑，utf-8编码文件比gb2312编码文件大。如果default-character-set=gbk，就不能存utf-8编码的字符，否则会提示“Data too long for column ‘xx’at row”的错误。如果数据量大，才有gbk会节省空间。Latin1和gbk类似。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;也正因为如此，如果网页使用了utf-8编码，就要保证所有的编码一致，即数据库也要用utf8编码，utf-8编码提交的网页也要是utf8的。 <br/><br/> <br/><br/>以下是一些用于查询和修改字符集的mysql命令。<br/><br/>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 查看数据库支持的所有字符集<br/><br/>mysql&gt;show character set;<br/><br/>或<br/><br/>mysql&gt;show char set;<br/><br/>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 查看当前的字符集设置<br/><br/>mysql&gt;status;<br/><br/>或<br/><br/>mysql&gt;&#92;s;<br/><br/>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 查看系统字符集设置<br/><br/>mysql&gt;show variables like &#039;char%&#039;;<br/><br/>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改服务器级设置<br/><br/>a.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 临时更改：<br/><br/>mysql&gt;SET GLOBAL character_set_server=utf8;<br/><br/>b.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 永久更改：<br/><br/>修改my.ini文件<br/><br/> [mysqld]<br/><br/>default-character-set=utf8<br/><br/>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改数据库级<br/><br/>a.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 临时更改：<br/><br/>mysql&gt;SET GLOBAL character_set_database=utf8;<br/><br/>b.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 永久更改<br/><br/>改了服务器级就可以了<br/><br/>6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改表级<br/><br/>mysql&gt;ALTER TABLE table_name DEFAULT CHARSET utf8;<br/><br/>改后永久生效<br/><br/>7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改列级<br/><br/>mysql&gt;alter table `products` change `products_model` `products_model` varchar( 20 )&nbsp;&nbsp;character set&nbsp;&nbsp;utf8 collate utf8_general_ci null default null;<br/><br/>更改后永久生效<br/><br/>8.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 更改连接字符集<br/><br/>a. 临时更改：<br/><br/>mysql&gt; set names utf8;<br/><br/>b. 永久更改：<br/><br/>修改my.ini文件<br/><br/>在[client]中增加：<br/><br/>default-character-set=utf8
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [实践OK]mysql连接字符串乱码之mysql连接通道中的字符集和校验规则---来源：淘宝团队，[转]深入Mysql字符集设置，比阿里巴巴技术团队的更形像 。]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>