我經常使用order by和limit來做數據分頁顯示並排序,一直也沒發現過什麼問題。但這兩天缺遇到一個嚴重的問題,在按時間戳升序排列並用limit分批讀取數據時,卻發現在某些記錄丟失了,表中明明有的記錄確死活讀取不到。研究了大半天終於發現了問題所在,記錄一下以防忘記,也是給大家提個醒。
Ver 14.14 Distrib 5.6.11, for Linux (x86_64) using EditLine wrapper
大概5000條數據, 大部分記錄的flag都等於0,pay_time字段時間戳格式都正確
篩選出flag=0的記錄,按pay_time升序依次讀取所有數據。
使用limit分批讀取數據,如:
select id, pay_time from order_customer_new where flag=0 order by pay_time asc, id asc limit 250, 10;
在讀取數據的過程中,發現有時間戳相等的記錄,分兩次讀取出來時,可能會丟失一條記錄。見下圖,id=465的記錄就丟失了。
當排序值相等,其先後順序的不確定的。這裡我猜想:當465和466處於limit末尾時466排在前面,而當處於limit開頭時,466缺排到後面去了。所以465丟失了,466出現了兩次。
排序值相等時,其順序的不確定應該是其結果不可預測。但真正進行排序時應該會采取一定的規則以確定唯一的排序結果,也就是說,即使有相等的排序值,多次排序的結果應該是一樣的。從以前的使用經歷看,mysql是這麼做的。但這次遇到的問題似乎說明mysql並不是這樣的。不知道mysql本來就是如此,還是一個bug。
既然猜想此問題是因為排序值相等造成順序不確定引起的,那麼就試試增加排序條件讓其排序結果是確定的、唯一的。一試果然OK,如下圖所示,465出來了。