數據庫與記憶體的直接互動——它是如何工作的?
我正在閱讀一本關於數據庫的書,其中的一章討論了緩衝區管理器及其替代策略。
我注意到 DBMS 直接與記憶體互動,而不是要求作業系統與虛擬記憶體互動。那是對的嗎?這種直接的溝通究竟是如何發生的?DBMS 允許分配多少記憶體?我從來沒有接觸過如此低級的函式呼叫,我很想看到一些解釋和例子。
如果您不知道要搜尋的正確關鍵字,那麼在 google 上查找此類資訊有點麻煩。
讓我們只討論 ENGINE=InnoDB 的 MySQL/MariaDB。(這實際上是當今唯一使用的引擎。)
- 所有 InnoDB 活動都發生在 buffer_pool 中。
- 所有數據和每個二級索引由 16KB 塊組成。
- 這些塊根據需要被帶入 buffer_pool,並根據需要刷新。
- 它使用 LRU(最近最少使用)算法來控制要彈出的塊。(LRU 有一些小的調整,所以它不完全是LRU。)
因此,給 InnoDB大部分RAM,然後讓它做它的事情是非常重要的。一個簡單的經驗法則:
innodb_buffer_pool_size
應設置為大約 70% 的 RAM。對於大多數應用程序,這是最重要的設置,也是唯一需要更改預設設置的設置。將 buffer_pool 設置得太大可能會導致交換。但是,由於 InnoDB 將其視為一個大數組,這可能會導致大量的交換,從而大大降低 MySQL/MariaDB 的速度。
InnoDB 具有用於讀取寫入塊的執行緒。特別是,刷新到磁碟在某種程度上是“在後台”完成的。這使得 an
INSERT
看起來比實際更快。我在這裡進一步討論記憶體分配
使用“虛擬記憶體”訪問文件是一種懶惰的做事方式。它適用於簡單的情況。但是,數據庫引擎需要高效且快速。當程式碼知道訪問模式時,最好使用為此調整的訪問方法。
例如,如果您要按順序讀取文件,最好(用於記憶體管理)在兩個“小”緩衝區之間進行 ping-ping;一個被讀入,一個被解析。(單個“循環”緩衝區是一個不錯的選擇。)
這種直接的溝通究竟是如何發生的?
因為所有內容都在 16KB 塊中,所以有一個數字可以唯一標識此類內容。它相當大(20?字節)。它至少包括“表空間”號,以及表空間內的塊號。這是取模 buffer_pool_instances 的數量來決定查看哪個實例。
在一個塊內,有表的行或二級索引的行,或它所代表的 B+Tree(參見 Wikipedia)中的節點的行。
如果塊不在 buffer_pool 中,它必須在讀取發生時等待。但是,在讀取發生之前,可能需要寫入以清除某些塊。通常,後台執行緒會刷新“臟”塊,以便在 buffer_pool 中始終存在一些空閒塊。(“免費”或“容易移除”,因為它們不髒。)