PostgreSQL 對於 C 語言編寫的函數(包括其他與 C 語言兼容的語言,如 C++、Rust 等),是動態裝載的,用 CREATE FUNCTION
創建完函數後,並不會立即裝載,而是有連接建立之後,客戶端第一次調用時纔會進行裝載,而且是裝入到會話進程的內存裏面去了。這時候,就算我們把 .so 文件刪除,如果會話之前已調過一次函數的話,客戶端還是可以繼續調用函數的。
如果我們改寫了函數代碼,重新生成了 .so 文件,把新的 .so 文件覆蓋老版本的 .so 文件,這時候在已有的會話裏調用函數的話,有時候會報函數版本錯誤“ERROR unrecognized function API version, sql status: XX000”;有時候更嚴重,會導致當前會話的進程 Segment Fault,導致整個 PostgreSQL 崩潰而重啓。這時候就算用 CREATE OR REPLACE FUNCTION
來重新裝載函數也不行,也會導致 PostgreSQL 重啓。
唯一可行的解決方案就是把 .so 文件版本化,每個編譯出來的 .so 文件加上版本號,每個版本的文件都不同,把新版本的文件拷到 PKGLIBDIR 下,再用 CREATE OR REPLACE FUNCTION
替換掉老版本的函數,這樣就算在已建立的會話裏調用時,也是調的新版本的函數了。老版本的 .so 文件也可以刪除了。