
PostgreSQL是最像Oracle的開源資料庫,我們可以拿Oracle來比較學習它的體系結構,比較容易理解,PostgreSQL的主要結構如下:

一、存盤結構
PG資料存盤結構分為:邏輯存盤結構和物理存盤存盤,其中:邏輯存盤結構是內部的組織和管理資料的方式;物理存盤結構是作業系統中組織和管理資料的方式,
1、邏輯存盤結構

所有資料庫物件都有各自的oid(object identifiers),oid是一個無符號的四位元組整數,相關物件的oid都存放在相關的system catalog表中,比如資料庫的oid和表的oid分別存放在pg_database,pg_class表中,
在邏輯存盤結構中有幾個術語需要解釋:
- 資料庫集群-Database cluster
也叫資料庫集簇,它是指有單個PostgreSQL服務器實體管理的資料庫集合,組成資料庫集群的這些資料庫使用相同的全域組態檔和監聽埠、共用行程和記憶體結構,一個DataBase Cluster可以包括:多個DataBase、多個User、以及Database中的所有物件,如上圖所示,
- **資料庫-Database **
在PostgreSQL中,資料庫本身也是資料庫物件,并且在邏輯上彼此分離,除資料庫之外的其他資料庫物件(例如:表、索引等等)都屬于他們各自的資料庫,
- 表空間-tablespace
資料庫在邏輯上分成多個存盤單元,稱作表空間,表空間用作把邏輯上相關的結構放在一起,資料庫邏輯上是由一個或多個表空間組成,初始化的時候,會自動創建pg_default和pg_global兩個表空間,
\db
其中:
pg_global:用于存放系統表,
pg_default:該表空間的物理檔案存盤在資料目錄中的base目錄中,

創建自己的表空間,并在該表空間上創建表
create tablespace mydemotbs location '/home/postgres/training/pgsql/data/mydemotbs';
create table testtable1(tid int primary key,tname text) tablespace mydemotbs;

- 模式-Schema
當創建一個資料庫時,會為其創建一個名為public的默認Schema,Schema是資料庫中的命名空間,在資料庫中創建的所有物件都是在Schema中創建,一個用戶可以從同一個客戶端連接中訪問不同的Schema,而不同的Schema中可以有多個同名的Table、Index、View、Sequence、Function等等資料庫物件,可以通過下面的方式來查看當前資料庫的Schema
\dn

- 段-segment
一個段是分配給一個邏輯結構(一個表、一個索引或其他物件)的一組區,是資料庫物件使用的空間的集合;段可以有表段、索引段、回滾段、臨時段和高速快取段等,
- 區-extent
區是資料庫存盤空間分配的一個邏輯單位,它由連續資料塊所組成,第一個段是由一個或多個盤區組成,當一段中間所有空間已完全使用,PostgreSQL為該段分配一個新的范圍,
- 塊-block(Page)
資料塊是PostgreSQL 管理資料檔案中存盤空間的單位,為資料庫使用的I/O的最小單位,是最小的邏輯部件,默認值8K,
- 資料庫物件-Database object
如:表、視圖、索引、序列、函式等等,在PostgreSQL中的所有資料庫物件都由各自的物件識別符號(OID)進行內部的管理,例如,資料庫的OID存盤在pg_database系統表中,可以通過下面的陳述句進行查詢,
select oid,datname from pg_database;

而資料庫中的表、索引、序列等資料庫物件的OID則存在了pg_class系統表中,例如可以通過下面的陳述句查詢前面創建的testtable1表的OID,
select oid,relname,relkind,relfilenode from pg_class where relname ='testtable1';

2、物理存盤結構
在執行initdb的時候會初始化一個目錄,通常我們都會在系統配置相關的環境變數$PGDATA來表示,初始化完成后,會再這個目錄生成相關的子目錄以及一些檔案,在postgresql中,表空間的概念并不同于其他關系型資料庫,這里一個Tablespace對應的都是一個目錄,如下圖就是PG的物理結構:

每個目錄的功能與作用如下所示:

而PostgreSQL的物理存盤結構主要是指硬碟上存盤的檔案,包括:資料檔案、日志檔案、引數檔案、控制檔案、redo日志(WAL),下面分別進行介紹,
- 資料檔案(表檔案)
顧名思義,資料檔案用于存盤資料,檔案名以OID命名,對于超出1G的表資料檔案,PostgreSQL會自動將其拆分為多個檔案來存盤,而拆分的檔案名將由pg_class中的relfilenode欄位來決定,如下所示:
select oid,relname,relkind,relfilenode from pg_class where relname ='testtable1';

查看目錄表空間mydemotbs的目錄(其中:13578是資料庫OID,16385是表的OID)

在PostgreSQL中,將保存在磁盤中的塊(Block)稱為Page,資料的讀寫是以Page為最小單位,每個Page默認的大小是8K,在編譯PostgreSQL時指定BLCKSZ大小將決定Page的大小,每個表檔案由逗哥BLCKSZ位元組大小的Page組成,在分析型資料庫中,適當增加BLCKSZ大小可以小幅度提升資料庫的性能,
- 日志檔案
PostgreSQL日志檔案的型別,分為以下幾種:
① 運行日志(pg_log)
默認沒有開啟,開啟后會自動生成,查看postgresql.conf檔案的配置可以看到相關的引數設定,這個日志一般是記錄服務器與DB的狀態,比如各種Error資訊,定位慢查詢SQL,資料庫的啟動關閉資訊,發生checkpoint過于頻繁等的告警資訊,諸如此類,該日志有.csv格式和.log,建議使用.csv格式,因為它一般會按大小和時間自動切割,pg_log是可以被清理洗掉,壓縮打包或者轉移,同時并不影響DB的正常運行,當我們有遇到DB無法啟動或者更改引數沒有生效時,第一個想到的就是查看這個日志,

② 重做日志(pg_xlog)
pg_xlog 這個日志是記錄的Postgresql的WAL信息,默認存盤在目錄$PGDATA/pg_wal/,是一些事務日志資訊(transaction log),默認單個大小是16M,原始碼安裝的時候可以更改其大小(./configure --with-wal-segsize=target_value 引數,即可設定)這些日志會在定時回滾恢復(PITR), 流復制(Replication Stream)以及歸檔時能被用到,這些日志是非常重要的,記錄著資料庫發生的各種事務資訊,不得隨意洗掉或者移動這類日志檔案,不然你的資料庫會有無法恢復的風險,
③ 事務日志(pg_xact)
pg_xact是事務提交日志,記錄了事務的元資料,默認開啟,內容一般不能直接讀,默認存盤在目錄$PGDATA/pg_xact/,
④ 服務器日志
如果用pg_ctl啟動的時候沒有指定-l引數來指定服務器日志,錯誤可能會輸出到cmd前臺,服務器日志記錄了資料庫的重要資訊,

- 引數檔案
主要包括postgresql.conf、pg_hba.conf和pg_ident.conf這三個引數檔案,下面分別進行介紹:
① postgresql.conf
PostgreSQL的主要引數檔案,有很詳細的說明和注釋,和Oracle的pfile,MySQL的my.cnf類似,默認在$PGDATA下,很多引數修改后都需要重啟,9.6之后支持了alter system來修改,修改后的會存在$PGDATA/postgresql.auto.conf下,可以reload或者 restart來使之生效,
② pg_hba.conf
這個是黑白名單的設定,檔案里有詳細的引數說明,默認引數如下:

③ pg_ident.conf
pg_ident.conf是用戶映射組態檔,用來配置哪些作業系統用戶可以映射為資料庫用戶,結合pg_hba.conf中,method為ident可以用特定的作業系統用戶和指定的資料庫用戶登錄資料庫,
- 控制檔案
控制檔案記錄了資料庫運行的一些資訊,比如資料庫id,是否open,wal的位置,checkpoint的位置等等,controlfile是很重要的檔案,
控制檔案的位置:$PGDATA/global/pg_control,可以使用命令bin/pg_controldata查看控制檔案的內容,如下:

- redo日志(WAL)
默認保存在$PGDATA/pg_wal目錄下,如下所示:

檔案名稱為16進制的24個字符組成,每8個字符一組,每組的意義如下:
00000001 00000000 00000001
時間線 邏輯ID 物理ID
通過下面的陳述句進行WAL的手動切換:
select pg_switch_wal();
再次查看pg_wal目錄,如下所示:


二、行程結構
執行下面的命令列出所有的PostgreSQL的行程,
ps -ef | grep postgres

① Postmaster行程
主行程Postmaster是整個資料庫實體的總控制行程,負責啟動和關閉資料庫實體,用戶可以運行postmaster,postgres命令加上合適的引數啟動資料庫,實際上,postmaster命令是一個指向postgres的鏈接,如下圖所示,

更多時候我們使用pg_ctl啟動資料庫,pg_ctl也是通過運行postgres來啟動資料庫,它只是做了一些包裝,讓我們更容易啟動資料庫,所以,主行程Postmaster實際是第一個postgres行程,此行程會fork一些與資料庫實體相關的輔助子行程,并管理他們,
當用戶與PostgreSQL資料庫建立連接時,實際上是先與Postmaster行程建立連接,此時,客戶端程式會發出身份證驗證的訊息給Postmaster行程,Postmaster主行程根據訊息中的資訊進行客戶端身份驗證,如果驗證通過,它會fork一個子行程postgres為這個連接服務,fork出來的行程被稱為服務行程,查詢pg_stat_activity表可以看到的pid,就是這些服務行程的pid,
select pid from pg_stat_activity;

② SysLogger行程
在postgresql.conf里啟用 運行日志(pg_log)后,會有SysLogger行程,SysLogger會在日志檔案達到指定的大小時關閉當前日志檔案,產生新的日志檔案,相關配置引數如下:

③ BgWriter后臺寫行程
BgWriter是PostgreSQL中在后臺將臟頁寫出到磁盤的輔助行程,引入該行程主要為達到如下兩個目的:
首先,資料庫在進行查詢處理時若發現要讀取的資料不在緩沖區中時要先從磁盤中讀入要讀取的資料所在的頁面,此時如果緩沖區已滿,則需要先選擇部分緩沖區中的頁面替換出去,如果被替換的頁面沒有被修改過,那么可以直接丟棄;但如果要被替換的頁已被修改,則必需先將這頁寫出到磁盤中后才能替換,這樣資料庫的查詢處理就會被阻塞,通過使用BgWriter定期寫出緩沖區中的部分臟頁到磁盤中,為緩沖區騰出空間,就可以降低查詢處理被阻塞的可能性,
其次,PostgreSQL在定期作檢查點時需要把所有臟頁寫出到磁盤,通過BgWriter預先寫出一些臟頁,可以減少設定檢查點時要進行的IO操作,使系統的IO負載趨向平穩,通過BgWriter對共享緩沖區寫操作的統一管理,避免了其他服務行程在需要讀入新的頁面到共享緩沖區時,不得不將之前修改過的頁面寫出到磁盤的操作,
④ WalWriter預寫日志寫行程
該行程用于保存WAL預寫日志,預寫式日志WAL(Write Ahead Log,也稱為Xlog)的中心思想是對資料檔案的修改必須是只能發生在這些修改已經記錄到日志之后,也就是先寫日志后寫資料,如果遵循這個程序,那么就不需要在每次事務提交的時候都把資料塊刷回到磁盤,這一點與Oracle資料庫是完全一致的,postgresql.conf檔案中與WalWriter行程相關的引數如下:
#------------------------------------------------------------------------------
# WRITE AHEAD LOG
#------------------------------------------------------------------------------
#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
⑤ PgArch歸檔行程
從PostgreSQL 8.x開始,有了PITR(Point-In-Time-Recovery)技術,該技術支持將資料庫恢復到其運行歷史中任意一個有記錄的時間點;PITR的另一個重要的基礎就是對WAL檔案的歸檔功能,PgArch輔助行程的目標就是對WAL日志在磁盤上的存盤形式進行歸檔備份,但在默認情況下,PostgreSQL是非歸檔模式,因此看不到PgArch行程,PgArch行程通過postgresql.conf檔案中的如下引數進行配置:
# - 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
⑥ AutoVacuum自動清理行程
在PG資料庫中,對資料進行UPDATE或者DELETE操作后,資料庫不會立即洗掉舊版本的資料,而是標記為洗掉狀態,這是因為PG資料庫具有多版本的機制,如果這些舊版本的資料正在被另外的事務打開,那么暫時保留他們是很有必要的,當事務提交后,舊版本的資料已經沒有價值了,資料庫需要清理垃圾資料騰出空間,而清理作業就是AutoVacuum行程進行的,postgresql.conf檔案中與AutoVacuum行程相關的引數有:
#------------------------------------------------------------------------------
# AUTOVACUUM
#------------------------------------------------------------------------------
#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_vacuum_insert_threshold = 1000 # min number of row inserts
# before vacuum; -1 disables insert
# vacuums
#autovacuum_analyze_threshold = 50 # min number of row updates before
# analyze
#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum
#autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table
# size before insert 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 = 2ms # 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
⑦ PgStat統計資訊收集行程
PgStat行程是PostgreSQL資料庫的統計資訊收集器,用來收集資料庫運行期間的統計資訊,如表的增刪改次數,資料塊的個數,索引的變化等等,收集統計資訊主要是為了讓優化器做出正確的判斷,選擇最佳的執行計劃,postgresql.conf檔案中與PgStat行程相關的引數,如下:
#------------------------------------------
# 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'
⑧ CheckPoint檢查點行程
檢查點是系統設定的事務序列點,設定檢查點保證檢查點前的日志資訊刷到磁盤中,postgresql.conf檔案中與之相關的引數有:
# - 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
三、記憶體結構
PostgreSQL的記憶體結構,分為:本地記憶體和共享記憶體,它們的關系如下圖所示:

① 本地記憶體:每個后端行程(backend process)自己使用的

② 共享記憶體:所有行程共同使用


轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/298286.html
標籤:PostgreSQL
