《DBNotes:Buffer Pool刷臟頁細節以及改進》

本筆記知識沿用之前DBNotes: Buffer Pool對于緩沖頁的鏈表式管理的部分知識

目錄

  • 獲取一個空閑頁的源碼邏輯
  • Page_Cleaner_Thread
  • LRU_Manager_Thread
  • Hazard Pointer作為驅逐算法改進
  • 參考

獲取一個空閑頁的源碼邏輯

任何一個讀寫請求都需要從Buffer pool來獲取所需頁面。如果需要的頁面已經存在于Buffer pool,那么直接利用當前頁面進行操作就行。但是如果所需頁面不在Buffer pool,比如UPDATE操作,那么就需要從Buffer pool中新申請空閑頁面,將需要讀取的數據放到Buffer pool中進行操作。

如何從buffer pool中獲取一個頁面呢?這依賴于buf_LRU_get_free_block函數,該函數會循環嘗試去淘汰LRU list上的頁面。每次循環都會訪問freelist,查看是否有足夠的空閑頁面,如果沒有,就繼續從LRUlist去淘汰。這樣的循環在負載較高的時候會加劇對freelist以及LRUlist的mutex的競爭。可以設置buf_pool->try_LRU_scan是做了一個優化,如果當前用戶線程掃描的時候 發現沒有空閑頁面,那么其他用戶線程就不需要進行同樣的掃描。

MySQL的free頁面的獲取依賴于Page_Cleaner_Thread的刷新能力,如果刷新不及時,那么系統就會使用上面所說的循環邏輯來為用戶線程申請空閑頁面,可以看出是十分耗時間的。而如果刷新過快,也會導致性能問題,因為刷新是需要io操作的。

所以引入獨立的線程負責LRU list的刷臟。目的是為了讓獨立線程根據系統負載動態調整LRU的刷臟能力。由于LRU list的刷臟從page cleaner線程中脫離出來,調整LRU list的刷臟能力不再會影響到page cleaner。

同時由于單線程LRUlist刷臟存在問題,設計者進行了改進。繼續將LRU list獨立于page cleaner threads并將LRU list單線程刷臟增加為多線程刷臟。page cleaner只負責flush list的刷臟,lru_manager_thread只負責LRU List刷臟。這樣的分離,可以使得LRU list刷臟和Flush List刷臟并行執行。

Page_Cleaner_Thread

主要負責flushlist的刷臟,避免用戶線程同步刷臟頁。

也是每隔一定時間刷一次臟頁,sleep time是自適應的,依賴于當前的lsn,flushlist中的oldest_modification以及當前的同步刷臟點。

與LRU_Manager_Thread不同,該線程每次執行刷的臟頁數量也是自適應的,依賴于當前系統中臟頁的比率,日志產生的速度以及幾個參數。

LRU_Manager_Thread

一個系統線程,隨著InnoDB啟動而work,作用是定期清理出空閑的數據頁(數量為innodb_LRU_scan_depth)并加入到Freelist中,防止用戶線程去做同步刷臟影響效率。

該線程每隔一段時間就去FLUSH。先嘗試從LRU中驅逐部分數據頁,如果數量不夠就從Flushlist中驅逐。

線程執行頻率是自適應的:

設定max_free_len = innodb_LRU_scan_depth * innodb_buf_pool_instances。

如果Freelist中的數量小于max_free_len 的1%,則sleep time = 0,表示這時候空閑頁太少了,需要一直執行buf_flush_LRU_tail操作,從而騰出空閑的數據頁。

如果Free List中的數量介于max_free_len的1%-5%,則sleep time減少50ms(默認為1000ms),如果Free List中的數量介于max_free_len的5%-20%,則sleep time不變,如果Free List中的數量大于max_free_len的20%,則sleep time增加50ms,但是最大值不超過rds_cleaner_max_lru_time

Hazard Pointer作為驅逐算法改進

在學術上,Hazard Pointer是一個指針,如果這個指針被一個線程所占有,在它釋放之前,其他線程不能對他進行修改,但是在InnoDB里面,概念剛好相反,一個線程可以隨時訪問Hazard Pointer,但是在訪問后,他需要調整指針到一個有效的值,便于其他線程使用。我們用Hazard Pointer來加速逆向的邏輯鏈表遍歷。 先來說一下這個問題的背景,我們知道InnoDB中可能有多個線程同時作用在Flush List上進行刷臟,例如LRU_Manager_Thread和Page_Cleaner_Thread。同時,為了減少鎖占用的時間,InnoDB在進行寫盤的時候都會把之前占用的鎖給釋放掉。這兩個因素疊加在一起導致同一個刷臟線程刷完一個數據頁A,就需要回到Flush List末尾(因為A之前的臟頁可能被其他線程給刷走了,之前的臟頁可能已經不在Flush list中了),重新掃描新的可刷盤的臟頁。另一方面,數據頁刷盤是異步操作,在刷盤的過程中,我們會把對應的數據頁IO_FIX住,防止其他線程對這個數據頁進行操作。我們假設某臺機器使用了非常緩慢的機械硬盤,當前Flush List中所有頁面都可以被刷盤(buf_flush_ready_for_replace返回true)。我們的某一個刷臟線程拿到隊尾最后一個數據頁,IO fixed,發送給IO線程,最后再從隊尾掃描尋找可刷盤的臟頁。在這次掃描中,它發現最后一個數據頁(也就是剛剛發送到IO線程中的數據頁)狀態為IO fixed(磁盤很慢,還沒處理完)所以不能刷,跳過,開始刷倒數第二個數據頁,同樣IO fixed,發送給IO線程,然后再次重新掃描Flush List。它又發現尾部的兩個數據頁都不能刷新(因為磁盤很慢,可能還沒刷完),直到掃描到倒數第三個數據頁。所以,存在一種極端的情況,如果磁盤比較緩慢,刷臟算法性能會從O(N)退化成O(N*N)。 要解決這個問題,最本質的方法就是當刷完一個臟頁的時候不要每次都從隊尾重新掃描。我們可以使用Hazard Pointer來解決,方法如下:遍歷找到一個可刷盤的數據頁,在鎖釋放之前,調整Hazard Pointer使之指向Flush List中下一個節點,注意一定要在持有鎖的情況下修改。然后釋放鎖,進行刷盤,刷完盤后,重新獲取鎖,讀取Hazard Pointer并設置下一個節點,然后釋放鎖,進行刷盤,如此重復。當這個線程在刷盤的時候,另外一個線程需要刷盤,也是通過Hazard Pointer來獲取可靠的節點,并重置下一個有效的節點。通過這種機制,保證每次讀到的Hazard Pointer是一個有效的Flush List節點,即使磁盤再慢,刷臟算法效率依然是O(N)。 這個解法同樣可以用到LRU List驅逐算法上,提高驅逐的效率。

參考

MySQL · 源碼分析 · Innodb緩沖池刷臟的多線程實現
MySQL · 源碼分析 · InnoDB LRU List刷臟改進之路
MySQL · 引擎特性 · InnoDB Buffer Pool

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

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

相關文章

WordPress刪除數據中標題重復文章的方法

一種是刪除重復的方法是:使用插件,大家可以去官網上下載 二種刪除重復的方法是:登錄數據庫,使用sql語句刪除,具體的語句為如下代碼: CREATE TABLE my_tmp AS SELECT MIN(ID) AS col1 FROM wp_posts GROUP BY post_titl…

hibernate配置

hibernate.cfg.xml <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd&quo…

html中表單元素_HTML中的表單元素

html中表單元素1)<input>元素 (1) The <input> Element) The <input> element is used to get input from the user in an HTML form. <input>元素用于以HTML形式從用戶獲取輸入。 <input> tag is used to get input using input element, the …

《搜索算法——DFS、BFS、回溯》

目錄深搜200. 島嶼數量695. 島嶼的最大面積130. 被圍繞的區域547. 省份數量417. 太平洋大西洋水流問題回溯廣搜111. 二叉樹的最小深度752. 打開轉盤鎖深搜與廣搜結合934. 最短的橋深搜 深搜DFS&#xff0c;在搜索到一個新節點時&#xff0c;立即對該新節點進行遍歷&#xff0c…

AP in R

AP聚類算法是目前十分火的一種聚類算法&#xff0c;它解決了傳統的聚類算法的很多問題。不僅簡單&#xff0c;而且聚類效果還不錯。這里&#xff0c;把前兩天學習的AP算法在R語言上面的模擬&#xff0c;將個人筆記拿出來與大家分享一下&#xff0c;不談AP算法的原理&#xff0c…

nginx 模塊解析

nginx的模塊非常之多&#xff0c;可以認為所有代碼都是以模塊的形式組織&#xff0c;這包括核心模塊和功能模塊&#xff0c;針對不同的應用場合&#xff0c;并非所有的功能模塊都要被用到&#xff0c;附錄A給出的是默認configure&#xff08;即簡單的http服務器應用&#xff09…

python關鍵字和保留字_Python關鍵字

python關鍵字和保留字關鍵詞 (Keywords) Keywords are the reserved words in Python programming language (and, any other programming languages like C, C, Java, etc) whose meanings are defined and we cannot change their meanings. In python programming languages…

《LeetcodeHot100非困難題補錄》

最近比較閑&#xff0c;也比較焦慮&#xff0c;刷刷題吧 目錄11. 盛最多水的容器22. 括號生成31. 下一個排列48. 旋轉圖像49. 字母異位詞分組56. 合并區間75. 顏色分類79. 單詞搜索114. 二叉樹展開為鏈表141. 環形鏈表148. 排序鏈表152. 乘積最大子數組169. 多數元素207. 課程表…

Java里String.split需要注意的用法

我們常常用String的split()方法去分割字符串&#xff0c;有兩個地方值得注意&#xff1a; 1. 當分隔符是句號時(".")&#xff0c;需要轉義&#xff1a; 由于String.split是基于正則表達式來分割字符串&#xff0c;而句號在正則表達式里表示任意字符。 //Wrong: //Str…

C# Socket 例子(控制臺程序)

服務器代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.IO;namespace TCPListener {class Program{static void Main(string[] args){const int BufferSize 1024;Con…

Scala中的值類

Value classes are a special mechanism in Scala that is used to help the compiler to avoid allocating run time objects. 值類是Scala中的一種特殊機制&#xff0c;用于幫助編譯器避免分配運行時對象。 This is done by defining a subclass of AnyVal. The only parame…

《MySQL8.0.22:Lock(鎖)知識總結以及源碼分析》

目錄1、關于鎖的一些零碎知識&#xff0c;需要熟知事務加鎖方式&#xff1a;Innodb事務隔離MVCC多版本并發控制常用語句 與 鎖的關系意向鎖行級鎖2、鎖的內存結構以及一些解釋3、InnoDB的鎖代碼實現鎖系統結構lock_sys_tlock_t 、lock_rec_t 、lock_table_tbitmap鎖的基本模式的…

關于ORA-04021解決辦法(timeout occurred while waiting to lock object)

某個應用正在鎖定該表或者包 表為 select b.SID,b.SERIAL#,c.SQL_TEXT from v$locked_object a, v$session b, v$sqlarea c where a.SESSION_ID b.SID and b.SQL_ADDRESS c.ADDRESS and c.sql_text like %table_name% 包為 select B.SID,b.USERNAME,b.MACHINE FROM V$ACCESS …

HtmlAutoTestFrameWork

前段時間做的自動化測試的是Silverlight的&#xff0c;框架都已經搭好。突然測試發現這里還有一個要發送郵件的html頁面&#xff0c;并且將另外啟動瀏覽器&#xff0c;于是今天下午把這個html的也寫出來。用法 &#xff1a; HtmlAutoTestFrameWork htf new HtmlAutoTestFrameW…

L8ER的完整形式是什么?

L8ER&#xff1a;稍后 (L8ER: Later) L8ER is an abbreviation of "Later". L8ER是“ Later”的縮寫 。 It is an expression, which is commonly used in messaging or chatting on social media networking sites like Facebook, Yahoo Messenger, and Gmail, etc…

Randomize select algorithm 隨機選擇算法

從一個序列里面選擇第k大的數在沒有學習算法導論之前我想最通用的想法是給這個數組排序&#xff0c;然后按照排序結果返回第k大的數值。如果使用排序方法來做的話時間復雜度肯定至少為O&#xff08;nlgn&#xff09;。 問題是從序列中選擇第k大的數完全沒有必要來排序&#xff…

《Linux雜記:一》

目錄CPU負載和CPU利用率CPU負載很高,利用率卻很低的情況負載很低,利用率卻很高常用linux命令常用的文件、目錄命令常用的權限命令常用的壓縮命令CPU負載和CPU利用率 可以通過 uptime , w 或者 top 命令看到CPU的平均負載。 Load Average :負載的3個數字,比如上圖的0.57、0.4…

IOS Plist操作

代碼&#xff1a;copy BUNDLE下的plist文件 到 library下面。 bundle下不支持些&#xff0c;library&#xff0c;doc路徑支持讀與寫。 (void)copyUserpigListToLibrary {NSFileManager *fileManager [NSFileManager defaultManager];NSArray *paths NSSearchPathForDirector…

《線程管理:線程基本操作》

目錄線程管理啟動線程與&#xff08;不&#xff09;等待線程完成特殊情況下的等待&#xff08;使用trycath或rall&#xff09;后臺運行線程線程管理 啟動線程與&#xff08;不&#xff09;等待線程完成 提供的函數對象被復制到新的線程的存儲空間中&#xff0c;函數對象的執行…

scala特質_Scala的特質

scala特質Scala特質 (Scala traits) Traits in Scala are like interfaces in Java. A trait can have fields and methods as members, these members can be abstract and non-abstract while creation of trait. Scala中的特性類似于Java中的接口 。 特征可以具有作為成員的…