1. 程式人生 > >PostgreSQL伺服器管理:伺服器設定和操作

PostgreSQL伺服器管理:伺服器設定和操作

本文件為PostgreSQL 9.6.0文件,本轉載已得到原譯者彭煜瑋授權。

1. PostgreSQL使用者賬戶

和對外部世界可訪問的任何伺服器守護程序一樣,我們也建議在一個獨立的使用者賬戶下執行PostgreSQL。這個使用者賬戶應該只擁有被該伺服器管理的資料,並且應該不能被其他守護程序共享(例如,使用使用者nobody是一個壞主意)。我們不建議把可執行檔案安裝為屬於這個使用者,因為妥協系統可能接著修改它們自己的二進位制檔案。

要在你的系統中增加一個 Unix 使用者賬戶,檢視一個命令useradd或adduser。通常會用postgres(本書中也假定用這個賬戶),但是你可以使用另一個名稱。

2. 建立一個數據庫集簇

在你能做任何事情之前,你必須在磁碟上初始化一個數據庫儲存區域。我們稱之為一個數據庫集簇(SQL標準使用的術語是目錄集簇)。一個數據庫集簇是被一個執行資料庫伺服器的單一例項所管理的一個數據庫的集合。在初始化之後,一個數據庫集簇將包含一個名為postgres的資料庫,它表示被功能、使用者和第三方應用所使用的預設資料庫。資料庫伺服器本身並不要求postgres資料庫存在。另一個在初始化過程中為每一個集簇建立的資料庫被稱為template1。顧名思義,它將被用於建立後續資料庫的模板;它不應該被用於實際工作(在集簇內建立新資料庫的更多資訊請見Chapter 22)。

在檔案系統術語中,一個數據庫集簇是一個單一目錄,所有資料都將被儲存在其中。我們稱它為資料目錄或資料區域。在哪裡儲存你的資料完全由你選擇。沒有預設的位置,不過/usr/local/pgsql/data或/var/lib/pgsql/data位置比較流行。要初始化一個數據庫集簇,使用和PostgreSQL一起安裝的命令initdb。你的資料庫集簇的檔案系統位置由-D選項指定,例如:


$ initdb -D /usr/local/pgsql/data

注意你必須在使用PostgreSQL使用者賬戶(如前一節所示)登入後執行這個命令。

Tip: 作為-D選項的一種替換方案,你可以設定環境變數PGDATA。

另一種替代方案是,你可以通過pg_ctl程式來執行initdb:


$ pg_ctl -D /usr/local/pgsql/data initdb

如果你使用pg_ctl來啟停伺服器(見Section 18.3),這種方法可能更直觀,以為這樣pg_ctl將是你用來管理資料庫伺服器例項的唯一命令。

如果你指定的目錄還不存在,initdb將嘗試建立它。當然,如果initdb沒有在父目錄中的寫許可權,這將會失敗。通常推薦讓PostgreSQL使用者擁有資料目錄及其父目錄,這樣就不存在上面的問題了。如果想要的父目錄也不存在,你將需要先建立它,如果父父目錄不可寫則使用 root 特權。因此,該過程可能像這樣:


root# mkdir /usr/local/pgsql
root# chown postgres /usr/local/pgsql
root# su postgres
postgres$ initdb -D /usr/local/pgsql/data

如果資料目錄存在並且已經包含檔案,initdb將拒絕執行。這可以避免無意中覆蓋一個已有的安裝。

因為資料目錄包含所有儲存在資料庫裡的資料,所以最重要的是保護這個目錄不受未授權的訪問。因此,initdb會回收禁止除PostgreSQL使用者之外所有使用者的訪問許可權。

不過,雖然目錄的內容是安全的,但預設的客戶端認證設定允許任意本地使用者連線到資料庫甚至成為資料庫超級使用者。如果你不信任其他本地使用者, 我們建議你使用initdb的-W、--pwprompt或--pwfile選項之一給資料庫超級使用者賦予一個口令。還可以指定-A md5或-A password,這樣就不會使用預設的trust 身份認證。或者在執行initdb之後、第一次啟動伺服器之前修改生成的pg_hba.conf檔案(另外一些可行的方法包括peer認證或者用檔案系統許可權限制連線。)。

initdb同時也為資料庫集簇初始化預設區域。 通常,它將只是使用環境中的區域設定並且把它們應用於被初始化的資料庫。 可以為資料庫指定一個不同的區域;特定資料庫集簇中使用的預設排序順序是通過initdb設定的, 雖然你可以建立使用不同排序順序的新資料庫,但在 initdb 建立的模板資料庫中使用的順序不能更改(除非刪除並重建它們)。使用非C或POSIX的區域還會對效能造成影響。因此,第一次就正確地選擇很重要。

initdb還為資料庫集簇設定預設的字符集編碼。通常字符集編碼應該選擇與區域設定匹配。

非C以及非POSIX區域對於字符集排序依賴於作業系統的排序規則庫。這控制著索引中儲存的鍵的排序。為此,通過快照恢復、二進位制流複製、更換不同的作業系統或者升級作業系統都不能把一個集簇切換到一種不相容的排序規則庫版本。

2.1. 二級檔案系統的使用

很多安裝會在檔案系統(卷)而不是機器的"根"捲上建立它們的資料庫集簇。如果你選擇這樣做,我們不建議嘗試使用二級卷的頂層目錄(掛載點)作為資料目錄。最好的做法是在PostgreSQL使用者擁有的掛載點目錄中建立一個目錄,然後在其中建立資料目錄。這可以避免許可權問題,特別是對於pg_upgrade這類操作,並且它也能在二級卷被斷線後確保乾淨的失敗。

2.2. 網路檔案系統的使用

許多安裝會在網路檔案系統上建立它們的資料庫集簇。有時直接通過NFS, 或通過內部使用NFS的網路附加儲存裝置(NAS)完成。 PostgreSQL不對 NFS檔案系統做特殊處理,即它假定NFS的行為和本地連線的裝置完全一樣。如果客戶端或者伺服器NFS沒有提供標準的檔案系統語義,這將導致可靠性問題 (參閱http://www.time-travellers.org/shane/papers/NFS_considered_harmful.html )。 具體來說,延遲(非同步)寫入到NFS伺服器可以導致資料損壞問題。 如果可能的話,把NFS檔案系統掛載為同步(無快取記憶體)可以避免這種災難。還有,我們不推薦軟掛載的NFS檔案系統。

儲存區域網路(SAN)通常使用非NFS的通訊協議,並且可能或者不可能遭受這類災難。建議諮詢供應商的文件來了解資料一致性保證。PostgreSQL無法做到比它所使用的檔案系統更可靠。

3. 啟動資料庫伺服器

在任何人可以訪問資料庫前,你必須啟動資料庫伺服器。 資料庫伺服器程式是postgres, 它必須知道在哪裡能找到它要用的資料。這是用-D選項實現的。 因此,啟動伺服器最簡單的方法是:


$ postgres -D /usr/local/pgsql/data

這將把伺服器放在前臺執行。這個步驟同樣必須以PostgreSQL使用者帳戶登入來操作。如果沒有-D選項,伺服器將嘗試使用環境變數PGDATA命名的目錄。如果這個環境變數也沒有提供則導致失敗。

通常最好在後臺啟動postgres。要這樣做,使用常用的 Unix shell 語法:


$ postgres -D /usr/local/pgsql/data >logfile 2>&1 &

如上所示,把伺服器的stdout和stderr輸出儲存到某個地方是非常重要的。這將對審計目的和診斷問題有所幫助。

postgres還接受其它一些命令列選項。

這些 shell 語法很容易讓人覺得無聊。因此我們提供了包裝器程式pg_ctl以簡化一些任務。例如:


pg_ctl start -l logfile

將在後臺啟動伺服器並且把輸出放到指定的日誌檔案中。-D選項和postgres中的一樣。pg_ctl還可以用於停止伺服器。

通常,你會希望在計算機啟動的時候啟動資料庫伺服器。自動啟動指令碼是作業系統相關的。PostgreSQL在contrib/start-scripts目錄中提供了幾種。安裝將需要 root 許可權。

不同的系統在引導時有不同的啟動守護程序的習慣。許多系統有一個檔案/etc/rc.local或/etc/rc.d/rc.local。其他的使用init.d或rc.d目錄。不管你做什麼,伺服器必須由PostgreSQL使用者賬戶而不是 root或任何其他使用者啟動。因此你可能應該在你的命令中使用su postgres -c '...'這種形式。例如:


su postgres -c 'pg_ctl start -D /usr/local/pgsql/data -l serverlog'

下面是一些更加與作業系統相關的建議(在每一種情況中要確保在我們展示通用值的地方使用正確的安裝目錄和使用者名稱)。

對於FreeBSD,找找PostgreSQL原始碼釋出中的檔案contrib/start-scripts/freebsd。

在OpenBSD上, 把下面幾行加到/etc/rc.local檔案中:


if [ -x /usr/local/pgsql/bin/pg_ctl -a -x /usr/local/pgsql/bin/postgres ]; then
    su -l postgres -c '/usr/local/pgsql/bin/pg_ctl start -s -l /var/postgresql/log -D /usr/local/pgsql/data'
    echo -n ' postgresql'
fi

在Linux系統上將


/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data
加入到/etc/rc.d/rc.local或/etc/rc.local中,還可以在PostgreSQL的原始碼釋出中找找檔案contrib/start-scripts/linux。

在使用systemd時,可以使用下面的服務單元檔案(例如/etc/systemd/system/postgresql.service):


[Unit]
Description=PostgreSQL database server
Documentation=man:postgres(1)

[Service]
Type=notify
User=postgres
ExecStart=/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGINT
TimeoutSec=0

[Install]
WantedBy=multi-user.target

使用Type=notify要求伺服器的二進位制檔案使用configure --with-systemd編譯。

要仔細地考慮超時設定。在寫作這份文件時,systemd的預設超時時長是 90 秒,並且將會殺死沒有在這段時間內報告準備好的程序。但是PostgreSQL伺服器可能因為執行崩潰恢復而導致啟動過程大大超過這個預設時間。建議的值是 0 禁用超時邏輯。

在NetBSD上,你可以根據愛好選擇FreeBSD或Linux的啟動指令碼。

在Solaris上,建立一個名為/etc/init.d/postgresql的檔案,其中包含下列行:


su - postgres -c "/usr/local/pgsql/bin/pg_ctl start -l logfile -D /usr/local/pgsql/data"

然後在/etc/rc3.d中建立一個符號連結S99postgresql指向它。

當伺服器在執行時,它的PID被儲存在資料目錄中的postmaster.pid檔案。這樣做 可以防止多個伺服器例項執行在同一個資料目錄中,並且也可以被用來關閉伺服器。

3.1. 伺服器啟動失敗

有幾個常見的原因會導致伺服器啟動失敗。通過檢查伺服器日誌或使用手工啟動的方法(不做標準輸出或標準錯誤的重定向), 就可以看到出現什麼錯誤訊息。下面我們詳細地解釋一些最常見的錯誤訊息。


LOG:  could not bind IPv4 socket: Address already in use
HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
FATAL:  could not create TCP/IP listen socket

正如這個訊息所說的,這表示:你試圖在一個已經有伺服器執行著的埠上再啟動另一個伺服器。不過,如果核心錯誤訊息不是Address already in use或其變體,那就有可能是別的問題。 例如,試圖在一個被保留的埠上啟動伺服器會收到下面這樣的訊息:


$ postgres -p 666
LOG:  could not bind IPv4 socket: Permission denied
HINT:  Is another postmaster already running on port 666? If not, wait a few seconds and retry.
FATAL:  could not create TCP/IP listen socket

像這樣的訊息:


FATAL:  could not create shared memory segment: Invalid argument
DETAIL:  Failed system call was shmget(key=5440001, size=4011376640, 03600).

可能意味著你的核心對共享記憶體區的限制小於PostgreSQL試圖建立的工作區域(本例中是 4011376640 位元組)。或者可能意味著根本就沒有 System-V 風格的共享記憶體支援被配置在你的核心中。作為一種臨時的解決方案, 你可以試著以小於正常數量的緩衝區(shared_buffers)啟動伺服器。 你最終還是會希望重新配置核心以增加共享記憶體允許的尺寸。 當你試圖在同一臺機器上啟動多個伺服器,並且它們所需的總空間超過了核心的限制,也會報這個錯。

一個這樣的錯誤:


FATAL:  could not create semaphores: No space left on device
DETAIL:  Failed system call was semget(5440126, 17, 03600).

並不意味著你已經用光了磁碟空間。它的意思是你的核心對System V訊號量的限制小於PostgreSQL想建立的數量。和上面一樣,你可以通過減少允許的連線數(max_connections)來繞開這個限制,但最終你還是會希望提高核心的限制。

如果你收到一個"illegal system call"錯誤, 那麼很有可能是你的核心根本不支援共享記憶體或者訊號量。這種情況下你唯一的選擇就是重新配置核心並且把這些特性開啟。

3.2. 客戶端連線問題

儘管可能在客戶端出現的錯誤情況範圍寬廣而且是應用相關的,但的確有幾種與伺服器的啟動方式直接相關。除了下面提到的幾種錯誤之外的問題都應該在相應的客戶端應用文件中。


psql: could not connect to server: Connection refused
        Is the server running on host "server.joe.com" and accepting
        TCP/IP connections on port 5432?

這是常見的"I couldn't find a server to talk to"失敗。上面的情況看起來是發生在嘗試 TCP/IP 通訊時。常見的錯誤是忘記把伺服器配置成允許 TCP/IP 連線。

另外,當試圖通過 Unix 域套接字與本地伺服器通訊時,你會看到這個:


psql: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

最後一行可以驗證客戶端是不是嘗試連線到正確的位置。如果實際上沒有伺服器在那裡執行,典型的核心錯誤訊息將是Connection refused或No such file or directory(值得注意的是這種環境中的Connection refused並不表示伺服器得到了你的連線請求並拒絕了它。那種情況會產生一個不同的訊息)。其它像Connection timed out這樣的訊息可能表示更基礎的問題,如缺少網路連線。

4. 管理核心資源

PostgreSQL某些時候會耗盡作業系統的各種資源限制,當同一個系統上執行著多個拷貝的伺服器或在一個非常大的安裝中時尤其如此。本節解釋了PostgreSQL使用的核心資源以及你可以採取的用於解決核心資源消耗相關問題的步驟。

4.1. 共享記憶體和訊號量

共享記憶體和訊號量一起被稱為"System V IPC"(其中還有訊息佇列,不過它與PostgreSQL無關)。除了在Windows上(PostgreSQL提供了自己的實現),這些功能都是執行PostgreSQL所必需的。

完全缺少這些功能通常表現為伺服器啟動時的Illegal system call錯誤。這種情況下,除了重新配置核心之外別無選擇。PostgreSQL沒有它們就不能工作。 不過,在現代作業系統中這種情況是罕見的。

當PostgreSQL超出了這些IPC的硬限制之一時,伺服器會拒絕啟動並且並且留下一條有指導性的錯誤訊息,其中描述了問題以及應該怎麼做。相關的核心引數在不同系統之間的命名方式一致,Table 18-1給出了一個概述。不過,設定它們的方法卻多種多樣。下面給出了對於某些平臺的建議:

Note: 
在PostgreSQL 9.3 之前,啟動伺服器所要求的 System V 共享記憶體的量要更大。如果你在執行著一個老版本的伺服器,請參考該伺服器版本的文件。

Table 18-1. System V IPC引數


image


PostgreSQL要求少量位元組的 System V 共享記憶體(在 64 位平臺上通常是 48 位元組)用於每一個伺服器拷貝。在大多數現代作業系統上,這個量很容易得到。但是,如果你運行了很多個伺服器拷貝,或者其他應用也在使用 System V 共享記憶體,可能需要增加SHMMAX(以位元組計的共享記憶體段的最大尺寸)或SHMALL(系統範圍內 System V 共享記憶體的總量)。注意在很多系統上SHMALL是以頁面而不是位元組來度量。

不太可能出問題的是共享記憶體段的最小尺寸(SHMMIN),對PostgreSQL來說應該最多大約是 32 位元組(通常只是1)。而系統範圍(SHMMNI)或每個程序(SHMSEG)的最大共享記憶體段數目不太可能會導致問題,除非你的系統把它們設成零。

PostgreSQL對每個允許的連線(max_connections)、每個允許的自動清理工作者程序(autovacuum_max_workers)和每個允許的後臺程序(max_worker_processes)使用一個訊號量, 以16個為一個集合。每個這種集合還包含第 17 個訊號量, 其中儲存一個"magic number",以檢測和其它應用使用的訊號量集合的衝突。 系統裡的最大訊號量數目是由SEMMNS設定的, 因此這個值必須至少和max_connections加autovacuum_max_workers再加max_worker_processes一樣大, 並且每 16 個連線外加工作者還要另外加一個(見Table 18-1中的公式)。引數SEMMNI 決定系統中同一時刻可以存在的訊號量集合的數目限制。因此這個引數必須至少為ceil((max_connections + autovacuum_max_workers + max_worker_processes + 5) / 16)。降低允許的連線數目是一種臨時的繞開失敗(來自函式semget)的方法,通常使用讓人混亂的措辭"No space left on device"。

在某些情況下可能還有必要增大SEMMAP,使之至少與SEMMNS相近。 這個引數定義訊號量資源對映的尺寸,在其中每個連續的可用訊號量塊都需要一項。 每當一個訊號量集合被釋放,那麼它要麼會被加入到該與被釋放塊相鄰的一個現有項,或者它會被註冊在一個新對映項中。如果對映被填滿,被釋放的訊號量將丟失(直到重啟)。因此訊號量空間的碎片時間長了會導致可用的訊號量比應有的訊號量少。

SEMMSL引數決定一個訊號量集合中可以有多少訊號量,對於PostgreSQL而言必須至少是 17。

許多其他設定與"semaphore undo"(訊號量撤銷)有關,例如SEMMNU和SEMUME,但不影響PostgreSQL。

AIX

至少到版本 5.1 為止,不再需要對這些引數(例如SHMMAX)做任何特殊的配置,這看起來就像是被配置成允許所有記憶體都被用作共享記憶體。這是一種通常被用於其他資料庫(DB/2)的配置。

但是,可能需要修改/etc/security/limits中的全域性ulimit資訊,預設的檔案尺寸硬限制(fsize)和檔案數量(nofiles)可能太低。

FreeBSD

可以使用sysctl或loader介面來改變預設配置。下列引數可以使用sysctl設定:


# sysctl kern.ipc.shmall=32768
# sysctl kern.ipc.shmmax=134217728
# sysctl kern.ipc.semmap=256

要讓這些設定在重啟之後也保持,請修改/etc/sysctl.conf。

對於sysctl所關心的來說這些訊號量相關的設定都是隻讀的,但是可以在/boot/loader.conf中設定:


kern.ipc.semmni=256
kern.ipc.semmns=512
kern.ipc.semmnu=256

修改這些值後需要一次重啟讓新設定能生效。 (注意:FreeBSD 不使用SEMMAP。較老的版本 會接受並且忽略kern.ipc.semmap的設定,而較新的 版本會完全拒絕它)。

你可能也希望你的核心將共享記憶體鎖定在 RAM 中並且防止它被換頁到交換分割槽。這可以使用sysctl的設定 kern.ipc.shm_use_phys來完成。

如果通過啟用sysctl的security.jail.sysvipc_allowed執行在 FreeBSD jail 中,執行在不同 jail 中的postmaster應當被不同的作業系統使用者執行。這可以提高安全性,因為它阻止非 root 使用者干涉不同 jail 中的共享記憶體或訊號量,並且它允許 PostgreSQL IPC 清理程式碼正確地工作(在 FreeBSD 6.0 及其後的版本中,IPC 清理程式碼不能正確地檢測到其他 jail 中的程序,也不能阻止不同 jail 中的 postmaster 執行在相同的埠)。

FreeBSD 4.0 之前的版本的工作與OpenBSD相似(見下文)。

NetBSD

在NetBSD 5.0 及其後的版本中,IPC 引數可以使用sysctl調整。例如:


$ sysctl -w kern.ipc.shmmax=16777216

要使這些設定在重啟後保持,請修改/etc/sysctl.conf。

你可能也希望你的核心將共享記憶體鎖定在 RAM 中並且防止它被換頁到交換分割槽。這可以使用sysctl的設定 kern.ipc.shm_use_phys來完成。

NetBSD 5.0 以前的版本的工作與OpenBSD相似(見下文),除了那些引數應該用關鍵詞options設定而不是option。

OpenBSD

當核心被編譯時,選項SYSVSHM和SYSVSEM需要被啟用(它們預設值)。共享記憶體的最大尺寸由選項SHMMAXPGS(以頁面計)決定。下面展示了一個如何設定多個引數的例子:


option        SYSVSHM
option        SHMMAXPGS=4096
option        SHMSEG=256

option        SYSVSEM
option        SEMMNI=256
option        SEMMNS=512
option        SEMMNU=256
option        SEMMAP=256

你可能也希望你的核心將共享記憶體鎖定在 RAM 中並且防止它被換頁到交換分割槽。這可以使用sysctl的設定 kern.ipc.shm_use_phys來完成。

HP-UX

預設的設定可以滿足正常的安裝。在HP-UX 10 上,SEMMNS的出廠預設值是 128,這可能對大型資料庫站點太低。

IPC引數可以在Kernel Configuration->Configurable Parameters下的System Administration Manager(SAM)中被設定。當你完成時選擇Create A New Kernel。

Linux

預設的最大段尺寸是 32 MB,並且預設的最大總尺寸是 2097152 個頁面。一個頁面幾乎總是 4096 位元組,除了在使用少見"huge pages"的核心配置中(使用getconf PAGE_SIZE來驗證)。

共享記憶體尺寸設定可以通過sysctl介面來更改。例如,要允許 16 GB:


$ sysctl -w kernel.shmmax=17179869184
$ sysctl -w kernel.shmall=4194304

另外在重啟之間這些設定可以被儲存在檔案/etc/sysctl.conf中。我們強烈推薦這樣做。

古老的髮型可能沒有sysctl程式,但是可以通過操縱/proc檔案系統來得到等效的更改:


$ echo 17179869184 >/proc/sys/kernel/shmmax
$ echo 4194304 >/proc/sys/kernel/shmall

剩下的預設值都被設定得很寬大,並且通常不需要更改。

OS X

在 OS X 中配置共享記憶體的推薦方法是建立一個名為/etc/sysctl.conf的檔案,其中包含這樣的變數賦值:


kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=1024

注意在某些 OS X 版本中,所有五個共享記憶體引數必須在/etc/sysctl.conf中設定,否則值將會被忽略。

注意近期的 OS X 版本會忽略把SHMMAX設定成非 4096 倍數值的嘗試。

在這個平臺上,SHMALL以 4kB 的頁面度量。

在更老的 OS X 版本中,你將需要重啟來讓共享記憶體引數的更改生效。到了 10.5,可以使用sysctl隨時改變除了SHMMNI之外的所有引數。但是最好還是通過/etc/sysctl.conf來設定你喜歡的值,這樣重啟之後這些值還能被保持。

只有在 OS X 10.3.9 及以後的版本中才遵循/etc/sysctl.conf檔案。如果你正在使用 10.3.x 之前的釋出,你必須編輯檔案/etc/rc並且在下列命令中改變值:


sysctl -w kern.sysv.shmmax
sysctl -w kern.sysv.shmmin
sysctl -w kern.sysv.shmmni
sysctl -w kern.sysv.shmseg
sysctl -w kern.sysv.shmall

注意/etc/rc通常會被 OS X 的系統更新所覆蓋,因此你應該在每次更新之後重做這些編輯。

在 OS X 10.2 及更早的版本中,應該在檔案/System/Library/StartupItems/SystemTuning/SystemTuning中編輯這些命令。

SCO OpenServer

在預設的配置中,只允許每個段有 512kB 的共享記憶體。要增加這個設定,首先更改到目錄/etc/conf/cf.d。要顯示SHMMAX的當前值,執行:


./configure -y SHMMAX

要為SHMMAX設定一個新值,執行:


./configure SHMMAX=value

這裡value是你要使用的新值(以位元組計)。在設定SHMMAX之後,重新編譯核心:


./link_unix

並且重啟。

Solaris 2.6 至 2.9 (Solaris 6 至 Solaris 9)

相似的設定可以在/etc/system中更改,例如:

set shmsys:shminfo_shmmax=0x2000000
set shmsys:shminfo_shmmin=1
set shmsys:shminfo_shmmni=256
set shmsys:shminfo_shmseg=256

set semsys:seminfo_semmap=256
set semsys:seminfo_semmni=512
set semsys:seminfo_semmns=512
set semsys:seminfo_semmsl=32
你需要重啟來讓更改生效。關於更老版本的 Solaris 下的共享記憶體的資訊請見http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html。

Solaris 2.10 (Solaris 10) 及以後
OpenSolaris

在 Solaris 10 及以後的版本以及 OpenSolaris 中,預設的共享記憶體和訊號量設定已經足以應付大部分PostgreSQL應用。Solaris 現在將SHMMAX的預設值設定為系統 RAM的四分之一。要進一步調整這個設定,使用與postgres使用者有關的一個專案設定。例如,以root執行下列命令:

projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged,8GB,deny)" -U postgres -G postgres user.postgres
這個命令增加user.postgres專案並且將用於postgres使用者的最大共享記憶體設定為 8GB,並且在下次使用者登入進來時或重啟PostgreSQL(不是重新載入)時生效。上述假定PostgreSQL是由postgres組中的postgres使用者所執行。不需要重新啟動伺服器。

對於將有巨大數量連線的資料庫伺服器,我們推薦的其他核心設定修改是:


project.max-shm-ids=(priv,32768,deny)
project.max-sem-ids=(priv,4096,deny)
project.max-msg-ids=(priv,4096,deny)

此外,如果你正在在一個區中執行PostgreSQL,你可能也需要提升該區的資源使用限制。更多關於projects 和prctl的資訊請見System Administrator's Guide中的 "Chapter2: Projects and Tasks"。

UnixWare

在UnixWare 7 上,預設配置中共享記憶體段的最大尺寸是 512 kB。要顯示SHMMAX的當前值,執行:


/etc/conf/bin/idtune -g SHMMAX

這將顯示當前值、預設值、最小值和最大值。要為SHMMAX設定一個新值,執行:


/etc/conf/bin/idtune SHMMAX value

這裡value是你想要使用的新值(以位元組計)。在設定SHMMAX之後,重新編譯核心:


/etc/conf/bin/idbuild -B

並且重啟。

4.2. 資源限制

Unix類作業系統強制了許多種資源限制,這些限制可能干擾你的PostgreSQL伺服器的操作。尤其重要的是對每個使用者的程序數目的限制、每個程序開啟檔案數目的限制以及每個程序可用的記憶體的限制。這些限制中每個都有一個"硬"限制和一個"軟"限制。實際使用的是軟限制,但使用者可以自己修改成最大為硬限制的數目。而硬限制只能由root使用者修改。系統呼叫setrlimit負責設定這些引數。 shell的內建命令ulimit(Bourne shells)或limit(csh)被用來從命令列控制資源限制。 在 BSD 衍生的系統上,/etc/login.conf檔案控制在登入期間設定的各種資源限制。詳見作業系統文件。相關的引數是maxproc、openfiles和datasize。例如:


default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...

(-cur是軟限制。增加-max可設定硬限制)。

核心也可以在某些資源上有系統範圍的限制。

在Linux上,/proc/sys/fs/file-max決定核心可以支援開啟的最大檔案數。你可以通過往該檔案寫入一個不同的數值修改此值, 或者通過在/etc/sysctl.conf中增加一個賦值來修改。 每個程序的最大開啟檔案數限制是在編譯核心的時候固定的;更多資訊請見/usr/src/linux/Documentation/proc.txt。

PostgreSQL伺服器為每個連線都使用一個程序, 所以你應該至少和允許的連線同樣多的程序,再加上系統其它部分所需要的程序數目。 通常這個並不是什麼問題,但如果你在一臺機器上執行多個伺服器,資源使用可能就會緊張。

開啟檔案的出廠預設限制通常設定為"socially friendly"的值, 它允許許多使用者在一臺機器上共存,而不會導致不成比例的系統資源使用。 如果你在一臺機器上執行許多伺服器,這也許就是你想要的,但是在專門的伺服器上, 你可能需要提高這個限制。

在另一方面,一些系統允許獨立的程序開啟非常多的檔案;如果不止幾個程序這麼幹,那系統範圍的限制就很容易被超過。如果你發現這樣的現像, 並且不想修改系統範圍的限制,你就可以設定PostgreSQL的 max_files_per_process配置引數來限制開啟檔案數的消耗。

4.3. Linux 記憶體過量使用

在 Linux 2.4 及其後的版本中,預設的虛擬記憶體行為對PostgreSQL不是最優的。由於核心實現記憶體過量使用的方法,如果PostgreSQL或其它程序的記憶體要求導致系統用光虛擬記憶體,那麼核心可能會終止PostgreSQL的 postmaster 程序(主伺服器程序)。

如果發生了這樣的事情,你會看到像下面這樣的核心訊息(參考你的系統文件和配置,看看在哪裡能看到這樣的訊息):

Out of Memory: Killed process 12345 (postgres).
這表明postgres程序因為記憶體壓力而被終止了。儘管現有的資料庫連線將繼續正常運轉,但是新的連線將無法被接受。要想恢復,PostgreSQL應該被重啟。

一種避免這個問題的方法是在一臺你確信其它程序不會耗盡記憶體的機器上執行PostgreSQL。 如果記憶體資源緊張,增加作業系統的交換空間可以幫助避免這個問題,因為記憶體不足(OOM)殺手(即終止程序這種行為)只有當實體記憶體和交換空間都被用盡時才會被呼叫。

如果PostgreSQL本身是導致系統記憶體耗盡的原因,你可以通過改變你的配置來避免該問題。在某些情況中,降低記憶體相關的配置引數可能有所幫助,特別是shared_buffers 和work_mem兩個引數。在其他情況中,允許太多連線到資料庫伺服器本身也可能導致該問題。在很多情況下,最好減小max_connections並且轉而利用外部連線池軟體。

在 Linux 2.6 及其後的版本中,可以修改核心的行為,這樣它將不會"過量使用"記憶體。儘管此設定不會阻止OOM 殺手被呼叫,但它可以顯著地降低其可能性並且將因此得到更魯棒的系統行為。這可以通過用sysctl選擇嚴格的過量使用模式來實現:

sysctl -w vm.overcommit_memory=2
或者在/etc/sysctl.conf中放置一個等效的項。你可能還希望修改相關的設定vm.overcommit_ratio。 詳細資訊請參閱核心文件的https://www.kernel.org/doc/Documentation/vm/overcommit-accounting檔案。

另一種方法,可以在改變或不改變vm.overcommit_memory的情況下使用。它將 postmaster 程序的程序相關的OOM score adjustment值設定為-1000,從而保證它不會成為 OOM 殺手的目標。 這樣做最簡單的方法是在 postmaster 的啟動指令碼中執行

echo -1000 > /proc/self/oom_score_adj
並且要在呼叫 postmaster 之前執行。請注意這個動作必須以 root 完成,否則它將不會產生效果。所以一個被 root 擁有的啟動指令碼是放置這個動作最容易的地方。如果這樣做,你還應該在呼叫 postmaster 之前在啟動指令碼中設定這些環境變數:


export PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
export PG_OOM_ADJUST_VALUE=0

這些設定將導致 postmaster 子程序使用普通的值為零的 OOM score adjustment 執行,所以 OOM 殺手仍能在需要時把它們作為目標。如果你想要子程序用某些其他 OOM score adjustment 值執行,可以為PG_OOM_ADJUST_VALUE使用其他的值(PG_OOM_ADJUST_VALUE也能被省略,那時它會被預設為零)。如果你沒有設定PG_OOM_ADJUST_FILE,子程序將使用和 postmaster 相同的 OOM score adjustment 執行,這是不明智的,因為重點是確保 postmaster 具有優先的設定。

更老的 Linux 核心不提供/proc/self/oom_score_adj,但是可能有一個具有相同功能的早期版本,它被稱為/proc/self/oom_adj。這種方式工作起來完全相同,除了禁用值是-17而不是-1000。

Note: 
有些廠商的 Linux 2.4 核心被報告有著 2.6 過量使用sysctl引數的早期版本。不過,在沒有相關程式碼的 2.4 核心裡設定vm.overcommit_memory為 2 將會讓事情更糟。我們推薦你檢查一下實際的核心原始碼(見檔案mm/mmap.c中的vm_enough_memory函式),驗證一下這個是在你的核心中是被支援的, 然後再在 2.4 安裝中使用它。文件檔案overcommit-accounting的存在不能當作是這個特性存在的證明。如果有疑問,請諮詢一位核心專家或你的核心廠商。

4.4. Linux 大頁面

在PostgreSQL使用大量 連續記憶體塊時利用大頁面來降低開銷。要在 PostgreSQL中啟用這個 特性,你需要一個 CONFIG_HUGETLBFS=y並且 CONFIG_HUGETLB_PAGE=y的核心。 你也還必須調節系統設定 vm.nr_hugepages。要估計所需的 大頁面的數量,關閉大頁面啟動 PostgreSQL並且從 proc 檔案系統檢查VmPeak值:


$ head -1 /path/to/data/directory/postmaster.pid
4170
$ grep ^VmPeak /proc/4170/status
VmPeak:  6490428 kB

6490428 / 2048 (在這種情況下PAGE_SIZE是 2MB)大約是 3169.154個大頁面,因此你將需要至少 3170個大頁面:


$ sysctl -w vm.nr_hugepages=3170

有時候核心會無法分配想要的數量的大頁面,所以可能有必要 重複該命令或者重新啟動。不要忘了向 /etc/sysctl.conf中增加一個項來讓這 個設定重啟後也能保持。

有必要給予資料庫伺服器作業系統使用者許可權,讓他能通過sysctl設定vm.hugetlb_shm_group以使用大頁面,以及用ulimit -l鎖定記憶體的許可權。

PostgreSQL中大頁面的預設行為是 儘可能使用它們並且在失敗時轉回到正常頁面。要強制使用大頁面,你可 以把 huge_pages設定成 on。注意在這種情況下如果沒有足夠的大頁面可用, PostgreSQL將會啟動失敗。

5. 關閉伺服器

有幾種關閉資料庫伺服器的方法。通過給postgres程序傳送不同的訊號,你就可以控制關閉型別。

SIGTERM

這是智慧關閉模式。在接收SIGTERM後, 伺服器將不允許新連線,但是會讓現有的會話正常結束它們的工作。僅當所有的會話終止後它才關閉。 如果伺服器處線上備份模式,它將等待直到線上備份模式不再被啟用。當線上備份模式被啟用時, 仍然允許新的連線,但是隻能是超級使用者的連線(這一例外允許超級使用者連線來終止線上備份模式)。 如果伺服器在恢復時請求智慧關閉,恢復和流複製只有在所有正常會話都終止後才停止。

SIGINT

這是快速關閉模式。伺服器不再允許新的連線,並向所有現有伺服器程序傳送SIGTERM,讓它們中斷當前事務並立刻退出。然後伺服器等待所有伺服器程序退出並最終關閉。 如果服務處於線上備份模式,備份模式將被終止並致使備份無用。

SIGQUIT

這是立即關閉模式。伺服器將給所有子程序傳送 SIGQUIT並且等待它們終止。如果有任何程序沒有在 5 秒內終止,它們將被髮送 SIGKILL。主伺服器程序將在所有子程序退出之後立刻退出,而無需做普通的資料庫關閉處理。這將導致在下一次啟動時(通過重放 WAL 日誌)恢復。只在緊急 時才推薦這種方式。

pg_ctl程式提供了一個傳送這些訊號關閉伺服器的方便的介面。 另外,你在非 Windows 系統上可以用kill直接傳送這些訊號。可以用ps程式或者從資料目錄的postmaster.pid檔案中找到postgres程序的PID。例如,要做一次快速關閉:


$ kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`

Important: 最好不要使用SIGKILL關閉伺服器。 這樣做將會阻止伺服器釋放共享記憶體和訊號量,那麼在開始一個新的伺服器之前,可能需要手動完成這些釋放。 此外,使用SIGKILL殺掉postgres程序時,postgres不會有機會將訊號傳播到它的子程序,所以也必須手工殺掉單個的子程序。

要終止單個會話同時允許其他會話繼續,使用pg_terminate_backend()(參閱Table 9-77) 或傳送SIGTERM訊號到該會話相關的子程序。

6. 升級一個PostgreSQL集簇

本節討論如何把你的資料庫資料從一個PostgreSQL發行升級到一個更新的發行。

PostgreSQL主版本用版本號的前兩個數字組表示,例如 8.4。PostgreSQL次要版本則由第三組版本數字表示,例如 8.4.2 是 8.4 的第二個次要發行。次要發行從來不改變內部儲存格式並且總是向前並向後相容同一主版本號