?
本文檔使用 php中文網(wǎng)手冊(cè) 發(fā)布
一次大型PostgreSQL安裝會(huì)很容易耗盡各種操作系統(tǒng)的資源上限。 甚至在有些系統(tǒng)上,出廠設(shè)置低得你都不用一次"大型"安裝。 如果你碰到這類問題,請(qǐng)繼續(xù)閱讀。
共享內(nèi)存和信號(hào)燈的正確叫法是"SystemV IPC"(還有消息隊(duì)列,不過與PostgreSQL無關(guān))。 盡管所有現(xiàn)代操作系統(tǒng)都提供這些特性,但并不是所有系統(tǒng)缺省都打開它或者有足夠的資源, 尤其是可用的RAM和數(shù)據(jù)庫應(yīng)用的需求增長。 (對(duì)于Windows移植,PostgreSQL自己提供這套機(jī)制的替換實(shí)現(xiàn), 所以大多數(shù)本條可以忽略不計(jì)。)
完全缺少這些機(jī)制的表現(xiàn)通常是在服務(wù)器啟動(dòng)時(shí)的Illegalsystemcall 錯(cuò)誤。這時(shí)除了重新配置內(nèi)核以外沒什么可做的。PostgreSQL沒它們不工作。 然而,在現(xiàn)代的操作系統(tǒng),這種情況是罕見的。
如果PostgreSQL超出了這些IPC資源的硬限制之 一的時(shí)候就會(huì)拒絕啟動(dòng),并且留下一條相當(dāng)有提示的錯(cuò)誤信息, 告訴你它碰到了什么問題以及需要為它做些什么(又見Section 17.3.1)。相關(guān)的內(nèi)核參數(shù)在不同系統(tǒng)之間有著相對(duì)固定的術(shù)語 ;Table 17-1是一個(gè)概況。不過,設(shè)置它們的方法卻多種多樣。 不過要注意的是,你可能最好重新啟動(dòng)機(jī)器,或者還要重新編譯內(nèi)核來修改這些設(shè)置。
Table 17-1. SystemVIPC參數(shù)
名稱 | 描述 | 合理取值 |
---|---|---|
SHMMAX | 最大共享內(nèi)存段尺寸(字節(jié)) | 最少若干兆(見本文) |
SHMMIN | 最小共享內(nèi)存段尺寸(字節(jié)) | 1 |
SHMALL | 可用共享內(nèi)存的總數(shù)量(字節(jié)或內(nèi)存頁數(shù)) | 如果是字節(jié),就和SHMMAX一樣;如果是頁數(shù),則為ceil(SHMMAX/PAGE_SIZE) |
SHMSEG | 每進(jìn)程最大共享內(nèi)存段數(shù)量 | 只需要1個(gè)段,不過缺省比這高得多。 |
SHMMNI | 系統(tǒng)范圍最大共享內(nèi)存段數(shù)量 | 類似SHMSEG加上用于其它應(yīng)用的空間 |
SEMMNI | 信號(hào)燈標(biāo)識(shí)符的最小數(shù)量(也就是套) | 至少ceil((max_connections+autovacuum_max_workers)/16) |
SEMMNS | 系統(tǒng)范圍的最大信號(hào)燈數(shù)量 | ceil((max_connections+autovacuum_max_workers)/16)*17加上用于其它應(yīng)用的空間 |
SEMMSL | 每套信號(hào)燈最小信號(hào)燈數(shù)量 | 至少17 |
SEMMAP | 信號(hào)燈映射里的記錄數(shù)量 | 參閱本文 |
SEMVMX | 信號(hào)燈的最大值 | 至少1000,缺省通常是32767,除非被迫,否則不要修改 |
最重要的共享內(nèi)存參數(shù)是SHMMAX(以字節(jié)記的共享內(nèi)存段可擁有的最大尺寸)。
如果你收到來自shmget
的類似"Inval idargument"這樣的錯(cuò)誤信息,
那么很有可能是你超過限制了。要求的共享內(nèi)存段數(shù)量與若干個(gè)
PostgreSQL配置參數(shù)相關(guān),如Table 17-2所示。
(任何錯(cuò)誤消息,你可能會(huì)包括分配請(qǐng)求失敗的確切大小。)
因此,作為一種臨時(shí)的解決方法,你可以降低這些設(shè)置來繞過失敗。
雖然它有可能獲得PostgreSQL運(yùn)行2MB的SHMMAX的,
你需要相當(dāng)可接受的性能??扇≡O(shè)置在數(shù)百兆到幾千兆字節(jié)。
有些系統(tǒng)對(duì)系統(tǒng)里面共享內(nèi)存的總數(shù)(SHMALL)還有限制。 請(qǐng)注意這個(gè)數(shù)值必須足夠大,大到PostgreSQL 加上其它使用共享內(nèi)存段的應(yīng)用的總和。注意:SHMALL 在很多系統(tǒng)上是用頁面數(shù),而不是字節(jié)數(shù)來計(jì)算的。
不太可能出問題的是共享內(nèi)存段的最小尺寸(SHMMIN), 對(duì)PostgreSQL來說大約是500kB左右(通常只是1), 而系統(tǒng)范圍(SHMMNI)或每進(jìn)程(SHMSEG) 最大共享內(nèi)存段數(shù)量不應(yīng)該會(huì)產(chǎn)生問題,除非你的系統(tǒng)把它們?cè)O(shè)成零。
PostgreSQL每個(gè)允許的連接使用一個(gè)信號(hào)燈(max_connections),
以16個(gè)為一套。每套信號(hào)燈還包含第17個(gè)信號(hào)燈,
它里面存儲(chǔ)一個(gè)"magicnumber",以檢測(cè)和其它應(yīng)用使用的信號(hào)燈集沖突。
系統(tǒng)里的最大信號(hào)燈數(shù)目是由SEMMNS設(shè)置的,
因此這個(gè)值應(yīng)該至少和max_connections加autovacuum_max_workers設(shè)置一樣大,
并且每16個(gè)連接還要另外加一個(gè)(參閱Table 17-1里面的公式)。參數(shù)SEMMNI
決定系統(tǒng)里一次可以存在的信號(hào)燈集的數(shù)目。因此這個(gè)參數(shù)至少應(yīng)該
為ceil((max_connections+autovacuum_max_workers)/16)。
降低允許的連接數(shù)目是一個(gè)臨時(shí)的繞開失敗的方法,這個(gè)啟動(dòng)失敗通常被
來自函數(shù)semget
的錯(cuò)誤響應(yīng)"Nospaceleftondevice"搞得很讓人迷惑。
有時(shí)候還可能有必要增大SEMMAP,使之至少按照SEMMNS配置。 這個(gè)參數(shù)定義信號(hào)燈資源映射的尺寸,可用的每個(gè)連續(xù)的信號(hào)燈塊在這個(gè)映射中存放一條記錄。 每當(dāng)一套信號(hào)燈被釋放,那么它要么會(huì)加入到該映射中一條相連的已釋放塊的入口中, 要么注冊(cè)成一條新的入口。如果映射填滿了碎片,那么被釋放的信號(hào)燈就丟失了(除非重啟)。 因此信號(hào)燈空間的碎片時(shí)間長了會(huì)導(dǎo)致可用的信號(hào)燈比應(yīng)該有的信號(hào)燈少。
SEMMSL參數(shù)決定一套信號(hào)燈里可以有多少信號(hào)燈, 對(duì)于PostgreSQL而言應(yīng)該至少是17。
許多設(shè)置與"semaphoreundo"(信號(hào)燈恢復(fù))有關(guān), 比如SEMMNU和SEMUME,這些不影響PostgreSQL。
Atleastasofversion5.1,itshouldnotbenecessarytodo anyspecialconfigurationforsuchparametersas SHMMAX,asitappearsthisisconfiguredto allowallmemorytobeusedassharedmemory.Thatisthe sortofconfigurationcommonlyusedforotherdatabasessuch asDB/2.
Itmight,however,benecessarytomodifytheglobal ulimitinformationin /etc/security/limits,asthedefaulthard limitsforfilesizes(fsize)andnumbersof files(nofiles)mightbetoolow.
共享內(nèi)存. 缺省時(shí)只支持4MB的共享內(nèi)存。請(qǐng)記住共享內(nèi)存是不能分頁的; 它是鎖在RAM里面的。要增加系統(tǒng)支持的共享緩沖區(qū)數(shù)目, 向內(nèi)核配置文件里增加下面的行:
options"SHMALL=8192" options"SHMMAX=\(SHMALL*PAGE_SIZE\)"
SHMALL以4KB頁為單位計(jì)算,所以1024頁面代表4M共享內(nèi)存。 所以上面的東西把共享內(nèi)存區(qū)域增加到32MB。對(duì)于運(yùn)行4.3或者更新版本的, 你可能需要增大KERNEL_VIRTUAL_MB,超過缺省的248。 做完上面的修改之后,編譯內(nèi)核并重啟。
信號(hào)燈. 你可能還需要增加信號(hào)燈的數(shù)量;系統(tǒng)缺省的總數(shù)60只能允許大概 50個(gè)PostgreSQL連接。 在內(nèi)核配置文件里設(shè)置你需要的值,比如:
options"SEMMNI=40" options"SEMMNS=240"
缺省設(shè)置只適合于很小的安裝(比如,缺省SHMMAX是32MB)。 我們可以用sysctl或loader接口來修改。 下面的參數(shù)可以用sysctl設(shè)置:
$sysctl-wkern.ipc.shmall=32768 $sysctl-wkern.ipc.shmmax=134217728 $sysctl-wkern.ipc.semmap=256
要想讓這些設(shè)置重啟后有效,修改/etc/sysctl.conf文件。
如果用sysctl,那么剩下的信號(hào)燈設(shè)置是只讀的, 但是信號(hào)燈可以在啟動(dòng)的時(shí)候,在loader提示符下設(shè)置:
(loader)setkern.ipc.semmni=256 (loader)setkern.ipc.semmns=512 (loader)setkern.ipc.semmnu=256
類似的,這些東西可以在/boot/loader.conf 中保存,以便重啟之后依然有效。
你可能還想配置內(nèi)核,把共享內(nèi)存裝載到RAM里,避免他們被交換到交換分區(qū)中。 這些可以通過使用sysctl設(shè)置 kern.ipc.shm_use_phys來實(shí)現(xiàn)。
如果通過啟用sysctl的security.jail.sysvipc_allowed 運(yùn)行在FreeBSDjail中,那么必須將postmaster 以不同操作系統(tǒng)的用戶身份運(yùn)行在不同的jail中。這樣有助于增強(qiáng)安全性, 因?yàn)樗乐沽朔莚oot用戶干擾不同jail中的共享內(nèi)存或信號(hào)燈, 并且允許PostgreSQLIPC清理代碼功能。在FreeBSD6.0及之后的版本中, IPC清理代碼并不能正確偵測(cè)在其它jail中的進(jìn)程,因此無法防止其它 jail中的postmaster進(jìn)程占用相同的端口。
FreeBSD4.0之前的版本類似NetBSD 和OpenBSD(見下文)。
編譯內(nèi)核時(shí)需要把選項(xiàng)SYSVSHM和SYSVSEM打開(缺省是打開的)。 共享內(nèi)存的最大尺寸是由選項(xiàng)SHMMAXPGS(以頁計(jì))決定的。 下面顯示了一個(gè)如何在NetBSD上設(shè)置這些參數(shù)的例子 (OpenBSD使用的是option):
optionsSYSVSHM optionsSHMMAXPGS=4096 optionsSHMSEG=256 optionsSYSVSEM optionsSEMMNI=256 optionsSEMMNS=512 optionsSEMMNU=256 optionsSEMMAP=256
你可能希望將共享內(nèi)存鎖在RAM中以避免它們被交換出去, 我們可以用sysctl設(shè)置 kern.ipc.shm_use_phys來實(shí)現(xiàn)這個(gè)目的。
缺省設(shè)置看來對(duì)普通安裝是足夠的了。對(duì)于HP-UX10, SEMMNS的出廠缺省是128,可能對(duì)大的數(shù)據(jù)庫站點(diǎn)來說太小了。
IPC可以在System AdministrationManager(SAM)下面的Kernel Configuration->ConfigurableParameters配置。 配置完了以后選擇CreateANewKernel選項(xiàng)。
缺省最大段是32MB,對(duì)于僅夠很小PostgreSQL安裝。 1頁總是4096字節(jié)除了在非通常內(nèi)核配置使用了"hugepages"( 使用getconfPAGE_SIZE檢驗(yàn))。缺省限制8GB,這個(gè)經(jīng)常是足夠的,不是總是這樣。 )
通過sysctl接口修改設(shè)置的共享內(nèi)存大小。比如,允許到16GB:
$sysctl-wkernel.shmmax=17179869184 $sysctl-wkernel.shmall=4194304
你可以把這些設(shè)置放到/etc/sysctl.conf里,在重啟后保持有效
老版本里可能沒有sysctl程序, 但是同樣的改變可以通過操作/proc文件系統(tǒng)來做:
$echo17179869184>/proc/sys/kernel/shmmax $echo4194304>/proc/sys/kernel/shmall
其余的默認(rèn)值是相當(dāng)夠用的大小,通常不需要更改。
在OSX10.3及以后的版本里,可以創(chuàng)建一個(gè)名為/etc/sysctl.conf的文件, 包含如下變量及相應(yīng)的值:
kern.sysv.shmmax=4194304 kern.sysv.shmmin=1 kern.sysv.shmmni=32 kern.sysv.shmseg=8 kern.sysv.shmall=1024
注意,在版本的OSX里所有五個(gè)共享內(nèi)存參數(shù)必須都在 /etc/sysctl.conf中設(shè)置,否則將會(huì)被忽略。
還要注意最近版本的OSX將拒絕把SHMMAX 的數(shù)值設(shè)置為非4096的倍數(shù)。
在這個(gè)平臺(tái)上,SHMALL是用4KB頁來度量的。
在較舊的OSX版本,你修改的共享內(nèi)存參數(shù),將需要重啟生效。像10.5在運(yùn)行中除了SHMMNI外都能修改, 使用sysctl。但仍然最好通過/etc/sysctl.conf設(shè)置你首選值,所以在重啟后將保留這些值。
/etc/sysctl.conf這個(gè)文件只在OSX10.3.9及之后的版本遵循使用。如果你運(yùn)行在10.3.x之前版本時(shí),你必須編輯 /etc/rc文件并且通過下面的命令修改這些值:
sysctl-wkern.sysv.shmmax sysctl-wkern.sysv.shmmin sysctl-wkern.sysv.shmmni sysctl-wkern.sysv.shmseg sysctl-wkern.sysv.shmall
請(qǐng)注意OSX系統(tǒng)更新會(huì)寫覆蓋/etc/rc文件,所以,你應(yīng)想到每個(gè)更新后重做這些編輯。
在OSX10.2和較早版本,在/System/Library/StartupItems/SystemTuning/SystemTuning文件里編輯這些命令替換。
缺省配置時(shí),只允許每段512KB共享內(nèi)存。要增大設(shè)置, 首先進(jìn)入/etc/conf/cf.d目錄。 要顯示當(dāng)前以字節(jié)記的SHMMAX,運(yùn)行
./configure-ySHMMAX
設(shè)置SHMMAX的新值:
./configureSHMMAX=value
這里value是你想設(shè)置的以字節(jié)記的新值。 設(shè)置完SHMMAX以后重新編譯內(nèi)核
./link_unix
andreboot.
至少到版本2.6為止,共享內(nèi)存段的缺省最大設(shè)置對(duì)PostgreSQL 來說是太低了。相關(guān)的設(shè)置可以在/etc/system里面修改,例如:
setshmsys:shminfo_shmmax=0x2000000 setshmsys:shminfo_shmmin=1 setshmsys:shminfo_shmmni=256 setshmsys:shminfo_shmseg=256 setsemsys:seminfo_semmap=256 setsemsys:seminfo_semmni=512 setsemsys:seminfo_semmns=512 setsemsys:seminfo_semmsl=32
你要重啟系統(tǒng)令修改生效。
又見http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-ins idesolaris.html 獲取關(guān)于Solaris里面的共享內(nèi)存的信息。
在UnixWare7上,缺省配置里的最大共享內(nèi)存段是512kB。 要顯示SHMMAX的當(dāng)前值,運(yùn)行:
/etc/conf/bin/ idtune-gSHMMAX
就會(huì)顯示當(dāng)前缺省的最小和最大值。 要給SHMMAX設(shè)置一個(gè)新值,運(yùn)行:
/etc/conf/bin/ idtuneSHMMAXvalue
value是你想設(shè)置的新值(單位:字節(jié))。 設(shè)置完SHMMAX后,重建內(nèi)核
/etc/conf/bin/ idbuild-B
然后重啟。
Table 17-2. PostgreSQL共享內(nèi)存的使用
使用 | 近似共享內(nèi)存所需要的字節(jié)數(shù)(8.3) |
---|---|
連接數(shù) | (1800+270*max_locks_per_transaction)*max_connections |
自動(dòng)清理工作者數(shù) | (1800+270*max_locks_per_transaction)*autovacuum_max_workers |
準(zhǔn)備事務(wù) | (770+270*max_locks_per_transaction)*max_prepared_transactions |
共享磁盤緩沖區(qū)大小 | (block_size+208)*shared_buffers |
WAL緩沖區(qū)大小 | (wal_block_size+8)*wal_buffers |
必需的固定空間大小 | 770kB |
Unix類系統(tǒng)強(qiáng)制了許多資源限制,這些限制可能干擾PostgreSQL
服務(wù)器的運(yùn)行。這里尤其重要是對(duì)每個(gè)用戶的進(jìn)程數(shù)目的限制、每個(gè)進(jìn)程打開文件數(shù)目、
以及每個(gè)進(jìn)程可用的內(nèi)存。這些限制中每個(gè)都有一個(gè)"硬"限制和
一個(gè)"軟"限制。實(shí)際使用的是軟限制,但用戶可以自己修改成
最大為硬限制的數(shù)目。而硬限制是只能由root用戶修改的限制。
系統(tǒng)調(diào)用setrlimit
負(fù)責(zé)設(shè)置這些參數(shù)。
shell的內(nèi)建命令ulimit(Bourneshells)或
limit(csh)就是用于在命令行上控制資源限制的。
在BSD衍生的系統(tǒng)上,/etc/login.conf
文件控制在登錄時(shí)對(duì)各種資源設(shè)置什么樣的限制數(shù)值。
參閱操作系統(tǒng)文檔獲取細(xì)節(jié)。相關(guān)的參數(shù)是maxproc,
openfiles,datasize。比如:
default:\ ... :datasize-cur=256M:\ :maxproc-cur=256:\ :openfiles-cur=256:\ ...
(-cur是軟限制,后面附加-max就可以設(shè)置硬限制。)
內(nèi)核通常也有一些系統(tǒng)范圍的資源限制。
在Linux上,/proc/sys/fs/file-max 決定內(nèi)核可以支持的最大文件數(shù)。你可以通過往該文件寫入一個(gè)不同的數(shù)值修改此值, 或者在/etc/sysctl.conf里增加一個(gè)賦值。 每個(gè)進(jìn)程的最大打開文件限制是在編譯內(nèi)核的時(shí)候固定的; 參閱/usr/src/linux/Documentation/proc.txt獲取更多信息。
PostgreSQL服務(wù)器每個(gè)連接都使用一個(gè)進(jìn)程, 所以你應(yīng)該至少允許和連接數(shù)相同的進(jìn)程數(shù),再加上系統(tǒng)其它部分所需要的數(shù)目。 通常這個(gè)并不是什么問題,但如果你在一臺(tái)機(jī)器上運(yùn)行多個(gè)服務(wù)器,資源使用可能就會(huì)緊張。
打開文件數(shù)目的出廠缺省設(shè)置通常設(shè)置為"社會(huì)友好"數(shù)值, 就是說允許許多用戶共存一臺(tái)機(jī)器,而不會(huì)導(dǎo)致系統(tǒng)資源使用的不當(dāng)比例。 如果你在一臺(tái)機(jī)器上運(yùn)行許多服務(wù)器,這也許就是你想要的,但是在特殊的服務(wù)器上, 你可能需要提高這個(gè)限制。
問題的另外一邊,一些系統(tǒng)允許獨(dú)立的進(jìn)程打開非常多的文件; 如果不止幾個(gè)進(jìn)程這么干,那系統(tǒng)范圍的上限就很容易達(dá)到。如果你發(fā)現(xiàn)這樣的現(xiàn)像, 并且不想修改系統(tǒng)范圍的限制,你就可以設(shè)置PostgreSQL的 max_files_per_process配置參數(shù)來限制打開文件數(shù)的消耗。
在Linux2.4以及之后的版本里,缺省的虛擬內(nèi)存的行為不是對(duì) PostgreSQL最優(yōu)的。原因在于內(nèi)核實(shí)現(xiàn)內(nèi)存 過量的方法,如果其它進(jìn)程的內(nèi)存請(qǐng)求導(dǎo)致系統(tǒng)用光虛擬內(nèi)存,那么內(nèi)核可能會(huì)終止 PostgreSQL服務(wù)器進(jìn)程。
如果發(fā)生了這樣的事情,你會(huì)看到像下面這樣的內(nèi)核信息 (參考你的系統(tǒng)文檔和配置,看看在哪里能看到這樣的信息):
OutofMemory:Killedprocess12345(postgres).
這表明postgres因?yàn)閮?nèi)存壓力而終止了。 盡管現(xiàn)有的數(shù)據(jù)連接將繼續(xù)正常運(yùn)轉(zhuǎn),但是新的連接將無法接受。 要想恢復(fù),你應(yīng)該重啟PostgreSQL。
一個(gè)避免這個(gè)問題的方法是在一臺(tái)你確信不會(huì)因?yàn)槠渌M(jìn)程而耗 盡內(nèi)存的機(jī)器上運(yùn)行PostgreSQL。 如果內(nèi)存資源緊張,增加交換空間的操作系統(tǒng)可以幫助避免這個(gè)問題,因?yàn)?內(nèi)存不足(OOM)的殺手是只有當(dāng)物理內(nèi)存和調(diào)用交換空間用盡。
在Linux2.6及以后的版本里,一個(gè)更好的解決方法是修改內(nèi)存的行為, 這樣它就不會(huì)再"過量"內(nèi)存。 雖然此設(shè)置不會(huì)阻止OOMkiller被調(diào)用 干脆,它會(huì)降低的機(jī)會(huì)顯著,因此將導(dǎo)致更強(qiáng)大的系統(tǒng)行為。 這是通過用sysctl選取一個(gè)嚴(yán)格的過提交模式實(shí)現(xiàn)的:
sysctl-wvm.overcommit_memory=2
或者在/etc/sysctl.conf里放一個(gè)等效的條目。 你可能還希望修改相關(guān)的vm.overcommit_ratio設(shè)置。 詳細(xì)信息請(qǐng)參閱內(nèi)核文檔的Documentation/vm/overcommit-accounting文件。
另一種方法,可以使用或不改變vm.overcommit_memory, 要將postmaster進(jìn)程的特定進(jìn)程的oom_adj值設(shè)置為-17,從而保證不會(huì)成為OOM殺手的目標(biāo)。 最簡單的方法這樣來執(zhí)行
echo-17>/proc/self/oom_adj
在postmaster的啟動(dòng)腳本之前調(diào)用postmaster。 請(qǐng)注意必須以root身份,完成此操作,或它將沒有任何影響;所以一個(gè)擁有root權(quán)限的啟動(dòng)腳本最容易做這事。 如果這樣做,你可能還要將-DLINUX_OOM_ADJ=0添加到CFLAGS編譯PostgreSQL。 這樣將導(dǎo)致postmaster子進(jìn)程以通常oom_adj值為0的運(yùn)行,所以O(shè)OM殺手在需要的時(shí)候以它們作為目標(biāo)。
Note: 有些供應(yīng)商的Linux2.4內(nèi)核有著早期2.6使用過量的sysctl。 不過,在沒有相關(guān)代碼的內(nèi)核里設(shè)置vm.overcommit_memory為2.4只會(huì)讓事情更糟, 而不是更好。我們建議你檢查一下實(shí)際的內(nèi)核源代碼(參閱文件mm/mmap.c 里面的
vm_enough_memory
函數(shù)),核實(shí)一下這個(gè)是在你的版本里存在的, 然后再在2.4內(nèi)核里使用這個(gè)特性。文檔文件overcommit-accounting 的存在不能當(dāng)作是這個(gè)特性存在的證明。如果有問題,請(qǐng)?jiān)儐柲愕膬?nèi)核供應(yīng)商的專家。