kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp
sar -n DEV 1

MySQL UTF8 编码下生僻字符

https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=C344D8D120B341A8DD328954A9B27A99

www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=20547

https://www.cnblogs.com/zhuawang/p/4203972.html

1、问题:mysql 遇到某些中文插入异常

最近有同学反馈了这样一个问题:

1
insert into tb(name) VALUES('𠕇');

上述语句在脚本中 load 入库的时候会 hang 住,web 前端、命令行操作则要么抛出

Incorrect string value: ‘\xF0\xA1\x8B\xBE\xE5\xA2…’ for column ‘name',

要么存入MYSQL数据库的内容会被截断或者乱码,而换做其它的中文则一切正常。

嗯,看起来有点奇怪哈,按理说 utf8 编码是覆盖了所有中文的,不应该出现上述问题。

2、原因:此 utf8 非彼 utf8

那我们先来看看插入异常的中文和正常的中文有啥区别:

1
2
3
4
kk@kk-B250M-D3H:~$ echo -n 𠕇|xxd
00000000: f0a0 9587                                ....
kk@kk-B250M-D3H:~$ echo -n 有|xxd
00000000: e69c 89                                  ...

可以看到上面插入异常的文字占了 4 个字节,而我们插入正常的则只占了 3 个字节。但是 utf8 字符编码不就是可变长,支持 1-4 字节的么?会和这个有关?

嗯,看看官方文档就知道了:

10.1.10.6 The utf8mb4 Character Set (4-Byte UTF-8 Unicode Encoding)

The character set named utf8 uses a maximum of three bytes per character and contains only BMP characters. As of MySQL 5.5.3, the utf8mb4 character set uses a maximum of four bytes per character supports supplemental characters:

For a BMP character, utf8 and utf8mb4 have identical storage characteristics: same code values, same encoding, same length.

For a supplementary character, utf8 cannot store the character at all, while utf8mb4 requires four bytes to store it. Since utf8 cannot store the character at all, you do not have any supplementary characters in utf8 columns and you need not worry about converting characters or losing data when upgrading utf8 data from older versions of MySQL.

utf8mb4 is a superset of utf8.

由官方文档可知,mysql 支持的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等等。

最初的 UTF-8 格式使用一至六个字节,最大能编码 31 位字符。最新的 UTF-8 规范只使用一到四个字节,最大能编码21位,正好能够表示所有的 17个 Unicode 平面。 utf8 是 Mysql 中的一种字符集,只支持最长三个字节的 UTF-8字符,也就是 Unicode 中的基本多文本平面。

Mysql 中的 utf8 为什么只支持持最长三个字节的 UTF-8字符呢?我想了一下,可能是因为 Mysql 刚开始开发那会,Unicode 还没有辅助平面这一说呢。那时候,Unicode 委员会还做着 “65535 个字符足够全世界用了”的美梦。Mysql 中的字符串长度算的是字符数而非字节数,对于 CHAR 数据类型来说,需要为字符串保留足够的长。当使用 utf8 字符集时,需要保留的长度就是 utf8 最长字符长度乘以字符串长度,所以这里理所当然的限制了 utf8 最大长度为 3,比如 CHAR(100) Mysql 会保留 300字节长度。至于后续的版本为什么不对 4 字节长度的 UTF-8 字符提供支持,我想一个是为了向后兼容性的考虑,还有就是基本多文种平面之外的字符确实很少用到。

要在 Mysql 中保存 4 字节长度的 UTF-8 字符,需要使用 utf8mb4 字符集,但只有 5.5.3 版本以后的才支持(查看版本: select version();)。我觉得,为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8. 对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR 替代 CHAR。

3、解决方案

知道原因了,当然得谈谈有哪些方案可以解决开头的问题。

3.1 升级 mysql 版本,并将utf8字符集升级到utf8mb4

升级你的 mysql 到 5.5.3 之后即可,查看当前环境版本:

1
select version();

MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8bp4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。

所以好的技术就是,采用对当前而言最好的解决方案,然后再逐步迭代满足新的需求。

3.1.1 直接修改表结构

1
2
3
4
5
6
7
8
--修改数据库字符集
ALTER DATABASE test CHARACTER SET = utf8mb4;

--修改表字符集
alter table test convert to character set utf8mb4;

--修改字符字符集
ALTER TABLE `test` CHANGE COLUMN `name` `name` varchar(12) CHARACTER SET utf8mb4;

3.1.2 修改数据库默认配置

1
2
3
4
5
6
7
[client]
default-character-set = utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
[mysql]
default-character-set = utf8mb4

https://ishare.iask.sina.com.cn/f/1H23TejZrutm.html

inner join、left join、right join、full outer join、union、union all的区别

https://www.cnblogs.com/logon/p/3748020.html

对于SQL的Join,在学习起来可能是比较乱的。我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚。Coding Horror上有一篇文章,通过文氏图 Venn diagrams 解释了SQL的Join。我觉得清楚易懂,转过来。

假设我们有两张表。Table A 是左边的表。Table B 是右边的表。其各有四条记录,其中有两条记录name是相同的,如下所示:让我们看看不同JOIN的不同

1.INNER JOIN

1
SELECT * FROM TableA INNER JOIN TableB ON TableA.name = TableB.name

2.FULL [OUTER] JOIN

(1)

1
SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name

4.RIGHT [OUTER] JOIN

RIGHT OUTERJOIN 是后面的表为基础,与LEFT OUTER JOIN用法类似。这里不介绍了。

5.UNION 与 UNION ALL

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。UNION 只选取记录,而UNION ALL会列出所有记录。

(1)

1
SELECT name FROM TableA UNION SELECT name FROM TableB

选取不同值

(2)

1
SELECT name FROM TableA UNION ALL SELECT name FROM TableB

全部列出来

(3)注意:

1
SELECT * FROM TableA UNION SELECT * FROM TableB

由于 id 1 Pirate 与 id 2 Pirate 并不相同,不合并

还需要注册的是我们还有一个是“交差集” cross join, 这种Join没有办法用文式图表示,因为其就是把表A和表B的数据进行一个 N*M 的组合,即笛卡尔积。表达式如下:SELECT * FROM TableA CROSS JOIN TableB

这个笛卡尔乘积会产生 4 x 4 = 16 条记录,一般来说,我们很少用到这个语法。但是我们得小心,如果不是使用嵌套的select语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性能来说是非常危险的,尤其是表很大的时候。

查看、挂载 window 共享 cifs

挂载共享文件

1
mount -t cifs -o username="administrator",password="123456" //192.168.100.191/bak 100.191_bak

查看共享文件夹

1
smbclient -L //192.168.100.191/ -U administrator%123456

以用户身份登录

以用户身份登录后,能像ftp用户一样,上传和下载文件,用put表示上传,get表示下载

1
smbclient //192.168.100.191/ -U administrator%123456

.smbclient命令说明

?或help 提供帮助

![shell command] 执行所用的shell命令

cd [目录] 切换服务器段指定目录

lcd [目录] 切换到客户端指定目录

dir 或 ls 列出当前目录下的文件

exit 或 quit 退出smbclient

get file1 file2 从服务器上下载文件file1,并以文件名file2保存在本地机上,如果不想改名可以把file2省略

mget file1 file2 file3 filen 从服务器上下载多个文件

md 或 mkdir 在服务器上创建目录

rd 或 rmdir 删除服务器目录

put file1 [file2] 想服务器上传一个文件file1,到服务器上改名为file2 mput file1 file2 filen 向服务器上传多个文件


https://blog.csdn.net/wangerge/article/details/1671959

https://www.csdn.net/tags/MtzakgxsMzkyNDgtYmxvZwO0O0OO0O0O.html