PostgreSQL服務器管理:服務器設置和操作
本文檔為PostgreSQL 9.6.0文檔,本轉載已得到原譯者彭煜瑋授權。
和對外部世界可訪問的任何服務器守護進程一樣,我們也建議在一個獨立的用戶賬戶下運行PostgreSQL。這個用戶賬戶應該隻擁有被該服務器管理的數據,並且應該不能被其他守護進程共享(例如,使用用戶nobody是一個壞主意)。我們不建議把可執行文件安裝為屬於這個用戶,因為妥協係統可能接著修改它們自己的二進製文件。
要在你的係統中增加一個 Unix 用戶賬戶,查看一個命令useradd或adduser。通常會用postgres(本書中也假定用這個賬戶),但是你可以使用另一個名稱。
在你能做任何事情之前,你必須在磁盤上初始化一個數據庫存儲區域。我們稱之為一個數據庫集簇(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沒有提供標準的文件係統語義,這將導致可靠性問題 (參閱https://www.time-travellers.org/shane/papers/NFS_considered_harmful.html )。 具體來說,延遲(異步)寫入到NFS服務器可以導致數據損壞問題。 如果可能的話,把NFS文件係統掛載為同步(無高速緩存)可以避免這種災難。還有,我們不推薦軟掛載的NFS文件係統。
存儲區域網絡(SAN)通常使用非NFS的通訊協議,並且可能或者不可能遭受這類災難。建議谘詢供應商的文檔來了解數據一致性保證。PostgreSQL無法做到比它所使用的文件係統更可靠。
在任何人可以訪問數據庫前,你必須啟動數據庫服務器。 數據庫服務器程序是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這樣的消息可能表示更基礎的問題,如缺少網絡連接。
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參數
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 下的共享內存的信息請見https://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將會啟動失敗。
Linux大頁麵特性的詳細描述可見https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.
有幾種關閉數據庫服務器的方法。通過給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信號到該會話相關的子進程。
本節討論如何把你的數據庫數據從一個PostgreSQL發行升級到一個更新的發行。
PostgreSQL主版本用版本號的前兩個數字組表示,例如 8.4。PostgreSQL次要版本則由第三組版本數字表示,例如 8.4.2 是 8.4 的第二個次要發行。次要發行從來不改變內部存儲格式並且總是向前並向後兼容同一主版本號中的次要發行,例如 8.4.2 與 8.4、8.4.1、8.4.6 兼容。要在兼容的版本間升級,你隻需要簡單地在服務器關閉時替換可執行文件並重啟服務器。數據目錄則保持不變 — 次要升級就這麼簡單。
對於PostgreSQL的主發行, 內部數據存儲格式常被改變,這使升級複雜化。傳統的把數據移動到 新主版本的方法是先轉儲然後重新載入到數據庫,不過這可能會很慢。 一種更快的方式是pg_upgrade。如下文所討論的, 複製方法也能被用於升級。
新的主版本也通常會引入一些用戶可見的不兼容性,因此可能需要應用程序編程上的改變。所有用戶可見的更改都被列在發行注記(Appendix E)中,請特別注意標有 "Migration" 的小節。如果你正在跨越幾個主版本升級,一定要閱讀每個中間版本的發行注記。
小心的用戶在完全切換過去之前將希望在新版本上測試他們的客戶端應用。因此,建立一個新舊版本的並存安裝通常是一個好主意。在測試一個PostgreSQL主要升級時,考慮下列可能的改變類別:
管理
用於管理員監控和控製服務器的功能在每一個主發行中經常會改變和增加。
SQL
通常這包括新的 SQL 命令功能並且在行為上沒有更改,除非在發行注記中有特別提到。
庫 API
通常libpq等庫值增加新功能,除非在發行注記中有特別提到。
係統目錄
係統目錄改變通常隻影響數據庫管理工具。
服務器 C-語言 API
這涉及到後端函數 API 中的改變,它使用 C 編程語言編寫。這些改變影響引用服務器內部後端函數的代碼。
6.1. 通過pg_dumpall升級數據
一種升級方法是從PostgreSQL的一個主版本轉儲數據並將它重新載入到另一個主版本中 — 要這樣做,你必須使用pg_dumpall這樣的邏輯備份工具,文件係統級別的備份方法將不會有用(這也阻止你在一個不兼容版本的PostgreSQL中使用一個數據目錄,因此在一個數據目錄上嚐試啟動一個錯誤的服務器版本不會造成很大的危害)。
我們推薦你從較新版本的PostgreSQL中使用pg_dump和pg_dumpall程序,這樣可以利用在這些程序中可能存在的改進。當前發行的轉儲程序可以讀取任何 7.0 以上版本服務器中的數據。
這些指令假定你現有的安裝位於/usr/local/pgsql目錄,並且數據區域在/usr/local/pgsql/data。請用你的路徑進行適當的替換。
1.如果在創建一個備份,確認你的數據庫沒有在被更新。這不會影響備份的完整性,但是那些更改當然不會被包括在備份中。如果必要,編輯/usr/local/pgsql/data/pg_hba.conf文件中的權限(或等效的方法)來不允許除你之外的任何人使用數據庫。關於訪問控製的額外信息請見Chapter 20。
要備份你的數據庫安裝,鍵入:
pg_dumpall > outputfile
要製作備份,你可以使用你正在運行版本的pg_dumpall命令,詳見Section 25.1.2。但是,要得到最好的結果,試試使用PostgreSQL 9.6.0 的pg_dumpall命令,因為這個版本包含了對舊版本的缺陷修複和改進。雖然這個建議可能看起來很奇怪,因為你還沒有安裝新版本,但如果你計劃平行地安裝新版本,遵循這個建議是很明智的。在這種情況下,你可以正常完成安裝並且稍後再來傳輸數據。這也將減少停機時間。
2.關閉就服務器:
pg_ctl stop
在那些自動啟動PostgreSQL的係統上,可能有一個啟動文件將完成同樣的事情。例如,在一個Red Hat Linux係統中,我們會發現這也能用:
/etc/rc.d/init.d/postgresql stop
3.如果從備份恢複,重命名或刪除舊的安裝目錄(如果它不是針對特定版本的)。重命名該目錄是一個好主意,而不是刪除它,因為如果你碰到問題並需要返回到它,它還存在。記住該目錄可能消耗可觀的磁盤空間。要重命名該目錄,使用類似的命令:
mv /usr/local/pgsql /usr/local/pgsql.old
(注意將該目錄作為一個單一單元移動,這樣相對路徑可以保持不變)。
4.安裝新版本的PostgreSQL在 Section 16.4.
5.如果需要,創建一個新的數據庫集簇。記住你必須在登錄到一個特殊的數據庫用戶賬戶(如果你在升級,你就已經有了這個賬戶)時執行這些命令。
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data
6.恢複你之前的pg_hba.conf以及任何postgresql.conf修改。
7.啟動數據庫服務器,也要使用特殊的數據庫用戶賬戶:
/usr/local/pgsql/bin/postgres -D /usr/local/pgsql/data
8.最後,使用新的 psql從備份恢複你的數據:
/usr/local/pgsql/bin/psql -d postgres -f outputfile
通過在一個不同的目錄中安裝新的服務器並且並行地在不同的端口運行新舊兩個服務器可以達到最低的停機時間。那麼你可以這樣用:
pg_dumpall -p 5432 | psql -d postgres -p 5433
來轉移你的數據。
6.2. 通過pg_upgrade升級數據
pg_upgrade模塊允許一個安裝從一個 PostgreSQL主版本“就地”升級成另一個主版本。 升級可以在數分鍾內被執行,特別是使用--link模式時。它 要求和上麵的pg_dumpall相似的步驟,例如啟動/停止 服務器、運行initdb。pg_upgrade 文檔概述了所需的步驟。
6.3. 通過複製升級數據
也可以使用某些複製方法來使用PostgreSQL的已更新版本創建一個後備服務器,例如Slony,它支持在不同主版本的PostgreSQL之間的複製。後備服務器可以在同一台計算機或者不同的計算機上。一旦它和主服務器(運行舊版本的PostgreSQL)同步好,你可以切換主機並且將後備服務器作為主機,然後關閉舊的數據庫實例。這樣一種切換使得一次升級的停機時間隻有數秒。
服務器在運行時,它不可能讓惡意用戶取代正常的數據庫服務器。然而,當服務器關閉時, 一個本地用戶可以通過啟動它們自己的服務器來欺騙正常的服務器。行騙的服務器可以讀取客戶端發送的密碼和查詢語句, 但是不會返回任何數據,因為PGDATA這個目錄是安全的(它有目錄權限)。 欺騙是可能的,因為任何用戶都可以啟動一個數據庫服務器;客戶端無法識別一個無效的服務器,除非它被專門配置。
一種阻止local連接欺騙的方法是使用一個 Unix 域套接字目錄 (unix_socket_directories),該目錄隻對一個被信任的本地用戶有寫權限。 這可以防止惡意用戶在該目錄中創建自己的套接字文件。如果你擔心有些應用程序可能仍然引用/tmp下的套接字文件並且因此容易受到欺騙,可在操作係統啟動時創建一個符號鏈接/tmp/.s.PGSQL.5432指向一個被重定位的套接字文件。你也可能需要修改/tmp清除腳本防止刪除這個符號鏈接。
local連接的另一個選項是對客戶端使用requirepeer指定所需的連接到該套接字的服務器進程的擁有者。
要在TCP連接上防止欺騙,最好的解決方案是使用 SSL 證書,並且確保客戶檢查服務器的證書。 要做到這點,服務器必須配置為僅接受hostssl連接,並且有 SSL 密鑰和證書文件。 TCP 客戶端連接必須使用sslmode=verify-ca或verify-full進行連接,並且安裝有適當的根證書文件。
PostgreSQL提供了幾個不同級別的加密, 並且在保護數據不會因為數據庫服務器偷竊、不道德的管理員、不安全網絡等因素而泄漏方麵 提供很高的靈活性。加密可能也是保護一些諸如醫療記錄或財務交易等敏感數據所要求的。
口令存儲加密
默認情況下,數據庫用戶的口令以 MD5 哈希的方式存儲, 所以管理員無法判斷賦予用戶的實際口令。如果 MD5 被加密用於客戶端認證, 那麼未加密的口令甚至都不可能臨時出現在服務器上,因為客戶端在透過網絡發送口令之前,就先用 MD5 加密過。
指定列加密
pgcrypto模塊允許對特定域進行加密存儲。這個功能隻對某些敏感數據有用。 客戶端提供解密的密鑰,然後數據在服務器端解密並發送給客戶端。
在數據被解密和在服務器與客戶端之間傳遞時,解密數據和解密密鑰將會在服務器端存在短暫的一段時間。 這就給那些能完全訪問數據庫服務器的人提供了一個短暫的截獲密鑰和數據的時間,例如係統管理員。
數據分區加密
存儲加密可以在文件係統層麵或者塊層麵上執行。Linux 文件係統加密 選項包括 eCryptfs 和 EncFS,而 FreeBSD 使用 PEFS。快層麵或者全 盤加密選項包括 Linux 上的 dm-crypt + LUKS 以及 FreeBSD 上的 GEOM 模塊 geli 及 gbde。很多其他操作係統也支持這個功能,包括 Windows。
這個機製避免了在整個計算機或者驅動器被盜的情況下, 未加密的數據被從驅動器中讀取。它無法防止在文件係統被掛 載時的攻擊,因為在掛載之後,操作係統提供數據的解密視圖。不過,要想掛載該文件係統,你需要有一些方法把加密密鑰傳遞給操作 係統,並且有時候這個密鑰就存儲在掛載該磁盤的主機上的某處。
跨網絡加密口令
MD5認證方法在將口令發送給服務器之前由客戶端對它進行雙重加密。第一次 MD5 加密是基於用戶名的, 然後在建立數據庫連接時,用服務器發送的隨機鹽粒再次加密口令。通過網絡傳遞給服務器的就是這個雙重加密的值。雙重加密 不僅可以防止口令被發現,還可以防止稍後另一個連接使用同樣的加密口令連接數據庫。
跨網絡加密數據
SSL 連接加密所有跨網絡發送的數據:口令、查詢以及返回的數據。pg_hba.conf文件允許管理員指定哪些主機可以使用 非加密連接(host),以及哪些主機需要使用 SSL 加密的連接(hostssl)。客戶端還可以指定它們隻通過 SSL 連接到服務器。我們還可以使用Stunnel或SSH加密傳輸。
SSL 主機認證
客戶端和主機都可以提供 SSL 證書給對方。這在兩邊都需要一些額外的配置, 但是這種方式提供了比僅使用口令更強的身份驗證。 它避免一個計算機偽裝成服務器,這個時長隻要足夠讀取客戶端發送的口令就行了。它還避免了 "中間人"攻擊,在其中有一台計算機處於客戶端和服務器之間並偽裝成服務器讀取和傳遞兩者之間的所有數據。
客戶端加密
如果服務器所在機器的係統管理員是不可信的,那麼客戶端加密數據也是必要的。在這種情況下,未加密的數據從來不會在數據庫服務器上出現。數據在發送給服務器之前加密,而數據庫結果在能使用之前必須在客戶端上解密。
PostgreSQL有一個對使用SSL連接加密客戶端/服務器通訊的本地支持,它可以增加安全性。這個特性要求在客戶端和服務器端都安裝OpenSSL並且在編譯PostgreSQL的時候打開這個支持(見Chapter 16)。
當SSL支持被編譯在PostgreSQL中時,可以通過將postgresql.conf中的 ssl設置為on讓PostgreSQL服務器帶著SSL支持被啟動。 服務器在同一個 TCP 端口監聽普通連接和SSL連接,並且將與任何正在連接的客戶端協商是否使用SSL。默認情況下,這是客戶端的選項,關於如何設置服務器來要求某些或者所有連接使用SSL請見Section 20.1。
PostgreSQL讀取係統範圍的OpenSSL配置文件。默認情況下,這個文件名為openssl.cnf並且被放置在openssl version -d所報告的目錄中。通過設置環境變量OPENSSL_CONF指定你想要的配置文件名可以覆蓋此默認配置。
OpenSSL支持範圍廣泛的密碼和認證算法。而在OpenSSL配置文件可以指定一個密碼列表, 你可以通過在postgresql.conf中修改ssl_ciphers來指定數據庫服務器使用的專用密碼。
Note: 使用NULL-SHA或NULL-MD5可以得到身份驗證但沒有加密開銷。不過,中間人能夠讀取和傳遞客戶端和服務器之間的通信。此外,加密開銷相比身份認證的開銷是最小的。出於這些原因,我們建議不要使用 NULL 密碼。
要SSL模式中啟動服務器,包含服務器證書和私鑰的文件必須存在。默認情況下,這些文件應該分別被命名為server.crt和server.key並且被放在服務器的數據目錄中,但是可以通過配置參數ssl_cert_file和ssl_key_file指定其他名稱和位置。
在 Unix 係統上,server.key上的權限必須不允許所有人或組的任何訪問,通過命令chmod 0600 server.key可以做到。或者,該文件可以由 root 所擁有並且具有組讀訪問(也就是0640權限)。這種設置適用於由操作係統管理證書和密鑰文件的安裝。用於運行PostgreSQL服務器的用戶應該被作為能夠訪問那些證書和密鑰文件的組成員。
如果私鑰被一個密碼保護著,服務器將提示要求這個密碼,並且在它被輸入前不會啟動。
在有些情況下,服務器證書可能由一個"中間" 證書頒發機構簽名,而不是直接由客戶端信任的證書頒發 機構直接簽名。要使用這樣的證書,請追加該簽發權的證書到server.crt文件,然後追加其父簽發權的證書,以此類推一直到一個被客戶端所信任的"根"或"中間"頒發機構,即由一個位於客戶端root.crt文件中的證書簽發。
9.1. 使用客戶端證書
要求客戶端提供受信任的證書,把你信任的證書頒發機構(CA)的證書放置在數據目錄的文件root.crt中。並且修改postgresql.conf中的參數ssl_ca_file為root.crt,還要把認證選項clientcert=1加入到pg_hba.conf文件中合適的hostssl行上。然後將在 SSL 連接啟動時從客戶端請求該證書(一段對於如何在客戶端設置證書的描述請見Section 32.18)。服務器將驗證客戶端的證書是由受信任的證書頒發機構之一簽名。
如果中間CA出現在root.crt中,該文件必須也包含到它們的根CA的證書鏈。如果參數ssl_crl_file被設置,證書撤銷列表(CRL)項也要被檢查(顯示 SSL 證書用法的圖標見https://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s02.html)。
clientcert認證選項適用於所有的認證方法,但僅適用於pg_hba.conf中用hostssl指定的行。 當clientcert沒有指定或設置為 0時,如果配置了 CA 文件,服務器將仍然會根據它驗證任何提交的客戶端證書 — 但是它將不會堅持要求出示一個客戶端證書。
請注意服務器的root.crt列出了頂級的 CA,它們對客戶端證書的簽名被認為是可信的。 原則上不需要列出簽名服務器證書的 CA,然而在大多數情況下,這些 CA 對於客戶端證書也是可信的。
如果你在設置客戶端證書,你可能希望用cert認證方法,這樣證書控製用戶認證以及提供連接安全(在使用cert認證方法時,沒有必要顯式地指定clientcert=1)。
9.2. SSL 服務器文件用法
Table 18-2總結了與服務器上 SSL 配置有關的文件(顯示的文件名是默認的或者是經典名稱。本地配置的名稱可能會不同)。
文件server.key、server.crt、root.crt和root.crl(或者被配置的其他名字)隻在服務器啟動期間被檢查,所以要使對它們的修改生效,你必須重啟服務器。
9.3. 創建自簽名的證書
要為服務器創建一個快速的自簽名的證書,可以使用下麵的OpenSSL命令:
openssl req -new -text -out server.req
填充那些openssl要求的信息。確保把本地主機名當做"Common Name"輸入;挑戰密碼可以留空。 該程序將生成一個用口令保護的密鑰,它不會接受小於四字符的口令。要移去密鑰(如果你想自動啟動服務器就必須這樣),運行下麵的命令:
openssl rsa -in privkey.pem -out server.key
rm privkey.pem
輸入舊口令解鎖現有密鑰。然後:
openssl req -x509 -in server.req -text -key server.key -out server.crt
將一個證書變成自簽名的證書並複製密鑰和證書到服務器將要查找它們的地方。最後執行:
chmod og-rwx server.key
如果文件的權限比這個更自由,服務器將拒絕該文件。要了解更多關於如何創建你的服務器私鑰和證書的細節, 請參考OpenSSL文檔。
自簽名的證書可以被用於測試,但由證書頒發機構(CA)(要麼是全局CA中的一個或者一個本地 CA)簽名的證書應該被用在生產中,這樣客戶端可以驗證服務器的身份。如果對於組織來說所有的客戶端都是本地的,建議使用本地CA。
可以使用SSH來加密客戶端和PostgreSQL服務器之間的網絡連接。如果處理得當,這將提供一個足夠安全的網絡連接,即使是對那些無 SSL 能力的客戶端。
首先確認在PostgreSQL服務器的同一台機器上正確運行著一個SSH服務器,並且你可以使用ssh作為某個用戶登入。然後你可以從客戶端機器采用下麵這種形式的命令建立一個安全的隧道:
ssh -L 63333:localhost:5432 joe@foo.com
-L參數中的第一個數(63333)是隧道在你那一端的端口號,它可以是任意未用過的端口(IANA 把端口 49152 到 65535 保留為個人使用)。第二個數(5432)是隧道的遠端:你的服務器所使用的端口號。在端口號之間的名字或 IP 地址是你準備連接的數據庫服務器的主機,至於你是從哪個主機登入的,在這個例子中則由foo.com表示。為了使用這個隧道連接到數據庫服務器,你在本地機器上連接到端口 63333:
psql -h localhost -p 63333 postgres
對於數據庫服務器,在這個環境中它將把你看做是連接到localhost的主機foo.com上的真實用戶joe,並且它會使用被配置用於來自這個用戶和主機的連接的認證過程。注意服務器將不會認為連接是 SSL 加密的,因為事實上SSH服務器和PostgreSQL服務器之間沒有加密。隻要它們在同一台機器上,這就不會造成任何額外的安全風險。
為了讓隧道設置成功,你必須允許通過ssh作為joe@foo.com連接,就像你已經嚐試使用ssh來創建一個終端會話。
你應當也已經設定好了端口轉發:
ssh -L 63333:foo.com:5432 joe@foo.com
但是數據庫服務器則將會看到連接從它的foo.com接口進來,它沒有被默認設置listen_addresses = 'localhost'所打開。這通常不是你想要的。
如果你必須通過某個登錄主機"跳"到數據庫服務器,一個可能的設置看起來像:
ssh -L 63333:db.foo.com:5432 joe@shell.foo.com
注意這種從shell.foo.com到db.foo.com的連接的方法將不會被 SSH 隧道加密。當網絡被限製於各種方法時,SSH 提供了相當多的配置可能性。詳情請參考 SSH 的文檔。
Tip: 一些其他的應用可以提供安全隧道,它們使用和剛剛描述的 SSH 概念上相似的過程。
要為操作係統注冊一個Windows 事件日誌庫,發出這個命令:
regsvr32 pgsql_library_directory/pgevent.dll
這會創建被事件查看器使用的注冊表項,默認事件源命名為PostgreSQL。
要指定一個不同的事件源名稱(見event_source)。使用/n和/i選項:
regsvr32 /n /i:event_source_name pgsql_library_directory/pgevent.dll
要從操作係統反注冊事件日誌庫,發出這個命令:
regsvr32 /u [/i:event_source_name] pgsql_library_directory/pgevent.dll
Note:
要啟用數據庫服務器中的事件日誌,在postgresql.conf中修改log_destination來包括eventlog。
最後更新:2017-08-21 13:02:20