PostgreSQL從小白到專家,是從入門逐漸能力提升的一個系列教程,內容包括對PG基礎的認知、包括安裝使用、包括角色權限、包括維護管理、、等內容,希望對熱愛PG、學習PG的同學們有幫助,歡迎持續關注CUUG PG技術大講堂。
第23講:緩沖區管理器
內容1 : 緩沖區概述
內容2 : 緩沖區管理器結構
內容3 : 緩沖區管理器鎖
內容4 : 緩沖區管理器如何工作
內容5 : 環形緩沖區
內容6 : 臟塊寫
緩沖區概述
· 緩沖區結構(存放各種類型的數據塊)
數據文件頁—表和索引塊
可用空間地圖塊
可見性地圖塊
緩沖區數組索引--buffer_ids
· Buffer Tag結構
RelFileNode (分別為表對象oid、數據庫oid、表空間oid)
頁面的fork number (分別為0、1、2)
頁面number 示例:
緩沖區標記{(16821、16384、37721)、0、7}
1、標識第七個塊中的頁
2、其關系的OID和fork號分別為37721和0(0即為存放表數據的文件)
3、該塊存放在OID為16384的數據庫中,表空間的OID為16821
· Backend進程讀數據塊到緩沖區
· 寫臟塊
下面進程工作時會導致臟塊寫:
· Checkpointer
· background writer
緩沖區管理器結構
· 管理器結構
· 第一層(Buffer Table)
在這一層內置的hash函數將buffer_tags映射到插槽,插槽中記錄了buffer_tags和描述層的buffer_id的映射關系。
· 第二層(Buffer Descriptor)
描述層包含了很多重要的信息,包括buffer_tag與緩沖池插槽id的映射關系,訪問次數統計,鎖等信息。
· Tag
· buffer_id
· refcount (被進程訪問過一次加一,被時鐘掃描過后減一,為零時可用)
· usage_count
· context_lock and io_in_progress_lock
· Flags
dirty bit
valid bit
io_in_progress bit
· freeNext
· Buffer Descriptors Layer (Loading the first page)
先請求一個緩沖區空間,buffer table層把描述層的buffer_id與buffer_tag進行映射;然后在描述層把buffer_tag與緩沖區id進行映射;最后把數據塊讀到相應的緩沖區槽中。
· 第三層(Buffer Pool)
緩沖池是存儲數據文件頁(如表和索引)的簡單數組。緩沖池數組的索引稱為buffer_ids。
緩沖池被分割成大小為8 KB的插槽,等于頁面大小。因此,每個槽可以存儲整個頁面。緩沖區管理器鎖
· Buffer Manager Locks
緩沖區管理器為許多不同的目的使用許多鎖
鎖是緩沖區管理器同步機制的一部分;它們與任何SQL語句和SQL選項都不相關
· Buffer Table 層的鎖
BufMappingLock保護整個緩沖表的數據完整性。它是一個輕量鎖,可以在共享和獨占模式下使用。在緩沖區表中搜索條目時,后端進程保存共享的BufMappingLock。當插入或刪除條目時,后端進程持有獨占鎖。
· Buffer Descriptor 層鎖
每個緩沖區描述符使用兩個輕量級鎖
· content_lock
· io_in_progress_lock
· content_lock
content_lock是一種典型的強制訪問限制的鎖。它可以用于共享和獨占模式。
當執行下列操作之一時,將獲取獨占內容鎖:
· dml操作
· 物理刪除元組或壓縮存儲頁上的可用空間(vacuum和HOT處理)
· 凍結存儲頁中的元組
· io_in_progress_lock
io_in_progress鎖用于等待緩沖區上的I/O完成。當PostgreSQL進程從存儲器加載/寫入頁面數據時,該進程在訪問存儲器時持有相應描述符的獨占io_in_progress鎖。
· spinlock
下面顯示如何固定緩沖區描述符:
1、獲取緩沖區描述符的自旋鎖。
2、將其refcount和usage_count的值增加1。
3、松開旋轉鎖。
下面顯示如何將臟位設置為“1”:
1、獲取緩沖區描述符的自旋鎖。
2、使用按位操作將臟位設置為“1”。
3、松開旋轉鎖。
緩沖區管理器如何工作
· 訪問已存放在緩沖區中的數據塊
· 加載數據塊到空的緩沖池插槽
· 加載數據塊到一個需要釋放的緩沖池插槽
· 緩沖區塊替換機制
替換頁面算法
· 時鐘掃描(8.1開始及以后的版本)
· LRU算法(8.1以前的版本)
· 時鐘掃描算法
緩沖區描述符顯示為藍色或青色框,框中的數字顯示每個描述符的使用計數,每掃描一次則減一,緩沖區每被訪問過一次則加一。
Ring Buffer
· Ring Buffer
· Bulk-reading
需要大塊的緩沖池時,如果掃描緩沖池時其大小超過(共享緩沖區/4)四分之一的空間時,還沒有找到足夠的緩沖池,則分配256KB環形緩沖區。
· Bulk-writing
執行下面列出的SQL命令時。在這種情況下,環緩沖區大小為16MB。
COPY FROM command.
CREATE TABLE AS command.
CREATE MATERIALIZED VIEW or REFRESH MATERIALIZED VIEW command.
ALTER TABLE command.
· Vacuum-processing
當自動真空機進行真空處理時。在這種情況下,環緩沖區大小為256 KB。
臟塊寫
· Flushing Dirty Pages
檢查點進程和后臺寫入進程將臟頁刷新到存儲區,檢查點與后臺寫進程分離。
檢查點進程將檢查點記錄寫入WAL段文件,并在檢查點啟動時刷新臟頁。
后臺寫進程的作用是減少檢查點密集寫的影響。后臺寫進程持續一點一點地刷新臟頁,對數據庫活動的影響最小。
默認情況下,后臺寫入程序每200毫秒喚醒一次(由bgwriter_delay定義),并最多刷新為100頁(由bgwriter_lru_maxpages 定義)
共享池緩沖區參數設置
· 共享緩沖區相關參數
shared_buffers參數設置 show shared_buffers;
Alter system set shared_buffers=256M;
wal_buffers參數設置 show wal_buffers;
Alter system set wal_buffers =4M;
effective_cache_size 參數設置 show effective_cache_size;
提供可用于磁盤高速緩存的內存量的估計值。它只是一個建議值,而不是確切分配的內存或緩存大小。它不會實際分配內存,而是會告知優化器內核中可用的緩存量。在一個索引的代價估計中,更高的數值會使得索引掃描更可能被使用,更低的數值會使得順序掃描更可能被使用。在設置這個參數時,還應該考慮PostgreSQL的共享緩沖區以及將被用于PostgreSQL數據文件的內核磁盤緩沖區。默認值是4GB。
以上就是【PostgreSQL從小白到專家】第23講 - 緩沖區管理 的內容,歡迎一起探討交流釘釘交流群:35,82,24,60,往期視頻及文檔內容聯系CUUG