• MySQL 配置文件中忘配置default-character-set引发的乱码问题


    字符集参考文献:

    http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_character_set_connection

    http://dev.mysql.com/doc/refman/5.6/en/faqs-cjk.html

    今天,一开发同事使用jdbc连接数据库执行一条语句无结果集,但是通过sqlyou执行相同的语句有返回结果。

    执行的语句where条件中含有中文,这应该是字符集引起的

    此开发测试实例刚迁移不久的,查看迁移前的环境默认字符集都是utf8

    查看当前数据库的字符集

    mysql> show variables like '%charac%';
    +--------------------------+----------------------------------+
    | Variable_name            | Value                            |
    +--------------------------+----------------------------------+
    | character_set_client     | utf8                             |
    | character_set_connection | utf8                             |
    | character_set_database   | latin1                           |
    | character_set_filesystem | binary                           |
    | character_set_results    | utf8                             |
    | character_set_server     | latin1                           |
    | character_set_system     | utf8                             |
    | character_sets_dir       | /usr/local/mysql/share/charsets/ |
    +--------------------------+----------------------------------+
    8 rows in set (0.00 sec)
    • character_set_client    
    • character_set_connection
    • character_set_results

       以上三个控制mysql client的字符集

    • character_set_database  

              设置数据库的默认字符集

    • character_set_server    

              设置以上所有的默认字符集

    发现server端的字符集和client端的全局字符集设置变量都是采用的默认值latin1

    发现配置文件中没有添加参数项  character-set-server=utf8

    造成乱码的原因:

    数据存储时的编码解码过程

    jdbc=>character_set_client=>table character

    每个环节的字符集编码都是utf8,没有转码过程

    character_set_client变为latin1后,读取数据的解码过程为

    jdbc<=character_set_client<=table character

    表中存储的是utf8编码格式,判断和character_set_client不一致则转码为latin1的二进制流,然后传输给远端的客户端,

    客户端jdbc通过设置的字符集展示结果,使用utf8展示latin1,所以出现了乱码。

    解决办法

    # character_set_filesystem 、character_set_system 、character_sets_dir除外都变更全局为utf8

    所有的应用需要重连数据库才能变更会话级别的字符集

    对于在字符集设置为latin1期间插入的数据编码存储过程:

    • 在terminal(这里为jdbc客户端)中使用输入法输入
    • terminal转换成utf8二进制流
    • 二进制流通过MySQL客户端传输到MySQL Server
    • Server通过character-set-client解码
    • 判断character-set-client和目标表的charset是否一致,character-set-client为latin1,目标表的字符集为utf8
    • 不一致则进行一次从client-charset到table-charset的一次字符编码转换,由latin1转码为utf8
    • 将转换后的字符编码二进制流存入文件中

    测试这种情况下将 中间环节的character-set-client变更为utf8,是否会出现乱码

    mysql> show  variables like '%char%';      
    +--------------------------+----------------------------------+
    | Variable_name            | Value                            |
    +--------------------------+----------------------------------+
    | character_set_client     | latin1                           |
    | character_set_connection | latin1                           |
    | character_set_database   | utf8                             |
    | character_set_filesystem | binary                           |
    | character_set_results    | latin1                           |
    | character_set_server     | utf8                             |
    | character_set_system     | utf8                             |
    | character_sets_dir       | /usr/local/mysql/share/charsets/ |
    +--------------------------+----------------------------------+
    8 rows in set (0.01 sec)
    
    mysql> update t1 set col='建军节' where id=4;    
    
    mysql> select * from t1 where id=4;
    +----+-----------+------+
    | id | col       | time |
    +----+-----------+------+
    |  4 | 建军节    | NULL |
    +----+-----------+------+
    
    
    解码编码转储
    
    crt terminal =》character_set_client =》character_set_server
    		utf8          latin1                 utf8			
    如果查询时任何一个环节的字符集变化都可能会造成乱码
    更改不同环节的字符集对应的数据显示
    1、改变客户端的字符集
    mysql> set names utf8;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select * from t1 where id=4;
    +----+-----------------------+------+
    | id | col                   | time |
    +----+-----------------------+------+
    |  4 | ??o???è??             | NULL |
    +----+-----------------------+------+
    2、更改crt terminal 的字符集为default
    mysql> select * from t1 where id=4;
    +----+-----------+------+
    | id | col       | time |
    +----+-----------+------+
    |  4 | 寤哄啗鑺   | NULL |
    +----+-----------+------+
    3、更改表字段字符集
    ALTER TABLE t1 CHANGE col col varchar(10) CHARACTER SET latin1;
    
    mysql> select * from t1 where id=4;
    +----+-----------+------+
    | id | col       | time |
    +----+-----------+------+
    |  4 | 建军节    | NULL |
    +----+-----------+------+
    

     更改表的字符集为latin1,读取数据涉及到变更的环节变为

    • 从文件读出二进制数据流(utf8存入)
    • 用表字符集latin1编码进行解码
    • 将数据转换为character-set-client的编码laint1

    对应的变更前的环节:

    • 从文件读出二进制数据流(utf8存入)
    • 用表字符集utf8编码进行解码
    • 将数据转换为character-set-client的编码laint1

    可以看出更改表数据字符集没有导致乱码的原因是,字符集整体经历的解码和转码过程是一致的,都经历了一次由utf8到latin1的转码。

    另一有关字符集的问题:为了支持表情符号,将系统级别的utf8设置为utf8mb4且相应的表也做了字符集的转变,重启应用不生效,重启数据库和应用才会生效

    参考文章为:

    http://blog.sina.com.cn/s/blog_93b45b0f0101glfx.html

    参考文章:

      编码解码过程  : http://cenalulu.github.io/mysql/mysql-mojibake/

  • 相关阅读:
    C#撸了个批量转换Word、Excel、PPT为PDF的软件 pdfcvt.com
    关于《图解国富论》若干问题的思考《六》
    关于《图解国富论》若干问题的思考《五》
    关于《图解国富论》若干问题的思考《四》
    关于《图解国富论》若干问题的思考《三》
    关于《图解国富论》若干问题的思考《二》
    关于《图解国富论》若干问题的思考《一》
    忆秦娥·娄山关
    《动物精神》笔记
    《非理性繁荣》笔记
  • 原文地址:https://www.cnblogs.com/Bccd/p/5941415.html
Copyright © 2020-2023  润新知