openGauss 資料與 PostgreSQL 的差異對比
-
前言
openGauss 資料庫已經發布 2.0.1 版本了,中啟乘數科技是一家專業的專注於極致效能的資料庫服務提供商,所以也關注 openGauss 資料庫的特性。因為 openGauss 是從 PostgreSQL 發展出來的,所以我們詳細講解對比一下 openGauss 與原生 PostgreSQL 資料庫的對比。 -
openGauss 大功能方面的變化
openGauss 是基於 PostgreSQL9.2 版本開發的,基本包括了 PostgreSQL9.4 的功能。目前 PostgreSQL 正式版本已經到 13 了, 14 的 beta 版本也釋出了。openGauss 只把 PostgreSQL9.4 之後的新版本的極少數功能移植進來了,絕大多數功能都沒有納入。
openGauss 最大的變化就是把 PostgreSQL 的程序模式改成了執行緒模式,當然這兩個模式其實各有優缺點。執行緒模式對短連線有優勢,比程序模式的資料庫可以承擔更大的併發短請求,但執行緒模式也有明顯的缺點,所有的執行緒共享記憶體,如果一個執行緒的的野指標把別人的記憶體改了,不會報錯,一時半會可能還發現不了,極端情況下會導致資料損壞而不被發現。所以說這個改變不能說有什麼明顯的好處,某些情況下可能還是一個退步。為了改成執行緒模式,openGauss 的把 C 語言的原始碼改成了 C++。C++的好處是容易封裝,壞處是移植性降低了。
當然 openGauss 增加了執行緒池的功能,目前還不清楚這個功能是否穩定可靠。如果穩定可靠可以不使用第三方的連線池工具了。
openGauss 另一個變化是把事務 ID(XID)從 32bit 改成了 64bit,64bit 的 xid 的好處是永遠不可能耗盡,好處是我們永遠不用擔心會發生 xid 回捲當機的風險。注意,雖然 xid 改為了 64bit,但是過期的事務 ID 依舊需要清理。實際上 PostgreSQL 資料庫預設達到 2 億事務就強制整理,而 32bit 的 xid 可以達到 20 億,所以我們實際上可以修改 autovacuum_freeze_max_age 為 10 億來推遲對 xid 的整理。
我們知道磁碟扇區大小是 512 位元組,一些 SSD 可以是 4k 大小,而資料庫一般是 8k/16k/32k,一個資料庫資料塊刷到作業系統的過程中可能發生當機造成這樣有塊斷裂問題,即塊中一半是新資料,另一半還是舊資料,這就是塊的邏輯損壞,這可能導致資料庫無法啟動。
MySQL 透過雙寫 double write 來解決這個問題,PostgreSQL 是透過 full_page_write 來解決這個問題,就是在資料頁第一次發生變更的時候將整個頁面記錄到 xlog 日誌中,這樣出了問題就有了完整的資料頁加 xlog 日誌進行恢復,這樣做的缺點是大大增加了 xlog 的日誌量,也對效能有一定影響。當然我們可以透過延長 checkpoint 的間隔時間來緩解這個問題。而 openGauss 實現了類似 MySQL 的雙寫,寫資料塊的同時將髒頁也寫到一個共享的雙寫空間裡,如果發生問題會從雙寫空間裡找到完整的資料頁進行恢復。雙寫特性引數 enable_double_write 需要配合增量檢查點一起使用。openGauss 這個功能有一定的實際價值。
openGauss 主備庫的模式與 PostgreSQL 有比較大的不同,PostgreSQL 的備庫模式是拉的模式,即備庫主動到主庫上拉 WAL 日誌,而 openGauss 改成了推的模式,推的模式是主庫主動把 WAL 模式推到備庫。而實際上改成這樣,導致搭建備庫更不方便了,因為搭建備庫時必須到主庫上修改引數 replconninfo1 或 replconninfo2,即 replconninfoN, N=1~8,而可以配置的引數只有 8 個,所以感覺 openGauss 後面最多隻能掛 8 個備庫。當年從 Oracle 轉到 PostgreSQL 上時,還比較慶幸不用動主庫了,一用 openGauss 感覺又回到瞭解放前。
openGauss 內建的了主備庫切換功能,讓使用者用起來更方便。但這個功能是和資料庫本身緊耦合的,同時不太穩定。筆者在測試中,備庫就報從主庫中斷開了,報大量的日誌把空間給撐爆了:
2021-06-24 08:38:43.824 [unknown] [unknown] localhost 47427058550848 0 0 [BACKEND] LOG: configuration file "/opt/software/openGauss
/data/slave/postgresql.conf" contains errors; unaffected changes were applied
2021-06-24 08:38:43.832 [unknown] [unknown] localhost 47428485064448 0 0 [BACKEND] LOG: Connect failed.
2021-06-24 08:38:43.833 [unknown] [unknown] localhost 47428485064448 0 0 [BACKEND] LOG: Connect failed.
2021-06-24 08:38:43.833 [unknown] [unknown] localhost 47428485064448 0 0 [BACKEND] LOG: Connect failed.
2021-06-24 08:38:43.833 [unknown] [unknown] localhost 47428485064448 0 0 [BACKEND] LOG: Connect failed.
2021-06-24 08:38:43.833 [unknown] [unknown] localhost 47428485064448 0 0 [BACKEND] LOG: Connect failed.
2021-06-24 08:38:43.833 [unknown] [unknown] localhost 47428485064448 0 0 [BACKEND] LOG: Connect failed.
從上面的日誌可以看出,列印日誌時,沒有任何間隔,不斷的列印,很快就會把空間給撐滿。這是一個很糟糕的設計,在生產系統中這也是一個很危險的情況,雖然有空間告警,但有可能還沒有等工程師來處理,空間就給撐滿了。
openGauss 摒除 recovery.conf 檔案。當然 PostgreSQL12 的版本也是摒除 recovery.conf 檔案。openGauss 是啟動資料庫是指定是備庫還是主庫:
gs_ctl start -D $GAUSSHOME/data/master -M standby
這個改變實際上是一個非常糟糕的改變,如果 DBA 忘加了“-M standby”,這個備庫就廢掉了,需要重新搭建。而原生 PostgreSQL 是建立了一個檔案來指示這個資料庫是主庫還是備庫,不會有這種誤操作的風險。好在 openGauss 提供了 gs_ctl build 命令重新搭建備庫,部分緩解了這個問題。
openGauss 有一個最大可用模式 most_available_sync,openGauss 認為原生 PostgreSQL 的流複製有一個痛點就是在一主一備的同步模式下,如果備庫當機,主庫會 hang,同步模式不會自動降級。所以 openGauss 設計了最大可用模式,即開啟該引數後在主從連線正常的情況下處於同步模式,如果備機斷連會立刻切為非同步模式,如果備機再次啟動會自動連線並切為同步模式。但實際上這種設計是一種奇怪的設計,如果出現問題立即降級,那麼與非同步模式有什麼區別?同步模式本身就是要保證故障切換後不丟失資料,當故障時主庫立即降級了,這時再切換了,直接就丟失資料了。如果允許丟資料,直接使用非同步複製就可以了,如果需要不丟資料,使用同步模式,如果一個備庫壞了主庫也不 hang,那麼就做兩個備庫的同步模式,這個 most_available_sync 模式感覺不太實用。
openGauss 支援了列存表,列存表支援壓縮。列存表使用中需要注意膨脹的一些問題,如果瞭解不深,建議不要使用。
openGauss 在每個庫下面會預設有個叫 dbe_perf 的 schema,這個 schema 下有有幾百個效能檢視,這些檢視大部分 pg 裡面都有,但是放在單獨的 schema 中方便檢視和管理,這個設計還不錯。
openGauss 中實現了 xlog 預分配,在 xlog 未寫滿時就分配下面一個或者幾個 xlog。網上有人說 PostgreSQL 不能預分配 WAL,這是錯誤的認識,實際上 PostgreSQL 是可以把原先使用的 WAL 日誌改名成預分配的 WAL 日誌的,引數 min_wal_size 就是指定了需要預先預留的 WAL 檔案數,這個引數預設是 80MB,這個值對於一些需要灌大量資料的資料庫來說,有點小了,可以把此值改大。
openGauss 實現了增量 checkpoint,官方稱讓資料庫更平滑。
openGauss 實現了並行恢復,預設是關閉的。
由於 openGauss 的物理備庫也會建複製槽,為了防止備庫把主庫的空間撐爆,openGauss 又增加了兩個引數:enable_xlog_prune 和 max_size_for_xlog_prune,允許刪除掉過多的 WAL 日誌防止把主庫撐爆:
postgres=# show max_size_for_xlog_prune;
max_size_for_xlog_prune
2147483647kB
(1 row)
但預設 max_size_for_xlog_prune 設定的比較大,起不到保護作用。
openGauss 支援與 oracle 使用方法基本相同的定時任務 dbms_job。
openGauss 有初步的邏輯解碼功能,但不如 PostgreSQL 完善。沒有完整的 PostgreSQL 的邏輯複製功能。
openGauss 的索引支援比新版本的 PostgreSQL 弱一些,如不支援 brin 索引,PostgreSQL 新版本對 Btree 索引有比較大的最佳化,這一塊 openGauss 也有一些缺失,也沒有布隆過濾器的功能。
- openGauss 一些硬傷
首先是不支援並行。這也很好理解,PostgreSQL 是從 9.6 開始支援並行了,而 openGauss 是基於 PostgreSQL9.4 的。目前 PostgreSQL 有強大的並行功能。目前不清楚 openGauss 什麼時候可以支援並行。
編譯過於複雜,依賴過多:編譯需要很多依賴,而且版本固定,造成跨平臺編譯的難度非常大,同時改成 C++,通用性差,你可能發現編譯華為的第三方編譯工具比編譯資料庫還麻煩。當然編譯資料庫方便是因為資料庫是從 PostgreSQL 中繼承過來的。
openGauss 把原生的 psql 命令改名為 gsql,gsql 需要加引數“-r”才能支援上下翻命令和自動補全。原先使用 oracle 時,oracle 的 sqlplus 就不支援這些功能被一堆人吐槽,後來用 rlwrap 勉強好一些了。當轉到 PostgreSQL 後,psql 的命令自動補全功能讓 DBA 幸福滿滿的。當初學者不知道“-r”引數時,一用 openGauss 又回到了 Oracle 的 sqlplus 時代。
openGauss 目前對外掛的支援不好,原生的 PostgreSQL 可以使用很多的外掛,也吸引了很多開發者開發外掛。而 openGauss 的“CREATE EXTENSION”還處於內部支援的階段。目前可以勉強支援 PostGIS。當然 openGauss 把一些常用的外掛內建在資料庫內部了,緩解了此問題。
openGauss 不支援表繼承,同時把原生 PostgreSQL 中的一些非常有用的工具都給去掉了,如 pg_waldump(或 pg_xlogdump)、pg_receivewal。
openGauss 相對於 PostgreSQL 資料庫來說臃腫一些,在 openGauss2.0 版本之前記憶體至少要 8GB,小了根本啟動不了,2.0 版本之後這一塊有比較大的改進,小記憶體也可以啟動了。原生 PostgreSQL 主程式小於 10MB,而 openGauss 則為 100MB:
[root@pg01 ~]# ls -l /usr/pgsql-12/bin/postgres
-rwxr-xr-x 1 root root 7731856 Aug 12 2020 /usr/pgsql-12/bin/postgres
[root@pg01 ~]#
[gauss@pgtrain bin]$ ls -l gaussdb
-rwxr-xr-x 1 gauss gauss 102432784 Jun 2 19:45 gaussdb
openGauss 比較大的問題是很多地方對 PostgreSQL 做了改動,感覺有些為了改動而改動,導致與很多 PostgreSQL 生態的軟體不能相容,這對於使用者是一個很大的問題。
當然最大的硬傷是文件不足。openGauss 對 PostgreSQL 做了很多的一些改變,卻沒有提供文件或提供的文件不全,openGauss 的官方文件基本是一個殘次品,如官方文件中居然沒有搭建備庫的說明,安裝手冊中提供的解除安裝方法是用 gs_uninstall 命令,但極簡版根本沒有 gs_uninstall 命令,實際上極簡版很多命令都沒有,文件中對此無任何提示,這一點很讓人無語。所以 openGauss 的文件比較原生的 PostgreSQL 基本是一個天上一個地上,比一些其它的著名開源軟體如 VUE、element-ui 的文件也根本沒法比,與 tidb 的文件相比也是差的非常遠。希望 openGauss 社群重視文件,讓文件的質量上一個臺階。