41.3. 存儲器管理

Table of Contents
SPI_palloc — 在上層執行器環境裡分配內存
SPI_repalloc — 在上層執行器環境裡重新分配內存
SPI_pfree — 在上層執行器環境裡釋放內存
SPI_copytuple — 在上層執行者環境裡制作一個行的拷貝
SPI_copytupledesc — 在上層執行者環境裡制作一個行描述符的拷貝
SPI_copytupleintoslot — 在上層執行者環境裡制作一行和描述器的拷貝
SPI_modifytuple — 通過替換一個給出行的選定的字段創建一行
SPI_freetuple — 釋放在上層執行者環境裡分配的一行
SPI_freetuptable — 釋放一個由 SPI_exec 或者類似的函數創建的行集
SPI_freeplan — 釋放一個前面保存的規劃

PostgreSQL存儲器環境中分配存儲器, 它提供了在許多地方分配的,有著不同的生命期的許多內存塊的一個方便的管理方法。 刪除一個環境則釋放所有在其內部分配的內存。 因此,我們沒必要跟蹤獨立的對象以避免內存洩漏;而是只要管理少量的環境。 palloc 和相關的函數從"當前"的環境中分配內存。

SPI_connect 創建一個新的存儲器環境並且將其標記為當前的環境。 SPI_finish恢復前一個內存環境並且刪除 SPI_connect 創建的環境。 這些動作確保在你的過程中分配的臨時內存在過程結尾的時候都被回收,避免內存洩漏。

不過,如果你的過程需要返回一個已分配的內存對象(比如一個傳遞引用的數據類型), 那麼你就不能用 palloc 分配返回的對象, 至少是不能在你已經和 SPI 聯接上的時候。如果你試圖這麼做, 那麼該對象將在 SPI_finish 的時候被釋放, 因而你的過程就不能可靠地工作了!

要解決這個問題,使用 SPI_palloc 分配你的返回對象。 SPI_palloc"上層執行者環境"中分配空間,也就是調用 SPI_connect 時候的當前環境內存環境,該環境是從你的過程返回數值的正確環境。

如果還沒有聯接到 SPI 的時候調用它,SPI_palloc 的行為和簡單的 palloc 一樣。 在一個過程和 SPI 管理器聯接之前,當前的內存環境是上層執行者環境,因此所有該過程使用 palloc 或者 SPI 工具函數分配的空間都是在這個環境中分配的。

在調用 SPI_connect 之後,當前環境是該過程私有的, 由 SPI_connect 制作的環境。 所有通過 palloc/repalloc 或者 SPI 工具函數(除了 SPI_copytupleSPI_copytupledescSPI_copytupleintoslotSPI_modifytuple, 和 SPI_palloc) 分配的內存都是在這個環境中分配的。 如果一個過程與 SPI 管理器斷開(通過 SPI_finish),那麼當前環境恢復為上層執行器環境, 並且所有在該過程的內存環境中分配的內存都釋放掉並且不能再次使用!

所有在本節內描述的函數都可以在已聯接的和未聯接的過程中使用。 在未聯接的過程中,他們的行為和下層的原始後端函數(palloc 等)相同。