b412.png 金倉數據庫作為國產數據庫中非常重要的一員,其地位也非常的重要。尤其隨着開源運動的興起,KingbaseES在數據庫領域顯示出舉足輕重的地位。這也很好地促進了金倉數據庫的發展。

人大金倉數據庫管理系統KingbaseES(簡稱:金倉數據庫或KingbaseES)是北京人大金倉信息技術股份有限公司研製開發的具有自主知識產權的通用關係型數據庫管理系統。

金倉數據庫基於PostgreSQL開發構建,因此這裏可以拿PostgreSQL來比較學習它的體系結構,這樣比較容易理解,其主要結構如下圖所示。 image.png

金倉數據庫的體系架構中最重要的就是數據的存儲結構,而數據存儲結構分為邏輯存儲結構和物理存儲存儲。其中,邏輯存儲結構是數據庫內部的組織和管理數據的方式;而物理存儲結構是操作系統中組織和管理數據的方式。

image.png
點擊這裏查看視頻講解:【趙渝強老師】國產金倉數據庫的體系架構

一、 邏輯存儲結構

金倉數據庫的邏輯存儲結構主要是指數據庫中的各種數據庫對象,包括:數據庫集羣、數據庫、表、索引、視圖等等。所有數據庫對象都有各自的對象標識符oid(object identifiers),它是一個無符號的四字節整數,相關對象的oid都存放在相關的系統目錄表中,比如數據庫的oid和表的oid分別存放在sys_database,sys_class表中。下圖展示了KingBaseES數據庫的邏輯存儲結構。 image.png

二、 物理存儲結構

數據庫實例初始化的時候會創建一個目錄,通常都會在系統配置相關的環境變量$KINGBASEDATA來表示。當數據庫初始化完成後,會在這個目錄生成相關的子目錄以及一些文件。下圖就是金倉數據庫的物理結構: image.png

金倉數據庫的物理存儲結構主要是指硬盤上存儲的文件,包括:數據文件、日誌文件、參數文件、控制文件、WAL預寫日誌文件等等。下面分別進行介紹。

2.1 數據文件

顧名思義,數據文件用於存儲數據,文件名以oid命名。對於超出1G的數據文件,KingBaseES會自動將其拆分為多個文件來存儲,而拆分的文件名將由sys_class中的relfilenode字段來決定。通過下面的步驟可以確定表所對應的數據文件。 (1)查看數據庫的oid。

kingbase=# select oid,datname from sys_database;

# 輸出的信息如下:  
  oid  |  datname  
-------+-----------
 14791 | test
 14792 | kingbase
     1 | template1
 14790 | template0
 14793 | security
 16384 | scott
(6 行記錄)

# 14792 是數據庫kingbase的OID。

(2)查詢前面創建的testtable1表的OID。

kingbase=# select oid,relname,relkind,relfilenode from sys_class
           where relname ='testtable1';

# 輸出的信息如下:  
  oid  |  relname   | relkind | relfilenode 
-------+------------+---------+-------------
 16428 | testtable1 | r       |       16428
(1 行記錄)

# 16428 是表testtable1的OID。

(3)查看錶空間mydemotbs對應的目錄,如下圖所示。 image.png

image.png

2.2 日誌文件

金倉數據庫的日誌文分為運行日誌、WAL預寫日誌、事務日誌和服務器日誌。

運行日誌(sys_log)

在默認的情況下,運行日誌沒有開啓。通過查看主kingbase.conf文件的配置可以看到相關的參數設置,開啓後會自動生成該日誌文件。運行時日誌一般是記錄數據庫服務器與數據庫的狀態,比如各種錯誤信息、定位慢查詢SQL、數據庫的啓動關閉信息、發生檢查點過於頻繁等的告警信息等等。該日誌有.csv格式和.log格式,建議使用.csv格式。因為.csv格式一般會按大小和時間自動切割。sys_log是可以被清理刪除、壓縮打包或者轉移,同時不影響數據庫的正常運行。當有遇到數據庫無法啓動或者更改參數沒有生效時,第一步就可以查看運行時日誌。下圖展示了主參數文件kingbase.conf中關於運行日誌的配置參數。 image.png

WAL預寫日誌(sys_wal)

sys_wal 這個目錄是記錄的KingBaseES的WAL信息。WAL是Write Ahead Logging的縮寫,即預寫日誌,它是保證數據完整性的一種標準方法。簡單來説就是在KingBaseES數據庫中要對數據文件進行修改時必須先寫入WAL日誌信息,即當WAL日誌記錄完成了持久化,刷新到永久儲存之後才能更改數據文件。根據這個原則就不需要在每次提交事務的時候都刷新數據到磁盤。因為當數據庫出現宕機發生數據丟失時,可以重新執行WAL日誌來達到恢復數據庫的目的。因此WAL日誌也可以叫做redo重做日誌,因為任何沒有寫到數據文件上的改動都可以根據日誌記錄進行重做。在默認的情況下,單個WAL預寫日誌文件的大小是16M,通過參數wal_segment_size決定。

kingbase=# show wal_segment_size;

# 輸出的信息如下:
 wal_segment_size 
------------------
 16MB
(1 行記錄)

下圖説明了數據提交與WAL日誌寫入時的關係。 image.png

事務日誌(sys_xact)

sys_xact是事務提交日誌,記錄了事務的元數據。默認開啓。內容一般不能直接讀。默認存儲在目錄$KINGBASE_DATA/sys_xact/。

服務器日誌

如果用sys_ctl啓動的時候沒有指定-l參數來指定服務器日誌,錯誤可能會輸出到cmd前台。下圖展示了在啓動數據庫服務器時,使用“-l”參數生成的服務器日誌文件,它記錄了數據庫的重要信息。 image.png

logfile文件的內容如下:

2025-09-11 12:04:10.504 CST [13066] LOG:  sepapower擴展初始化完成
2025-09-11 12:04:10.521 CST [13066] LOG:  正在啓動 KingbaseES V009R001C010
2025-09-11 12:04:10.521 CST [13066] LOG:  正在監聽IPv4地址"0.0.0.0",端口 54321
2025-09-11 12:04:10.521 CST [13066] LOG:  正在監聽IPv6地址"::",端口 54321
2025-09-11 12:04:10.522 CST [13066] LOG:  在Unix套接字 "/tmp/.s.KINGBASE.54321"上偵聽
2025-09-11 12:04:10.773 CST [13066] LOG:  日誌輸出重定向到日誌收集進程
2025-09-11 12:04:10.773 CST [13066] HINT:  後續的日誌輸出將出現在目錄 "/home/kingbase/kdb/kes_oracle_instance/sys_log"中.

2.3 控制文件

控制文件記錄了數據庫運行時的一些信息,比如數據庫oid、是否是打開狀態、WAL的位置、檢查點的信息等等。金倉數據庫的控制文件是很重要的數據庫文件。控制文件默認保存在文件$ KINGBASE_DATA/global/sys_control,可以使用命令bin/sys_controldata查看控制文件的內容,具體的操作步驟如下: (1)進入金倉數據庫的Server目錄。

cd /home/kingbase/kdb/Server/

(2)執行命令查看控制文件的內容。

[kingbase@kingbase Server]$ bin/sys_controldata ~/kdb/kes_oracle_instance/

# 輸出的信息如下:
sys_control版本:                       1201
Catalog版本:                          202502271
數據庫系統標識符:                     7548668357165694582
數據庫簇狀態:                         在運行中
sys_control最後修改:                  2025年09月11日 星期四 12時04分10秒
最新檢查點位置:                       0/8000130
最新檢查點的REDO位置:                 0/8000130
最新檢查點的重做日誌文件:             000000010000000000000008
最近檢查點的WalTimeLineID:            1
最新檢查點的PrevTimeLineID:           1
最新檢查點的full_page_writes:         開啓
最新檢查點的NextXID:                  0:1117
最新檢查點的NextOID:                  16400
最新檢查點的NextMultiXactId:          1
最新檢查點的NextMultiOffsetD:         0
最新檢查點的oldestXID:                1064
最新檢查點的oldestXID所在的數據庫:   1
最新檢查點的oldestActiveXID:          0
最新檢查點的oldestMultiXid:           1
最新檢查點的oldestMulti所在的數據庫: 1
最新檢查點的oldestCommitTsXid:        0
最新檢查點的newestCommitTsXid:        0
最新檢查點的時間:                     2025年09月11日 星期四 12時04分05秒
不帶日誌的關係:                       0/3E8使用虛假的LSN計數器
最小恢復結束位置:                     0/0
最小恢復結束位置時間表:               0
開始進行備份的點位置:                 0/0
備份的最終位置:                       0/0
需要終止備份的記錄:                   否
wal_level設置:                       replica
wal_log_hints設置:                   關閉
max_connections設置:                 100
max_worker_processes設置:            30
max_wal_senders設置:                  10
max_prepared_xacts設置:              0
max_locks_per_xact設置:               64
track_commit_timestamp設置:           關閉
最大數據校準:                         8
數據庫塊大小:                         8192
大關係的每段塊數:                     131072
WAL的塊大小:                          8192
每一個WAL段字節數:                    16777216
標識符的最大長度:                     64
在索引中可允許使用最大的列數:         32
TOAST區塊的最大長度:                  1988
大對象區塊的大小:                     2048
日期/時間存儲類型:                    64位整數
正在傳遞Float4類型的參數:             由值
正在傳遞Float8類型的參數:             由值
數據頁校驗和版本:                     0
數據頁校驗和算法設備:                 0
當前身份驗證:                         cc0df2ed4d3a338f6ae2838c46cc123e2634be5
數據庫模式:                          1
身份驗證方法模式:                    0

2.4 參數文件

金倉數據庫的參數文件主要包括四個,它們分別是kingbase.conf、sys_hba.conf、sys_ident.conf和kingbase.auto.conf。下表對這四個參數文件的作用分別進行了介紹。 image.png

三、 進程結構

執行下面的命令列出所有的KingBaseES的進程。

[kingbase@kingbase ~]$ ps -ef | grep kingbase:

# 輸出的信息如下:
...... kingbase: kes_oracle_instance: logger   
...... kingbase: kes_oracle_instance: checkpointer   
...... kingbase: kes_oracle_instance: background writer   
...... kingbase: kes_oracle_instance: walwriter   
...... kingbase: kes_oracle_instance: autovacuum launcher   
...... kingbase: kes_oracle_instance: stats collector   
...... kingbase: kes_oracle_instance: kwr collector   
...... kingbase: kes_oracle_instance: ksh writer   
...... kingbase: kes_oracle_instance: ksh collector   
...... kingbase: kes_oracle_instance: logical replication launcher 

# 注意:該命令最後有一個冒號。

下面分別介紹各個進程的作用。

3.1、 總控制進程kingbase

進程kingbase是整個數據庫實例的總控制進程,負責啓動和關閉數據庫實例。用户可以運行kingbase命令,並加上合適的參數啓動數據庫。下面展示了該進程的相關信息:

kingbase   13066       1  0 13:21 ?        00:00:00 /home/kingbase/kdb/KESRealPro/V009R001C010/Server/bin/kingbase -D /home/kingbase/kdb/kes_oracle_instance

而更多時候使用sys_ctl啓動數據庫,sys_ctl也是通過運行kingbase命令來啓動數據庫實例,它只是做了一些包裝,讓用户更容易啓動數據庫,所以主進程kingbase實際是第一個金倉數據庫進程,此進程會fork一些與數據庫實例相關的輔助子進程,並管理他們。

當用户與KingBaseES數據庫建立連接時,實際上是先與kingbase進程建立連接。此時,客户端程序會發出身份證驗證的消息給kingbase進程,kingbase主進程根據消息中的信息進行客户端身份驗證。如果驗證通過,它會fork一個子進程kingbase為這個連接服務,fork出來的進程被稱為服務進程。

通過查詢sys_stat_activity表可以看到這些服務進程的pid,下面的步驟將要是如何查看服務進程。 (1)查詢sys_stat_activity表獲取服務進程的pid。

kingbase=# select pid,application_name from sys_stat_activity;

# 輸出的信息如下:
  pid  |  application_name   
-------+---------------------
 13073 | auto vacuum
 13077 | sys_ksh collector
 13078 | logical replication
 13076 | ksh writer
 13186 | ksql
 13071 | background flush
 13070 | check pointer
 13072 | wal flush
(8 行記錄)

(2)在操作系統上查看對應的進程信息。

[kingbase@kingbase Server]$ ps -ef|egrep \
"13073|13077|13078|13076|13186|13071|13070|13072"

# 輸出的信息如下:
kingbase 13070 13066 ... : checkpointer   
kingbase 13071 13066 ... : background writer   
kingbase 13072 13066 ... : walwriter   
kingbase 13073 13066 ... : autovacuum launcher   
kingbase 13076 13066 ... : ksh writer   
kingbase 13077 13066 ... : ksh collector   
kingbase 13078 13066 ... : logical replication launcher   
kingbase 13186 13066 ... : system kingbase [local] idle

3.2、 系統日誌進程SysLogger

在kingbase.conf裏啓用運行日誌後,會有SysLogger進程。SysLogger會在日誌文件達到指定的大小時關閉當前日誌文件,產生新的日誌文件。

image.png

3.3、 寫進程BgWriter

BgWriter是KingBaseES中在後台將髒頁寫出到磁盤的輔助進程,引入該進程主要為達到如下兩個目的:

  • 首先,數據庫在進行查詢處理時若發現要讀取的數據不在緩衝區中時要先從磁盤中讀入要讀取的數據所在的頁面,此時如果緩衝區已滿,則需要先選擇部分緩衝區中的頁面替換出去。如果被替換的頁面沒有被修改過,那麼可以直接丟棄;但如果要被替換的頁已被修改,則必需先將這頁寫出到磁盤中後才能替換,這樣數據庫的查詢處理就會被阻塞。通過使用BgWriter定期寫出緩衝區中的部分髒頁到磁盤中,為緩衝區騰出空間,就可以降低查詢處理被阻塞的可能性。
  • 其次,KingBaseES在定期作檢查點時需要把所有髒頁寫出到磁盤,通過BgWriter預先寫出一些髒頁,可以減少設置檢查點時要進行的I/O操作,使系統的I/O負載趨向平穩。通過BgWriter對共享緩衝區寫操作的統一管理,避免了其他服務進程在需要讀入新的頁面到共享緩衝區時,不得不將之前修改過的頁面寫出到磁盤的操作。

下面展示瞭如何在ksql命令行工具中查看與BgWriter後台寫進程相關的參數及其默認值。

--連續兩次寫數據之間的間隔時間
kingbase=# show bgwriter_delay;
 bgwriter_delay 
----------------
 200ms
(1 行記錄)

--每次寫的最大數據量,默認值是100
kingbase=# show bgwriter_lru_maxpages;
 bgwriter_lru_maxpages 
-----------------------
 100
(1 行記錄)

--每次寫入磁盤的數據塊數
kingbase=# show bgwriter_lru_multiplier;
 bgwriter_lru_multiplier 
-------------------------
 2
(1 行記錄)

--當數據頁大小達到bgwriter_flush_after時觸發BgWriter,默認值為512KB
kingbase=# show bgwriter_flush_after;
 bgwriter_flush_after 
----------------------
 512kB
(1 行記錄)

3.4、 預寫日誌進程WalWriter

該進程用於保存WAL預寫日誌掃WAL預寫日誌文件。預寫日誌WAL的中心思想是對數據文件的修改必須是隻能發生在這些修改已經記錄到日誌之後,也就是先寫日誌後寫數據。如果遵循這個過程,那麼就不需要在每次事務提交的時候都把數據塊刷回到磁盤,這一點與Oracle數據庫是完全一致的。kingbase.conf文件中與WalWriter進程相關的參數如下:

#------------------------------------------------------------------------------
# WRITE-AHEAD LOG
#------------------------------------------------------------------------------

# - Settings -

#wal_level = replica			# minimal, replica, or logical
					# (change requires restart)
#fsync = on				# flush data to disk for crash safety
					# (turning this off can cause
					# unrecoverable data corruption)
#synchronous_commit = on		# synchronization level;
					# off, local, remote_write, remote_apply, or on
#wal_sync_method = fsync		# the default is the first option
					# supported by the operating system:
					#   open_datasync
					#   fdatasync (default on Linux)
					#   fsync
					#   fsync_writethrough
					#   open_sync
#full_page_writes = on			# recover from partial page writes
#wal_compression = off			# enables compression of full-page writes;
					# off, kblz, lz4, zstd, or on
#wal_log_hints = off			# also do full page writes of non-critical updates
					# (change requires restart)
#wal_init_zero = on			# zero-fill new WAL files
#wal_recycle = on			# recycle WAL files
#wal_buffers = -1			# min 32kB, -1 sets based on shared_buffers
					# (change requires restart)
#wal_writer_delay = 200ms		# 1-10000 milliseconds
#wal_writer_flush_after = 1MB		# measured in pages, 0 disables

#commit_delay = 0			# range 0-100000, in microseconds
#commit_siblings = 5			# range 1-1000

3.5、 歸檔進程Archive Process

金倉數據庫支持PITR(Point-In-Time-Recovery,基於時間點的恢復)技術,該技術支持將數據庫恢復到其運行歷史中任意一個有記錄的時間點。PITR的另一個重要的基礎就是對WAL文件的歸檔功能。歸檔進程的目標就是對WAL日誌在磁盤上的存儲形式進行歸檔備份。但在默認情況下,金倉數據庫是非歸檔模式,因此看不到歸檔進程。歸檔進程通過kingbase.conf文件中的如下參數進行配置:

# - Archiving -

archive_mode = off		# enables archiving; off, on, or always
				# (change requires restart)
archive_command = 'exit 0'	# command to use to archive a logfile segment
				# placeholders: %p = path of file to archive
				#               %f = file name only
				# e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
#archive_timeout = 0		# force a logfile segment switch after this
				# number of seconds; 0 disables

3.6、 自動清理進程AutoVacuum

在金倉數據庫數據庫中,對數據進行UPDATE或者DELETE操作後,數據庫不會立即刪除舊版本的數據,而是標記為刪除狀態。這是因為金倉數據庫數據庫具有多版本的機制,如果這些舊版本的數據正在被另外的事務打開,那麼暫時保留這些舊版本數據是很有必要的。而當事務提交後,舊版本的數據已經沒有價值了,數據庫需要清理垃圾數據騰出空間,而清理工作就是AutoVacuum進程進行的。kingbase.conf文件中與AutoVacuum進程相關的參數如下所示。

#------------------------------------------------------------------------------
# AUTOVACUUM
#------------------------------------------------------------------------------

#autovacuum = on			# Enable autovacuum subprocess?  'on'
					# requires track_counts to also be on.
#log_autovacuum_min_duration = -1	# -1 disables, 0 logs all actions and
					# their durations, > 0 logs only
					# actions running at least this number
					# of milliseconds.
#autovacuum_max_workers = 3		# max number of autovacuum subprocesses
					# (change requires restart)
#autovacuum_naptime = 1min		# time between autovacuum runs
#autovacuum_vacuum_threshold = 50	# min number of row updates before
					# vacuum
#autovacuum_analyze_threshold = 50	# min number of row updates before
					# analyze
#autovacuum_vacuum_scale_factor = 0.2	# fraction of table size before vacuum
#autovacuum_analyze_scale_factor = 0.1	# fraction of table size before analyze
#autovacuum_freeze_max_age = 200000000	# maximum XID age before forced vacuum
					# (change requires restart)
#autovacuum_multixact_freeze_max_age = 400000000	# maximum multixact age
					# before forced vacuum
					# (change requires restart)
#autovacuum_vacuum_cost_delay = 2ms	# default vacuum cost delay for
					# autovacuum, in milliseconds;
					# -1 means use vacuum_cost_delay
#autovacuum_vacuum_cost_limit = -1	# default vacuum cost limit for
					# autovacuum, -1 means use
					# vacuum_cost_limit			

3.7、 統計信息收集進程:stats collector process

統計信息收集進程是金倉數據庫的統計信息收集器,用來收集數據庫運行期間的統計信息,如表的增刪改次數、數據塊的個數、索引的變化等等。收集統計信息主要是為了讓優化器做出正確的判斷,選擇最佳的執行計劃。Kingbase.conf文件中與統計信息收集進程相關的參數,如下:

#-----------------------------------------------------------------
# STATISTICS
#-----------------------------------------------------------------
# - Query and Index Statistics Collector -

#track_instance = off
#track_sql = off
#track_wait_timing = on
#track_activities = on
#track_counts = on
#track_io_timing = off
#track_functions = none			# none, pl, all
#track_activity_query_size = 1024	# (change requires restart)
#stats_temp_directory = 'sys_stat_tmp'

3.8、 檢查點進程CheckPoint

檢查點是系統設置的事務序列點,設置檢查點保證檢查點前的日誌信息已經成功寫入到磁盤中。kingbase.conf文件中與之相關的參數有:

#checkpoint_timeout = 5min		# range 30s-1d
max_wal_size = 1GB
min_wal_size = 80MB
#checkpoint_completion_target = 0.5	# checkpoint target duration, 0.0 - 1.0
#checkpoint_flush_after = 0		# measured in pages, 0 disables
#checkpoint_warning = 30s		# 0 disables

四、 內存結構

金倉數據庫的內存結構分為兩種不同的類型,它們分別是本地內存和共享內存。它們的關係如下圖所示: image.png

4.1、本地內存

金倉數據庫的本地內存是指每個後台進程(backend process)自己使用的內存區域,下表列舉了KingBaseES中的本地內存以及它們的作用。 image.png

image.png

4.2、共享內存

金倉數據庫的共享內存是指每個後台進程(backend process)共同使用的內存區域,下表列舉了KingBaseES中的共享內存以及它們的作用。 image.png