圖解PostgreSQL--local buffer的分配

yzs87發表於2020-01-08

本文介紹本地緩衝的管理。

一、資料結構

圖解PostgreSQL--local buffer的分配

1、陣列LocalBufferDescriptors[]為本地緩衝塊的描述符,buf_id從-2開始,都是負數。為和共享緩衝區有區別,通過是否為負值就可以判斷是否是本地緩衝區
2、陣列大小由變數num_temp_buffers控制
3、LocalBufferBlockPointers陣列為本地緩衝塊的指標。這些陣列的初始化由函式InitLocalBuffers完成,此時並沒有分配本地緩衝塊記憶體。
4、本地緩衝塊記憶體的申請和分配由函式GetLocalBufferStorage完成。第一次時從記憶體上下文LocalBufferContext中分配16個頁大小的block,然後將第一個頁地址分配給LocalBufferBlockPointers[i],並不是一下子全部分配,下次使用時再分配陣列下一個頁。
5、16個頁的block用完,再次申請32個頁的block;同理32個頁的block用完,申請64個頁的block,每次都是之前的兩倍。
6、最大一次分配1個GB的block

二、分配local buffer原理

、本地buffer的分配由函式LocalBufferAlloc來完成,用於臨時表的讀寫。
2、同樣需要先初始化tag:newTag,唯一標記一個物理頁
3、第一次使用臨時表時,需要通過calloc建立一系列緩衝區(InitLocalBuffers完成):幾個陣列,大小為num_temp_buffers,即該變數控制大小。

  • LocalBufferDescriptors[]:儲存本地緩衝塊的描述符
  • LocalBufferBlockPointers[]:本地緩衝塊指標陣列,儲存指向塊的指標
  • LocalRefcount[]:每個描述符引用次數
  • LocalBufHash:使用者管理本地緩衝塊的hash表,key為tag,value為buffer的陣列下標。
    4、通過tag從LocalBufHash表中查詢,看有沒有,是否已經載入到記憶體。
    5、LocalBufHash表中已存在:
       1)獲取其ID,然後獲取local buffer的描述符bufHdr
       2)原子操作讀出bufHdr的state即buf_state
       3)buf_state的usagecount保持為1?refcount+1
       4)buf為BM_VALID,則foundPtr為TRUE,表示命中緩衝,否則為false
       5)返回該描述符bufHdr
    6、LocalBufHash不存在:
       1)通過該值nextFreeLocalBuf遍歷本地緩衝區,若超過NlocBuffer值則從頭開始遍歷
       2)LocalRefcount對應的引用值不為0,則返回到1);否則取出其bufHdr的state
       3)usagecount=0,表示沒有人在用,則LocalRefcount=1後退出迴圈,進入步驟7
       4)usagecount>0,則將usagecount-1後返回1)重新選擇下一個
    7、buf_satate為BM_DIRTY,則需要刷髒:
       1)獲取具體頁localpage,smgropen一個oreln,如開啟checksum則計算checksum並寫入localpage;smgrwrite將其寫入到磁碟;最後將狀態置為非BM_DIRTY
    8、如果第一次使用本地buffer,則需要呼叫GetLocalBufferStorage將其掛到TopMemoryContext
    9、如果該buffer緩衝區的資料有效,則需要更新hash表:將該tag從LocalBufHash中刪除,並將狀態置為 ~(BM_VALID | BM_TAG_VALID),其bufHdr->tag需要清空
    10、將新的tag newTag插入hash表LocalBufHash
    11、將bufHdr->tag替換成newTag,此時是我們的tag了。
    12、buf_state清空,並且置為BM_TAG_VALID,且usagecount加1,foundPTR為false
    13、返回buf描述符bufHdr


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31493717/viewspace-2672559/,如需轉載,請註明出處,否則將追究法律責任。

相關文章