PostgreSQL 日常數據庫維護工作


日常數據庫維護工作
定期備份,定期”清理“數據庫,周期性的日志文件管理
check_postgres可用於檢測數據庫的健康並報告異常情況

1. 日常清理

PostgreSQL數據庫要求周期性的清理維護。對於很多安裝,讓自動清理守護進程來執行清理已經足夠

1.1. 清理的基礎知識

PostgreSQL的VACUUM命令出於幾個原因必須定期處理每一個表:
1. 恢復或重用被已更新或已刪除行所占用的磁盤空間。
2. 更新被PostgreSQL查詢規划器使用的數據統計信息。
3. 更新可見性映射,它可以加速只用索引的掃描。
4. 保護老舊數據不會由於事務ID回卷或多事務ID回卷而丟失。
有 兩 種VACUUM的變體:標准VACUUM和VACUUM FULL。
VACUUM FULL可以收回更多磁盤空間但是運行起來更慢。VACUUM FULL要求在其工作的表上得到一個排他鎖,因此無法和對此表的其他使用並行。
標准形式的VACUUM可以和生產數據庫操作並行運行(SELECT、INSERT、UPDATE和DELETE等命令將繼續正常工作,但在清理期間你無法使
用ALTER TABLE等命令來更新表的定義)。
VACUUM會產生大量I/O流量,這將導致其他活動會話性能變差。
-bash-4.2$ vacuumdb --help
vacuumdb cleans and analyzes a PostgreSQL database.

Usage:
vacuumdb [OPTION]... [DBNAME]

Options:
-a, --all vacuum all databases
-d, --dbname=DBNAME database to vacuum
-e, --echo show the commands being sent to the server
-f, --full do full vacuuming
-F, --freeze freeze row transaction information
-j, --jobs=NUM use this many concurrent connections to vacuum
-q, --quiet don't write any messages
-t, --table='TABLE[(COLUMNS)]' vacuum specific table(s) only
-v, --verbose write a lot of output
-V, --version output version information, then exit
-z, --analyze update optimizer statistics
-Z, --analyze-only only update optimizer statistics; no vacuum
--analyze-in-stages only update optimizer statistics, in multiple
stages for faster results; no vacuum
-?, --help show this help, then exit

Connection options:
-h, --host=HOSTNAME database server host or socket directory
-p, --port=PORT database server port
-U, --username=USERNAME user name to connect as
-w, --no-password never prompt for password
-W, --password force password prompt
--maintenance-db=DBNAME alternate maintenance database

Read the description of the SQL command VACUUM for details.

Report bugs to <pgsql-bugs@postgresql.org>.
-bash-4.2$ vacuumdb -d hq -f -z -v >> /tmp/vacuumdb.log
INFO: vacuuming "pg_catalog.pg_statistic"
INFO: "pg_statistic": found 127 removable, 402 nonremovable row versions in 26 pages

1.2. 恢復磁盤空間

在PostgreSQL中,一次行的UPDATE或DELETE不會立即移除該行的舊版本。這種方法對於從多版本並發控制(MVCC)獲益是必需的:
當舊版本仍可能對其他事務可見時,它不能被刪除。但是最后,任何事務都不會再對一個過時的或者被刪除的行版本感興
趣。它所占用的空間必須被回收來用於新行,這樣可避免磁盤空間需求的無限制增長。這通過運行VACUUM完成。
VACUUM的標准形式移除表和索引中的死亡行版本並將該空間標記為可在未來重用。不過,它將不會把該空間交還給操作系統,除非在
特殊的情況中表尾部的一個或多個頁面變成完全空閑並且能夠很容易地得到一個排他表鎖。
相反,VACUUM FULL通過把死亡空間之外的內容寫成一個完整的新版本表文件來主動緊縮表。這將最小化表的尺寸,但是要花較長的時間。
它也需要額外的磁盤空間用於表的新副本,直到操作完成。
例行清理的一般目標是多做標准的VACUUM來避免需要VACUUM FULL。
  提示: 當一個表因為大量更新或刪除活動而包含大量死亡行版本時,純粹的VACUUM可能不能令人滿意。
如果你有這樣一個表並且你需要回收它占用的過量磁盤空間,你將需要使用VACUUMFULL,或者CLUSTER,或者ALTER TABLE的表重寫變體之一。
  提示: 如果你有一個表,它的整個內容會被周期性刪除,考慮用TRUNCATE而不是先用DELETE再用VACUUM。

1.3. 更新規划器統計信息

PostgreSQL查詢規划器依賴於有關表內容的統計信息來為查詢產生好的計划。
這些統計信息由ANALYZE命令收集,它除了直接被調用之外還可以作為VACUUM的一個可選步驟被調用。
擁有適度准確的統計信息很重要,否則差的計划可能降低數據庫性能。
自動清理守護進程如果被啟用,當一個表的內容被改變得足夠多時,它將自動發出ANALYZE命令。
  提示: 自動清理守護進程不會為外部表發出ANALYZE命令,因為無法確定一個合適的頻度。

1.4. 更新可見性映射

清理機制為每一個表維護着一個可見性映射,它被用來跟蹤哪些頁面只包含對所有活動事務可見的元組。
這樣做有兩個目的。
第一,清理本身可以在下一次運行時跳過這樣的頁面,因為其中沒有什么需要被清除。
第二,這允許PostgreSQL回答一些只用索引的查詢,而不需要引用底層表。

1.5. 防止事務ID 回卷失敗

PostgreSQL的 MVCC 事務語義依賴於能夠比較事務 ID(XID)數字
如果一個行版本的插入 XID 大於當前事務的 XID,它就是“屬於未來的”並且不應該對當前事務可見。
必要至少每 20 億個事務就清理每個數據庫中的每個表。
周期性的清理能夠解決該問題的原因是,VACUUM會把行標記為 凍結,這表示它們是被一個在足夠遠的過去提交的事務所插入,
這樣從 MVCC 的角度來看,效果就是該插入事務對所有當前和未來事務來說當然都 是可見的。
PostgreSQL保留了一個特殊的 XID(FrozenTransactionId),這個 XID 並不遵循普通 XID 的比較規則 並且總是被認為比任
何普通 XID 要老。普通 XID 使用模-232算 法來比較。
VACUUM通常會跳過不含有任何死亡行版本的頁面,但是不會跳過那些含有帶舊XID值的行版本的頁面。
要保證所有舊的行版本都已經被凍結,需要對整個表做一次掃描。vacuum_freeze_table_age控制VACUUM什么時候這樣做:如果該表經
過vacuum_freeze_table_age減去vacuum_freeze_min_age個事務還沒有被完全掃描過,則會強制一次全表清掃。將這個參數設置為 0
將強制VACUUM總是掃描所有頁面而實際上忽略可見性映射。
一個數據庫的pg_database行的datfrozenxid列是出現在該數據庫中的未凍結 XID 的下界 — 它只是數據庫中每一個表的relfrozenxid值的最小值。

SELECT c.oid::regclass as table_name,
greatest(age(c.relfrozenxid),age(t.relfrozenxid)) as age
FROM pg_class c
LEFT JOIN pg_class t ON c.reltoastrelid = t.oid
WHERE c.relkind IN ('r', 'm');
SELECT datname, age(datfrozenxid) FROM pg_database;

age列度量從該截斷 XID 到當前事務 XID 的事務數。
VACUUM通常只掃描從上次清理后備修改過的頁面,但是只有當全表被掃描時relfrozenxid才能被推進。
當relfrozenxid比vacuum_freeze_table_age個事務還老時、當VACUUM的FREEZE選項被使用時或當所有頁面正好要求清理來移除死亡行版本時,全表將被掃描。
如果出於某種原因自動清理無法從一個表中清除舊的 XID,當數據庫的最舊 XID 和回卷點之間達到 1 千萬個事務時,系統將開始發出這樣的警告消息:
WARNING: database "mydb" must be vacuumed within 177009986 transactions
HINT: To avoid a database shutdown, execute a database-wide VACUUM in "mydb".
如果這些警告被忽略,一旦距離回滾點只剩下 1 百萬個事務時,該系統將會關閉並且拒絕開始任何新的事務:
ERROR: database is not accepting commands to avoid wraparound data loss in database mydb
HINT: Stop the postmaster and vacuum that database in single-user mode.
由於一旦系統進入到安全關閉模式,它將不會執行命令。做這個操作的唯一方法是停止服務器並且以單一用戶啟動服務器來執行VACUUM。
1.5.1. 多事務和回卷
Multixact ID被用來支持被多個事務鎖定的行。
只要有多於一個事務並發地鎖住一個行, 鎖信息將使用一個“多個事務ID”(或簡稱多事務 ID)來編碼。
作為一種安全設備,對任何多事務年齡超過 autovacuum_multixact_freeze_max_age的表, 都將發生一次全表清理掃描。
如果已用的成員存儲空間超過總量的 50%,全表清理掃描 也將逐步在所有表上進行,這會從那些具有最老多事務年齡的表開始。

1.6. 自動清理后台進程

PostgreSQL有一個可選的但是被高度推薦的特性autovacuum,它的目的是自動執行VACUUM和ANALYZE 命令。
當它被啟用時,自動清理會檢查被大量插入、更新或刪除元組的表。這些檢查會利用統計信息收集功能,
因此除非track_counts被設置為true,自動清理不能被使用。在默認配置下,自動清理是被啟用的並且相關配置參數已被正確配置。
#autovacuum = on # Enable autovacuum subprocess? 'on'
# requires track_counts to also be on.
#track_counts = on
“自動清理后台進程”實際上由多個進程組成。有一個稱為 自動清理啟動器的常駐后台進程, 它負責為所有數據庫啟動自動清理工作者進程。

2. 日常重建索引

在某些情況下值得周期性地使用REINDEX命令或一系列獨立重構步驟來重建索引。
已經完全變成空的B樹索引頁面被收回重用。但是,還是有一種低效的空間利用的可能性:如果一個頁面上除少量索引鍵之外的全部鍵被刪除,該頁面仍然被分配。
因此,在這種每個范圍中大部分但不是全部鍵最終被刪除的使用模式中,可以看到空間的使用是很差的。對於
這樣的使用模式,推薦使用定期重索引。
對於非B樹索引可能的膨脹還沒有很好地定量分析。在使用非B樹索引時定期監控索引的物理尺寸是個好主意。
對於B樹索引,一個新建立的索引比更新了多次的索引訪問起來要略快, 因為在新建立的索引上,邏輯上相鄰的頁面通常物理上也相鄰
。僅僅為了提高訪問速度也值得定期重索引。
REINDEX在所有情況下都可以安全和容易地使用。但是由於該命令要求一個排他表鎖,因此更好的方法是用一個由創建和替換步驟組成的序列來執行索引重建。
支持帶CONCURRENTLY選項的CREATE INDEX的索引類型可以用這種方式重建。

3. 日志文件維護

把數據庫服務器的日志輸出保存在一個地方是個好主意, 而不是僅僅通過/dev/null丟棄它們。 在進行問題診斷的時候,日志輸出是非常寶貴的。
如果你簡單地把postgres的stderr定向到一個文件中,你會得到日志輸出, 但是截斷該日志文件的唯一方法是停止並重起服務器。這
一個更好的辦法是把服務器的stderr輸出發送到某種日志輪轉程序里。

postgresql.conf里logging_collector為true


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM