❝Жизнь слишком коротка, чтобы держать собаку
❞
1. Предпосылки
MySQL можно назвать языком баз данных, который относительно прост в использовании, но также подвержен ошибкам. Когда вы уверенно тапаете на очередную строчку SQL и готовитесь героически развернуться, не глядя на результат, результат выполнения, не соответствующий ожиданиям, ударит вас по лицу"pia~ pia~"звенеть.
Некоторое время назад Xianyu столкнулся с таким требованием при написании бага: запрашивать набор данных в порядке возрастания веса, а вновь добавленные данные должны оказаться в конце списка по времени. Увидев это требование, Сяньюй даже не подумал об этом, только одинorder by
, а затем уверенно оглянуться назад, не взяв ни одной ошибки. Неожиданно через два дня продукт сообщил, что результат выполнения не оправдал ожиданий. С менталитетом «вы, должно быть, лжете мне и смотрите, как я дам вам пощечину», я выполнил SQL:
SELECT * FROM member_tool_config WHERE isv_id IS NULL and user_id IS NULL ORDER BY weight ASC;
Хм? Наверное, сегодняшний ветер немного шумит, что сказывается на результате выполнения SQL... Забудьте, давайте честно проверим баг.
2. Расстройство, вызванное «заказом»
После некоторого расследования было установлено, что виновником на самом деле былorder by
. когда используешьorder by
Когда в поле есть несколько строк с одним и тем же значением, это вызовет описанную выше проблему беспорядка, здесь мы рассмотримофициальное объяснение[1]:
❝If multiple rows have identical values in the
❞ORDER BY
columns, the server is free to return those rows in any order, and may do so differently depending on the overall execution plan. In other words, the sort order of those rows is nondeterministic with respect to the nonordered columns.
Обратите внимание на формулировку здесьis free to return those rows in any order
. Когда есть несколько строк с одинаковым значением, MySQL"Свободный дух"с участием"любой порядок"Вернуть результирующий набор. Конечно, он не будет таким безудержным.Чиновник также сказал позже, что окончательная реализация может быть разной в зависимости от плана выполнения, а значит, конечный результат нестабилен.
3. Как решить
Поскольку в официальной документации также говорится, что на результат выполнения во многом влияет план выполнения, значит, при использованииorder by
Нам нужно уточнить область запроса, уточнить условия запроса и позволить MySQL лучше понять наши потребности во время выполнения. Например, в приведенном выше примере, помимо использования весов, вы также можете увеличить время создания в качестве одного из условий сортировки. Конкретный SQL выглядит следующим образом:
SELECT * FROM member_tool_config WHERE isv_id IS NULL and user_id IS NULL ORDER BY weight,gmt_create ASC;
4. Резюме
Хотя проблема решена и официальная документация проверена, мне всегда кажется, что ее немного не хватает. Если у кого-то есть лучшее объяснение, пожалуйста, поделитесь. Наконец, я хотел бы поблагодарить менеджера по продукту за то, что он позволил Xianyu почувствовать «интересность» MySQL во время написания ошибок.
Reference
[1]LIMIT Query Optimization: https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
В этой статье используетсяmdniceнабор текста