其实我纠结挺久,要不要写这一篇文章,不怎么想让大家感觉我好像只会字符集一样。。Mysql在数据的存储上,提供了不同的字符集支持。在数据的比对上,又提供了不同的字符序支持。与Oracle实例级别的设置不同,Mysql很灵活,它提供了不同级别的设置,包括:Server级,Database级,Table级和Column级。(简单的概念了解下,和今天讲得内容关系不大)今天只研究字符集,不讨论字符序~
控制Mysql字符集的参数有这么多,先简单解释下这些参数的含义。character_set_client:客户端的字符集,当客户端向服务端发送请求时,请求以该字符集进行编码。character_set_connection:客户机/服务器连接的字符集
character_set_database:默认数据库的字符集,无论默认数据库如何改变,都是这个字符集;如果没有默认数据库,那就使用 character_set_server指定的字符集,这个变量建议由系统自己管理,不要人为定义。
character_set_filesystem:把os上文件名转化成此字符集,即把 character_set_client转换character_set_filesystem, 默认binary是不做任何转换的
character_set_results:结果集,返回给客户端的字符集
character_set_server:数据库服务器的默认字符集
character_set_system:系统字符集,这个值总是utf8,不需要设置。这个字符集用于数据库对象(如表和列)的名字,也用于存储在目录表中的函数的名字。
Sample1:模拟场景:character_set_server=utf8,character_set_client=gbk,character_set_results=gbk,terminal(我的iterm工具)的字符集为gbk。首先,创建一个测试表t_char
将terminal的字符集修改为gbk
执行命令:mysql -S data/my3306/mysql.sock -proot gu -e "set character_set_client=gbk;set character_set_results=gbk;truncate table t_char;insert into t_char values('中');select c1,hex(c1) from t_char;"
从上图中能看到,虽然我的客户端字符集为GBK,但是数据还是以UTF8的格式正确存进了数据库,并且结果显示也正常。(原理和Oracle字符集差不多)Sample2:模拟场景:character_set_server=utf8,character_set_client=gbk,character_set_results=gbk,terminal(我的iterm工具)的字符集为UTF8。将terminal的字符集修改为UTF8
执行命令:mysql -S data/my3306/mysql.sock -proot gu -e "set character_set_client=gbk;set character_set_results=gbk;truncate table t_char;insert into t_char values('中');select c1,hex(c1) from t_char;"
期待的乱码终于出现,并且hex(c1)查出来的值为'E6B693',并不是我们熟悉的'E4B8AD'。那说明存进数据库就已经乱码了,已经不是改一下terminal字符集就能解决的。验证下猜测,只修改terminal字符集为GBK,继续查c1的值,为: '涓'。很明显这个结果是错误的。
那么为什么数据库会存错呢?因为terminal为utf8,在shell窗口执行那一串命令时,'中'是以utf8编码的,但又告诉数据库,client端字符集为GBK,那么数据库就把utf8格式的'中',当成GBK格式的'中'做了一次转码,那肯定就转乱套了呀。。Sample3:模拟场景:character_set_server=utf8,character_set_client=utf8,character_set_results=utf8,terminal(我的iterm工具)的字符集为UTF8。
当然,保持字符集一致,那永远也不会出现乱码的问题!(PS:所以每次发版的时候,我们都要跟研发同事说,注意sql文件的编码格式!)总结:通过这三个例子的说明,不知道大家有没有明白呢?其实Mysql的字符集和Oracle差不多。Oracle通过设置NLS_LANG来指定客户端字符集,Mysql通过设置character_set_client 来指定字符集。只是Mysql多了一个character_set_results参数控制返回客户端结果集的字符集参数。Mysql中没有dump()函数,可以用hex()函数,查看汉字转内码。还有很多强大的函数,大家可以去官网查一查~之前的字符集相关文章链接:如果没看过的可以看下,保证你以后遇上任何数据库乱码的问题都能解决!