zoukankan      html  css  js  c++  java
  • 数据库连接字符编码问题

    查看数据表字符编码命令

    show create table table_name;
    show create table student;
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                                                                                                                                                                              |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | student | CREATE TABLE `student` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(6) NOT NULL,
      `age` int(3) NOT NULL,
      `sex` varchar(2) DEFAULT NULL,
      `address` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)

    1 JDBC Driver使用的JDBC URL中关于字符编码的配置参数主要有两个:
    useUnicode:是否使用自定义的编码方案
    characterEncoding:指定的编码方案

    一个具体的JDBC URL的例子如下:
    jdbc:mysql://localhost:3306/demo1?useSSL=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull

    这里的"characterEncoding"用来配置将字符流转换成字节流的时候所使用的编码方案,编码得到的字节流将在网络中传输。

    整个转换过程可以描绘成如下的步骤:
    1)发送端使用配置的"characterEncoding"值,将字符流编码成字节流
    2)将1)中得到的字节流通过网络传输到接收端
    3)在接收端,已经预先接收获取发送端配置的"characterEncoding"值,利用该值,解码字节流,得到字符流

    2 字符集和字符编码

    字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,这里的字符可以是英文字符,汉字字符,或者其他国家语言字符。
    常见字符集包括:ASCII字符集、LATIN1字符集、GB2312字符集、GBK字符集、GB18030字符集、Unicode字符集等。字符编码方式是用一个或多个字节表示字符集中的一个字符。每种字符集都有自己特有的编码方式,因此同一个字符,在不同字符集的编码方式下,会产生不同的二进制。ASCII是基于罗马字母表的一套字符集,它采用1个字节的低7位表示字符,高位始终为0。LATIN1字符集相对于ASCII字符集做了扩展,仍然使用一个字节表示字符,但启用了高位,扩展了字符集的表示范围。GB2312、GBK、GB18030字符集是支持中文的字符集,字符集范围GB2312<GBK< GB18030。GBK字符集的字符有一字节编码和两字节编码方式。对于00-7F的字符与ASCII保持一致,汉字采用2个字节表示。第一字节范围是81-FE,避免与00-7F冲突。Unicode字符集是计算机科学领域里的一项业界标准,支持了所有国家的文字字符。Unicode字符集有好几种编码方式,比如常见的utf-8,utf-16,utf-32等。Utf8采用1-4个字节表示字符,utf-16采用固定的2个字节,utf-32则采用4个字节存储。

    3 msql 中字符集编码环境变量

    变量名

    含义

    character_set_server

    默认的内部操作字符集

    character_set_client

    客户端来源数据使用的字符集

    character_set_connection

    连接层字符集

    character_set_results

    查询结果字符集

    character_set_database

    当前选中数据库的默认字符集

    character_set_system

    系统元数据(字段名等)字符集 

    详细说明

    3.1库、表、列字符集的由来
    (1).建库时,若未明确指定字符集,则采用character_set_server指定的字符集。
    (2).建表时,若未明确指定字符集,则采用当前库所采用的字符集。
    (3).新增,修改表字段时,若未明确指定字符集,则采用当前表所采用的字符集。

    3.2 更新、查询涉及到得字符集变量

    用户在更新(插入,删除,修改),查询数据库时,最常使用的字符集变量主要包含character_set_client,character_set_connection,character_set_result。
    更新流程字符集转换过程:客户端-》character_set_client-》character_set_connection-》表字符集。
    查询流程字符集转换过程:表字符集-》character_set_result-》客户端

    3.3 mysql 字符编码转换过程

    如果以上各个系统变量的设置不一致,比如character_set_client为UTF8,而character_set_database为GBK,则会出现需要进行编码转换的情况。那么字符集转换的原理是什么?假设GBK字符集的字符串“小明”,需要转为UTF8字符集存储,实际就是对于“小明”字符串中的每个汉字去UTF8编码表里面查询对应的二进制,然后存储,仅此而已,编码转换并不涉及到复杂的算法。mysql字符集转换主要涉及到几个步骤:

    1) 将数据从character_set_client设置转换为character_set_connection设置;

    2) 将character_set_connection设置转为表字段的字符集设置;

    3) 将操作结果从表字段字符集转为character_set_results设置。

    下面我通过一个常用的场景来描述字符集转换的流程。用户通过mysql命令行(如果是远程连接:SecureCRT),敲入命令“insert into T values(1,’小明’)”,字符串’小明’在流转过程中二进制存储内容。

    a) 用户采用的客户端为utf8字符集,character_set_client=gbk,character_set_connection=gbk, 表T采用gbk字符集。

     

    由于character_set_client、character_set_connection和表字符集均为GBK,不涉及编码转换。因此,表虽然为字符集虽然为GBK,但“小明”的编码并非为GBK编码的二进制流,而是UTF8的二进制流,两个汉字占用了6个字节,而读取则是一个逆向的过程,不涉及到编码转换,查询依然能正确返回“小明”。

    b)  在a)的情况下,改变character_set_client的设置为utf8,查询插入的值。

     

    可以看到返回的值是“灏忔槑”, 这是由于表的字符集是GBK,而客户端请求是UTF8,那么server将二进制流E5B08FE6988E对应的GBK汉字“灏忔槑”转为UTF8汉字对应的二进制流E7818FE5BF94E6A791,因此查询结果在SecureCRT就显示为“灏忔槑”,即通常我们所谓的乱码。

    c) 在b)的情况下,设置SecureCRT的字符集为GBK,看看SecureCRT字符集设置对结果影响

     

    可以看到返回的是另外一组字符“鐏忓繑妲�”,整个流转过程与b)一样,只是在第一步发生了字节流转换,设置SecureCRT字符集编码,只是改变了显示方式。

    4 查看当前数据库配置文件位置

    4.1 在linux系统中可以通过使用命令查询

    # which mysqld
    /usr/local/mysql/bin/mysqld
    # /usr/local/mysql/bin/mysqld --verbose --help |grep -A 1 'Default options'
    2016-06-02 16:49:39 0 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.6.25-log) starting as process 8253 ...
    2016-06-02 16:49:41 8253 [Note] Plugin 'FEDERATED' is disabled.
    Default options are read from the following files in the given order: 默认的选项是按照给定的顺序读取从以下文件:
    /etc/mysql/my.cnf /etc/my.cnf ~/.my.cnf 

    4.2 在 window 系统查看可以使用mysql workbench点击server status即可

  • 相关阅读:
    Javascript arguments.callee和caller的区别
    HTTP报错401和403详解及解决办法
    win10设置vscode的终端为管理员权限
    Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值
    Vue生命周期中mounted和created的区别
    Git可视化教程——Git Gui的使用
    url的三个js编码函数escape(),encodeURI(),encodeURIComponent()简介【转】
    在window系统上安装redis服务-Invalid argument during startup: Failed to open the .conf
    事务基础知识-->Spring事务管理
    线程本地变更,即ThreadLocal-->Spring事务管理
  • 原文地址:https://www.cnblogs.com/zhaopengcheng/p/8350253.html
Copyright © 2011-2022 走看看