目錄
PostgreSQL 名稱來源
It was originally named POSTGRES, referring to its origins as a successor to the Ingres database developed at the University of California, Berkeley.
In 1996, the project was renamed to PostgreSQL to reflect its support for SQL.
PostgreSQL 的發音為 [ˈpəʊsɡreˈsɪkl], 中間部分類似於 progress 的發音
服務端安裝
參考官方安裝說明 https://www.postgresql.org/download/linux/ubuntu/
# 創建軟件源
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
# 添加key
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# 更新倉庫
sudo apt update
# 安裝之前可以看一下有哪些版本
apt-cache search postgresql
# 安裝, 20.04默認是postgresql-14, 22.40是postgresql-15
sudo apt install postgresql
# 檢查
sudo systemctl status postgresql
# 查看端口
sudo netstat -lnp
客戶端安裝
Windows下可以直接使用Navicat, pg自己的圖形客戶端是 pgAdmin, 基於python和javascript.
pgAdmin 4 is a complete rewrite of pgAdmin, built using Python and Javascript/jQuery. A desktop runtime written in NWjs allows it to run standalone for individual users
Ubuntu20.04, pgAdmin4
sudo vi /etc/apt/sources.list.d/pgadmin4.list
# 寫入以下內容
deb https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/focal pgadmin4 main
# 更新並安裝
sudo apt update
sudo apt install pgadmin4-desktop
登錄驗證
訪問驗證機制
- pg的驗證和權限是分開的, 一個用戶首先要能通過驗證進行訪問, 然后才是根據授權訪問對應的數據庫
- pg的訪問驗證設置, 默認的配置文件位於 /etc/postgresql/[版本號]/main/pg_hba.conf, 版本號可能是14, 15等
- 只有當這個role/user在pg中存在, 才能對pg進行訪問. pg安裝后, 默認的role為postgres, 是一個superuser
驗證配置文件說明
配置文件 pg_hba.conf, 配置說明 https://www.postgresql.org/docs/14/auth-pg-hba-conf.html
客戶端認證由配置文件控制, 通常為名為 pg_hba.conf 的文件, 存儲在集群的數據目錄(HBA 代表 host-based authentication 的縮寫). 當數據目錄初始化時, 會生成一個默認的 pg_hba.conf 文件. 可以通過修改主配置文件, 將文件放到其他路徑.
pg_hba.conf 文件通常的格式是按行組織的文本記錄
- 使用#號標識注釋
- 如果一行未結束需要換行, 使用
\
符號. - 每行記錄由一些空格或tab分隔的字段組成. 如果字段包含空格, 需要用雙引號包圍.
- 每行記錄指定了: 連接類型, 客戶端IP范圍, 數據庫名, 用戶名, 驗證方式.
- 匹配的第一個記錄(匹配連接類型+客戶端地址+數據庫+用戶名)將用於驗證
- 沒有缺省或再次驗證, 只要一個記錄被選中, 那么驗證就只用這個記錄處理, 如果沒有命中的記錄, 就返回拒絕.
注意, 驗證只要匹配了一個記錄(方式), 就用這個方式處理, 不會有多次匹配.
初始配置示例
這是默認的配置, 注意幾點
- 因為local ... peer是本地socket, 優先級最高, 用戶不是postgres就是all, 如果在命令行運行psql, 會基於用戶的linux用戶名, 用這些規則進行驗證
- linux下的postgres用戶, 因為在pg中的同名user/role存在, 因此可以通過驗證
- 如果用其它用戶訪問psql, 例如
ubuntu
用戶運行psql -l
, 會報failed: FATAL: role "ubuntu" does not exist
錯誤, 通過sudo -u postgres createuser --interactive
創建一個名為ubuntu的user之后, 就可以運行psql -l
了.
# "local" is for Unix domain socket connections only
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 scram-sha-256
host all all 0.0.0.0/0 trust
# IPv6 local connections:
host all all ::1/128 scram-sha-256
# Allow replication connections from localhost, by a user with the replication privilege.
local replication all peer
host replication all 127.0.0.1/32 scram-sha-256
host replication all ::1/128 scram-sha-256
記錄格式
local database user auth-method [auth-options]
host database user address auth-method [auth-options]
hostssl database user address auth-method [auth-options]
hostnossl database user address auth-method [auth-options]
hostgssenc database user address auth-method [auth-options]
hostnogssenc database user address auth-method [auth-options]
host database user IP-address IP-mask auth-method [auth-options]
hostssl database user IP-address IP-mask auth-method [auth-options]
hostnossl database user IP-address IP-mask auth-method [auth-options]
hostgssenc database user IP-address IP-mask auth-method [auth-options]
hostnogssenc database user IP-address IP-mask auth-method [auth-options]
連接方式
- local 使用本機Unix-domain sockets, 如果沒有local開頭的記錄, 則不允許用Unix-domain sockets連接
- host 使用TCP/IP連接, 包含SSL和GSSAPI方式
- hostssl TCP/IP + 使用SSL
- hostnossl TCP/IP + 不使用SSL
- hostgssenc TCP/IP + GSSAPI 加密
- hostnogssenc TCP/IP + 不使用 GSSAPI 加密
數據庫, 指定匹配的數據庫
- 數據庫名 指定數據庫, 多個數據庫使用逗號連接
- all 匹配所有
- sameuser 與此數據庫同名的用戶, 必須是這個用戶
- samerole 與此數據庫同名的role, 用戶必須屬於這個role
- samegroup 以廢棄
- replication
- @ 可以用@號指定文件
用戶, 指定匹配的用戶
- 用戶名 指定的用戶, 多個用戶用+號連接
- all 所有用戶
- @ 可以用@號指定文件
客戶端地址
- 172.20.143.89/32 IPv4地址或范圍
- 172.20.1.1/255.0.0.0 IPv4地址范圍的另一種格式
- fe80::7a31:c1ff:0000:0000/96 IPv6地址或范圍
- all 所有地址
- samenet 同一子網的地址
- samehost 當前主機的所有地址
- .example.com 域名通配
驗證方式
- trust 無條件通過
- reject 直接拒絕
- scram-sha-256 使用SCRAM-SHA-256驗證
- md5 使用 Perform SCRAM-SHA-256 或 MD5 驗證
- password 使用未加密的密碼驗證, 注意這種方式下, 密碼在網絡中是明文傳輸
- gss 使用 GSSAPI 驗證, 僅適用於 TCP/IP 連接.
- sspi 使用 SSPI 驗證, 僅適用於 Windows
- ident 通過ident服務器, 獲取當前客戶端操作系統用戶名, 並與請求的數據庫用戶名進行校驗, 僅適用於 TCP/IP 連接.
- peer 從操作系統獲取用戶名, 僅適用於 local 方式的連接
- ldap Authenticate using an LDAP server.
- radius Authenticate using a RADIUS server
- cert 使用 SSL 客戶端證書進行驗證
- pam 使用操作系統提供的 Pluggable Authentication Modules (PAM) 服務進行驗證
- bsd 使用操作系統提供的 BSD Authentication service 進行驗證
驗證選項
- 根據不同的驗證方式提供的選項
默認的 postgres 用戶
安裝后, Ubuntu系統中會增加一個 postgres 用戶
$ more /etc/passwd
...
postgres:x:113:121:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
因為pg中也存在 postgres 這個superuser, 這個用戶可以直接訪問 postgresql
$ sudo su postgres
[sudo] password for milton:
postgres@ubuntu:/home/milton$ psql
psql (14.2 (Ubuntu 14.2-1.pgdg20.04+1))
Type "help" for help.
postgres=#
postgres-# \q
postgres@ubuntu:/home/milton$
配置
查看數據庫列表
sudo -u postgres psql -l
創建用戶
創建用戶, 這個 createuser 命令只是一個perl腳本, 專門用於 postgresql 創建用戶, 准確的說是對應 local peer的用戶, 因為里面不設置密碼
sudo -u postgres createuser --interactive
[sudo] password for milton:
Enter name of role to add: dbuser
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
在命令行下執行psql或postgres時, postgresql 會用linux用戶名進行驗證, 所以如果創建了用戶為 milton, 如果再創建一個名為 milton 的 linux 用戶就可以直接訪問. 如果不對應linux用戶, 則只能通過host方式登錄
User, Role, Group
在 PostgreSQL 中, user, group, role這三者可以認為是等價的, role和user唯一的區別在於user默認可以登錄數據庫. 在其他數據庫例如Oracle, role只用於授權和分組不能用於登錄, 而在 PostgreSQL 中, role 可以用於登錄. 在 PostgreSQL 中, CREATE USER 和 CREATE GROUP 其實是 CREATE ROLE 的別名.
CREATE USER = CREATE ROLE + LOGIN PERMISSION
也可以使用 CREATE USER 創建一個 PostgreSQL 用戶
CREATE USER myuser WITH PASSWORD 'secret_passwd';
也可以使用以下等價的 CREATE ROLE 命令
CREATE ROLE myuser WITH LOGIN PASSWORD 'secret_passwd';
這兩個語句創建的用戶是完全一樣的, 這樣新創建的用戶, 除了有public role的權限以外沒有任何其他權限. 所有的users和roles的權限, 都繼承自public role
創建數據庫
# 使用 postgres 用戶
createdb milton
# 或者 sudo
sudo -u postgres createdb milton
# 指定用戶
sudo -u postgres createdb testdb -O postgres
主配置
對應的配置文件在 /etc/postgresql/
sudo vi /etc/postgresql/14/main/postgresql.conf
主配置文件說明 https://www.postgresql.org/docs/14/runtime-config-connection.html
服務IP listen_addresses
# 監聽所有地址
listen_addresses = '*'
# 監聽指定地址
listen_addresses = '192.168.10.20'
服務端口 port
port = 5432
密碼加密方式 password_encryption
password_encryption = scram-sha-256 # scram-sha-256 or md5
用戶名命名空間 db_user_namespace, 如果設置為on, 用戶創建時可以使用 username@dbname 這樣的格式, 用於與數據庫綁定. 這時候依然可以創建全局用戶, 但是連接時客戶端必須加上 @
db_user_namespace = off
數據類型
數值
- 整數 smallint, integer, bigint
- 自增整數 serial, bigserial
- 金額浮點 decimal, numeric
字符
- character(n) 定長字符串
- character varying(n) 相當於mysql的varchar, 有長度限制
- text 不定長,不限長字符串
日期
- timestamp, 這個相當於mysql的datetime
其它
pg還支持坐標, uuid, xml, json等字段格式
命令行操作
連接db
psql -h localhost -p 5432 -U postgres runoobdb
Compare To MySQL
- Pg 支持多個表從同一個序列中取 id
- Pg 支持 OVER 子句, OVER 子句能簡單的解決 "每組取 top 5" 這類問題
- Pg 不存在需要 utf8mb4 顯示 emoji 的問題
參考
- 管理user和role https://aws.amazon.com/blogs/database/managing-postgresql-users-and-roles/
- MySQL PostgreSQL Difference