MYSQL查詢結(jié)果實(shí)現(xiàn)發(fā)送給客戶端
MYSQL取數(shù)據(jù)和發(fā)數(shù)據(jù)的流程(邊讀邊發(fā))
- 1.服務(wù)端,獲取一行數(shù)據(jù),存到net_buffer中,可以理解為結(jié)果集
- 2.繼續(xù)讀取數(shù)據(jù),直到net_buffer寫(xiě)滿,調(diào)用網(wǎng)絡(luò)接口發(fā)出去
- 3.如果發(fā)送成功,就清空net_buffer
- 4.如果發(fā)送失敗,就說(shuō)明socket send buffer 寫(xiě)滿了,進(jìn)入等待,直到有足夠的空間可寫(xiě),再繼續(xù)發(fā)送。
注意net_buffer滿了就發(fā)給客戶端而不是等查詢語(yǔ)句查詢完所有數(shù)據(jù)才發(fā),其中net_buffer默認(rèn)大小是16k,所以服務(wù)器占用內(nèi)存最多是16k,不會(huì)因?yàn)椴樵?00G的數(shù)據(jù)導(dǎo)致內(nèi)存爆掉。
如果客戶端接收數(shù)據(jù)太慢,就會(huì)導(dǎo)致數(shù)據(jù)在socket send buffer 堆積,導(dǎo)致發(fā)送數(shù)據(jù)到客戶端的線程進(jìn)入等待,由于net_buffer數(shù)據(jù)沒(méi)有發(fā)送出去,net_buffer一直沒(méi)法清空,查詢語(yǔ)句就要等待net_buffer清空才能繼續(xù)執(zhí)行,導(dǎo)致服務(wù)端查詢速度變慢。
Sending to client
假設(shè)使用show processlist發(fā)現(xiàn)一條語(yǔ)句的state是“Sending to client”,就是上面說(shuō)的在等待socket send buffer 有足夠空間可以將net_buffer中的數(shù)據(jù)寫(xiě)進(jìn)去發(fā)送給客戶端。
Sending Data
一個(gè)查詢語(yǔ)句的狀態(tài)是這樣的:
- 1.首先將語(yǔ)句狀態(tài)寫(xiě)成Sending Data
- 2.將查詢需要的列信息發(fā)送給客戶端
- 3.繼續(xù)執(zhí)行查詢
- 4.完成查詢,將狀態(tài)寫(xiě)成空
但是MYSQL8好像改了,我看到的是executing
LRU(Least Recently Used )算法
最近最少使用算法是一種內(nèi)存淘汰機(jī)制,核心是--內(nèi)存空間不足時(shí),將最少使用的數(shù)據(jù)頁(yè)淘汰
innodb管理Buffer Pool 的LRU算法,是通過(guò)鏈表來(lái)實(shí)現(xiàn)的,每個(gè)鏈表節(jié)點(diǎn)就是一個(gè)數(shù)據(jù)頁(yè)。
- 1.鏈表中任意一個(gè)數(shù)據(jù)頁(yè)被訪問(wèn)到時(shí),就將這個(gè)節(jié)點(diǎn)放在鏈表的頭節(jié)點(diǎn)
- 2.當(dāng)訪問(wèn)一個(gè)鏈表中沒(méi)有的數(shù)據(jù)頁(yè),需要加載到BufferPool并且放在頭節(jié)點(diǎn)
- 3.當(dāng)新節(jié)點(diǎn)要進(jìn)來(lái)時(shí),如果鏈表空間不足了,就把鏈表尾節(jié)點(diǎn)從鏈表中刪除。
但是這個(gè)LRU在某些場(chǎng)景時(shí)有很大問(wèn)題的
比如一個(gè)語(yǔ)句查詢了歷史數(shù)據(jù)表(非業(yè)務(wù)熱點(diǎn)數(shù)據(jù)表)的所有數(shù)據(jù),這就會(huì)把鏈表中之前維護(hù)的熱點(diǎn)數(shù)據(jù)頁(yè)都淘汰掉,留下一些非業(yè)務(wù)熱點(diǎn)數(shù)據(jù)頁(yè),會(huì)導(dǎo)致緩存命中率急劇降低,磁盤(pán)IO壓力倍增。
針對(duì)這種清空,Innodb對(duì)LRU算法進(jìn)行了優(yōu)化
就是對(duì)鏈表進(jìn)行了分區(qū),前5/8是young區(qū),后3/8是old區(qū)。
- 1.如果young的數(shù)據(jù)頁(yè)被訪問(wèn)到了,和普通LRU算法一樣,移到鏈表頭部。
- 2.如果鏈表空間滿了,此時(shí)有個(gè)新的數(shù)據(jù)頁(yè)要加進(jìn)來(lái),和普通LRU算法一樣首先把鏈表尾部的數(shù)據(jù)頁(yè)淘汰,不過(guò)這個(gè)新的數(shù)據(jù)頁(yè)不是放在鏈表頭部,而是放在old區(qū)的第一個(gè)位置。
- 3.對(duì)于old區(qū)的數(shù)據(jù)頁(yè),每次訪問(wèn)都要進(jìn)行判斷:
如果該數(shù)據(jù)頁(yè)在old待的時(shí)間大于1秒,就移動(dòng)到整個(gè)鏈表的頭節(jié)點(diǎn)。
如果小于1秒,就不改變位置。
這個(gè)1秒是由innodb_old_blocks_time參數(shù)控制的。
這樣一來(lái),短時(shí)間內(nèi)的非熱點(diǎn)數(shù)據(jù)只會(huì)存在于old區(qū),一段時(shí)間內(nèi)不被訪問(wèn)就慢慢掉到尾部被淘汰了,不會(huì)影響到真正的熱點(diǎn)數(shù)據(jù),它們會(huì)一直在young區(qū)。保證了不影響正常業(yè)務(wù)。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決修改mysql的data_dir所引發(fā)的錯(cuò)誤問(wèn)題
本文給大家分享解決修改mysql的data_dir所引發(fā)的錯(cuò)誤問(wèn)題,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友參考下吧2017-04-04mysql如何按字段查詢重復(fù)的數(shù)據(jù)
這篇文章主要介紹了mysql如何按字段查詢重復(fù)的數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05MySQL InnoDB架構(gòu)的相關(guān)總結(jié)
InnoDB存儲(chǔ)引擎架構(gòu)作為MySQL最常用的存儲(chǔ)引擎,每個(gè)后端程序員都應(yīng)有所了解,本文將具體講述MySQL InnoDB架構(gòu)的相關(guān)知識(shí),感興趣的朋友可以參考下2021-05-05MySQL實(shí)現(xiàn)向表中添加多個(gè)字段 類型 注釋
這篇文章主要介紹了MySQL實(shí)現(xiàn)向表中添加多個(gè)字段 類型 注釋方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04檢查并修復(fù)mysql數(shù)據(jù)庫(kù)表的具體方法
這篇文章介紹了檢查并修復(fù)mysql數(shù)據(jù)庫(kù)表的具體方法,有需要的朋友可以參考一下2013-09-09SQL中CAST()實(shí)例之轉(zhuǎn)換數(shù)據(jù)類型
CAST函數(shù)用于將某種數(shù)據(jù)類型的表達(dá)式顯式轉(zhuǎn)換為另一種數(shù)據(jù)類型,下面這篇文章主要給大家介紹了關(guān)于SQL中CAST()實(shí)例之轉(zhuǎn)換數(shù)據(jù)類型的相關(guān)資料,需要的朋友可以參考下2023-01-01mysql中索引與FROM_UNIXTIME的問(wèn)題
這篇文章主要介紹了mysql中索引與FROM_UNIXTIME的問(wèn)題的相關(guān)資料,需要的朋友可以參考下2017-05-05