MySQL关闭,kill还是kill -9 ?

本文转载自微信公众号「DBA随笔」,作者DBA随笔。转载本文请联系DBA随笔公众号。

今天在线上遇到了一个MySQL字符比较的问题,感觉很有意思,专门研究了下,估计大家都没有遇到过,这里跟大家分享一下。

1.背景

背景介绍:

MySQL里面有一张表,根据where条件匹配查询某一条记录的时候,手误输入了一个空格,发现这一条数据仍然能查出来,我建了一个测试表,还原如下:

22:57:02>createtable t00 (id int primary key,name varchar(10));
Query OK,0 rows affected (0.01 sec)

22:57:11>insertinto t00 values(1,'aaa'),(2,'bbb');
Query OK,2 rows affected (0.00 sec)
Records:2 Duplicates:0 Warnings:0

22:57:22>select*from t00 where name='aaa';
+----+------+
| id | name |
+----+------+
|1| aaa |
+----+------+
1 row inset(0.00 sec)

22:57:32>select*from t00 where name='aaa ';
+----+------+
| id | name |
+----+------+
|1| aaa |
+----+------+
1 row inset(0.00 sec)

插入(1,’aaa’)这条记录,使用where=’aaa’和’aaa ‘这两个条件去匹配,居然都能够查到这条记录。

一开始我怀疑是这个8.0.19版本MySQL实例配置有问题,换了一个5.5低版本的MySQL实例,再次测试,还是复现这个问题。看来不是版本上的问题,一定是某种配置的问题。

晚上回到家,又用了自己搭建的一个8.0.22版本的MySQL实例重新执行上面的命令,竟然惊奇的发现,不复现了。。。晕死。8.0.22版本测试的结果是:

23:35:30>>select*from t0;
+------+------+
| id | name |
+------+------+
|1| aaa |
|2| bbb |
+------+------+
2 rows inset(0.01 sec)

23:35:34>>select*from t0 where name='aaa';
+------+------+
| id | name |
+------+------+
|1| aaa |
+------+------+
1 row inset(0.00 sec)

23:35:46>>select*from t0 where name='aaa ';
Empty set(0.00 sec)

2.分析思路

1)为什么’aaa’和’aaa ‘一样?

首先我用命令在MySQL上检测了一下这两个字符串在MySQL中是否一样:

### MySQL实例一
23:39:09>select'aaa'='aaa ';
+------------------+
|'aaa'='aaa '|
+------------------+
|1|
+------------------+
1 row inset(0.00 sec)


### MySQL实例二
23:35:54>>select'aaa'='aaa ';
+------------------+
|'aaa'='aaa '|
+------------------+
|0|
+------------------+
1 row inset(0.00 sec)

从上面的结果可以看出来,这两个实例上,关于字符的比较规则不一样。

到这里,可能部分同学就已经知道答案了。不过还是往下再看看。

2)比较规则哪里不一样?

我们可以用下面的命令,先看一下utf8相关的字符集下的比较规则,如下:

23:45:18> show collation like'utf8%';
+----------------------------+---------+-----+---------+----------+---------+---------------+
| Collation | Charset | Id | Default | Compiled | Sortlen | Pad_attribute |
+----------------------------+---------+-----+---------+----------+---------+---------------+
| utf8mb4_0900_ai_ci | utf8mb4 |255| Yes | Yes |0| NO PAD |
| utf8mb4_0900_as_ci | utf8mb4 |305|| Yes |0| NO PAD |
| utf8mb4_0900_as_cs | utf8mb4 |278|| Yes |0| NO PAD |
| utf8mb4_0900_bin | utf8mb4 |309|| Yes |1| NO PAD |
| utf8mb4_bin | utf8mb4 |46|| Yes |1| PAD SPACE |
| utf8mb4_croatian_ci | utf8mb4 |245|| Yes |8| PAD SPACE |
| utf8mb4_cs_0900_ai_ci | utf8mb4 |266|| Yes |0| NO PAD |
| utf8mb4_cs_0900_as_cs | utf8mb4 |289|| Yes |0| NO PAD |
| utf8_unicode_ci | utf8 |192|| Yes |8| PAD SPACE |
........
| utf8_vietnamese_ci | utf8 |215|| Yes |8| PAD SPACE |
+----------------------------+---------+-----+---------+----------+---------+---------------+
103 rows inset(0.00 sec)

在最后一列,我们可以看到一个pad属性,这个属性里面包含2个值,分别是no pad 和pad space。

3)尝试去官方文档中查找这俩属性的意思

果然,不出意外,找到了一些蛛丝马迹:

https://dev.mysql.com/doc/refman/8.0/en/char.html

To determine the pad attribute for a collation, use the INFORMATION_SCHEMA COLLATIONS table, which has a PAD_ATTRIBUTE column.

For nonbinary strings (CHAR, VARCHAR, and TEXT values), the string collation pad attribute determines treatment in comparisons of trailing spaces at the end of strings. NO PAD collations treat trailing spaces as significant in comparisons, like any other character. PAD SPACE collations treat trailing spaces as insignificant in comparisons; strings are compared without regard to trailing spaces.

上面这段话描述的意思大概是:

要确定排序规则的填充属性,请使用 information_schema.collations 表,该表具有 pad_attribute 列。

对于非二进制字符串(char,varchar和text),字符串的填充属性决定了比较字符串末尾空格时的处理方式。

NO PAD 排序规则将尾随空格视为重要的比较,更加严格,就像任何其他字符一样;

PAD SPACE 排序规则在比较中将尾随空格视为无关紧要,比较字符串时不考虑尾随空格,也就是有无空格一个样。

这里我们就可以根据实际使用的比较规则来查看对应的pad属性了:

先看实例一:

### MySQL实例一
00:01:31>show variables like'%colla%';
+-------------------------------+--------------------+
| Variable_name | Value |
+-------------------------------+--------------------+
| collation_connection | utf8_general_ci |
| collation_database | utf8mb4_0900_ai_ci |
| collation_server | utf8mb4_0900_ai_ci |
| default_collation_for_utf8mb4 | utf8mb4_0900_ai_ci |
+-------------------------------+--------------------+
4 rows inset(0.01 sec)

00:01:45>select collation_name,character_set_name,pad_attribute from information_schema.collationswhere collation_name like'utf8_gen
eral_ci';
+-----------------+--------------------+---------------+
| collation_name | character_set_name | pad_attribute |
+-----------------+--------------------+---------------+
| utf8_general_ci | utf8 | PAD SPACE |
+-----------------+--------------------+---------------+
1 row inset(0.00 sec)

再来看实例二:

### 实例二
mysql--root@localhost:(none) 23:53:52>>show variables like '%colla%';
+-------------------------------+--------------------+
| Variable_name | Value |
+-------------------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database | utf8mb4_0900_ai_ci |
| collation_server | utf8mb4_0900_ai_ci |
| default_collation_for_utf8mb4 | utf8mb4_0900_ai_ci |
+-------------------------------+--------------------+
4 rows inset(0.00 sec)

00:03:47>>select collation_name,character_set_name,pad_attribute from information_schema.collationswhere collation_name like'utf8mb4_0900_ai_ci';
+--------------------+--------------------+---------------+
| collation_name | character_set_name | pad_attribute |
+--------------------+--------------------+---------------+
| utf8mb4_0900_ai_ci | utf8mb4 | NO PAD |
+--------------------+--------------------+---------------+
1 row inset(0.00 sec)

到这里,真相大白。

实例一的连接比较规则是utf8_general_ci,对应的填充规则是pad space属性,代表字符比较过程中,末尾空格不重要,所以加不加空格结果都是一样的;

实例二的连接比较规则是utf8mb4_0900_ai_ci,对应的填充规则是no pad属性,代表字符比较过程中,末尾空格重要,所以加不加空格结果不一样。

3.如何让字符匹配更严格?

1)修改连接的比较规则为utf8mb4_0900_ai_ci,当然,这个修改需要搭配默认字符集

这个方案比较容易理解,不赘述。

2)使用like模糊匹配进行比较

3)where条件之前,添加binary关键字

上述2、3两种方法可见下面的测试:

00:19:13>select*from t00;
+----+------+
| id | name |
+----+------+
|1| aaa |
|2| bbb |
+----+------+
2 rows inset(0.00 sec)

00:19:18>select*from t00 where name='aaa';
+----+------+
| id | name |
+----+------+
|1| aaa |
+----+------+
1 row inset(0.00 sec)

00:19:28>select*from t00 where name='aaa ';
+----+------+
| id | name |
+----+------+
|1| aaa |
+----+------+
1 row inset(0.00 sec)
### 下面两种方案,可以防止'aaa '匹配到'aaa'
00:19:31>select*from t00 where name like'aaa ';
Empty set(0.00 sec)

00:19:57>select*from t00 where binary name ='aaa ';
Empty set(0.00 sec)

今天文章就到这里吧。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/263405.html<

(0)
运维的头像运维
上一篇2025-05-04 13:29
下一篇 2025-05-04 13:30

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注