电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

淺談MySQL數(shù)據(jù)查詢太多會OOM嗎

瀏覽:8日期:2023-10-17 18:44:27
目錄全表掃描對server層的影響全表掃描對InnoDB的影響InnoDB內(nèi)存管理小結(jié)

我的主機內(nèi)存只有100G,現(xiàn)在要全表掃描一個200G大表,會不會把DB主機的內(nèi)存用光?

邏輯備份時,可不就是做整庫掃描嗎?若這樣就會把內(nèi)存吃光,邏輯備份不是早就掛了?所以大表全表掃描,看起來應(yīng)該沒問題。這是為啥呢?

全表掃描對server層的影響

假設(shè),我們現(xiàn)在要對一個200G的InnoDB表db1. t,執(zhí)行一個全表掃描。當(dāng)然,你要把掃描結(jié)果保存在客戶端,會使用類似這樣的命令:

mysql -h$host -P$port -u$user -p$pwd -e 'select * from db1.t' > $target_file

InnoDB數(shù)據(jù)保存在主鍵索引上,所以全表掃描實際上是直接掃描表t的主鍵索引。這條查詢語句由于沒有其他判斷條件,所以查到的每一行都可以直接放到結(jié)果集,然后返回給客戶端。

那么,這個“結(jié)果集”存在哪里呢?服務(wù)端無需保存一個完整結(jié)果集。取數(shù)據(jù)和發(fā)數(shù)據(jù)的流程是這樣的:

獲取一行,寫到net_buffer。這塊內(nèi)存的大小是由參數(shù)net_buffer_length定義,默認(rèn)16k 重復(fù)獲取行,直到net_buffer寫滿,調(diào)用網(wǎng)絡(luò)接口發(fā)出去 若發(fā)送成功,就清空net_buffer,然后繼續(xù)取下一行,并寫入net_buffer 若發(fā)送函數(shù)返回EAGAIN或WSAEWOULDBLOCK,就表示本地網(wǎng)絡(luò)棧(socket send buffer)寫滿了,進(jìn)入等待。直到網(wǎng)絡(luò)棧重新可寫,再繼續(xù)發(fā)送

查詢結(jié)果發(fā)送流程

淺談MySQL數(shù)據(jù)查詢太多會OOM嗎

可見:

一個查詢在發(fā)送過程中,占用的MySQL內(nèi)部的內(nèi)存最大就是net_buffer_length這么大,不會達(dá)到200G socket send buffer 也不可能達(dá)到200G(默認(rèn)定義/proc/sys/net/core/wmem_default),若socket send buffer被寫滿,就會暫停讀數(shù)據(jù)的流程

所以MySQL其實是“邊讀邊發(fā)”。這意味著,若客戶端接收得慢,會導(dǎo)致MySQL服務(wù)端由于結(jié)果發(fā)不出去,這個事務(wù)的執(zhí)行時間變長。

比如下面這個狀態(tài),就是當(dāng)客戶端不讀socket receive buffer內(nèi)容時,在服務(wù)端show processlist看到的結(jié)果。

服務(wù)端發(fā)送阻塞

淺談MySQL數(shù)據(jù)查詢太多會OOM嗎

若看到State一直是“Sending to client”,說明服務(wù)器端的網(wǎng)絡(luò)棧寫滿了。

若客戶端使用–quick參數(shù),會使用mysql_use_result方法:讀一行處理一行。假設(shè)某業(yè)務(wù)的邏輯較復(fù)雜,每讀一行數(shù)據(jù)以后要處理的邏輯若很慢,就會導(dǎo)致客戶端要過很久才取下一行數(shù)據(jù),可能就會出現(xiàn)上圖結(jié)果。

因此,對于正常的線上業(yè)務(wù)來說,若一個查詢的返回結(jié)果不多,推薦使用mysql_store_result接口,直接把查詢結(jié)果保存到本地內(nèi)存。

當(dāng)然前提是查詢返回結(jié)果不多。如果太多,因為執(zhí)行了一個大查詢導(dǎo)致客戶端占用內(nèi)存近20G,這種情況下就需要改用mysql_use_result接口。

若你在自己負(fù)責(zé)維護(hù)的MySQL里看到很多個線程都處于“Sending to client”,表明你要讓業(yè)務(wù)開發(fā)同學(xué)優(yōu)化查詢結(jié)果,并評估這么多的返回結(jié)果是否合理。

若要快速減少處于這個狀態(tài)的線程的話,可以將net_buffer_length設(shè)置更大。

有時,實例上看到很多查詢語句狀態(tài)是“Sending data”,但查看網(wǎng)絡(luò)也沒什么問題,為什么Sending data要這么久?一個查詢語句的狀態(tài)變化是這樣的:

MySQL查詢語句進(jìn)入執(zhí)行階段后,先把狀態(tài)設(shè)置成 Sending data 然后,發(fā)送執(zhí)行結(jié)果的列相關(guān)的信息(meta data) 給客戶端 再繼續(xù)執(zhí)行語句的流程 執(zhí)行完成后,把狀態(tài)設(shè)置成空字符串。

即“Sending data”并不一定是指“正在發(fā)送數(shù)據(jù)”,而可能是處于執(zhí)行器過程中的任意階段。比如,你可以構(gòu)造一個鎖等待場景,就能看到Sending data狀態(tài)。

讀全表被鎖:

session1 session2 begin select * from t where id=1 for update 啟動事務(wù)select * from t lock in share mode (blocked)

Sending data狀態(tài)

淺談MySQL數(shù)據(jù)查詢太多會OOM嗎

可見session2是在等鎖,狀態(tài)顯示為Sending data。

僅當(dāng)一個線程處于“等待客戶端接收結(jié)果”的狀態(tài),才會顯示'Sending to client' 若顯示成“Sending data”,它的意思只是“正在執(zhí)行”

所以,查詢的結(jié)果是分段發(fā)給客戶端,因此掃描全表,查詢返回大量數(shù)據(jù),并不會把內(nèi)存打爆。

以上是server層的處理邏輯,在InnoDB引擎里又是怎么處理?

全表掃描對InnoDB的影響

InnoDB內(nèi)存的一個作用,是保存更新的結(jié)果,再配合redo log,避免隨機寫盤。

內(nèi)存的數(shù)據(jù)頁是在Buffer Pool (簡稱為BP)管理,在WAL里BP起加速更新的作用。BP還能加速查詢。

由于WAL,當(dāng)事務(wù)提交時,磁盤上的數(shù)據(jù)頁是舊的,若這時馬上有個查詢來讀該數(shù)據(jù)頁,是不是要馬上把redo log應(yīng)用到數(shù)據(jù)頁?

不需要。因為此時,內(nèi)存數(shù)據(jù)頁的結(jié)果是最新的,直接讀內(nèi)存頁即可。這時查詢無需讀磁盤,直接從內(nèi)存取結(jié)果,速度很快。所以,Buffer Pool能加速查詢。

而BP對查詢的加速效果,依賴于一個重要的指標(biāo),即:內(nèi)存命中率。可以在show engine innodb status結(jié)果中,查看一個系統(tǒng)當(dāng)前的BP命中率。一般情況下,一個穩(wěn)定服務(wù)的線上系統(tǒng),要保證響應(yīng)時間符合要求的話,內(nèi)存命中率要在99%以上。

執(zhí)行show engine innodb status ,可以看到“Buffer pool hit rate”字樣,顯示的就是當(dāng)前的命中率。比如下圖命中率,就是100%。

淺談MySQL數(shù)據(jù)查詢太多會OOM嗎

若所有查詢需要的數(shù)據(jù)頁都能夠直接從內(nèi)存得到,那是最好的,對應(yīng)命中率100%。

InnoDB Buffer Pool的大小是由參數(shù) innodb_buffer_pool_size確定,一般建議設(shè)置成可用物理內(nèi)存的60%~80%。

在大約十年前,單機的數(shù)據(jù)量是上百個G,而物理內(nèi)存是幾個G;現(xiàn)在雖然很多服務(wù)器都能有128G甚至更高的內(nèi)存,但是單機的數(shù)據(jù)量卻達(dá)到了T級別。

所以,innodb_buffer_pool_size小于磁盤數(shù)據(jù)量很常見。若一個 Buffer Pool滿了,而又要從磁盤讀入一個數(shù)據(jù)頁,那肯定是要淘汰一個舊數(shù)據(jù)頁的。

InnoDB內(nèi)存管理

使用的最近最少使用 (Least Recently Used, LRU)算法,淘汰最久未使用數(shù)據(jù)。

基本LRU算法

TODO

InnoDB管理BP的LRU算法,是用鏈表實現(xiàn)的: state1,鏈表頭部是P1,表示P1是最近剛被訪問過的數(shù)據(jù)頁 此時,一個讀請求訪問P3,因此變成狀態(tài)2,P3被移到最前 狀態(tài)3表示,這次訪問的數(shù)據(jù)頁不存在于鏈表,所以需要在BP中新申請一個數(shù)據(jù)頁Px,加到鏈表頭。但由于內(nèi)存已滿,不能申請新內(nèi)存。于是清空鏈表末尾Pm數(shù)據(jù)頁內(nèi)存,存入Px的內(nèi)容,放到鏈表頭部

最終就是最久沒有被訪問的數(shù)據(jù)頁Pm被淘汰。若此時要做一個全表掃描,會咋樣?若要掃描一個200G的表,而這個表是一個歷史數(shù)據(jù)表,平時沒有業(yè)務(wù)訪問它。

那么,按此算法掃描,就會把當(dāng)前BP里的數(shù)據(jù)全部淘汰,存入掃描過程中訪問到的數(shù)據(jù)頁的內(nèi)容。也就是說BP里主要放的是這個歷史數(shù)據(jù)表的數(shù)據(jù)。

對于一個正在做業(yè)務(wù)服務(wù)的庫,這可不行呀。你會看到,BP內(nèi)存命中率急劇下降,磁盤壓力增加,SQL語句響應(yīng)變慢。

所以,InnoDB不能直接使用原始的LRU。InnoDB對其進(jìn)行了優(yōu)化。

改進(jìn)的LRU算法

淺談MySQL數(shù)據(jù)查詢太多會OOM嗎

InnoDB按5:3比例把鏈表分成New區(qū)和Old區(qū)。圖中LRU_old指向的就是old區(qū)域的第一個位置,是整個鏈表的5/8處。即靠近鏈表頭部的5/8是New區(qū)域,靠近鏈表尾部的3/8是old區(qū)域。

改進(jìn)后的LRU算法執(zhí)行流程:

1. 狀態(tài)1,要訪問P3,由于P3在New區(qū),和優(yōu)化前LRU一樣,將其移到鏈表頭部 =》狀態(tài)22. 之后要訪問一個新的不存在于當(dāng)前鏈表的數(shù)據(jù)頁,這時依然是淘汰掉數(shù)據(jù)頁Pm,但新插入的數(shù)據(jù)頁Px,是放在LRU_old處3. 處于old區(qū)的數(shù)據(jù)頁,每次被訪問的時候都要做如下判斷:

若該數(shù)據(jù)頁在LRU鏈表中存在的時間超過1s,就把它移動到鏈表頭部 若該數(shù)據(jù)頁在LRU鏈表中存在的時間短于1s,位置保持不變。1s是由參數(shù)innodb_old_blocks_time控制,默認(rèn)值1000,單位ms。

該策略,就是為了處理類似全表掃描的操作量身定制。還是掃描200G歷史數(shù)據(jù)表:4. 掃描過程中,需要新插入的數(shù)據(jù)頁,都被放到old區(qū)域5. 一個數(shù)據(jù)頁里面有多條記錄,這個數(shù)據(jù)頁會被多次訪問到,但由于是順序掃描,這個數(shù)據(jù)頁第一次被訪問和最后一次被訪問的時間間隔不會超過1秒,因此還是會被保留在old區(qū)域6. 再繼續(xù)掃描后續(xù)的數(shù)據(jù),之前的這個數(shù)據(jù)頁之后也不會再被訪問到,于是始終沒有機會移到鏈表頭部(New區(qū)),很快就會被淘汰出去。

可以看到,這個策略最大的收益,就是在掃描這個大表的過程中,雖然也用到了BP,但對young區(qū)完全沒有影響,從而保證了Buffer Pool響應(yīng)正常業(yè)務(wù)的查詢命中率。

小結(jié)

MySQL采用的是邊算邊發(fā)的邏輯,因此對于數(shù)據(jù)量很大的查詢結(jié)果來說,不會在server端保存完整的結(jié)果集。所以,如果客戶端讀結(jié)果不及時,會堵住MySQL的查詢過程,但是不會把內(nèi)存打爆。

而對于InnoDB引擎內(nèi)部,由于有淘汰策略,大查詢也不會導(dǎo)致內(nèi)存暴漲。并且,由于InnoDB對LRU算法做了改進(jìn),冷數(shù)據(jù)的全表掃描,對Buffer Pool的影響也能做到可控。

全表掃描還是比較耗費IO資源的,所以業(yè)務(wù)高峰期還是不能直接在線上主庫執(zhí)行全表掃描的。

到此這篇關(guān)于淺談MySQL數(shù)據(jù)查詢太多會OOM嗎的文章就介紹到這了,更多相關(guān)MySQL數(shù)據(jù)查詢OOM內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: MySQL 數(shù)據(jù)庫
相關(guān)文章:
主站蜘蛛池模板: 铝合金线槽_铝型材加工_空调挡水板厂家-江阴炜福金属制品有限公司 | 全自动面膜机_面膜折叠机价格_面膜灌装机定制_高速折棉机厂家-深圳市益豪科技有限公司 | 爆破器材运输车|烟花爆竹运输车|1-9类危险品厢式运输车|湖北江南专用特种汽车有限公司 | 水平筛厂家-三轴椭圆水平振动筛-泥沙震动筛设备_山东奥凯诺矿机 包装设计公司,产品包装设计|包装制作,包装盒定制厂家-汇包装【官方网站】 | 广州小程序开发_APP开发公司_分销商城系统定制_小跑科技 | MES系统-WMS系统-MES定制开发-制造执行MES解决方案-罗浮云计算 | 玉米深加工机械,玉米加工设备,玉米加工机械等玉米深加工设备制造商-河南成立粮油机械有限公司 | 发电机价格|发电机组价格|柴油发电机价格|柴油发电机组价格网 | ALC墙板_ALC轻质隔墙板_隔音防火墙板_轻质隔墙材料-湖北博悦佳 | 机床主轴维修|刀塔维修|C轴维修-常州翔高精密机械有限公司 | 济南ISO9000认证咨询代理公司,ISO9001认证,CMA实验室认证,ISO/TS16949认证,服务体系认证,资产管理体系认证,SC食品生产许可证- 济南创远企业管理咨询有限公司 郑州电线电缆厂家-防火|低压|低烟无卤电缆-河南明星电缆 | 大_小鼠elisa试剂盒-植物_人Elisa试剂盒-PCR荧光定量试剂盒-上海一研生物科技有限公司 | 洛阳防爆合格证办理-洛阳防爆认证机构-洛阳申请国家防爆合格证-洛阳本安防爆认证代办-洛阳沪南抚防爆电气技术服务有限公司 | 快干水泥|桥梁伸缩缝止水胶|伸缩缝装置生产厂家-广东广航交通科技有限公司 | 英国雷迪地下管线探测仪-雷迪RD8100管线仪-多功能数字听漏仪-北京迪瑞进创科技有限公司 | 丁基胶边来料加工,医用活塞边角料加工,异戊二烯橡胶边来料加工-河北盛唐橡胶制品有限公司 | 复合土工膜厂家|hdpe防渗土工膜|复合防渗土工布|玻璃纤维|双向塑料土工格栅-安徽路建新材料有限公司 | 【MBA备考网】-2024年工商管理硕士MBA院校/报考条件/培训/考试科目/提前面试/考试/学费-MBA备考网 | 衬氟止回阀_衬氟闸阀_衬氟三通球阀_衬四氟阀门_衬氟阀门厂-浙江利尔多阀门有限公司 | 防爆电机_ybx3系列电机_河南省南洋防爆电机有限公司 | 硅胶布|电磁炉垫片|特氟龙胶带-江苏浩天复合材料有限公司 | 宁夏活性炭_防护活性炭_催化剂载体炭-宁夏恒辉活性炭有限公司 | 压力变送器-上海武锐自动化设备有限公司 | 石膏基自流平砂浆厂家-高强石膏基保温隔声自流平-轻质抹灰石膏粉砂浆批发-永康市汇利建设有限公司 | 浙江上沪阀门有限公司 | 蓝牙音频分析仪-多功能-四通道-八通道音频分析仪-东莞市奥普新音频技术有限公司 | 一体化隔油提升设备-餐饮油水分离器-餐厨垃圾处理设备-隔油池-盐城金球环保产业发展有限公司 | 玉米加工设备,玉米深加工机械,玉米糁加工设备.玉米脱皮制糁机 华豫万通粮机 | 苏州同创电子有限公司 - 四探针测试仪源头厂家 | 电杆荷载挠度测试仪-电杆荷载位移-管桩测试仪-北京绿野创能机电设备有限公司 | 高压绝缘垫-红色配电房绝缘垫-绿色高压绝缘地毯-上海苏海电气 | 注塑_注塑加工_注塑模具_塑胶模具_注塑加工厂家_深圳环科 | 一氧化氮泄露报警器,二甲苯浓度超标报警器-郑州汇瑞埔电子技术有限公司 | 液氮罐(生物液氮罐)百科-无锡爱思科 | 济南网站建设_济南网站制作_济南网站设计_济南网站建设公司_富库网络旗下模易宝_模板建站 | 武汉高低温试验箱_恒温恒湿试验箱厂家-武汉蓝锐环境科技有限公司 | 技德应用| 智能门锁电机_智能门锁离合器_智能门锁电机厂家-温州劲力智能科技有限公司 | 塑料检查井_双扣聚氯乙烯增强管_双壁波纹管-河南中盈塑料制品有限公司 | 蓝鹏测控平台 - 智慧车间系统 - 车间生产数据采集与分析系统 | 金属清洗剂,防锈油,切削液,磨削液-青岛朗力防锈材料有限公司 |