概述
最近出了个bug,有人反馈某个用户的审批记录的排序是乱的,而且是只有这个用户才有,其他用户并没有
原因
查看代码发现是通过ORM获取的,相当于SQL:
select id,credit_audit_id, admin_name,rejection, create_time from credit_audit_record where credit_audit_id = '56556' and alias = 'C1000100' and save_status = 0;
SQL并没有加order by来排序,那一般情况下,是使用主键来进行正序排序的,看一下表结构:
> desc credit_audit_record;
+--------------------+---------------------+------+-----+---------------------+----------------+
| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA |
+--------------------+---------------------+------+-----+---------------------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| credit_audit_id | int(10) | NO | MUL | NULL | |
| admin_id | varchar(20) | NO | | | |
| admin_name | varchar(30) | NO | | | |
可以看到,id是自增主键
我们直接使用sql来查看结果吧:
> select id,credit_audit_id, admin_name,rejection,create_time from credit_audit_record where credit_audit_id = '56556' and alias = 'C1000100' and save_status = 0;
+--------+-----------------+------------+-----------+---------------------+
| ID | CREDIT AUDIT ID | ADMIN NAME | REJECTION | CREATE TIME |
+--------+-----------------+------------+-----------+---------------------+
| 109962 | 56556 | | | 2022-01-02 17:00:01 |
| 112294 | 56556 | aaa | | 2022-01-10 14:42:17 |
| 112653 | 56556 | bbb | | 2022-01-12 10:46:04 |
| 109963 | 56556 | ccc | | 2022-01-02 17:03:02 |
+--------+-----------------+------------+-----------+---------------------+
结果出乎意料,没有加order by的情况下,select的时候,并不是根据id来进行正序排序的
我一直以为不加order by的情况下,select的时候默认是会按照id进行正序排序的,但现实情况有可能不是的
查阅相关文档:
https://segmentfault.com/a/1190000016251056
https://blog.csdn.net/qq_35383263/article/details/81433693
https://www.imooc.com/article/4925
原因可能是:
MySQL SELECT 默认排序是按照物理存储顺序显示。(不进行额外排序)也就是说SELECT * FROM 会产生“表扫描”。如果表没有增,删,改操作,记录会显示为插入的顺序。这就是初始为什么像是递增的原因。
那么,当我们进行增,删,改以后不难发现会乱序,这便是问题所在。增删改是惯用功能,因此必须注意这个细节。当我们不进行ORDER BY来规定排序时,MySQL将会以最快的形式(物理存储顺序)展示数据,导致乱序。
结论是:
如果在sql语句中不指定order by排序条件,那么得到的结果集的排序顺序是与查询列有关的。因为不同的查询列可能会用到不同的索引,从而导致顺序不同,具体原因就不深究了。
看网上大神的说法是:没有条件的情况下,数据库默认排序顺序是不好确定的,也不应该决定于什么因素,不同的数据库实现不同.只能用order by 来限定。
反正,不要迷信mysql默认会按照你以为的顺序排序,想要排序就先给你想要排序的字段创建索引(提高效率),然后再order by这个字段进行排序。
总之一句话:
没有条件的情况下,数据库默认排序顺序是不确定的
解决
解决方法很简单,如果是需要排序的话,一定要加一个order by