1.高可用
服務可用時間量,冗余是高可用的基礎
2.備用數據庫
備用數據庫的想法是保留始終具有相同數據的生產數據庫的副本,並且可以在故障發生時使用備份數據庫。有以下幾種方式對備用數據庫進行分類。
根據復制的性質:
物理備份數據庫:復制磁盤塊
邏輯備份數據:復制數據流更改
備份的同步性:
異步:存在數據丟失的可能性
同步:不存在數據丟失的可能性,主設備的提交等待備用設備的響應。
3.件目錄結構
postgresql的磁盤布局:
data/base
存放各數據庫實例對應文件夾,命名方式是數據庫的OID,select oid,datname from pg_database;可以查詢每個數據庫的OID,對應的可以在base目錄下找到這個數據庫的文件夾。
數據表使用表名對應的relfilenode作為文件名存放在數據庫文件夾下,select relfilenode,relname from pg_class;
可以查詢表的relfilenode,然后在相應的數據庫文件夾下可以看到這個表的文件,該文件用於存儲表的數據,最大1G,超出自動擴展,擴展名為relfilenode.1,relfilenode.2 ...
為了提高I/O性能,pg總是以8K大小的塊執行IO。因此數據文件總是以8K的步長增長。(物理復制時,雙方需要使用相同的塊大小)
global -全局數據
包括全局系統表
pg_clog -提交日志
提交日志是一個工作數據庫實例的一個重要組成部分。它存儲系統上進行的事物的狀態。
一個事物有四種狀態(TRANSACTION_STATUS_IN_PROGRESS,TRANSACTION_STATUS_COMMITTED,TRANSACTION_STATUS_ABORTED,TRANSACTION_STATUS_SUB_COMMITTED),
如果一個事物的提交日志的狀態是不可用,postgresql將不知道是否應該被看到。
pg_hba.conf -基於主機的網絡配置
常用認證方式
trust
ident
md5
pg_ident.conf -身份認證
pg_notify-監聽、通知數據
系統存儲關於監聽、通知的信息(異步后端接口)
pg_serial-關於提交序列化事物的信息
序列化事物的信息存儲在這里。我們必須在磁盤上存儲序列化事物提交信息,以確保長時間運行的事物不會膨脹內存,內部采用一個簡單的SLRU結構來跟蹤這些事物
pg_snapshot-輸出快照
pg_stat_tmp-臨時統計數據
該信息被大多數pg_stat_*系統視圖所需要
pg_subtrans -子事物數據
pg_xlog postgresql的事物日志(WAL)
WAL(Write Ahead Log)和XLOG是一個事物的兩個名字。默認事物日志文件大小16M。
xlog不可能無限增大,需要刪除無用的xlog,原則:如果xlog文件中的所有更改也被放到數據文件中,xlog才可以被截斷(刪除)。需要檢查點的配置
postgresql.conf -pg配置文件
4.配置參數
shared_buffers
數據庫服務使用的共享內存緩沖區。默認值128MB。(一般使用Mem的25%,不超過40%,因為pg還要依賴於os cache)
background writer
pg的一個獨立子進程,用於將shared_buffers中的dirty buffer寫入磁盤。(數據的修改不用立即寫入磁盤,因為寫入了wal日志,可以用於故障恢復)
background writer會根據LRU鏈表,掃描shared buffers,如果發現臟頁,就會調用系統write,寫入磁盤。具體調用策略見下面參數
bgwriter_delay
指定background writer將dirty buffer寫入磁盤的頻率,默認200ms,即200ms寫一次,寫入周期200ms。
bgwriter_lru_maxpages
指定一次寫入周期 寫入的dirty buffer的最大數量(單位buffers),默認值100
bgwriter_lru_multiplier
一次寫入周期要寫到磁盤的dirt buffers的數量T,是基於上一個周期內server進程需要的新的buffers數量N。
bgwriter_lru_multiplier是一個乘法因子p,T = N * p;較大的值為峰值提供了緩沖,較小的值則需要服務器進程完成寫入。
例:
上一個寫入周期內服務器使用了100個new buffer(100次寫產生不同的臟數據),bgwriter_lru_multiplier使用了默認值2.那么這次會將100*2個dirty buffers寫到磁盤中,也就是騰出了200個干凈的buffers,
如果再下一次寫入周期前,服務器申請的buffers數量小於這個值,則自然夠用,如果大於200,那么需要服務器自己去觸發將dirty buffers寫入磁盤。
備注
上面的寫入磁盤行為指的是普通意義的向磁盤文件寫,但是會被操作系統緩存,所以實際行為可能沒有寫到磁盤中。
bgwriter_flush_after
當超過bgwriter_flush_after bytes的數據被bgwriter寫時,強制OS將緩存數據寫入物理磁盤。默認值為512KB
write ahead log(WAL)
wal_level
指定寫入到wal中的信息,默認是minimal,只寫從crash中恢復或者快速shutdown需要的信息。
replica 是在minimal的基礎上添加wal archiving需要的信息。
logical 增加邏輯編碼需要的信息。minimal wal不包含從base backup和wal log重新構造數據庫數據的信息。replica或者logical可以。老版本的參數archive或者hot_standby 在這里被映射到replica模式
fsync
指明數據更新時是否調用fsync將數據從os cache中刷新到磁盤。
synchronous_commit
指定在向事物提交指令返回success之前是否需要等待wal records寫到物理磁盤。可選值on,remote_apply,remote_write,local,off。
如果synchronous_standby_names非空(集群),這個參數控制事物提交是否需要等待wal records被復制到standby servers。
如果設置成on,事物提交 需要等到current synchronous standby應答已經收到事物記錄切刷新到磁盤。
如果設置成remote_apply,事物提交 需要等到current synchronous standby應答已經收到事物記錄且應用到內存中。
當設置成remote_write,事物提交需要等到current synchronous standby應答已經收到事物記錄且寫到了os cache中。
local表示事物提交只需要等到本機wal records flush to disk。
如果synchronous_standby_names為空,on,remote_apply,remote_write,local提供同樣的同步級別:事物提交需要等到wal record flush to disk(由fsync來控制)
wal_sync_method
強制wal 從os cache更新信息到磁盤的方法,如果fsync是關閉的,這個參數無效。
下面open開頭的是基於linux open功能函數,f開頭的是基於linux sync功能函數
Short answer seems to be that the physical write is guaranteed: open = immediately; fsync = at commit
open_datasync
fdatasync(linux默認選項)
和fsync類似,但是只在必要的時候才將metadata寫到磁盤。如:文件access time,modified time改變不需要flushing,file size改變需要寫到磁盤(因為時間相關的元數據出錯不影響文件讀寫,size出錯會導致新增數據讀不到)
fsync
將緩存的內核數據刷新到物理磁盤,同時刷新文件的metadata(文件屬性:大小,修改更新時間等)數據到磁盤。一般文件元數據和文件不在一起,所以這里需要寫兩次磁盤(兩次尋址)
fsync_writethrough
open_sync
full_page_writers
當設置為on的時候,pg server會在checkpoint之后頁的第一次修改之時將整個頁寫到wal records中(wal replay從最后一個checkpoint之后開始)。
這是因為當向數據庫寫入一個頁時,可能發生os奔潰,導致數據庫中的這個頁同時存在新舊數據,存儲在wal log中的行修改記錄不足以進行奔潰恢復。關閉這個參數不影響PITR。默認on
wal_log_hints
當這個參數為on時,PostgreSQL服務器一個檢查點之后頁面被第一次修改期間把該磁盤頁面的整個內容都寫入WAL,即使對所謂的提示位做非關鍵修改也會這樣做。默認關閉
wal_compression
設置為on時,server會壓縮一個整頁鏡像到wal log中(當開啟full_page_writes或者在base backup期間)。壓縮的頁鏡像會在wal 回放時解壓。默認off。開啟會減小內存消耗,但是增加cpu消耗
wal_buffers
wal data(寫入磁盤之前存在內存中的數據量)使用的共享內存大小。默認是shared_buffers/32.不大於wal segment(一般16M)。
wal_writer_delay
指定flush wal的頻率。每執行完一次flush就會sleep wal_writer_delay ms,除非被異步提交事物喚醒。如果距離上次flush時間不到wal_write_delay並且新產生的wal data小於wal_writer_flush_after bytes,則寫wal信息只會寫到os,不會刷新到磁盤。
即 將wal刷新到磁盤的條件:執行周期大於等於wal_write_delay,或者小於wal_write_delay但是新產生的wal data大小大於wal_writer_flush_after。
wal_writer_delay默認值是200ms。
wal_writer_flush_after
指定觸發wal writer flush的 wal data的大小。默認值為1MB。
commit_delay
flush wal data之前的等待的時間間隔,單位us。通過一次flush多個事物日志來提高吞吐量(如果在給定的時間間隔內同時有其它事物提交)。
當准備提交事物的時候如果並發活躍事物數量大於commit_siblings才會應用commit_delay機制(避免無效等待,如:延遲之后只提交了自己的事物)。如果關閉了fsync,也不會采用delay機制。默認值為0(no delay)
commit_siblings
應用commit_delay的前提:統一時間並發活躍連接的數量。
5.checkpoints
At checkpoint time,all dirty data pages are flushed to disk and a special checkpoint record is written to the log file
checkpoint_timeout
執行檢查點時間周期。默認值是5min。即5分鍾執行一次checkpoints
checkpoint_comletion_target
指定checkpoint任務實際完成時間:checkpoint_timeout * checkpoint_comletion_target。 默認值0.5(即需要2.5min完成一次檢查點操作)
主要用來控制checkpoint操作進行磁盤IO的速率,checkpoint進程會根據這個值來調整磁盤IO的速率(避免IO負載過高)。
checkpoint_flush_after
當執行檢查點的時候,如果超過checkpoint_flush_after bytes的數據被寫入了,那么強制os刷新數據到物理磁盤。這樣限制了內存頁的臟數據數量,減少了刷新數據到磁盤時的停頓時間。默認值256KB
checkpoint_warning
當填充檢查點段文件的總時間超過這個時間時,向server log中寫入日志記錄。
max_wal_size
wal log的最大數量,這是一個軟限制,如wal_keep_segments設置的較大。默認值是1GB。增大這個值可能導致crash recovery時間延長
min_wal_size
只要磁盤使用量低於這個值,老的wal 文件會被循環使用而不是刪除。可以理解為wal日志的保留磁盤大小,在這個大小之內的文件不會被刪除,后續可以直接復寫,那么其磁盤空間也是一直被自己占着。
6.Vacuum
autovacuum
默認為on,表示后台是否開啟vacuum daemon線程。vacuum用於回收數據庫的無用數據
log_autovacuum_min_duration
vacuum執行時間超過設置值,則會打印日志記錄
autovacuum_max_workers
vacuum線程的最大數量,默認值為 3
autovacuum_naptime
vacuum執行間隔,默認1min
autovacuum_vacuum_threshold
Specifies the minimum number of updated or deleted tuples needed to trigger a VACUUM in any one table. The default is 50 tuples.(指定表級別 觸發vacuum的修改操作的閾值)
autovacuum_analyze_threshold
Specifies the minimum number of inserted, updated or deleted tuples needed to trigger an ANALYZE in any one table. The default is 50 tuples.(指定表級別觸發analyze的最小改動條數)
autovacuum_vacuum_scale_factor
Specifies a fraction of the table size to add to autovacuum_vacuum_threshold when deciding whether to trigger a VACUUM. The default is 0.2 (20% of table size). (觸發vacuum的乘數因子)
autovacuum_analyze_scale_factor
Specifies a fraction of the table size to add to autovacuum_analyze_threshold when deciding whether to trigger an ANALYZE. The default is 0.1 (10% of table size).(觸發vacuum analyze的乘數因子)
觸發vacuum的條件: update/delete 行數 > autovacuum_vacuum_threshold + 表的行數 * autovacuum_vacuum_scale_factor (對應默認值為 50+count(*) * 20%)
觸發vacuum analyze的條件:同上(對應默認值為 50+count(*) * 10%)
vacuum執行器分為 LAZY vacuum和FULL vacuum
lazy vacuum
手動執行不帶參數的vacuum或者數據庫autovacuum都是使用這個,會找到dead的tuple,標記為空間可用(不進行空間合並),清理index,更新統計信息。可以和增刪改查並行運行,但是不能修改表結構
full vacuum
手動執行vacuum full。 除了lazy vacuum的功能外還進行空間合並(將數據移到連續磁盤空間,類似聚餐索引執行功能)。所以需要鎖表。
別人此時不能操作這個表。full vacuum或者alter table,或者手動cluster都需要和這個表一樣大的額外磁盤空間,用於拷貝數據。
analyze
用於收集表的信息,方便查詢優化器(query planner)進行優化sql查詢,
執行方式: analyze 或者 vacuum analyze 或者 使用工具vacuumdb -z
7.Archiving(用於集群)
archive_mode
歸檔事物日志到另外的一個磁盤或者文件中。
當使能了archive_mode,完整的wal segments會被發送到archive storage(自己通過archive_command指定的一個磁盤空間/文件)。值;off,on,always。
一般情況下on和always一致。當設置了always,在archive recovery和standby mode兩種情況下依然可以執行歸檔。在always模式下,所有的文件(從archive中恢復的或者流復制的流文件)會被再一次歸檔。
archive_command
實際執行歸檔操作的命令。如果archive_command為empty,server還是會積累wal segments以期望archive_command會被盡快提供。
archive_timeout
archive_command僅應用在完整的wal segments上。如果服務器只產生很少的wal數據,那么事物完成和它被安全的記錄到歸檔存儲之間有一個很長的延遲。archive_timeout指定切換到新的wal segment file的時間間隔(前提是有數據改動),
8.Replication(復制,用於集群)
下面的參數控制內建的流控制特性。數據庫服務實例會成為master或者slave server。master可以發送數據,slave接收master發來的復制數據。當使用級聯復制時,standby server可以發送接收數據。
8.1Sending Server
這些參數可以在任何發送復制集數據的server上設置。
max_wal_senders
指定最大數量的並發連接數(簡單理解為slave的數量)。由於time_wait的存在,可能需要設置的比實際使用值稍大。
max_replication_slots
指定replication slots的最大數量。只有wal_level設置成replica/logical時,replication slot才有效。
wal_keep_segments
指定pg_xlog目錄保存的wal log的最小數量。每個文件一般是16M。
wal_sender_timeout
指定復制流連接的超時時間,用於感知故障。默認是60S
track_commit_timestamp
記錄事物提交時間
Master server
下面這些參數在master server上設置,在slave server上無效(無影響)
synchronous_standby_names
指定同步流復制的standby server,配合synchronous_commit使用,提交事物時需要收到standby server的應答之后才能完成提交,如配置項 2(slave1,slave2,slave3,slave4) 表示提交事物需要得到兩個slave的應答,優先取配置中前面的slave的應答,即這里取slave1和slave2的應答。如果slave1或者slave2某個掛了,下一個接管應答。上面的slave1,slave2...指的是slave的名字,由參數項application_name設置。如果這個參數沒有配置,則不會使用同步配置
vacuum_defer_cleanup_age
指定vacuum延遲清理的事物的數量。默認值為0,表示在其它事物中不被看到的無用行的(mvcc產生,如update會復制一條新行數據,老的行被標記為清除)可以被盡快清除。對於單機版,這個參數設置為0正常使用,但是對於集群模式,master感知到dead row只是根據本身來判斷的,不能確定slave是否有用。所以這里做一個清理延遲,如設置成100,表示保留最近的100條事物產生的dead row。這個參數只能降低沖突的概率,如果需要更精確,可以使用hot_standby_feedback。
8.2Standby Servers
下面的設置控制standby server接收復制數據的行為。配置在master上無影響。
hot_standby
指定在recovery期間(standby一直處於這個狀態),是否允許連接查詢
max_standby_archive_delay
應用當前wal segments的總時間(應用時間+等待本地沖突的sql查詢的時間)。當要應用的wal信息和standby server上的sql查詢沖突時,需要等待一定時間之后把sql查詢cancel掉。默認值是30S,設置成-1表示一直等到sql查詢執行結束,這會導致wal archive信息不斷增大但是得不到應用。
max_standby_streaming_delay
參數意義同上,只是這個wal data來自流復制,上面的wal data是來自wal archive。
場景舉例:master發來的wal 信息是刪除一個表,slave正在該表執行sql查詢。
wal_receiver_status_interval
指定slave向master發送replication 信息最長時間間隔,默認10S,發送的主要信息:最后一條事物日志的位置(寫到os cache),最后一條flush到磁盤的事物日志,最后一條應用的事物日志。write事物日志或者flush位置改變都會觸發一次發送,或者最長等到這個最大時間間隔。
hot_standby_feedback
指定slave是否將當前執行的查詢反饋給master。這能盡可能的減少由於master的cleanup record導致的slave查詢取消。反饋信息發送次數為在wal_receiver_status_interval時間間隔內最多一次
wal_receiver_timeout
復制連接的超時時間。默認值60S。用於感知master故障。
wal_retrieve_retry_interval
指定slave在wal 數據源(streaming replication,local pg_xlog or wal archive)不可用時的重試等待時間。默認5S。
9.lsn(log sequence number)
wal日志為了replay的有序性需要加上編號。實現的時候,是按日志的產生的順序寫入磁盤的,即使是寫到磁盤緩沖區中,也是按產生的順序一次寫到日志緩沖區中,再將日志順序寫到磁盤。
因此采用日志在日志文件中的偏移來代替這個日志編號,可以通過日志編號迅速定位到日志。這個日志編號就叫做lsn。
故障恢復或者重啟后需要進行數據恢復,從pg_controldata中找出最后一個checkpoint檢查點位置,從這個位置之后定位到wal log文件的位置,然后讀取后面的wal log進行恢復。但是checkpoint之后的wal log對應操作是否在之前已經刷新到了磁盤,這個難以確定。所以在每個數據塊的塊頭記錄下最后一次修改這個數據塊操作的日志編號lsn,當redo log時,將數據塊加載到緩沖區中,若塊頭的lsn大於當前lsn,表示當前日志不需要重做(恢復),繼續redo下一條日志。通過這種方法避免了同一個操作被多次執行。
10.pg_clog
默認大小8K,每2bit 存儲一個事物的提交狀態,也就是一個文件可以存儲32K個事物。
pg_clog將32個事物分為一組,存儲這些事物的最大LSN。存儲在SlruSharedData結構中。
在將clog buffer write磁盤前,需要確保該clog page對應事物的xlog LSN已經flush到磁盤。
11.測試工具類
pg_test_fsync
測試不同的同步方法的寫入速率
pg_xlogdump
查看wal log日志信息,查看時間點
pg_xlogdump -fb 00000001000000000000000A
pg_controldata
pg_rewind
pg_rewind 工具主要實現了從源集群到目的集群的文件級別數據同步。但是和rsync的區別是,pg_rewind 不需要去讀那些未變化的文件塊,當數據量比較大而變化較小的時候,pg_rewind會更快。
需要將下面兩個參數打開: wal_log_hints=on, full_page_writes=on
12.pg事物隔離級別
臟讀
不可重復讀
幻影讀
事物隔離級別:read uncommitted,read committed,repeatable read,serializable
pg實現了后三種,第一種效果同read committed。
read committed
默認隔離級別。只能讀到自己sql查詢之前已經提交的事物(可以看到本事物內自己之前做的修改)。即前提條件:在當前查詢之前已提交(不要求在自己的事物開始之前提交)
repeatable read
只能 看到本事物開始前已經提交的事物(可以看到本事物內自己之前做的修改)。即前提條件:在當前事物之前已提交。
serializable
類似序列化讀寫,最嚴格的隔離級別
13.mvcc
select txid_current(); 查詢當前的事物id
select xmin,xmax,cmin,cmax,ctid,* from test; 查詢當前表的內部字段
begin transaction isolation level read committed; 在當前session中設置事物級別為讀已提交
begin transaction isolation level repeatable read; 在當前session中設置事物級別為重復讀
begin transaction isolation level serializable;
xmin,xmax
xmin在創建記錄時(insert tuple),記錄此值為插入tuble的事物id
xmax在更新或者刪除tuple時,記錄當前事物id。或者為0(無刪除更新操作)
舉例:
當前事物id為1000,插入一條記錄A之后,A的(xmin,xmax)為(1000,0),再起一個事物插入B 對應(1001,0)
窗口1新起一個事物,事物id為1002,更新B(不提交),在本事物中查看B(1002,0),新開一個shell后台(窗口2),查看B(1001,1002),表示B是由事物1001創建的,由事物1002修改,但是還沒有提交。
實際上,上面操作,窗口1(操作者)和窗口2(觀察者)看到的不是同一條記錄 ,pg的MVCC機制決定,更新操作會創建新的tuple.
在事物1002中刪除A(不提交),在本事物中查不到A的信息了,在其它窗口查看,A(1000,1002)
即xmax表示當前行待刪除,由於mvcc的作用,其它事物依然能看到老的數據,update對老數據的操作等同刪除。
cmin,cmax
同一個事物中的,該行記錄對應的sql的執行的順序,從0開始。
舉例:
在同一個事物中執行三次插入操作,產生三條記錄A,B,C 則他們分別對應的(cmin,cmax)為(0,0),(1,1),(2,2)
此時update B記錄,那么B對應的(cmin,cmax)變為(3,3)
pg判斷自身可見性原理(自身未提交事物):
xmax為0,則判斷xmin是否為當前事物id;
若xmax不為0,則判斷xmax是否為當前事物id(判斷是否被自身刪除)
14.集群配置
一個集群是一組主機共同工作並被視為一個主機,提供了水平伸縮性,可以抵御少數節點故障。
根據共享內容可以划分為兩種集群:
共享存儲:所有節點訪問相同的存儲設備
不共享:每個節點有自己的存儲空間
異步復制和同步復制:
異步復制:事物被提交到master上之后數據才可以復制,slave不會超前master,通常滯后一些
同步復制:事物同時再master和slave上提交
單master復制和多master復制
單master復制:寫操作只發送到一台服務器,該服務器同步數據到內部設置的slave上。slave只接收讀操作
多master復制:允許寫操作發送到所有集群內部的服務器。
邏輯復制和物理復制:
邏輯復制:復制的是實際操作的sql
物理復制:系統將復制數據到遠程服務器上,復制內容是數據的二進制格式。