跳至內容
出自 Arch Linux 中文维基

PostgreSQL是一個開源的,社區驅動的,符合標準的 對象-關係型 資料庫系統。


安裝

警告:在升級到新版本的 PostgreSQL 包前,請先查看 #升級 PostgreSQL 一節中的必要步驟。

安裝 postgresql。這同時會創建一個名為 postgres 的新系統用戶。

你現在可以通過提權工具來切換到 postgres 用戶下。

初始化配置

在 PostgreSQL 可以正常使用之前,資料庫集群必須被初始化:

[postgres]$ initdb -D /var/lib/postgres/data

其中 -D 提供了資料庫集群的默認數據存放位置(如果需要修改目錄位置,可以參考#修改默認數據目錄)。initdb 也支持多種其它的命令行參數:

這篇文章的某些內容需要擴充。

原因:PostgreSQL 還支持 ICU 區域設置。[1] (在 Talk:PostgreSQL 中討論)


  • 默認情況下,資料庫集群的區域設置和編碼 是從當前環境中派生的(使用 $LANG 值)。如果這不是你想要的,你可以使用 --locale=locale(其中 locale 是從系統的 可用區域設置 中選擇的)和 --encoding=encoding(必須與選擇的區域設置匹配)來覆蓋默認值。(一旦資料庫啟動,你可以使用 [postgres]$ psql -l 檢查使用了哪些值。)
    注意:使用除 C.UTF-8CPOSIXucs_basic 以外的區域設置可能會導致 排序規則版本不匹配,如果提供區域設置的庫(glibcicu)更新,則需要重新索引。
  • 如果數據目錄所在的文件系統沒有數據校驗和功能,你可能會想要啟用 PostgreSQL 自帶的 校驗和 功能來提高數據完整性保障 - 使用 --data-checksums 參數即可。相關細節可參考 #Enable data checksumming。(一旦資料庫啟動,你可以使用 [postgres]$ psql --tuples-only -c "SHOW data_checksums" 檢查是否啟用了該功能。)
注意:/var/lib/postgres/data/ 目錄設置了 CNo_COWfile attribute[2] 這會在 Btrfs禁用校驗和
  • 默認使用 trust 認證方法,這意味著主機上的任何人都可以以任何資料庫用戶身份連接。你可以使用 --auth-local=peer --auth-host=scram-sha-256 來使用更安全的認證方法。
  • -c/--set 選項可用於設置任何 postgresql.conf 參數,避免手動編輯 postgresql.conf 的需要。
  • 更多選項,請參閱 initdb --help官方文檔

示例:

[postgres]$ initdb --locale=C.UTF-8 --encoding=UTF8 -D /var/lib/postgres/data --data-checksums

屏幕上應該會出現許多行,其中幾行以 ... ok 結尾:

The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "C.UTF-8".
The default text search configuration will be set to "english".

Data page checksums are enabled.

creating directory /var/lib/postgres/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: warning: enabling "trust" authentication for local connections
initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    pg_ctl -D /var/lib/postgres/data -l logfile start

如果你看到的是這些行,那麼初始化過程成功了。使用 exit 返回到普通用戶。

警告:
提示:如果你將根目錄更改為 /var/lib/postgres 以外的路徑,你將需要 編輯 服務文件。如果根目錄在 home 下,請確保將 ProtectHome 設置為 false。

最後,啟動啟用 postgresql.service 服務。

創建第一個資料庫/用戶

提示:如果你創建一個與你的 Linux 用戶名相同的 PostgreSQL 角色/用戶,它將允許你在訪問 PostgreSQL 資料庫 shell 時無需指定登錄用戶(這非常方便)。

以 postgres 用戶身份,使用 createuser 命令添加一個新的資料庫角色/用戶:

[postgres]$ createuser --interactive

使用 createdb 命令,創建一個上述用戶可以讀寫的新資料庫(如果資料庫用戶與你的 Linux 用戶名相同,請從你的登錄 shell 執行此命令,否則請在以下命令中添加 -O database-username):

$ createdb myDatabaseName
提示:如果你沒有授予新用戶資料庫創建權限,請在上述命令中添加 -U postgres

熟悉 PostgreSQL

連接資料庫 shell

登錄為 postgres 用戶,啟動主資料庫 shell psql,你可以創建/刪除資料庫或表、配置權限和運行 SQL 命令。使用 -d 選項連接你創建的資料庫(如果沒有指定資料庫,psql 會嘗試連接與你用戶名同名的資料庫)。

[postgres]$ psql -d myDatabaseName

一些有用的命令:

  • 獲取幫助
=> \help
  • 列出所有資料庫
=> \l
  • 連接到特定資料庫
=> \c database
  • 列出所有用戶以及他們的權限
=> \du
  • 展示當前資料庫中所有的表相關的匯總信息
=> \dt
  • 退出 psql
=> \q 或是 Ctrl+d

當然也有更多元命令,但這些應該能夠幫助您開始。要查看所有元命令:

=> \?

可選配置

PostgreSQL 資料庫伺服器的配置文件是 postgresql.conf。該文件位於伺服器的數據目錄中,通常為 /var/lib/postgres/data。該目錄還包含其他主要配置文件,包括定義認證設置的 pg_hba.conf,適用於本地用戶其他主機用戶

注意:默認情況下,普通用戶無法瀏覽或搜索此目錄。這就是為什麼 findlocate 無法找到配置文件的原因。

默認限制資料庫超級用戶的訪問權限

默認情況下,pg_hba.conf 允許任何本地用戶以任何資料庫用戶身份連接,包括資料庫超級用戶。 這可能不是您想要的,因此為了限制對 postgres 用戶的全局訪問,請更改以下行:

/var/lib/postgres/data/pg_hba.conf
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" 僅用於 Unix 域套接字連接
local   all             all                                     trust

改為:

/var/lib/postgres/data/pg_hba.conf
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" 僅用於 Unix 域套接字連接
local   all             postgres                                peer

您可以根據需要或軟體要求稍後添加其他行。

要求登錄密碼

編輯 /var/lib/postgres/data/pg_hba.conf 並將每個用戶(或 all 以影響所有用戶)的認證方法設置為 scram-sha-256

/var/lib/postgres/data/pg_hba.conf
# TYPE  DATABASE        USER            ADDRESS                 METHOD 

# "local" 僅用於 Unix 域套接字連接
local   all             user                                    scram-sha-256
注意:更改 pg_hba.conf 中的認證方法不會更新資料庫中存儲的哈希密碼 [3]。要從 md5 遷移到 scram-sha-256,您需要為每個資料庫用戶設置新密碼。

重啟 postgresql.service,然後使用 ALTER USER user WITH ENCRYPTED PASSWORD 'password'; 重新添加每個用戶的密碼。

配置 PostgreSQL 僅通過 UNIX 套接字訪問

最初創建集群時,將 -c listen_addresses='' 附加到 initdb 命令中。

對於現有集群,編輯 postgresql.conf 並在連接和認證部分設置:

/var/lib/postgres/data/postgresql.conf
listen_addresses = ''

這將完全禁用網絡監聽。 之後,您應該重啟 postgresql.service 以使更改生效。

配置 PostgreSQL 以允許遠程主機訪問

在連接和認證部分,根據需要設置 listen_addresses 行:

/var/lib/postgres/data/postgresql.conf
listen_addresses = 'localhost,my_local_ip_address'

您可以使用 '*' 來監聽所有可用地址。

注意:PostgreSQL 默認使用 TCP 埠 5432 進行遠程連接。確保此埠在您的防火牆中打開並能夠接收傳入連接。您也可以在配置文件中更改此埠,位於 listen_addresses 下方。

然後在認證配置中添加如下行:

/var/lib/postgres/data/pg_hba.conf
# TYPE  DATABASE        USER            ADDRESS                 METHOD
# IPv4 本地連接:
host    all             all             ip_address/32           scram-sha-256

其中 ip_address 是遠程客戶端的 IP 地址。

請參閱 pg_hba.conf 的文檔。

注意:

本文或本章節的事實準確性存在爭議。

原因: 官方文檔指出 md5 使用挑戰-響應認證,這「防止了密碼嗅探」。也許不應將其視為與明文發送密碼一樣不安全。(在 Talk:PostgreSQL 中討論)



如果未通過 SSL 安全連接發送,無論是發送明文密碼還是 md5 哈希值都不安全。請參閱 使用 SSL 保護 TCP/IP 連接 以了解如何配置 PostgreSQL 使用 SSL。

之後,您應該重啟 postgresql.service 以使更改生效。

要進行故障排除,請查看伺服器日誌文件:

# journalctl -u postgresql.service

配置 PostgreSQL 使用 PAM 認證

PostgreSQL 提供了多種認證方法。如果您希望允許用戶使用其系統密碼進行認證,則需要執行額外的步驟。首先,您需要為連接啟用 PAM

例如,與上述相同的配置,但啟用了 PAM:

/var/lib/postgres/data/pg_hba.conf
# IPv4 本地連接:
host   all   all   my_remote_client_ip_address/32   pam

然而,PostgreSQL 伺服器在沒有 root 權限的情況下運行,無法訪問 /etc/shadow。我們可以通過允許 postgres 組訪問此文件來解決此問題:

# setfacl -m g:postgres:r /etc/shadow

修改默認數據目錄

默認設置下,新創建的資料庫會被存放於 /var/lib/postgres/data 目錄下。如果要更改目錄位置,可以參考下列步驟:

創建一個新文件夾,並將其所有者設為 postgres 用戶:

# mkdir -p /pathto/pgroot/data
# chown -R postgres:postgres /pathto/pgroot

切換到 postgres 用戶,然後初始化新集群:

[postgres]$ initdb -D /pathto/pgroot/data

通過編輯 postgresql.service附加配置片段,以覆蓋 EnvironmentPIDFile 設置。例如:

/etc/systemd/system/postgresql.service.d/PGROOT.conf
[Service]
Environment=PGROOT=/pathto/pgroot
PIDFile=/pathto/pgroot/data/postmaster.pid

如果您想使用 /home 目錄作為默認目錄或用於表空間,需要在此文件中額外添加一行:

ProtectHome=false

將新資料庫的默認編碼更改為 UTF-8

注意:如果您在運行 initdb 時使用了 -E UTF8 或在使用 UTF-8 區域設置時,這些步驟不是必需的。

在創建新資料庫時(例如使用 createdb blog),PostgreSQL 實際上會複製一個模板資料庫。有兩個預定義的模板:template0 是原始的,而 template1 是供管理員更改的現場模板,默認情況下使用。要更改新資料庫的編碼,其中一個選項是更改現場 template1。為此,登錄到 PostgreSQL shell(psql)並執行以下操作:

首先,我們需要刪除 template1。模板無法直接刪除,因此我們首先將其修改為普通資料庫:

UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1';

現在我們可以刪除它:

DROP DATABASE template1;

下一步是從 template0 創建一個新資料庫,並使用新的默認編碼:

CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UNICODE';

現在將 template1 修改為實際模板:

UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';

可選地,如果您不希望任何人連接到此模板,請將 datallowconn 設置為 FALSE

UPDATE pg_database SET datallowconn = FALSE WHERE datname = 'template1';
注意:最後一步在使用 pg_upgrade 升級時可能會產生問題。

現在您可以創建一個新資料庫:

[postgres]$ createdb blog

如果您重新登錄到 psql 並檢查資料庫,您應該看到新資料庫的正確編碼:

\l
                              List of databases
  Name    |  Owner   | Encoding  | Collation | Ctype |   Access privileges
-----------+----------+-----------+-----------+-------+----------------------
blog      | postgres | UTF8      | C         | C     |
postgres  | postgres | SQL_ASCII | C         | C     |
template0 | postgres | SQL_ASCII | C         | C     | =c/postgres
                                                     : postgres=CTc/postgres
template1 | postgres | UTF8      | C         | C     |

啟用數據校驗和

如果您的資料庫文件位於沒有校驗和的文件系統上,其數據可能會因位衰減和硬體故障而遭受靜默數據損壞。雖然這些事件很少見,但如果您關心數據完整性,您可能希望啟用 PostgreSQL 的內置數據校驗和。此功能必須在集群級別啟用,而不是按資料庫或按表啟用。

注意:此功能有一些注意事項:
  • 存在 最小的性能影響,尤其是在從磁碟讀取大型數據集時。內存操作不受影響。
  • PostgreSQL 無法修復損壞的數據 - 它只會中止從損壞頁面讀取的事務,以防止進一步的損壞或無效的執行結果。
  • 校驗和僅覆蓋磁碟數據(行)頁面,不包括元數據或控制結構。內存頁面不進行校驗和。糾錯存儲和 ECC 內存仍然有益。
  • 要在集群創建期間啟用校驗和,請將 --data-checksums 參數添加到 initdb
  • 要驗證是否啟用了校驗和,請運行 [postgres]$ psql --tuples-only -c "SHOW data_checksums"(應列印 offon)。
  • 要在現有集群上切換校驗和:
  1. 停止 postgresql.service
  2. 運行 [postgres]$ pg_checksums --pgdata /var/lib/postgres/data --enable(或 --disable 如果您不再需要校驗和)。啟用校驗和將重寫所有資料庫頁面,對於大型資料庫實例,這將需要一些時間。
  3. 啟動 postgresql.service

圖形化管理工具

  • phpPgAdmin — 基於 Web 的 PostgreSQL 管理工具。
https://github.com/phppgadmin/phppgadmin || phppgadminAUR
  • pgAdmin-desktop — pgAdmin 的桌面用戶界面,一個全面的 PostgreSQL 設計和管理的圖形用戶界面。
https://www.pgadmin.org/ || pgadmin4-desktopAUR
  • pgAdmin — 全面的 PostgreSQL 設計和管理圖形用戶界面。
https://www.pgadmin.org/ || pgadmin4[損壞的連結:package not found]
  • pgModeler — PostgreSQL 的圖形化模式設計工具。
https://pgmodeler.io/ || pgmodelerAUR
  • Postbird — 跨平台的 PostgreSQL 圖形用戶界面客戶端,使用 JavaScript 編寫,基於 Electron 運行。
https://github.com/paxa/postbird || postbird-binAUR
  • rainfrog — Postgres 的資料庫管理 TUI
https://github.com/achristmascarl/rainfrog || rainfrog

支持多種資料庫管理系統的工具,請參見 List of applications/Documents#Database tools

設置備份

建議為包含重要數據的資料庫設置備份。請參閱 PostgreSQL 文檔中的 備份與恢復 章節。PostgreSQL 維基中還有一個 備份工具列表,儘管它可能不是最新的或完整的。請記住,除非您定期執行測試恢復,否則不能信任備份系統!

升級 PostgreSQL

這篇文章的某些內容需要擴充。

原因:How to upgrade when using third party extensions? (在 Talk:PostgreSQL#pg_upgrade problem if extensions (like postgis) are used 中討論)

升級 PostgreSQL 大版本(例如從 14.x 升級到 15.y)需要一些額外的維護工作。

注意:應遵循 PostgreSQL 官方的 升級文檔
警告:以下指令可能導致數據丟失。不要盲目運行下面的命令,確保你理解它們在做什麼。請先備份

通過以下命令獲取當前使用的資料庫版本:

# cat /var/lib/postgres/data/PG_VERSION

為了避免意外升級到不兼容的資料庫版本,建議 跳過更新 PostgreSQL 包。

小版本升級是安全的。然而,如果你意外升級到一個不同的大版本,你可能無法訪問任何數據。請務必查看 PostgreSQL 主頁 以確認每個升級所需的步驟。有關為什麼會出現這種情況的更多信息,請參閱 版本策略

有兩種主要的方法可以升級你的 PostgreSQL 資料庫。請閱讀官方文檔以獲取詳細信息。

pg_upgrade

pg_upgrade 工具嘗試在集群之間複製儘可能多的兼容數據,並升級其他所有內容。儘管它需要訪問源和目標 PostgreSQL 版本的二進制文件,但它通常是升級大多數實例的最快方法。請閱讀 pg_upgrade(1) 手冊頁以了解它執行的操作。對於非平凡的實例(例如帶有流複製或日誌傳送的實例),請先閱讀 上游文檔

對於希望使用 pg_upgrade 的用戶,有一個 postgresql-old-upgrade 包,它將始終運行比實際 PostgreSQL 包低一個主要版本的版本。這可以與新版本的 PostgreSQL 一起安裝。要從舊版本的 PostgreSQL 升級,可以使用 AUR 包,例如 postgresql-12-upgradeAUR。(你必須使用與你升級到的 PostgreSQL 版本打包的 pg_upgrade 版本。)

請注意,資料庫集群目錄不會隨版本變化而變化,因此在運行 pg_upgrade 之前,有必要重命名現有的數據目錄並遷移到一個新目錄。必須使用與舊集群相同的參數初始化新的資料庫集群。

當你準備好開始升級時:

  1. 當舊資料庫集群仍在運行時,收集用於創建它的 initdb 參數。請參閱 #初始化配置 以獲取更多信息。
  2. 停止 postgresql.service。檢查 單元狀態確保 PostgreSQL 已正確停止。如果停止失敗,pg_upgrade 將失敗並顯示 The source cluster was not shut down cleanly
  3. 升級 postgresql, postgresql-libs, 和 postgresql-old-upgrade
  4. 確保 /var/lib/postgres/olddata 不存在。如果你在上次升級後沒有刪除它,請現在刪除。
  5. 重命名舊集群目錄,然後創建一個新的集群和臨時工作目錄:
    # mv /var/lib/postgres/data /var/lib/postgres/olddata
    # mkdir /var/lib/postgres/data /var/lib/postgres/tmp
    # chown postgres:postgres /var/lib/postgres/data /var/lib/postgres/tmp
    [postgres]$ cd /var/lib/postgres/tmp
    
  6. 使用與舊集群相同的 initdb 參數初始化新集群:
    [postgres]$ initdb -D /var/lib/postgres/data --locale=C.UTF-8 --encoding=UTF8 --data-checksums
  7. 升級集群,將下面的 PG_VERSION 替換為舊的 PostgreSQL 版本號(例如 15):
    [postgres]$ pg_upgrade -b /opt/pgsql-PG_VERSION/bin -B /usr/bin -d /var/lib/postgres/olddata -D /var/lib/postgres/data
    提示:在支持 reflinks 的文件系統(例如 BtrfsXFS)上,可以附加 --clone 選項以加快文件複製速度。
    如有必要,調整新集群的配置文件(例如 pg_hba.confpostgresql.conf)以匹配舊集群。
  8. 再次啟動postgresql.service
  9. 可選: 運行 [postgres]$ vacuumdb --all --analyze-in-stages 以重新計算查詢分析器統計信息,這 應該會在升級後不久提高查詢性能。(添加 --jobs=NUMBER_OF_CPU_CORES 參數可能會提高此命令的性能。)
  10. 可選: 備份 /var/lib/postgres/olddata 目錄,以防你需要恢復之前的 PostgreSQL 版本。
  11. 刪除包含舊集群數據的 /var/lib/postgres/olddata 目錄。
  12. 刪除 /var/lib/postgres/tmp 目錄。
  13. 如果你使用 pgbackrestAUR,請運行 stanza-upgrade 命令。

手動轉儲和重新加載

你也可以這樣做(在升級並安裝 postgresql-old-upgrade 之後)。

注意:
  • 以下是升級自 PostgreSQL 14 的命令。你可以在 /opt/ 中找到適用於你 PostgreSQL 集群版本的類似命令,前提是你安裝了相應版本的 postgresql-old-upgrade 包。
  • 如果你自定義了 pg_hba.conf 文件,你可能需要臨時修改它以允許從本地系統完全訪問舊資料庫集群。升級完成後,將你的自定義設置應用到新資料庫集群並 restart postgresql.service

停止 postgresql.service

# mv /var/lib/postgres/data /var/lib/postgres/olddata
# mkdir /var/lib/postgres/data
# chown postgres:postgres /var/lib/postgres/data
[postgres]$ initdb -D /var/lib/postgres/data --locale=C.UTF-8 --encoding=UTF8 --data-checksums
[postgres]$ /opt/pgsql-14/bin/pg_ctl -D /var/lib/postgres/olddata/ start
# cp /usr/lib/postgresql/postgis-3.so /opt/pgsql-14/lib/ # 仅当安装了 postgis 时
[postgres]$ pg_dumpall -h /tmp -f /tmp/old_backup.sql
[postgres]$ /opt/pgsql-14/bin/pg_ctl -D /var/lib/postgres/olddata/ stop

啟動 postgresql.service

[postgres]$ psql -f /tmp/old_backup.sql postgres

故障排除

提高小事務的性能

如果你在本地機器上使用 PostgresSQL 進行開發,並且感覺速度較慢,可以嘗試在配置中關閉 synchronous_commit。但請注意 注意事項

警告:這是一個非常粗糙的解決方案,可能會破壞資料庫或導致數據丟失,因此請務必備份。

PostgreSQL database unable to start after package update when using extensions

The cause in this case is mostly the existing package is not compiled for the newer version (and it may be up-to-date), the solution is rebuilding the package either manually or waiting for an update to the extension package.

Failing to start a PostgreSQL server with the older version of the database while upgrading to the newer version with extensions

This is caused because the old version of postgres from the package postgresql-old-upgrade does not have the required extensions (.so files) in its lib directory, the current solution is dirty, and might cause a lot of problems so keep a backup of the database just in case, basically copy the required extension .so files from /usr/lib/postgresql/ to /opt/pgsql-XX/lib/ (remember to replace XX with the major version of postgresql-old-upgrade).

For example, for timescaledb

# cp /usr/lib/postgresql/timescaledb*.so /opt/pgsql-13/lib/
警告:while copying the .so files was enough for me, it might be required to copy more files to the correct directories under /opt/pgsql-XX/.

to know the exact files to copy, check the contant of the package of the extension using :

$ pacman -Ql package_name
警告:This is a very dirty solution that may break or cause data loss in the database, so keep a backup.

警告:資料庫 "postgres" 的排序規則版本不匹配

你可能會看到類似這樣的信息:

WARNING:  database "postgres" has a collation version mismatch
DETAIL:  The database was created using collation version X.YY, but the operating system provides version X.ZZ.
HINT:  Rebuild all objects in this database that use the default collation and run ALTER DATABASE postgres REFRESH COLLATION VERSION, or build PostgreSQL with the right library version.

That means collation provider library (glibc or icu) was updated which might have made some indexes invalid. So that means need to reindex those databases.

You can do that with:

[postgres]$ psql -c 'REINDEX DATABASE' postgres
[postgres]$ psql -c 'ALTER DATABASE postgres REFRESH COLLATION VERSION'

Repeat this above for all other databases by replacing postgres with respective DB name.

提示:This issue can be avoided by using the C.UTF-8, C, POSIX or ucs_basic locale for the database cluster.