本文將從日常使用的角度對比學習國產數據庫openGauss與開源數據庫PostgreSQL之間的差異點。
1.服務的啟動模式
在主備場景下,PG服務啟動命令不區分角色,openGauss服務啟動需要指定啟動模式,參考如下鏈接:
《openGauss數據庫服務啟動模式分析》
2.服務的關閉模式
PostgreSQL
smart quit after all clients have disconnected
fast quit directly, with proper shutdown (default)
immediate quit without complete shutdown; will lead to recovery on restart
openGauss
fast quit directly, with proper shutdown
immediate quit without complete shutdown; will lead to recovery on restart
smart模式下,數據庫會等待所有的客戶端鏈接主動斷開連接,此時數據庫服務不允許接受新連接請求,但允許現有連接繼續操作,直到所有連接都主動退出之后,數據庫主進程才會發送SIGUSR2信號給checkpointer進程去執行shutdown checkpoint類型的檢查點。這樣所有客戶端連接提交的數據都已刷盤,下次PG啟動時不需要做crash恢復。
fast模式是默認關閉方式,這種模式下數據庫會通過發送SIGTERM信息來立刻終止所有打開的事務,同時也不允許接受新的連接請求。終止客戶端連接之后也會發起shutdown checkpoint類型的檢查點來避免下次啟動服務時做restart point。這種模式也是生產中推薦的使用方式,會終止當前的客戶端連接。
immediate模式,這種模式數據庫會強制關閉相關進程,數據庫主進程會發送SIGQUIT信號給所有進程強制退出。這樣情況下數據庫關閉之前并沒有做一次干凈的checkpoint操作。下次服務啟動需要從事務日志文件讀取最后一次提交的位點及最后一次checkpoint位點之間的事務日志來做apply,刷新到磁盤數據文件(注意:這里的數據文件是指data file,不是xlog file)。
上述三種模式,smart其實極少使用,生產通常也是使用fast模式,immediate模式只有在緊急情況下才會考慮。
3.xlog
由于歷史原因,PG對xlog的命名更新為了wal,包括相應的二進制工具、命令參數、系統相關函數等。
例如查看事務日志點位信息
PostgreSQL
postgres=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/174E780
(1 row)
openGauss
openGauss=# select pg_current_xlog_location();
pg_current_xlog_location
--------------------------
0/22331C0
(1 row)
openGauss設置xlog目錄路徑設置的幾種方式可以參考:《openGauss數據庫安裝部署之xlog目錄設置》
4.歸檔
歸檔開關參數都是archive_mode,但是歸檔命令參數有區別。
PostgreSQL
archive_command = 'cp %p /opt/archive/%f'
pg里面是配置archive_command參數,可以配置shell命令。
openGauss
archive_dest='/opt/archive'
openGauss是配置archive_dest參數,直接配置歸檔路徑即可。
5.public模式的使用權限
PostgreSQL
pg里面創建的用戶默認是具有public模式的使用及創建權限,owner用戶可以管理自己的對象。
postgres=> select * from pg_namespace where nspname='public' ;
oid | nspname | nspowner | nspacl
------+---------+----------+-------------------------------------
2200 | public | 10 | {postgres=UC/postgres,=UC/postgres}
(1 row)
上面從schema元數據列nspacl也可以看到默認是具有UC權限(U:usage,C create)
openGauss
gs_initdb初始化時使用-S, --security后,用戶默認將不具有public模式的使用權限。
openGauss=# select nspacl from pg_namespace where nspname='public' ;
nspacl
--------------
{omm=UC/omm}
(1 row)
上面從schema元數據列nspacl也可以看到默認不具有模式的使用權限。
下面進行測試,可以看到有報錯提示
openGauss=# \c - test
Password for user test:
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "postgres" as user "test".
openGauss=> create table public.t(id int);
ERROR: permission denied for schema public
DETAIL: N/A
6.ssl
《openGauss數據庫與PostgreSQL對比測試SSL之自簽名私有證書測試》
《openGauss數據庫與PostgreSQL對比測試SSL之自簽名CA證書單向認證測試》
《openGauss數據庫與PostgreSQL對比測試SSL之自簽名CA證書雙向認證測試》
簡單總結如下,詳細測試對比參考上面的文章鏈接。
- PostgreSQL需要編譯支持openssl,而openGauss已經內置支持。
- openGauss不會識別openssl默認配置文件,需要顯示指定openssl.cnf文件路徑,否則會報錯找不到配置文件。
- openGauss與PostgreSQL對clientcert=verify-full認證支持有差異。
7.sha256口令加密
用戶口令加密的參數名稱有區別,同時sha256算法有不同的實現,互相不兼容。
PostgreSQL
password_encryption = 'scram-sha-256'
pg里面是配置password_encryption參數,可以配置md5或者scram-sha-256。
openGauss
password_encryption_type=1
openGauss是配置password_encryption_type參數,0 只支持標準的md5口令存儲,與PG保持兼容,1 支持md5和國密的sha256,2 只支持國密sha256,不兼容PG。
8.copy
copy的分隔符:
PostgreSQL
postgres=# \copy t to t.dat delimiter '@$'
ERROR: COPY delimiter must be a single one-byte character
openGaussB

copy的容錯機制
openGauss
表結構
CREATE TEMP TABLE foo (a bigint, b text);
數據文件tab.dat
1 one
2
3 three 111
four 4
5 five
普通的copy導入,因為有多余的數據項會報錯
omm=# copy foo from '/home/omm/tab.dat';
ERROR: extra data after last expected column
CONTEXT: COPY foo, line 3: " 3 three 111"
copy使用ignore_extra_data忽略多余的列
omm=# copy foo from '/home/omm/tab.dat' with(ignore_extra_data);
ERROR: invalid input syntax for type bigint: " four 4"
CONTEXT: COPY foo, line 4, column a: " four 4"
copy使用log_errors和reject_limit
omm=# copy foo from '/home/omm/tab.dat' with(ignore_extra_data,log_errors,reject_limit 'unlimited');
COPY 4
reject_limit參數對copy from的容錯機制設置數值上限,一旦錯誤數據超過選項指定條數,則會按照原有機制報錯。取值范圍:正整數(1-INTMAX),‘unlimited’(無最大值限制)
此時已經導入成功了4條數據,可以從下面的查詢看出。
omm=# select * from foo;
a | b
---+-------
1 | one
2 |
3 | three
5 | five
(4 rows)
還有一條報錯的信息記錄在系統自動創建的pgxc_copy_error_log表中。
omm=# \x
Expanded display is on.
omm=# select * from pgxc_copy_error_log ;
-[ RECORD 1 ]-------------------------------------------------
relname | pg_temp_gaussdb_8_1_140368156813056.foo
begintime | 2021-06-27 11:29:00.529073+00
filename | /home/omm/tab.dat
lineno | 4
rawrecord |
detail | invalid input syntax for type bigint: " four 4"
上面rawrecord是沒有內容的,使用log_errors_data替代log_errors會記錄rawrecord
truncate table pgxc_copy_error_log;
truncate table foo;
copy foo from '/home/omm/tab.dat' with(ignore_extra_data,log_errors_data,reject_limit 'unlimited');
omm=# select * from pgxc_copy_error_log ;
-[ RECORD 1 ]-------------------------------------------------
relname | pg_temp_gaussdb_8_1_140368156813056.foo
begintime | 2021-06-27 11:34:34.104653+00
filename | /home/omm/tab.dat
lineno | 4
rawrecord | four 4
detail | invalid input syntax for type bigint: " four 4"
9.Upsert(insert or update)
PostgreSQL
create table test_upsert (id int primary key, info varchar);
postgres=# insert into test_upsert (id,info)
postgres-# values (1,'aaa');
INSERT 0 1
下面插入主鍵重復的數據
postgres=# insert into test_upsert (id,info)
postgres-# values (1,'bbb');
ERROR: duplicate key value violates unique constraint "test_upsert_pkey"
DETAIL: Key (id)=(1) already exists.
不使用upsert語法,會報錯返回給客戶端,不太友好
postgres=# insert into test_upsert (id,info)
postgres-# values (1,'bbb')
postgres-# on conflict(id) do update set info=excluded.info;
INSERT 0 1
postgres=# select * from test_upsert;
id | info
----+------
1 | bbb
(1 row)
使用upsert語法,有沖突時可選擇do nothing跳過或者do update覆蓋更新
openGauss
omm=# create table test_upsert (id int primary key, info varchar);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_upsert_pkey" for table "test_upsert"
CREATE TABLE
omm=# insert into test_upsert (id,info)
values (1,'aaa');omm-#
INSERT 0 1
omm=# insert into test_upsert (id,info)
values (1,'bbb');
ERROR: duplicate key value violates unique constraint "test_upsert_pkey"
DETAIL: Key (id)=(1) already exists.
omm=# insert into test_upsert (id,info)
values (1,'bbb')
ON DUPLICATE KEY update info=excluded.info;
INSERT 0 1
omm=# select * from test_upsert;
id | info
----+------
1 | bbb
(1 row)
10.分區表
《openGauss數據庫PostgreSQL表分區語法測試》
簡單總結如下,詳細測試對比參考上面的文章鏈接。
- openGauss目前只支持聲明式分區,支持范圍分區、列表分區、哈希分區以及INTERVAL-RANGE的自動擴展間隔分區。PostgreSQL支持繼承及聲明式分區,不支持自動擴展間隔分區。
- 自動擴展間隔分區的分區字段目前只支持時間類型(date或timestamp)。
- openGauss目前不支持子分區,PG支持聲明式子分區。
- 對于聲明式分區的分區來說,分區必須具有和分區表正好相同的列集合,表結構必須嚴格一致,而在表繼承中,子表可以有父表中沒有出現過的額外列,同時表繼承允許多繼承。




