MySQL分頁排序中的坑

今天項目提測,被測出了一個奇怪的bug,第一頁最后一條數(shù)據(jù)和第二頁的第一條數(shù)據(jù)重復(fù)了,并且神奇的丟失了一個條數(shù)據(jù),下面開始來分析一下這個場景。

第一頁
第二頁

場景為對一些作業(yè)進行按時間排序,但是有的作業(yè)時間是相同的。

對代碼進行查看發(fā)現(xiàn),代碼并沒有什么問題,只是簡單的查詢?nèi)磿r間排序分頁返回給前端。

所以去看一看mysql對limit的解釋,從官方文檔中發(fā)現(xiàn)了這樣一句話

如果多個行在列中具有相同的值ORDER BY,則服務(wù)器可以按任意順序自由返回這些行,并且根據(jù)總體執(zhí)行計劃可能會有所不同。換句話說,這些行的排序順序?qū)τ跓o序列是非確定性的。

根據(jù)這句話我們可以發(fā)現(xiàn),在order by的值相同時,返回的順序不一定一致。

下面我們來思考一下造成這個坑的原因是什么呢?

在MySQL 5.6版本,優(yōu)化器在遇到order by xxx limit x,x 時,會做一個優(yōu)化,使用優(yōu)先隊列,來進行排序,這樣的好處在于在排序過程中,僅保留需要的n條數(shù)據(jù)即可。

如果你已經(jīng)熟悉了各大排序的特點,那么可以知道堆排序是不穩(wěn)定排序,所以導(dǎo)致了今天的這個問題。

下面分享一下各個排序的穩(wěn)定性:

  1. 冒泡排序:穩(wěn)定
  2. 選擇排序:不穩(wěn)定,每次選擇最小的與之前交換,可能會將相同元素的順序打亂
  3. 插入排序:穩(wěn)定
  4. 快速排序:不穩(wěn)定,不穩(wěn)定發(fā)生在key與相遇點進行交換時。
  5. 歸并排序:穩(wěn)定
  6. 基數(shù)排序:穩(wěn)定
  7. 希爾排序:不穩(wěn)定,插入順序不同,相同元素可能在不同的插入順序中分別排序
  8. 堆排序:不穩(wěn)定,可能子節(jié)點與父節(jié)點進行交換時,將兩個相同元素順序打亂,5(left) 6(root) 5(right) -> 5 5 6,此時right位于5的left

下面說一下問題的解決方法:

  1. order by后加一個唯一字段(id)進行排序
  2. 給order by字段加上索引

世上沒有解決不了的bug,也許只是方向不對

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容