Mysql 编码问题


原文链接: Mysql 编码问题

mysql 编码问题

如何识别乱码的本来想要表达的文字
要从乱码字符中反解出原来的正确文字需要对各个字符集编码规则有较为深刻的掌握。但是原理很简单,这里用最常见的UTF-8被错误用GBK展示时的乱码为例,来说明具体反解和识别过程。

第1步 编码
假设我们在页面上看到寰堝睂这样的乱码,而又得知我们的浏览器当前使用GBK编码。那么第一步我们就能先通过GBK把乱码编码成二进制表达式。当然查表编码效率很低,我们也可以用以下SQL语句直接通过MySQL客户端来做编码工作:

mysql [localhost] {msandbox} > select hex(convert('寰堝睂' using gbk));
+-------------------------------------+
| hex(convert('寰堝睂' using gbk)) |
+-------------------------------------+
| E5BE88E5B18C |
+-------------------------------------+
1 row in set (0.01 sec)
第2步 识别
现在我们得到了解码后的二进制字符串E5BE88E5B18C。然后我们将它按字节拆开。

Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
E5 BE 88 E5 B1 8C
然后套用之前UTF-8编码介绍章节中总结出的规律,就不难发现这6个字节的数据符合UTF-8编码规则。如果整个数据流都符合这个规则的话,我们就能大胆假设乱码之前的编码字符集是UTF-8

第3步 解码
然后我们就能拿着E5BE88E5B18C用UTF-8解码,查看乱码前的文字了。当然我们可以不查表直接通过SQL获得结果:

mysql [localhost] {msandbox} ((none)) > select convert(0xE5BE88E5B18C using utf8);
+------------------------------------+
| convert(0xE5BE88E5B18C using utf8) |
+------------------------------------+
| 很屌 |
+------------------------------------+
1 row in set (0.00 sec)

字符集查看

查看当前数据库的字符集和校对规则:
mysql> show variables like 'character_set_database';
mysql> show variables like 'collation_database';
数据库编码:
ALTER DATABASE db_name DEFAULT CHARACTER SET character_name
show create database db_name;
表的字符集和校对规则:
ALTER TABLE logtest CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> show create table table_name \G;
查看字段编码:
alter table db_name.tbl_name change name name varchar(50) character set latin1 collate latin1_swedish_ci;
show full fields from db_name.tbl_name;

show full columns from table_name;
show full fields from table_name;

MySQL处理连接时,外部连接发送过来的SQL请求会根据以下顺序进行转换:
character_set_client //客户连接所采用的字符集
|
character_set_connection //MySQL连接字符集
|
character_set_database //数据库所采用的字符集(表,列)
|
character_set_results //客户机显示所采用的字符集

utf8mb4 编码

CREATE DATABASE example_staging DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

- CHARACTER 字符集 
- COLLATE 校对集

mysqldump -uroot -p example --default-character-set=utf8mb4 > /tmp/example.sql
mysql --default-character-set=utf8mb4 -uroot -p example_staging < /tmp/example.sql

解决: 保持mariadb 版本一致 mariadb:5.5

字符集是utf8:

CREATE DATABASE IF NOT EXISTS yourdbname DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
alter table table db_name.tbl_name convert to character set utf8 collate utf8_general_ci; 修改字符集
COLLATE utf8_general_ci: 数据库校对规则。该三部分分别为数据库字符集、通用、区分大小写。
utf8_unicode_ci比较准确,
utf8_general_ci速度比较快。通常情况下 utf8_general_ci的准确性就够我们用的了,在我看过很多程序源码后,发现它们大多数也用的是utf8_general_ci,所以新建数据 库时一般选用utf8_general_ci就可以了。

gbk字符集:

create database yourdb DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;

旧数据升级办法

以原来的字符集为latin1为例,升级成为utf8的字符集。原来的表: old_table (default charset=latin1),新表:new_table(default charset=utf8)。
第一步:导出旧数据
mysqldump --default-character-set=latin1 -hlocalhost -uroot -B my_db --tables old_table > old.sql
第二步:转换编码(类似unix/linux环境下)
iconv -t utf-8 -f gb2312 -c old.sql > new.sql
或者可以去掉 -f 参数,让iconv自动判断原来的字符集
iconv -t utf-8 -c old.sql > new.sql
在这里,假定原来的数据默认是gb2312编码。
第三步:导入
修改old.sql,在插入/更新语句开始之前,增加一条sql语句:

"SET NAMES utf8;"

,保存。
mysql -hlocalhost -uroot my_db < new.sql
大功告成!!

MySQL数据库从GBK转换到UTF-8最简单解决方案

--default-character-set=utf8 指定导出sql文件编码utf8格式
1、使用mysqldump导出 [表结构],如:

  mysqldump -d -u root -p 数据库名 >/root/struct.sql

2、使用mysqldump以[指定utf8编码]导出[表数据](其中--default-character-set=utf8 为所需编码,可按需修改),如:

  mysqldump --default-character-set=utf8 -t -u root -p 数据库名 >/root/data.sql

3、打开表结构转存(/root/struct.sql),将所有CREATE TABLE中的编码替换为所需编码;

 ` DEFAULT CHARSET=gbk; =>   DEFAULT CHARSET=utf8 ; `

4、 重新导入

导出表时,如果出现1044错误,添加 --skip-lock-tables 可以解决:
mysqldump -d -u root -p 数据库名 --skip-lock-tables >/root/struct.sql
mysqldump --default-character-set=utf8 -t -u root -p 数据库名 --skip-lock-tables >/root/data.sql

dedecms GBK 转 UTF8

docker exec -i mariadb mysqldump -d -uroot -p guoan >guoanstuct.sql
docker exec -i mariadb mysqldump -t --default-character-set=utf8 -uroot -p guoan >guoan.sql

`