从数据库基础的对照测试实验入手,一点点分析数据库的异常行为,降低DBA/运维对于bug分析的难度,也不需要一些诸如strace/jstack/gdb等分析工具,好的技术需要用好方法,能力有限,欢迎指点。
在MySQL中,反引号 ` 实际上是用来引用数据库对象的名称,如表名、列名等,以区分MySQL的保留关键字和特殊字符。而星号 * 用作通配符,它不需要用反引号引用。下面语句的反引号 ` 通常用于引用标识符,不适用于表中所有列输出,在标准的MySQL中,这实际上会产生一个错误,因为没有列名为 * 的列。
但是在客户的数据库中,该SQL却执行成功了,但是我在另外一台测试数据库中,却是报错,理论上报错是符合预期的,那客户的数据库是怎么回事呢?
这里不建议大家关注业务影响,这个问题可大可小,主要是兴趣所致分析该问题的原因:
本着深入探究问题的动机,作为小白,我们应该做大量单变量测试,不断向问题原因靠拢,最终定位。
本地尝试相同版本的数据库,发现问题复现了。但是在高版本的数据库中就没有出现,从而推断,这个问题在高版本数据库已经解决了。然后我们使用二分法,从低/高版本分别测试,验证问题复现版本,寻找交叉点,来判断下这个问题的解决版本。
create table t1(id int,name varchar(255));insert into t1 value(1,'chenyuan'),(2,'liu');
mysql [localhost:5712] {root} (test) > select `*` from t1;
+------+----------+
| id | name |
+------+----------+
| 1 | chenyuan |
| 2 | liu |
+------+----------+
2 rows in set (0.00 sec)
mysql [localhost:5720] {root} (test) > select `*` from t1;
+------+----------+
| id | name |
+------+----------+
| 1 | chenyuan |
| 2 | liu |
+------+----------+
2 rows in set (0.00 sec)
mysql [localhost:5725] {root} (test) > select `*` from t1;
+------+----------+
| id | name |
+------+----------+
| 1 | chenyuan |
| 2 | liu |
+------+----------+
2 rows in set (0.00 sec)
mysql [localhost:5729] {root} (test) > select `*` from t1;
+------+----------+
| id | name |
+------+----------+
| 1 | chenyuan |
| 2 | liu |
+------+----------+
2 rows in set (0.00 sec)
mysql [localhost:5730] {root} (test) > select `*` from t1;
+------+----------+
| id | name |
+------+----------+
| 1 | chenyuan |
| 2 | liu |
+------+----------+
2 rows in set (0.00 sec)
mysql [localhost:5731] {root} (test) > select `*` from t1;
ERROR 1054 (42S22): Unknown column '*' in 'field list'
mysql [localhost:5732] {root} (test) > select `*` from t1;
ERROR 1054 (42S22): Unknown column '*' in 'field list'
mysql [localhost:5733] {root} (test) > select `*` from t1;
ERROR 1054 (42S22): Unknown column '*' in 'field list'
mysql [localhost:5741] {root} (test) > select `*` from t1;
ERROR 1054 (42S22): Unknown column '*' in 'field list'
从上面的测试可以得出,当前这个缺陷,MySQL官方应该在5.7.31的发布中修复了,那么究竟触发了什么bug呢?
MySQL 5.7.31 Release Notes:
https://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-31.html
我们可以看下5731做了哪些变更。当前这个问题还是很有区分度的,直接就扫到了原因和Bug号。
It is possible to define a column named
*
(single asterisk character), but
SELECT `*`
was treated identically to
SELECT *
, making it impossible to select only this column in a query; in other words, the asterisk character was expanded to a list of all table columns even when it was surrounded by backticks. (Bug #30528450)
-
5.7的patch【修复版本5731】:https://github.com/mysql/mysql-server/commit/5c8c085ba96d30d697d0baa54d67b102c232116b