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即可

  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/zhaopengcheng/p/8350253.html
Copyright © 2011-2022 走看看