Limit 分頁的一個bug

問題描述

今天遇到了一個bug, 非常奇怪,實習生用代碼了一個limit 的分頁,定時任務執(zhí)行時候發(fā)現(xiàn)每次都會丟一半的數(shù)據(jù)。
仔細查看了日志發(fā)現(xiàn)共有18頁,但是從第10頁開始每次查詢到的數(shù)據(jù)都是0條 ???
哈哈哈,有點蒙

原因分析

然后仔細梳理了一下業(yè)務邏輯發(fā)現(xiàn)了,原來犯了如此低級的一個錯誤, ??????

業(yè)務邏輯:
起一個定時任務,消費100條數(shù)據(jù),采用分頁每次讀取50條,消費成功后更新數(shù)據(jù)狀態(tài),然后再取下一頁
因為生產(chǎn)環(huán)境數(shù)據(jù)量太大,所以在本機造了20條數(shù)據(jù),每次讀4條 進行測試
代碼運行分析如下:
第一輪

//查詢總數(shù)
SELECT COUNT(1) from students s2 

//for 循環(huán)分頁查詢 
 select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 0, 4 
<結(jié)果返回的是sID包含:1,2,3,4>

//消費完成更新數(shù)據(jù)狀態(tài)
UPDATE students set sInt_10 = 1 where sId in (1,2,3,4)

第二輪

select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 4, 4
<結(jié)果返回的是sID包含:9,10,11,12>

image.png
//消費完成更新數(shù)據(jù)狀態(tài)
UPDATE students set sInt_10 = 1 where sId in (9,10,11,12)

到這里發(fā)現(xiàn)問題了,居然返回的是9,10,11,12 而不是5,6,7,8; 說明原本設(shè)想的第2頁數(shù)據(jù)被跳過了;
忽然反應過來了,因為我們加了where 條件導致第一次更新了1,2,3,4的狀態(tài)后,第二次再查詢只是查了1,2,3,4之外的數(shù)據(jù),但是我們的limit 又改變了offset; 所以導致第二次查詢丟1頁(5,6,7,8);第三次查詢丟2頁(5,6,7,8; 13,14,15,16)

解決方案

每次都讀4條,一直到讀取不到數(shù)據(jù)為止
第二次查詢

select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 0, 4
image.png

更新第二次查詢到的數(shù)據(jù)狀態(tài)

UPDATE students set sInt_10 = 1 where sId in (5,6,7,8)

第三次查詢

select * from students s where s.sInt_10 = 0 order by s.sId ASC LIMIT 0, 4
image.png

更新第三次查詢到的數(shù)據(jù)狀態(tài)

UPDATE students set sInt_10 = 1 where sId in (13,14,15,16)

這樣就一切正常了

總結(jié)

其實這個分頁問題是一個很基礎(chǔ)的問題,但是這次踩坑是因為實際項目中大家都很少寫sql了。中型公司有ORM,大型公司有專業(yè)DBA,程序員只需要RPC 走微服務就好了;
所以基礎(chǔ)知識還是很重要

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

相關(guān)閱讀更多精彩內(nèi)容

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