日常工作中常见的内容:
数据库的字符集和排序规则:
Flask中数据库引擎的连接方式:
engine = create_engine(f'mysql+pymysql://{DB_USER}:{password}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8mb4',
echo=False, pool_recycle=1, pool_size=20, max_overflow=0)
查看我们的建表语句:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for title
-- ----------------------------
DROP TABLE IF EXISTS `title`;
CREATE TABLE `title` (
`id` int(0) NOT NULL AUTO_INCREMENT,
`treatment` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`relate_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
mysql配置文件:
[mysqld]
character_set_server=utf8
这么多的关于字符集的设置,当你遇到乱码或者一些不可控制的查询错误,匹配错误的时候,并且问题可能是字符集方面的时候,有没有理出头绪来解决?
1. 从服务端角度来分析
服务端字符集方面最常见的配置就是在my.cnf[Linux]下配置:
- character_set_server=utf8
这个单从服务的角度主要定义客户端和服务端沟通的默认字符集编码规则。包括:
- character_set_client : 服务器解码使用的字符集编码(服务器字符集)
- character_set_results :返回给客户端数据的字符集编码 (响应结果字符集
- character_set_connection : 服务端处理请求的时候使用的字符集编码 (客户端字符集)
以上三个设置在建表语句中也会执行,有如下的关系:
那么根据建表语句的代码,就是在建库建表的时候,事实上会覆盖数据库服务端默认定义的字符集编码。
2. 从数据库角度来分析
建库建表的时候需要指定字符集(CHARACTER SET) 和排序规则(COLLATE)
通过查看建表语句:
- 针对库表以及字段,都需要设置字符集和排序规则.
- 对程序结构的理解,其实这是一种小范围配置覆盖大范围配置的行为.
排序规则的指定:
- 不同排序规则的特性有所不同:
- utf8_general_ci: 校对速度快,但准确度稍差。
- utf8_general_cs: 准确度高,但校对速度稍慢。
3. 一些需要重点区分的概念:
ci和cs的区别:
- ci的完整英文是’Case Insensitive’, 即“大小写不敏感”
- cs的完整英文是‘Case Sensitive’,即“大小写敏感”
utf8和utf8mb4的区别:
- mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。
- utf8 是3字节,文字等级的存储是没有问题。
- 有的时候需要存储多文本平面的 Unicode字符,比如表情。这时候utf8就会报错,需要使用4字节支持的utf8mb4。
- utf8mb4是utf8的超集。
总结
如果遇到一些问题,where条件没有生效,乱码等一些情况。可以按照如下顺序排查:
- 先从字段–> 表–>库的顺序进行字符集的排查, 然后检查数据库的配置my.cnf[Linux]
如果是表名大小写敏感问题:
root用户修改:sudo vim /etc/my.cnf;
在[mysqld]下一行加入:lower_case_table_names=1;[大小写不敏感]
重新启动数据库即可 :sudo /etc/init.d/mysql restart;