惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
Hugging Face - Blog
Hugging Face - Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
WordPress大学
WordPress大学
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
博客园 - Franky
博客园 - 司徒正美
酷 壳 – CoolShell
酷 壳 – CoolShell
爱范儿
爱范儿
Jina AI
Jina AI
Last Week in AI
Last Week in AI
雷峰网
雷峰网
IT之家
IT之家
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX

MySQL

请教大家一个关于 mysql 服务崩溃的问题 数据库连接数超了如何解决 count 的语句优化问题 连接 MySQL 很慢的问题 MYSQL UPDATE 在很短的时间内更新相同的语句,就会有告警,导至事务失败,有没有人遇到这问题? MySQL 磁盘读取飙升,导致阿里云服务器卡死 求 Macos 下面 homebrew 安装 mysql 到指定目录的方法 使用 EXISTS 优化 IN 子查询 什么时候可以将 mysql 默认隔离机制改为读已提交 跨平台的 MySQL Parser MySQL 大表排序有什么好的方案?只能上 Mongo? Mysql 无法修改自增主键的 AUTO_INCREMENT 值 升级服务器后, mysql 性能反而更慢了,求排查思路 《高性能 MySQL》第三版:是否已经过时? 两个人的数据开发团队,被要求从零开始治理企业数据 MySQL 8.4 LTS 与 Metabase 奇怪兼容性问题:降级到 8.0.4 后问题解决 (1Panel and BT Panel 复现) 公司内网,怎么搭建主备 mysql,高可用。故障自动切。 不买云服务 mysql 自增 ID 突然变为 int 最大值问题 覆盖还原 data 文件夹后, mysql 无法启动了 生产力工具 各位大佬,有个奇葩的技术问题 关于 mysql trx_id 的疑惑 发帖一问 sql 性能讨论 数据库高频更新问题 谁遇到过没 有啥好的解决方案部 有用过 SyncNavigator 或者类似的简单数据库同步软件吗, mysql 遇到最愚蠢的查询性能问题,求解决 有什么优雅的 mysql 增加字段名的方法呢? 各位 Mysql 大佬,问一个 8.0 版本 json 的问题 mysql online DDL 时间很长,咋整,数据量不多,就 30W 数据库中 select for update 和 version 乐观锁各自的适用场景是啥?
坑爹的字符集问题:踩到了 MySQL 的 bug
mikewang · 2025-05-22 · via MySQL

昨天的 /t/1133223 吸引了大家不少的讨论,今天我来说一个工作上遇到的问题。

准确地说,这个问题是 MySQL 字符集中的校对规则出了 BUG ,字符集本身是无辜的。

这个 bug 现在都还在,欢迎大家验证哈。


故事是这样的。

同事在连 MySQL 库做测试时发现了一个诡异的现象:查不到匹配的数据。

相关语句简化如下(主键等字段已省略):

create table t1 ( c1 varchar(16), key idx (c1) ) collate=utf8mb4_bin;

insert into t1 values ('000\n'), ('123\n'), ('abc\n');

select * from t1 where c1 like 'abc%';

这怎么看,都应该匹配出 'abc\n',对吧?

事实情况是:

mysql> select * from t1 where c1 like 'abc%';
Empty set (0.00 sec)

天塌了,查出来竟然是空的。

然后我拿同样的语句在 OceanBase 上跑了一下,竟然也是空。(两眼一黑)


可能会有人说,那肯定是你写的语句有问题,或者 utf8mb4_bin 就这样,吧啦吧啦。

那如果这样呢:

mysql> alter table t1 drop index idx;
Query OK, 0 rows affected (0.001 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> select * from t1 where c1 like 'abc%';
+------+
| c1   |
+------+
| abc
 |
+------+
1 row in set (0.001 sec)

哎,索引删了就好了。

总不能说,加个索引,能把结果集搞没吧。那肯定 bug 了。


那到底是咋回事呢:带上索引,我们 explain 看一下。

mysql> explain format=tree select * from t1 where c1 like 'abc%' \G
*************************** 1. row ***************************
EXPLAIN: -> Filter: (t1.c1 like 'abc%')  (cost=0.46 rows=1)
    -> Covering index range scan on t1 using idx over ('abc' <= c1 <= 'abc?????????????')  (cost=0.46 rows=1)

1 row in set (0.001 sec)

原来这个前置匹配,因为有索引,优化为了范围查询。后面的一串 ? 其实是 0xff,没什么问题。

那看下 'abc\n''abc' 呢?

mysql> set collation_connection=utf8mb4_bin;
Query OK, 0 rows affected (0.000 sec)

mysql> select 'abc\n' < 'abc';
+-----------------+
| 'abc\n' < 'abc' |
+-----------------+
|               1 |
+-----------------+
1 row in set (0.000 sec)

再次两眼一黑。我倒,怎么会这样。这是什么排序规则。看下 utf8mb4_bin 吧。

mysql> show collation like 'utf8mb4_bin';
+-------------+---------+----+---------+----------+---------+---------------+
| Collation   | Charset | Id | Default | Compiled | Sortlen | Pad_attribute |
+-------------+---------+----+---------+----------+---------+---------------+
| utf8mb4_bin | utf8mb4 | 46 |         | Yes      |       1 | PAD SPACE     |
+-------------+---------+----+---------+----------+---------+---------------+
1 row in set (0.001 sec)

Pad_attributePAD SPACE,表示对齐长度时,后面补空格。这下就说通了。空格是 0x20,换行符是 0x0a\n 小。

所以!!虽然反直觉,在 utf8mb4_bin 下,'abc\n' 就是 'abc' 小!

结论:like 'abc%' 的范围查询优化有问题。


关于这个 bug ,我已经向 MySQL 提交了 patch ,但是似乎没有得到关注。我看了下更新日志,我提的另一个 patch 已经被合入,但是这个问题依然还在。看来涉及到字符集,这个坑麻烦到他们都不想处理了。

[ 同一时间提交的代码已经合入 ]

[ 这个问题还是打开的 ]


如果哪天他们合入或者解决了,我再 append 新的进展。