成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

寫了一個(gè)分頁(yè) SQL,因?yàn)榇中某隽?Bug 造成了 OOM!

數(shù)據(jù)庫(kù) MySQL
本文介紹了一個(gè)生產(chǎn)事故,并對(duì)事故和改進(jìn)方法進(jìn)行了分析,希望對(duì)你理解數(shù)據(jù)庫(kù)分頁(yè)有所幫助。

大家好,我是君哥。

最近上完線后,凌晨收到一個(gè)生產(chǎn)告警,一個(gè) OOM 異常導(dǎo)致了服務(wù)重啟。今天來分享一下這個(gè)事故。

1.事故現(xiàn)場(chǎng)

事故的代碼邏輯并不復(fù)雜,從一個(gè)大概有 8 萬(wàn)數(shù)據(jù)的表里面查出數(shù)據(jù),匯總后對(duì)數(shù)據(jù)做處理。因?yàn)閿?shù)據(jù)量有 8 萬(wàn),這里做了分頁(yè)查詢,每頁(yè)查詢 1000 條。這里貼一下代碼:這里我們假定這個(gè)表名叫 sql_bug。

private void testSQLBug(){
 List<SQLBugData> sqlBugDatas = new ArrayList<>();
 int pageSize = 1000;
 int pageNumber = 0;
 while (true){
  List<SQLBugData> data = sqlBugDataMapper.queryData(pageSize, pageNumber);
  if (CollectionUtils.isEmpty(data)){
   break;
  }
  //過濾掉不符合條件的數(shù)據(jù)。
  filterData(data);
  sqlBugDatas.addAll(data);
  if (data.size() <= pageSize){
   break;
  }
  pageNumber++;
 }
}

下面我們看一下 sql,這里用 Oracle 數(shù)據(jù)庫(kù),orm 框架用的 mybatis,sql 在 mapper.xml 文件中:

select * from sql_bug order by id
offset #{pageNumber} rows fetch first #{pageSize} rows only

仔細(xì)看上面的 sql,我們可以看到 Offset 這個(gè)參數(shù)傳入了 pageNumber。那后果是什么呢?查詢語(yǔ)句每次偏移量加 1,表里有 8 萬(wàn)條數(shù)據(jù),相當(dāng)于得查詢 79000 次循環(huán)才能結(jié)束。sqlBugDatas 數(shù)據(jù)量一直累加,最終觸發(fā) OOM。

2.原因分析

開發(fā)同事為什么會(huì)出這個(gè) bug 呢?原因是錯(cuò)誤地把 offset 這個(gè)變量理解成是頁(yè)碼的偏移量。正確的寫法:

select * from sql_bug order by id
offset #{pageNumber}*#{pageSize} rows fetch first #{pageSize} rows only

為什么測(cè)試沒有測(cè)出來呢?測(cè)試環(huán)境數(shù)據(jù)量比較小,并沒有出現(xiàn) OOM 的情況。

代碼 review 為什么沒有發(fā)現(xiàn)?由于交付的代碼量很大,做代碼 review 的同事主要關(guān)注點(diǎn)在業(yè)務(wù)邏輯的正確性上面,并沒有精力能看到這么細(xì)節(jié)的問題。

3.分頁(yè)寫法

使用 offset 進(jìn)行分頁(yè)的寫法很常見,比如使用 MySQL 的 limit 語(yǔ)法,sql 如下:

select * from sql_bug order by id
limit #{pageNumber}*#{pageSize},#{pageSize}

但是使用 Offset 進(jìn)行分頁(yè)的寫法并不推薦,因?yàn)橛猩疃确猪?yè)的性能問題,后面的頁(yè)耗時(shí)會(huì)越來越多。下圖是阿里開發(fā)手冊(cè)關(guān)于分頁(yè)場(chǎng)景的一個(gè)規(guī)范。

遵循這個(gè)規(guī)范,我們每次查詢的時(shí)候,不妨傳入一個(gè)主鍵 id。先改寫一下代碼:

private void testSQLBug(){
 List<SQLBugData> sqlBugDatas = new ArrayList<>();
 String id = null;
 int pageSize = 0;
 while (true){
  List<SQLBugData> data = sqlBugDataMapper.queryData(id, pageSize);
  if (CollectionUtils.isEmpty(data)){
   break;
  }
  id = data.get(data.size()-1).getId();
  //過濾掉不符合條件的數(shù)據(jù)。
  filterData(data);
  sqlBugDatas.addAll(data);
  if (data.size() <= pageSize){
   break;
  }
 }
}

配合上面代碼,把 sql 也改寫一下,這里使用 mysql 語(yǔ)法:

select * from sql_bug 
<if test="id != null">            
 where id <![CDATA[>]]> #{id}
</if>   
order by id
limit #{pageSize}

也可以使用 rownum 來控制,下面再改寫一下(Oracle 語(yǔ)法):

select * from(
 select * from sql_bug 
 <if test="id != null">            
  where id <![CDATA[>]]> #{id}
 </if>   
 order by id
)
where rownum <![CDATA[<]]> #{pageSize} + 1

我個(gè)人更推薦 rownum 寫法,原因有 2 個(gè):

  • 這種語(yǔ)法更容易理解,如果出問題的 sql 使用這個(gè)語(yǔ)法,大概率是不會(huì)出這個(gè) bug 的;
  • 國(guó)內(nèi)好多公司做信創(chuàng)改造,國(guó)產(chǎn)數(shù)據(jù)庫(kù)對(duì)這種語(yǔ)法支持更好一些。

4.總結(jié)

本文介紹了一個(gè)生產(chǎn)事故,并對(duì)事故和改進(jìn)方法進(jìn)行了分析,希望對(duì)你理解數(shù)據(jù)庫(kù)分頁(yè)有所幫助。

責(zé)任編輯:姜華 來源: 君哥聊技術(shù)
相關(guān)推薦

2012-03-10 21:22:57

Lumia

2018-05-23 21:19:44

云計(jì)算企業(yè)云支出

2009-03-18 10:54:45

職場(chǎng)誠(chéng)信危機(jī)

2013-09-04 09:59:33

擬物化UI設(shè)計(jì)扁平化

2020-10-28 08:18:54

Linux 5.10函數(shù)Linux

2022-11-13 10:07:22

SpringSpringBoot

2018-10-16 09:45:36

谷歌AI游戲

2023-08-07 13:33:50

谷歌AI

2025-02-11 09:17:57

2020-11-02 08:19:18

RPC框架Java

2020-05-07 07:42:00

Bugrm -fr *

2021-10-08 07:50:57

軟件設(shè)計(jì)程序

2021-08-12 00:03:37

JSStrview視圖

2024-02-04 16:14:38

線程開發(fā)

2021-05-10 09:52:35

技術(shù)隱私瀏覽器

2020-07-21 08:42:16

搞垮服務(wù)器日志

2014-12-17 09:40:22

dockerLinuxPaaS

2025-02-13 07:00:00

Dubbo-goJava服務(wù)端

2009-09-14 17:08:02

WebFormView

2024-04-22 00:00:01

Redis集群
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美一区二区三区视频 | 天天夜夜人人 | 成人天堂 | 欧美成人不卡 | 国产精品久久久久久久久久东京 | 一区二区三区中文字幕 | 国产精品国产精品国产专区不片 | 九九久久免费视频 | 久久午夜视频 | 久久国产婷婷国产香蕉 | 福利视频网 | 国产一区h | 视频一区二区在线观看 | 亚洲精品日本 | 看一级毛片 | www.久久 | 国产精品波多野结衣 | 特级毛片 | 一区二区三区回区在观看免费视频 | 在线成人一区 | 日韩精品在线免费 | 国产一区二区三区在线 | 奇米影视在线 | 国产免费一区二区 | 久久久久一区二区 | 久久久久久毛片免费观看 | 国产在线二区 | 国产亚洲精品成人av久久ww | 欧美日本亚洲 | 亚洲成人精品 | 国产精品激情在线 | 成人网视频 | 99小视频 | 美女黄视频网站 | 亚洲小视频在线播放 | av在线免费观看网站 | 天天草狠狠干 | 中文字幕视频在线看5 | 99综合网 | 精品国产乱码久久久久久闺蜜 | 亚洲男人网 |