PostgreSQL體系架構(gòu)

PG的幾個主要進(jìn)程,以及PG的核心架構(gòu)。進(jìn)程和體系結(jié)構(gòu)詳見下圖:


從上面的體系結(jié)構(gòu)圖可以看出來,PG使用經(jīng)典的C/S架構(gòu),進(jìn)程架構(gòu)。在服務(wù)器端有主進(jìn)程、服務(wù)進(jìn)程、子進(jìn)程、共享內(nèi)存以及文件存儲幾大部分,下面著重講述服務(wù)器端的進(jìn)程部分:

1. Postmaster主進(jìn)程和服務(wù)進(jìn)程

當(dāng)PG數(shù)據(jù)庫啟動時,首先會啟動Postmaster主進(jìn)程。這個進(jìn)程是PG數(shù)據(jù)庫的總控制進(jìn)程,負(fù)責(zé)啟動和關(guān)閉數(shù)據(jù)庫實例。實際上Postmaster進(jìn)程是一個指向postgres命令的鏈接,如下:

[postgres@drz ~]$ ll /opt/postgresql/bin/postmaster

lrwxrwxrwx. 1 postgres dba 8 Aug? 7 23:33 /opt/postgresql/bin/postmaster -> postgres

當(dāng)用戶和PG數(shù)據(jù)庫建立連接時,要先與Postmaster進(jìn)程建立連接,此時客戶端進(jìn)程會發(fā)送身份驗證消息給Postmaster主進(jìn)程,Postmaster主進(jìn)程根據(jù)消息進(jìn)行身份驗證,驗證通過后,Postmaster主進(jìn)程會fork出一個會話服務(wù)進(jìn)程為這個用戶連接服務(wù)。可以通過pg_stat_activity表來查看服務(wù)進(jìn)程的pid,如下:

test=# select pid,usename,client_addr,client_port from pg_stat_activity;

? pid? | usename? | client_addr | client_port

-------+----------+-------------+-------------

26402 | postgres |? ? ? ? ? ? |? ? ? ? ? -1

(1 row)


2. BgWriter(后臺寫)進(jìn)程

BgWriter進(jìn)程是把共享內(nèi)存中的臟頁寫到磁盤上的進(jìn)程。它的作用有兩個:一是定期把臟數(shù)據(jù)從內(nèi)存緩沖區(qū)刷出到磁盤中,減少查詢時的阻塞;二是PG在定期作檢查點時需要把所有臟頁寫出到磁盤,通過BgWriter預(yù)先寫出一些臟頁,可以減少設(shè)置檢查點(CheckPoint,數(shù)據(jù)庫恢復(fù)技術(shù)的一種)時要進(jìn)行的IO操作,使系統(tǒng)的IO負(fù)載趨向平穩(wěn)。BgWriter是PostgreSQL 8.0以后新加的特性,它的機制可以通過postgresql.conf文件中以"bgwriter_"開頭配置參數(shù)來控制:

# - Background Writer -

#bgwriter_delay = 200ms? ? ? ? ? ? ? ? # 10-10000ms between rounds? ? ? ? ? ? ? ? ? ? ?

#bgwriter_lru_maxpages = 100? ? ? ? ? ? # 0-1000 max buffers written/round

#bgwriter_lru_multiplier = 2.0? ? ? ? ? # 0-10.0 multiplier on buffers scanned/round

#bgwriter_flush_after = 512kB? ? ? ? ? # measured in pages, 0 disables

bgwriter_delay:

backgroud writer進(jìn)程連續(xù)兩次flush數(shù)據(jù)之間的時間的間隔。默認(rèn)值是200,單位是毫秒。

bgwriter_lru_maxpages:

backgroud writer進(jìn)程每次寫的最多數(shù)據(jù)量,默認(rèn)值是100,單位buffers。如果臟數(shù)據(jù)量小于該數(shù)值時,寫操作全部由backgroud writer進(jìn)程完成;反之,大于該值時,大于的部分將有server process進(jìn)程完成。設(shè)置該值為0時表示禁用backgroud writer寫進(jìn)程,完全有server process來完成;配置為-1時表示所有臟數(shù)據(jù)都由backgroud writer來完成。(這里不包括checkpoint操作)

bgwriter_lru_multiplier:

這個參數(shù)表示每次往磁盤寫數(shù)據(jù)塊的數(shù)量,當(dāng)然該值必須小于bgwriter_lru_maxpages。設(shè)置太小時需要寫入的臟數(shù)據(jù)量大于每次寫入的數(shù)據(jù)量,這樣剩余需要寫入磁盤的工作需要server process進(jìn)程來完成,將會降低性能;值配置太大說明寫入的臟數(shù)據(jù)量多于當(dāng)時所需buffer的數(shù)量,方便了后面再次申請buffer工作,同時可能出現(xiàn)IO的浪費。該參數(shù)的默認(rèn)值是2.0。

bgwriter的最大數(shù)據(jù)量計算方式:

1000/bgwriter_delay*bgwriter_lru_maxpages*8K=最大數(shù)據(jù)量

bgwriter_flush_after:

數(shù)據(jù)頁大小達(dá)到bgwriter_flush_after時觸發(fā)BgWriter,默認(rèn)是512KB。


3. PgArch(歸檔)進(jìn)程

類似于Oracle數(shù)據(jù)庫的ARCH歸檔進(jìn)程,不同的是ARCH是吧redo log進(jìn)行歸檔,PgArch是把WAL日志進(jìn)行歸檔。再深入點,WAL日志會被循環(huán)使用,也就是說,過去的WAL日志會被新產(chǎn)生的日志覆蓋,PgArch進(jìn)程就是為了在覆蓋前把WAL日志備份出來。歸檔日志的作用是為了數(shù)據(jù)庫能夠使用全量備份和備份后產(chǎn)生的歸檔日志,從而讓數(shù)據(jù)庫回到過去的任一時間點。PG從8.X版本開始提供的PITR(Point-In-Time-Recovery)技術(shù),就是運用的歸檔日志。

PgArch進(jìn)程通過postgresql.conf文件中的如下參數(shù)進(jìn)行配置:


# - Archiving -

#archive_mode = off? ? ? ? ? ? # enables archiving; off, on, or always

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (change requires restart)

#archive_command = ''? ? ? ? ? # command to use to archive a logfile segment

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # placeholders: %p = path of file to archive

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #? ? ? ? ? ? ? %f = file name only

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'

#archive_timeout = 0? ? ? ? ? ? # force a logfile segment switch after this

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # number of seconds; 0 disables

archive_mode:

表示是否進(jìn)行歸檔操作,可選擇為off(關(guān)閉)、on(啟動)和always(總是開啟),默認(rèn)值為off(關(guān)閉)。

archive_command:

由管理員設(shè)置的用于歸檔WAL日志的命令。在用于歸檔的命令中,預(yù)定義變量“%p”用來指代需要歸檔的WAL全路徑文件名,“%f”表示不帶路徑的文件名(這里的路徑都是相對于當(dāng)前工作目錄的路徑)。每個WAL段文件歸檔時將調(diào)用archive_command所指定的命令。當(dāng)歸檔命令返回0時,PostgreSQL就會認(rèn)為文件被成功歸檔,然后就會刪除或循環(huán)使用該WAL段文件。否則,如果返回一個非零值,PostgreSQL會認(rèn)為文件沒有被成功歸檔,便會周期性地重試直到成功。

archive_timeout:

表示歸檔周期,在超過該參數(shù)設(shè)定的時間時強制切換WAL段,默認(rèn)值為0(表示禁用該功能)。


4. PgStat(統(tǒng)計數(shù)據(jù)收集)進(jìn)程

PgStat進(jìn)程是PostgreSQL數(shù)據(jù)庫的統(tǒng)計信息收集器,用來收集數(shù)據(jù)庫運行期間的統(tǒng)計信息,如表的增刪改次數(shù),數(shù)據(jù)塊的個數(shù),索引的變化等等。收集統(tǒng)計信息主要是為了讓優(yōu)化器做出正確的判斷,選擇最佳的執(zhí)行計劃。postgresql.conf文件中與PgStat進(jìn)程相關(guān)的參數(shù),如下:

#------------------------------------------------------------------------------

# RUNTIME STATISTICS

#------------------------------------------------------------------------------

# - Query/Index Statistics Collector -

#track_activities = on

#track_counts = on

#track_io_timing = off

#track_functions = none? ? ? ? ? ? ? ? # none, pl, all

#track_activity_query_size = 1024? ? ? # (change requires restart)

#stats_temp_directory = 'pg_stat_tmp'

track_activities:表示是否對會話中當(dāng)前執(zhí)行的命令開啟統(tǒng)計信息收集功能,該參數(shù)只對超級用戶和會話所有者可見,默認(rèn)值為on(開啟)。

track_counts:表示是否對數(shù)據(jù)庫活動開啟統(tǒng)計信息收集功能,由于在AutoVacuum自動清理進(jìn)程中選擇清理的數(shù)據(jù)庫時,需要數(shù)據(jù)庫的統(tǒng)計信息,因此該參數(shù)默認(rèn)值為on。

track_io_timing:定時調(diào)用數(shù)據(jù)塊I/O,默認(rèn)是off,因為設(shè)置為開啟狀態(tài)會反復(fù)的調(diào)用數(shù)據(jù)庫時間,這給數(shù)據(jù)庫增加了很多開銷。只有超級用戶可以設(shè)置

track_functions:表示是否開啟函數(shù)的調(diào)用次數(shù)和調(diào)用耗時統(tǒng)計。

track_activity_query_size:設(shè)置用于跟蹤每一個活動會話的當(dāng)前執(zhí)行命令的字節(jié)數(shù),默認(rèn)值為1024,只能在數(shù)據(jù)庫啟動后設(shè)置。

stats_temp_directory:統(tǒng)計信息的臨時存儲路徑。路徑可以是相對路徑或者絕對路徑,參數(shù)默認(rèn)為pg_stat_tmp,設(shè)置此參數(shù)可以減少數(shù)據(jù)庫的物理I/O,提高性能。此參數(shù)只能在postgresql.conf文件或者服務(wù)器命令行中修改。


5. AutoVacuum(自動清理)進(jìn)程

在PG數(shù)據(jù)庫中,對數(shù)據(jù)進(jìn)行UPDATE或者DELETE操作后,數(shù)據(jù)庫不會立即刪除舊版本的數(shù)據(jù),而是標(biāo)記為刪除狀態(tài)。這是因為PG數(shù)據(jù)庫具有多版本的機制,如果這些舊版本的數(shù)據(jù)正在被另外的事務(wù)打開,那么暫時保留他們是很有必要的。當(dāng)事務(wù)提交后,舊版本的數(shù)據(jù)已經(jīng)沒有價值了,數(shù)據(jù)庫需要清理垃圾數(shù)據(jù)騰出空間,而清理工作就是AutoVacuum進(jìn)程進(jìn)行的。postgresql.conf文件中與AutoVacuum進(jìn)程相關(guān)的參數(shù)有:


#------------------------------------------------------------------------------

# AUTOVACUUM PARAMETERS

#------------------------------------------------------------------------------

#autovacuum = on? ? ? ? ? ? ? ? ? ? ? ? # Enable autovacuum subprocess?? 'on'

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # requires track_counts to also be on.

#log_autovacuum_min_duration = -1? ? ? # -1 disables, 0 logs all actions and

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # their durations, > 0 logs only

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # actions running at least this number

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # of milliseconds.

#autovacuum_max_workers = 3? ? ? ? ? ? # max number of autovacuum subprocesses

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (change requires restart)

#autovacuum_naptime = 1min? ? ? ? ? ? ? # time between autovacuum runs

#autovacuum_vacuum_threshold = 50? ? ? # min number of row updates before

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # vacuum

#autovacuum_analyze_threshold = 50? ? ? # min number of row updates before

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # analyze

#autovacuum_vacuum_scale_factor = 0.2? # fraction of table size before vacuum

#autovacuum_analyze_scale_factor = 0.1? # fraction of table size before analyze

#autovacuum_freeze_max_age = 200000000? # maximum XID age before forced vacuum

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (change requires restart)

#autovacuum_multixact_freeze_max_age = 400000000? ? ? ? # maximum multixact age

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # before forced vacuum

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (change requires restart)

#autovacuum_vacuum_cost_delay = 20ms? ? # default vacuum cost delay for

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # autovacuum, in milliseconds;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # -1 means use vacuum_cost_delay

#autovacuum_vacuum_cost_limit = -1? ? ? # default vacuum cost limit for

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # autovacuum, -1 means use

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # vacuum_cost_limit


autovacuum:是否啟動系統(tǒng)自動清理功能,默認(rèn)值為on。

log_autovacuum_min_duration:這個參數(shù)用來記錄 autovacuum 的執(zhí)行時間,當(dāng) autovaccum 的執(zhí)行時間超過 log_autovacuum_min_duration參數(shù)設(shè)置時,則autovacuum信息記錄到日志里,默認(rèn)為 "-1", 表示不記錄。?

autovacuum_max_workers:設(shè)置系統(tǒng)自動清理工作進(jìn)程的最大數(shù)量。

autovacuum_naptime:設(shè)置兩次系統(tǒng)自動清理操作之間的間隔時間。

autovacuum_vacuum_threshold和autovacuum_analyze_threshold:設(shè)置當(dāng)表上被更新的元組數(shù)的閾值超過這些閾值時分別需要執(zhí)行vacuum和analyze。

autovacuum_vacuum_scale_factor和autovacuum_analyze_scale_factor:設(shè)置表大小的縮放系數(shù)。

autovacuum_freeze_max_age:設(shè)置需要強制對數(shù)據(jù)庫進(jìn)行清理的XID上限值。

autovacuum_vacuum_cost_delay:當(dāng)autovacuum進(jìn)程即將執(zhí)行時,對 vacuum 執(zhí)行 cost 進(jìn)行評估,如果超過 autovacuum_vacuum_cost_limit設(shè)置值時,則延遲,這個延遲的時間即為 autovacuum_vacuum_cost_delay。如果值為 -1, 表示使用?vacuum_cost_delay 值,默認(rèn)值為 20 ms。

autovacuum_vacuum_cost_limit:這個值為 autovacuum 進(jìn)程的評估閥值, 默認(rèn)為 -1, 表示使用 "vacuum_cost_limit " 值,如果在執(zhí)行?autovacuum 進(jìn)程期間評估的cost 超過 autovacuum_vacuum_cost_limit, 則 autovacuum 進(jìn)程則會休眠。


6. WalWriter(預(yù)寫式日志寫)進(jìn)程

預(yù)寫式日志W(wǎng)AL(Write Ahead Log,也稱為Xlog)的中心思想是對數(shù)據(jù)文件的修改必須是只能發(fā)生在這些修改已經(jīng)記錄到日志之后,也就是先寫日志后寫數(shù)據(jù)(日志先行)。使用這種機制可以避免數(shù)據(jù)頻繁的寫入磁盤,可以減少磁盤I/O。數(shù)據(jù)庫在宕機重啟后可以運用這些WAL日志來恢復(fù)數(shù)據(jù)庫。postgresql.conf文件中與WalWriter進(jìn)程相關(guān)的參數(shù)如下:


#------------------------------------------------------------------------------

# WRITE AHEAD LOG

#------------------------------------------------------------------------------

# - Settings -

#wal_level = minimal? ? ? ? ? ? ? ? ? ? # minimal, replica, or logical

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (change requires restart)

#fsync = on? ? ? ? ? ? ? ? ? ? ? ? ? ? # flush data to disk for crash safety

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (turning this off can cause

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # unrecoverable data corruption)

#synchronous_commit = on? ? ? ? ? ? ? ? # synchronization level;

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # off, local, remote_write, remote_apply, or on

#wal_sync_method = fsync? ? ? ? ? ? ? ? # the default is the first option

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # supported by the operating system:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #? open_datasync

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #? fdatasync (default on Linux)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #? fsync

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #? fsync_writethrough

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #? open_sync

#full_page_writes = on? ? ? ? ? ? ? ? ? # recover from partial page writes

#wal_compression = off? ? ? ? ? ? ? ? ? # enable compression of full-page writes

#wal_log_hints = off? ? ? ? ? ? ? ? ? ? # also do full page writes of non-critical updates

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (change requires restart)

#wal_buffers = -1? ? ? ? ? ? ? ? ? ? ? # min 32kB, -1 sets based on shared_buffers

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # (change requires restart)

#wal_writer_delay = 200ms? ? ? ? ? ? ? # 1-10000 milliseconds

#wal_writer_flush_after = 1MB? ? ? ? ? # measured in pages, 0 disables

#commit_delay = 0? ? ? ? ? ? ? ? ? ? ? # range 0-100000, in microseconds

#commit_siblings = 5? ? ? ? ? ? ? ? ? ? # range 1-1000


wal_level:控制wal存儲的級別。wal_level決定有多少信息被寫入到WAL中。 默認(rèn)值是最小的(minimal),其中只寫入從崩潰或立即關(guān)機中恢復(fù)的所需信息。replica?增加 wal 歸檔信息 同時包括 只讀服務(wù)器需要的信息。(9.6 中新增,將之前版本的?archive?和?hot_standby?合并)?

logical?主要用于logical decoding 場景

fsync:該參數(shù)直接控制日志是否先寫入磁盤。默認(rèn)值是ON(先寫入),表示更新數(shù)據(jù)寫入磁盤時系統(tǒng)必須等待WAL的寫入完成。可以配置該參數(shù)為OFF,表示更新數(shù)據(jù)寫入磁盤完全不用等待WAL的寫入完成。

synchronous_commit:參數(shù)配置是否等待WAL完成后才返回給用戶事務(wù)的狀態(tài)信息。默認(rèn)值是ON,表明必須等待WAL完成后才返回事務(wù)狀態(tài)信息;配置成OFF能夠更快地反饋回事務(wù)狀態(tài)。

wal_sync_method:WAL寫入磁盤的控制方式,默認(rèn)值是fsync,可選用值包括open_datasync、fdatasync、fsync_writethrough、fsync、open_sync。open_datasync和open_sync分別表示在打開WAL文件時使用O_DSYNC和O_SYNC標(biāo)志;fdatasync和fsync分別表示在每次提交時調(diào)用fdatasync和fsync函數(shù)進(jìn)行數(shù)據(jù)寫入,兩個函數(shù)都是把操作系統(tǒng)的磁盤緩存寫回磁盤,但前者只寫入文件的數(shù)據(jù)部分,而后者還會同步更新文件的屬性;fsync_writethrough表示在每次提交并寫回磁盤會保證操作系統(tǒng)磁盤緩存和內(nèi)存中的內(nèi)容一致。

full_page_writes:表明是否將整個page寫入WAL。

wal_buffers:用于存放WAL數(shù)據(jù)的內(nèi)存空間大小,系統(tǒng)默認(rèn)值是64K,該參數(shù)還受wal_writer_delay、commit_delay兩個參數(shù)的影響。?

wal_writer_delay:WalWriter進(jìn)程的寫間隔時間,默認(rèn)值是200毫秒,如果時間過長可能造成WAL緩沖區(qū)的內(nèi)存不足;時間過短將會引起WAL的不斷寫入,增加磁盤I/O負(fù)擔(dān)。?

wal_writer_flush_after:

commit_delay:表示一個已經(jīng)提交的數(shù)據(jù)在WAL緩沖區(qū)中存放的時間,默認(rèn)值是0毫秒,表示不用延遲;設(shè)置為非0值時事務(wù)執(zhí)行commit后不會立即寫入WAL中,而仍存放在WAL緩沖區(qū)中,等待WalWriter進(jìn)程周期性地寫入磁盤。

commit_siblings:表示當(dāng)一個事務(wù)發(fā)出提交請求時,如果數(shù)據(jù)庫中正在執(zhí)行的事務(wù)數(shù)量大于commit_siblings值,則該事務(wù)將等待一段時間(commit_delay的值);否則該事務(wù)則直接寫入WAL。系統(tǒng)默認(rèn)值是5,該參數(shù)還決定了commit_delay的有效性。

?wal_writer_flush_after:當(dāng)臟數(shù)據(jù)超過閾值時,會被刷出到磁盤。


7. CheckPoint(檢查點)進(jìn)程

檢查點是系統(tǒng)設(shè)置的事務(wù)序列點,設(shè)置檢查點保證檢查點前的日志信息刷到磁盤中。postgresql.conf文件中與之相關(guān)的參數(shù)有:

# - Checkpoints -

#checkpoint_timeout = 5min? ? ? ? ? ? ? # range 30s-1d

#max_wal_size = 1GB

#min_wal_size = 80MB

#checkpoint_completion_target = 0.5? ? # checkpoint target duration, 0.0 - 1.0

#checkpoint_flush_after = 256kB? ? ? ? # measured in pages, 0 disables

#checkpoint_warning = 30s? ? ? ? ? ? ? # 0 disables

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容