数据库连接字符编码问题
查看数据表字符编码命令
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字符集编码,只是改变了显⽰⽅式。unicode字符的种类有
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-0216:49:390 [Note] /usr/local/mysql/bin/mysqld (mysqld 5.6.25-log) starting as process 8253 ...
2016-06-0216:49:418253 [Note] Plugin 'FEDERATED'is disabled.
Default options are read from the following files in the given order: 默认的选项是按照给定的顺序读取从以下⽂件:
/etc/mysql/myf /etc/myf ~/.myf
4.2 在 window 系统查看可以使⽤mysql workbench点击server status即可