MySQL—緩存

目錄標題

  • 為什么要有Buffer Pool
    • buffer pool有多大
    • buffer pool緩存什么
  • 如何管理Buffer Pool
    • 如何管理空閑頁
    • 如何管理臟頁
    • 如何提高緩存命中率
      • 預讀失效
      • buffer pool污染
    • 臟頁什么時候會被刷入到磁盤

為什么要有Buffer Pool

雖然說MySQL的數據是存儲在磁盤中,但是也不能每次都從磁盤里面讀取數據,這樣性能是極差的。所以InnoDB存儲引擎設計了一個緩沖池(Buffer Pool),來提高數據庫的讀寫能力。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jh1cSEOi-1691669854943)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20230810195513568.png)]

有了緩沖池后:

  • 當讀取數據時,如果數據存在于 Buffer Pool 中,客戶端就會直接讀取 Buffer Pool 中的數據,否則再去磁盤中讀取。
  • 當修改數據時,首先是修改 Buffer Pool 中數據所在的頁,然后將其頁設置為臟頁,最后由后臺線程將臟頁寫入到磁盤。

buffer pool有多大

Buffer Pool 是在 MySQL 啟動的時候,向操作系統申請的一片連續的內存空間,默認配置下 Buffer Pool 只有 128MB 。可以通過調整 innodb_buffer_pool_size 參數來設置 Buffer Pool 的大小,一般建議設置成可用物理內存的 60%~80%。

buffer pool緩存什么

InnoDB會把存儲的數據劃分為若干個頁,以頁作為磁盤和內存交互的基本單位,一個頁默認大小為16KB,MySQL啟動時,InnoDB會為buffer pool申請一篇連續的內存空間,然后按照默認的16KB的大小劃分出一個個的頁,buffer pool中的頁就叫做緩存頁。

Buffer Pool 除了緩存「索引頁」和「數據頁」,還包括了 undo 頁,插入緩存、自適應哈希索引、鎖信息等等。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3kfPU1xv-1691669854944)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20230810195810532.png)]

為了更好的管理這些在 Buffer Pool 中的緩存頁,InnoDB 為每一個緩存頁都創建了一個控制塊,控制塊信息包括「緩存頁的表空間、頁號、緩存頁地址、鏈表節點」等等。

控制塊也是占有內存空間的,它是放在 Buffer Pool 的最前面,接著才是緩存頁,如下圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SJ0ZMqA3-1691669854945)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20230810200153750.png)]

上圖中控制塊和緩存頁之間灰色部分稱為碎片空間。

如何管理Buffer Pool

如何管理空閑頁

為了能夠快速找到空閑的緩存頁,可以使用鏈表結構,將空閑緩存頁的「控制塊」作為鏈表的節點,這個鏈表稱為 Free 鏈表(空閑鏈表)。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qfQgWFBG-1691669854945)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20230810200339489.png)]

Free 鏈表上除了有控制塊,還有一個頭節點,該頭節點包含鏈表的頭節點地址,尾節點地址,以及當前鏈表中節點的數量等信息。

Free 鏈表節點是一個一個的控制塊,而每個控制塊包含著對應緩存頁的地址,所以相當于 Free 鏈表節點都對應一個空閑的緩存頁。

有了 Free 鏈表后,每當需要從磁盤中加載一個頁到 Buffer Pool 中時,就從 Free鏈表中取一個空閑的緩存頁,并且把該緩存頁對應的控制塊的信息填上,然后把該緩存頁對應的控制塊從 Free 鏈表中移除。

如何管理臟頁

buffer pool不僅提高讀性能,還要提高寫性能。在更新數據的時候,不需要每次都要寫入磁盤,而是將buffer pool對應的緩存頁標記為臟頁,然后由后臺線程將臟頁寫入到磁盤。

那為了能快速知道哪些緩存頁是臟的,于是就設計出 Flush 鏈表,它跟 Free 鏈表類似的,鏈表的節點也是控制塊,區別在于 Flush 鏈表的元素都是臟頁。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-O7RbqxhN-1691669854946)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20230810200719929.png)]

如何提高緩存命中率

使用LRU算法,該算法的思路是,鏈表頭部的節點是最近使用的,而鏈表末尾的節點是最久沒被使用的。那么,當空間不夠了,就淘汰最久沒被使用的節點,從而騰出空間。

簡單的 LRU 算法并沒有被 MySQL 使用,因為簡單的 LRU 算法無法避免下面這兩個問題:

  • 預讀失效;
  • Buffer Pool 污染;

預讀失效

先來說說 MySQL 的預讀機制。程序是有空間局部性的,靠近當前被訪問數據的數據,在未來很大概率會被訪問到。所以,MySQL 在加載數據頁時,會提前把它相鄰的數據頁一并加載進來,目的是為了減少磁盤 IO。但是可能這些被提前加載進來的數據頁,并沒有被訪問,相當于這個預讀是白做了,這個就是預讀失效

怎么解決預讀失效而導致緩存命中率降低的問題?

最好就是讓預讀的頁停留在 Buffer Pool 里的時間要盡可能的短,讓真正被訪問的頁才移動到 LRU 鏈表的頭部,從而保證真正被讀取的熱數據留在 Buffer Pool 里的時間盡可能長。MySQL 是這樣做的,它改進了 LRU 算法,將 LRU 劃分了 2 個區域:old 區域 和 young 區域。young 區域在 LRU 鏈表的前半部分,old 區域則是在后半部分,如下圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KHKrD20P-1691669854946)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20230810201102871.png)]

劃分這兩個區域后,預讀的頁就只需要加入到 old 區域的頭部,當頁被真正訪問的時候,才將頁插入 young 區域的頭部。如果預讀的頁一直沒有被訪問,就會從 old 區域移除,這樣就不會影響 young 區域中的熱點數據。

buffer pool污染

當某一個 SQL 語句掃描了大量的數據時,在 Buffer Pool 空間比較有限的情況下,可能會將 Buffer Pool 里的所有頁都替換出去,導致大量熱數據被淘汰了,等這些熱數據又被再次訪問的時候,由于緩存未命中,就會產生大量的磁盤 IO,MySQL 性能就會急劇下降,這個過程被稱為 Buffer Pool 污染

怎么解決出現 Buffer Pool 污染而導致緩存命中率下降的問題?

MySQL 是這樣做的,進入到 young 區域條件增加了一個停留在 old 區域的時間判斷。具體是這樣做的,在對某個處在 old 區域的緩存頁進行第一次訪問時,就在它對應的控制塊中記錄下來這個訪問時間:

  • 如果后續的訪問時間與第一次訪問的時間在某個時間間隔內,那么該緩存頁就不會被從 old 區域移動到 young 區域的頭部
  • 如果后續的訪問時間與第一次訪問的時間不在某個時間間隔內,那么該緩存頁移動到 young 區域的頭部

這個間隔時間是由 innodb_old_blocks_time 控制的,默認是 1000 ms。也就說,只有同時滿足「被訪問」與「在 old 區域停留時間超過 1 秒」兩個條件,才會被插入到 young 區域頭部,這樣就解決了 Buffer Pool 污染的問題 。另外,MySQL 針對 young 區域其實做了一個優化,為了防止 young 區域節點頻繁移動到頭部。young 區域前面 1/4 被訪問不會移動到鏈表頭部,只有后面的 3/4被訪問了才會。

臟頁什么時候會被刷入到磁盤

  • 當 redo log 日志滿了的情況下,會主動觸發臟頁刷新到磁盤;
  • Buffer Pool 空間不足時,需要將一部分數據頁淘汰掉,如果淘汰的是臟頁,需要先將臟頁同步到磁盤;
  • MySQL 認為空閑時,后臺線程會定期將適量的臟頁刷入到磁盤;
  • MySQL 正常關閉之前,會把所有的臟頁刷入到磁盤;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36124.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36124.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36124.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

抖音關鍵詞搜索小程序排名怎么做

抖音關鍵詞搜索小程序排名怎么做 1 分鐘教你制作一個抖音小程序。 抖音小程序就是我的視頻,左下方這個藍色的鏈接,點進去就是抖音小程序。 如果你有了這個小程序,發布視頻的時候可以掛載這個小程序,直播的時候也可以掛載這個小…

Express 實戰(一):概覽

在正式學習 Express 內容之前,我們有必要從大的方面了解一下 Node.js 。 在很長的一段時間里,JavaScript 一門編寫瀏覽器中運行腳本的語言。不過近些年,隨著互聯網的發展以及技術進步,JavaScript 迎來了一個集中爆發的時代。一個…

谷歌關閉跨域限制.(生成一個開發瀏覽器),Chrome關閉跨域

(一)、首先找到瀏覽器在電腦磁盤中的位置,并復制 (二)、復制一個瀏覽器的快捷方式到桌面(不影響正常瀏覽器) (三)、chrom鼠標右鍵屬性,修改快捷方式的目標 (四)chrome.exe 后面添加 --disable-web-security --user-data-dir 復制的Chrome瀏覽…

787. 歸并排序

文章目錄 QuestionIdeasCode Question 給定你一個長度為 n 的整數數列。 請你使用歸并排序對這個數列按照從小到大進行排序。 并將排好序的數列按順序輸出。 輸入格式 輸入共兩行,第一行包含整數 n 。 第二行包含 n 個整數(所有整數均在 1~109 范圍…

JUC并發編程(JUC核心類、TimeUnit類、原子操作類、CASAQS)附帶相關面試題

目錄 1.JUC并發編程的核心類 2.TimeUnit(時間單元) 3.原子操作類 4.CAS 、AQS機制 1.JUC并發編程的核心類 雖然java中的多線程有效的提升了程序的效率,但是也引發了一系列可能發生的問題,比如死鎖,公平性、資源管理…

【100天精通python】Day34:使用python操作數據庫_ORM(SQLAlchemy)使用

目錄 專欄導讀 1 ORM 概述 2 SQLAlchemy 概述 3 ORM:SQLAlchemy使用 3.1 安裝SQLAlchemy: 3.2 定義數據庫模型類: 3.3 創建數據表: 3.4 插入數據: 3.5 查詢數據: 3.6 更新數據: 3.7 刪…

C/C++中volatile關鍵字詳解

1. 為什么用volatile? C/C 中的 volatile 關鍵字和 const 對應,用來修飾變量,通常用于建立語言級別的 memory barrier。這是 BS 在 "The C Programming Language" 對 volatile 修飾詞的說明: A volatile specifier is a hint to a…

【Git】 git push origin master Everything up-to-date報錯

hello,我是索奇,可以叫我小奇 git push 出錯?顯示 Everything up-to-date 那么看看你是否提交了message 下面是提交的簡單流程 git add . git commit -m "message" git push origin master 大多數伙伴是沒寫git commit -m "…

AI自動駕駛

AI自動駕駛 一、自動駕駛的原理二、自動駕駛的分類三、自動駕駛的挑戰四、自動駕駛的前景五、關鍵技術六、自動駕駛的安全問題七、AI數據與自動駕駛八、自動駕駛的AI算法總結 自動駕駛技術是近年來備受關注的熱門話題。它代表了人工智能和機器學習在汽車行業的重要應用。本文將…

UML之四種事物

目錄 結構事物 行為事物 分組事物: 注釋事物 結構事物 1.類(Class) -類是對一組具有相同屬性、方法、關系和語義的對象的描述。一個類實現一個或多個接口 2.接口(interface) -接口描述 了一個類或構件的一個服務的操作集。接口僅僅是定義了一組操作的規范&…

案例16 基于Spring Boot實現學生新增案例

基于Spring Boot實現學生新增。 1. 創建Spring Boot項目 創建Spring Boot項目&#xff0c;項目名稱為case16-springboot-student01。 ? 2. 設置項目信息 ? 3. 選擇依賴 選擇Lombok ? 選擇Spring Web ? 4. 設置項目名稱 ? 5. Maven依賴 <?xml version"1.0&qu…

Nature子刊 |腸道宏病毒組揭示百歲老人長壽秘訣

發表期刊&#xff1a;nature microbiology 發表時間&#xff1a;2023 影響因子&#xff1a;28.3 DOI: 10.1038/s41564-023-01370-6 研究背景 衰老是一種不可逆轉的自然過程&#xff0c;隨著年齡的增長&#xff0c;機體諸多方面出現功能性下降&#xff0c;與衰老相關的疾病&a…

生成式AI顛覆傳統數據庫的十種方式

對于生成式AI的所有閃光點&#xff0c;這個新時代最大的轉變可能深埋在軟件堆棧中。AI算法正在不易覺察地改變一個又一個數據庫。他們正在用復雜、自適應且看似更直觀的AI新功能顛覆傳統數據庫。 目錄 1、向量和嵌入 2、查詢模型 3、建議 4、索引范例 5、數據分類 6、更…

Unity 框架學習--1

由淺入深&#xff0c;慢慢演化實現框架 兩個類的實現代碼完全一樣&#xff0c;就只有類名或類型不一樣的時候&#xff0c;而且還需要不斷擴展&#xff08;未來會增加各種事件&#xff09;的時候&#xff0c;這時候就用 泛型 繼承 來提取&#xff0c;繼承解決擴展的問題&#…

【RabbitMQ與SpringBoot集成測試收發消息】

【RabbitMQ與SpringBoot集成測試收發消息】 一、環境說明二、實驗步驟三、小結 一、環境說明 安裝環境&#xff1a;虛擬機VMWare Centos7.6 Maven3.6.3 JDK1.8RabbitMQ版本&#xff1a;rabbitmq-server-3.8.8-1.el7.noarch.rpm編程工具Idea 運行JDK為17 二、實驗步驟 在Rab…

List和數組互轉方法以及踩坑點

一、數組轉List 1. 使用for循環逐個添加 String[] arr {"A", "B", "C"}; List<String> list new ArrayList<>(); for (String element : arr) {list.add(element); }2. 使用Arrays.asList(arr) String[] arr {"A", …

TypeScript 泛型的深入解析與基本使用

系列文章目錄 文章目錄 系列文章目錄前言一、泛型的概念二、泛型函數三、泛型類四、泛型接口五、泛型約束總結前言 泛型是TypeScript中的一個重要概念,它允許我們在定義函數、類或接口時使用參數化類型,增強了代碼的靈活性和重用性。本文將深入探討泛型的概念,以及如何在Ty…

智能駕駛系列報告之一:智能駕駛 ChatGPT時刻有望來臨

原創 | 文 BFT機器人 L3 功能加速落地&#xff0c;政策標準有望明確 L2 發展日益成熟&#xff0c;L3 功能加速落地。根據市場監管總局發布的《汽車駕駛自動化分級》與 SAE發布的自動駕駛分級標準&#xff0c;自動駕駛主要分為 6 個級別&#xff08;0 級到 5 級&#xff0c;L0 …

Tomcat多實例部署及nginx+tomcat的負載均衡和動靜分離

Tomcat多實例部署 安裝 jdk、tomcat&#xff08;流程可看之前博客&#xff09; 配置 tomcat 環境變量 [rootlocalhost ~]# vim /etc/profile.d/tomcat.sh#tomcat1 export CATALINA_HOME1/usr/local/tomcat/tomcat1 export CATALINA_BASE1/usr/local/tomcat/tomcat1 export T…

Delphi調用WindowsAPI獲取窗口進程

Delphi有封裝的很好的WindowsAPI&#xff0c;直接調用即可&#xff0c;大體上和C差不多&#xff0c;有些地方需要額外處理。 給出一個實例&#xff1a; varg_process: THandle;procedure initGlobal(); beginvarg_handle: HWND;g_handle : FindWindow(clsName, name);if g_ha…