目錄
一、KingbaseES資料庫簡介:
資料庫包括兩層概念:
資料庫管理系統:
關系型資料庫:
二、KingbaseES總體結構:
邏輯功能架構:
架構基礎:
三、資料訪問:
SQL:
PL/SQL:
四、存盤結構:
物理存盤結構:
物理存盤結構簡介:
資料檔案:
控制檔案:
日志檔案:
WAL日志:
邏輯存盤結構:
邏輯存盤結構概述:
表空間:
資料檔案(磁盤管理):
Page/Block(頁)
Extent(區)
Global Allocation Map(簡稱GAM)
Page Free Space(簡稱PFS)
段(表、索引):
Index Allocation Map(簡稱IAM)
sys_class.relfilenode
五、事務:
資料庫事務:
事務的特性:
原子性(Atomicity):
一致性(Consistency):
隔離性(Isolation):
持久性(Durability):
資料庫對事務的管理:
資料的一致性和并發控制
事務的隔離級別:
讀已提交 (Read committed)
可串行化 (Serializable)
并發控制的實作
多版本并發控制
六、實體體系結構:
實體結構
資料庫檔案
KingbaseES 實體
后臺行程
服務行程
記憶體管理
資料頁面快取
日志頁面快取
鎖快取
臨時分配的記憶體
七、后臺作業行程:
一、KingbaseES資料庫簡介:
資料庫包括兩層概念:
- 資料庫是一個物體,它是能夠合理的保管資料的“倉庫”,用戶在倉庫中存放需要進行管理的事務資料,"資料"和"庫"兩個概念結合成為資料庫,
- 資料庫是資料管理的一種方法和技術,它能更合適地組織資料、更方便地維護資料、更嚴格的控制資料和更有效的利用資料,
資料庫管理系統:
資料庫管理系統是一種操縱和管理資料庫的大型軟體,用于建立、使用和維護資料庫,簡稱DBMS,它對資料庫進行統一的管理和控制,以保證資料庫的安全性和完整性,
關系型資料庫:
關系型資料庫將復雜的資料結構歸結為簡單的二元關系(即二維表格形式),在關系型資料庫中,對資料的操作幾乎全部建立在一個或者多個關系表格上,通過這些關聯的表格分類、合并、連接或選取等運算實作資料的管理,KingbaseES屬于典型的商用關系型資料庫管理系統,
關系型資料庫特點:
關系型資料庫在存盤資料時實際上是采用一張二維表(類似Word及Excel中表格), 通過SQL結構化查詢語言來存取、管理關系型資料庫的資料, 關系型資料庫在保持資料安全和資料一致性方面很強,遵循ACID理論,
二、KingbaseES總體結構:
金倉資料庫KingbaseES V8R3 的技術架構如下圖所示:

- 存盤管理層:主要實作資料存盤管理、資料復制、資料完整性保護、封鎖、并發控制、事務管理、快取管理、日志空間管理等;
- SQL處理層:主要負責SQL介面底層(函式、索引、資料字典、存盤程序、觸發器)的實作、決議、優化、執行和快取處理等
- 傳輸層:主要實作基于SSL的可信傳輸,
SSL(Secure Sockets Layer 安全套接字協議),及其繼任者傳輸層安全(Transport Layer Security,TLS)是為網路通信提供安全及資料完整性的一種安全協議,TLS與SSL在傳輸層與應用層之間對網路連接進行加密,
- 介面層:提供各種常見資料庫訪問介面:(ODBC/JDBC/ESQL/PERL/PHP/MYBATIS/HIBERNATE/.NET/EF6)及其驅動程式實作
- 工具層:提供給管理員大量便捷高效的資料庫管理工具和開發工具,
KingbaseES 的安全防護手段和策略貫穿以上各個層次,提供特權分立、訪問控制、存盤加密等多種安全組件和功能,為資料庫管理系統提供內核級的層層安全防護,
邏輯功能架構:

架構基礎:
在資料庫術語里,KingbaseES使用客戶端/服務器的模型,一次KingbaseES會話由下列相關的行程組成:
- 服務器行程:
管理資料庫檔案、接受來自客戶端應用與資料庫的連接并代表客戶端在資料庫上執行操作,
- 客戶端行程:
客戶端應用本身是多種多樣的:可以是一個面向文本的工具,也可以是一個圖形界面的應用,或是一個通過訪問資料庫來顯示網頁的網頁服務器,或是一個特制的資料庫管理工具,
與典型的客戶端/服務器應用(C/S應用)一樣,這些客戶端和服務器可以運行在不同的主機上,它們通過TCP/IP網路連接通訊,
KingbaseES服務器可以處理來自客戶端的多個并發請求,因此,它為每個連接啟動一個新的行程,從此時開始,客戶端和新服務器行程就不再經過最初的kingbase行程的干涉進行通訊,因此,主服務器行程總是在運行并等待著客戶端聯接,而客戶端和相關聯的服務器行程則是起起停停,
三、資料訪問:
SQL:
SQL語言是一種非程序化的資料庫命令語言,它能使用戶方便地操縱關系資料庫,目前絕大多數的關系資料庫系統都支持它,
作為關系資料庫的通用語言,結構化查詢語言SQL是操控資料庫的基礎,幾乎所有常見關系資料庫管理系統都支持結構化查詢語言SQL,用戶需要使用SQL陳述句來訪問資料庫中的資料并完成資料庫各項操作,
PL/SQL:
PL/SQL是一種用于KingbaseES資料庫系統的可載入的程序語言,能夠使得結構化查詢語言SQL更加易用,此外,所有用SQL陳述句撰寫的程式都是可移植的,這些程式通常僅需通過很少的修改,便可從一個資料庫移植到另一個資料庫,
KingbaseES資料庫系統提供PL/SQL語言,這種程序化的語言允許用戶創建存盤程序、用戶自定義函式、觸發器,
這些程序或用戶自定義函式有輸入、輸出引數和回傳值,我們統一把使用PL/SQL語言創建的存盤程序、用戶自定義函式以及觸發器統一稱為“存盤模塊”,存盤模塊與表和視圖等資料庫物件一樣被存盤在資料庫中,供用戶隨時呼叫,在功能上,相當于客戶端的一段SQL批處理程式,它為用戶提供了一種高效率的編程手段,成為現代資料庫系統的重要特征,
四、存盤結構:
KingbaseES的資料存盤管理主要完成資料檔案空間分配回收、組織和管理等功能,這些管理,是按頁面為單位進行的,
在KingbaseES資料庫中,資料檔案被組織成一個個頁面(Page),頁面大小為8k,對資料檔案的I/O操作都是以頁面為單位,
物理存盤結構:
物理存盤結構簡介:
KingbaseES資料庫初始化程序會創建一個資料庫實體,KingbaseES創建資料庫實體時會自動創建資料庫:SAMPLES、SECURITY和TEST,每個資料庫中可以包含多個資料庫物件,如表、索引、序列等,

KingbaseES資料庫實體管理的所有資料在物理上都以作業系統檔案的方式存放在磁盤上,
物理資料庫結構可以在作業系統級別上查看,
RDBMS的一個特點是邏輯資料結構(如表、視圖和索引)獨立于物理存盤結構,
關系資料庫管理系統(Relational Database Management System:RDBMS)是指包括相互聯系的邏輯組織和存取這些資料的一套程式 (資料庫管理系統軟體),關系資料庫管理系統就是管理關系資料庫,并將資料邏輯組織的系統,
因為物理和邏輯結構是分開的,所以可以在不影響對邏輯結構訪問的情況下管理資料的物理存盤,例如,重命名資料庫檔案不會重命名存盤在其中的表,一般而言,資料庫集簇所使用的配置和資料檔案都被一起存盤在集簇的資料目錄里,常用的目錄名為data,由不同資料庫實體所管理的多個集簇可以在同一臺機器上共存,
data目錄包含幾個子目錄以及一些控制檔案,如表"data目錄下的內容"所示,除了這些必要的東西之外,kingbase.conf、sys_hba.conf和sys_ident.conf通常都存盤在data中,但也可以將其存放在地方,
data目錄:

| 檔案名 | 描述 |
| SYS_VERSION | 一個包含KingbaseES主版本號的檔案 |
| base | 包含每個資料庫對應的子目錄的子目錄 |
| global | 包含集簇范圍的表的子目錄,比如sys_database |
| sys_commit_ts | 包含事務提交時間戳資料的子目錄 |
| sys_clog | 包含事務提交狀態資料的子目錄 |
| sys_dynshmem | 包含被動態共享記憶體子系統所使用的檔案的子目錄 |
| sys_logical | 包含用于邏輯復制的狀態資料的子目錄 |
| sys_multixact | 包含多事務(multi-t ransaction)狀態資料的子目錄(用于共享的行鎖) |
| sys_notify | 包含LISTEN/NOTIFY狀態資料的子目錄 |
| sys_replslot | 包含復制槽資料的子目錄 |
| sys_serial | 包含已提交的可序列化事務資訊的子目錄 |
| sys_snapshots | 包含匯出的快照的子目錄 |
| sys_stat | 包含用于統計子系統的永久檔案的子目錄 |
| sys_stat_tmp | 包含用于統計資訊子系統的臨時檔案的子目錄 |
| sys_subtrans | 包含子事務狀態資料的子目錄 |
| sys_tblspc | 包含指向表空間的符號鏈接的子目錄 |
| sys_twophase | 包含用于預備事務狀態檔案的子目錄 |
| sys_xlog | 包含 WAL (預寫日志)檔案的子目錄 |
| kingbase.auto.conf | 一個用于存盤由ALTER SYSTEM 設定的配置引數的檔案 |
| kingbase.opts | 一個 記錄服務器最后一次啟動時使用的命令列引數的檔案 |
| postmaster.pid | 一個鎖檔案,記錄著當前的 kingbase 行程ID(PID)、集簇資料目錄路 徑、kingbase啟動時間戳、埠號、Unix域套接字目 錄路徑(Windows上為空)、第一個可用的listen_a ddress(IP地址或者*,或者為空表示不在TCP上監聽 )以及共享記憶體段ID(服務器關閉后該檔案不存在) |
資料檔案:
資料檔案包含資料和物件,例如表、索引、存盤程序和視圖,
控制檔案:
KingbaseES主服務器的配置主要通過修改組態檔kingbase.conf完成,組態檔sys_hba.conf和sys_ident.conf主要用于控制客戶端認證,
日志檔案:
日志檔案記錄資料庫的操作資訊,包含恢復資料庫中的所有事務所需的資訊,
WAL日志:
預寫式日志(Write-Ahead Logging(WAL))是保證資料完整性、實作事務日志的一種標準方法,WAL的中心思想是對資料檔案的修改(它們是表和索引的載體)當且僅當只能發生在這些修改已經被記錄在日志中之后,即在描述這些變化的日志被刷到持久存盤以后,如果遵循這種程序,將不需要在每個事務提交時刷寫資料頁面到磁盤,因為知道在發生崩潰時可以使用日志來恢復資料庫:任何還沒有被應用到資料頁面的改變可以根據其日志記錄重做
WAL的優點:
使用WAL顯著減少了磁盤寫的次數,因為只有日志檔案需要被刷出到磁盤以保證事務被提交,而被事務改變的每一個資料檔案不必被刷出,日志檔案被按照順序寫入,因此同步日志的代價要遠小于刷寫資料頁面的代價,在處理很多影響資料存盤不同部分的小事務的服務器上這一點尤其明顯,
使用WAL能夠保證資料頁的完整性,
提供資料庫在線備份和恢復的可能,通過歸檔的WAL檔案,可以支持恢復到手頭的WAL檔案包含的任意時刻:只需要簡單地安裝以前的資料庫的物理備份,然后重放WAl到自己希望的時間,另外,物理備份還不必是資料庫狀態的一個即時快照--如果它是花了一段時間制作的話,因為WAL日志的重放將修復任何內部的不一致,
WAL配置:
在KingbaseES中,主要通過設定kingbase.conf檔案中相關引數來配置WAL,部分WAL相關的引數還會影響資料庫的性能,參考服務器配置可獲取有關服務器配置的一般資訊,
邏輯存盤結構:
邏輯存盤結構概述:
KingbaseES資料庫為資料庫中的所有物件分配邏輯空間,并存放在資料檔案中,在KingbaseES資料庫內部,所有的資料檔案組合在一起被劃分到一個或者多個表空間中,所有的資料庫內部物件都存放在這些表空間中,同時,表空間被進一步劃分為段、簇和頁(也稱塊),通過這種細分,可以使得KingbaseES資料庫能夠更加高效地控制磁盤空間的利用率,
表空間是資料庫的邏輯劃分,一個表空間只能屬于一個資料庫,所有的資料庫物件都存放在指定的表空間中,但主要存放的是表,所以稱作表空間,
用戶可以通過“CREATE TABLESPACE”陳述句來創建自己的表空間,對已經存在的表空間,用戶可以通過“DROP TABLESPACE”陳述句來將其洗掉,
表空間:
表空間允許在檔案系統里定義那些代表資料庫物件的檔案存放的位置, 一旦創建了表空間,那么就可以在創建資料庫物件的時候參考它,一個資料庫可以有一個或多個表空間,創建資料庫時自動創建系統表空間,并為預設的默認表空間,一個表空間只隸屬于一個資料庫,只有在創建了資料庫之后才能創建屬于它的表空間,
隸屬于一個資料庫的表空間用于存盤該資料庫的資料庫物件,在創建資料庫物件時可以使用TABLESPACE子句指明該物件所使用的表空間;沒有給出 TABLESPACE 子句,則這些物件使用預設表空間,
KingbaseES中的表空間允許資料庫管理員在檔案系統中定義用來存放表示資料庫物件的檔案的位置,一旦被創建,表空間就可以在創建資料庫物件時通過名稱參考,
通過使用表空間,管理員可以控制一個KingbaseES安裝的磁盤布局,這么做至少有兩個用處,首先,如果初始化集簇所在的磁區或者卷用光了空間,而又不能在邏輯上擴展或者做別的什么操作,那么表空間可以被創建在一個不同的磁區上,直到系統可以被重新配置,
其次,表空間允許管理員根據資料庫物件的使用模式來優化性能,例如,一個很頻繁使用的索引可以被放在非常快并且非常可靠的磁盤上,如一種非常貴的固態設備,同時,一個很少使用的或者對性能要求不高的存盤歸檔資料的表可以存盤在一個便宜但比較慢的磁盤系統上,
資料檔案(磁盤管理):

Page/Block(頁)
將資料檔案中的空間從邏輯上劃分成一個個頁面(資料塊),頁面是資料庫I/O的基本單位,即只能整頁讀寫資料檔案,頁面的大小默認是8K,
Extent(區)
把資料檔案中8個連續的Page構成的空間稱為一個Extent,Extent是資料庫進行資料檔案空間分配/釋放的基本單位,每個表、索引、序列物件都是由若干個區組成,
Global Allocation Map(簡稱GAM)
負責記錄其所在資料檔案的Extent的分配情況,GAM頁中除GAM頭外,剩下空間的每一位(bit)均對應一個Extent的分配情況,若某bit位為1,則表明該bit位所關聯的Extent已被分配,反之未被分配,一個8K大小的GAM頁面所能覆寫的檔案范圍是:(8*1024-64)*(8*8K),約4GB空間,我們約定第一個GAM頁出現在檔案的第3個頁面位置(即:第2個索引位置),因此,第N個GAM頁的出現位置是:8*8128*8*N+2
Page Free Space(簡稱PFS)
用于記錄本資料檔案中頁面的空間使用情況,對檔案中的每個頁面,PFS中都有一個位元組與之對應,該位元組記錄了該頁面的狀態,每個頁面可能有三種狀態:PFS_FREE:該頁面已被物理分配,但尚未分配給任何物件或控制頁PFS_DATA:該物件被分配作為資料頁使用; PFS_CTRL:該物件被分配作為控制頁使用,與GAM頁類似,PFS頁前64bytes被預留位頁頭,剩下8*1024-64=8128一共覆寫8128*8K=64MB空間,故PFS頁每隔8128個頁面出現一次,系統初始化把第一個PFS頁放在資料檔案的第二個頁面位置,即:第1號資料頁面,由此可知,第N個PFS頁的位置在8128*N+1,
段(表、索引):

Index Allocation Map(簡稱IAM)
負責記錄分配給其的Extent情況,每個IAM頁只隸屬于一個資料庫物件(例如:表),但一個資料庫物件可包含多個IAM頁,由此可見IAM頁與資料庫物件的關系是1對1,而資料庫物件與IAM頁的關系是1對多.IAM的結構與GAM頁類似,除IAM頭外,剩下空間的每一位(bit)均對應著一個與IAM相關的Extent,若某bit位為1,則表明該bit位所關聯的Extent已被分配給該IAM,反之未被分配,若一個IAM頁面大小為8K,則除IAM頭(64 bytes)外,一個IAM頁面所能覆寫的檔案范圍是:(8*1024-64)*(8*8K),約4GB空間,但與GAM也不同之處在于:IAM的出現位置不固定,只在在創建資料庫物件的時候才分配
sys_class.relfilenode
負責記錄隸屬于該表/索引的第一個IAM頁的地址,從而可以找出隸屬于該表/索引的所有頁面
五、事務:
資料庫事務:
資料庫中的事務一個獨立的邏輯單元,一個或多個 SQL陳述句的集合,資料庫作業的基本單位是事務,事務是不能被拆分的,一個事務執行的結果只可能有兩個:事務內的陳述句都成功執行,事務執行成功,即事務提交;或事務執行失敗,本事務不對資料造成任何影響,即事務回滾,為了更形象的描述事務,舉一個簡單的例子:銀行資料庫如何處理客戶轉賬,一個客戶有這樣的要求:把一筆錢從 A 帳戶轉到 B 帳戶,這個要求可以拆分為三個獨立的部分:
-
帳戶A劃走這筆錢
-
帳戶B增加這筆錢
-
記錄這筆交易
整個交易程序資料庫確保最終達到如下兩種狀態中的一個:
-
三條陳述句都成功執行,達到轉賬目的并且做交易記錄, 整個事務提交,資料應用到資料庫,
-
其中一條陳述句執行程序發生錯誤,比如 A 帳戶資金不足,B帳戶不存在,或者在整個交易程序中發生硬體故障,資料庫停機, 整個事務回滾,執行成功的陳述句被撤銷,執行失敗的陳述句不對資料造成影響,還未執行的陳述句不再執行,資料回滾到此事務未開始的狀態, 無論什么原因,整個業務邏輯不允許出現諸如帳戶 A 上的錢被劃走,而卻沒有到達帳戶B,或者這個交易沒有被記錄這樣的中間結果,整個交易必須是原子性的,要么整個操作成功,要么整個操作失敗,資料庫的事務概念正是吻合了此要求,
一條 SQL 陳述句成功執行標志著:
-
SQL陳述句被決議,語法正確,
-
SQL陳述句是有效的,語意正確,
-
一些資料可能被更改,但是這些更改不是永久性的,在此陳述句所在事務提交前,資料的更改并沒有在整個資料庫生效,
對于事務的執行結果,只能有提交和回滾,
-
提交操作意味著:事務內的陳述句對資料的改變被資料庫接受,這將造成資料對于整個資料庫發生永久性的改變,
-
回滾操作意味著:這個事務內所有對資料造成的更改全部被撤銷,
一條 SQL 陳述句執行失敗會回滾整個事務,
事務的特性:
為了保證資料庫中的資料一致性,確保KingbaseES 能夠在并發訪問和系統發生故障時對資料進行維護,事務作為資料庫作業的基本單位,具有下列四個特性,稱為事務的 ACID 特性,
原子性(Atomicity):
一個事務對資料庫的所有操作,是一個不可分割的作業單元,這些操作要么全部執行,要么什么也不做,
一致性(Consistency):
一個事務獨立執行的結果應保持資料庫的一致性,即資料不會因為事務的執行而遭受破壞,例如事務的概念里銀行轉賬的例子,保證了資料的一致性,
隔離性(Isolation):
在多個事務并發執行時,系統應保證與這些事務先后單獨執行時的結果一樣,此時稱事務達到了隔離性的要求,也就是在多個并發事務執行時,保證執行結果是正確的,如同單用戶環境一樣,隔離性是由KingbaseES 的并發控制子系統實作的,
持久性(Durability):
一個事務一旦完成全部操作后,它對資料庫的所有更新應永久地反映在資料庫中,即使以后系統發生故障,也應保留這個事務執行的痕跡,事務的持久性由 KingbaseES 的恢復管理子系統實作,
事務是恢復和并發控制的基本單位,KingbaseES 能夠保證事務的 ACID 特性不被破壞,分為以下幾種情況:
-
多個事務并發運行時,不同事務的操作交叉執行,KingbaseES保證多個事務的交叉運行不影響這些事務的原子性,
-
事務在運行程序中被強行終止,KingbaseES保證被強行終止的事務對資料庫和其他事務沒有任何影響,
資料庫對事務的管理:
對于事務的管理,KingbaseES 支持事務的隱式和顯式提交,即自動提交和非自動提交,
自動提交事務
默認一個 SQL 陳述句為一個事務,當此陳述句執行成功后,由系統隱式提交,資料更改被資料庫接受,當 SQL 執行失敗,自然視做回滾,不對資料造成影響, KingbaseES 默認提交事務方式為自動提交,
非自動提交事務
事務的開始為第一個 SQL 陳述句,事務的結束必須用戶顯式的使用 COMMIT 陳述句提交整個事務或者使用 ROLLBACK 陳述句回滾整個事務,如果客戶端連接斷開,那么未提交的事務做回滾操作, 當用戶想自己控制事務的執行,可以顯式的用 BEGIN 陳述句開始一個事務,然后在事務結束時應該使用 COMMIT 或 ROLLBACK 陳述句顯式提交,
介面中也有對事務提交方式的控制,配置相應的組態檔可以使會話處于自動提交或非自動提交模式,
一個事務的提交和回滾對資料庫實體造成的影響為:
一個事務提交對資料庫實體造成如下影響:
所有資料庫更改對整個資料庫生效,
保證此事務產生的日志寫到磁盤,
釋放所有此事務進行程序中申請的鎖,
資料庫標記此事務結束,
一個事務回滾對資料庫實體造成如下影響:
撤銷所有對資料的更改到此事務開始之前的狀態,
釋放所有此事務進行程序中申請的鎖,
資料庫標記此事務結束,
資料的一致性和并發控制
在實際應用中資料庫資源對用戶是共享的,不同的用戶在不同或相同的時刻使用資料庫,這就是資料庫的并發操作,在多用戶資料庫環境中,并發操作提高了資料庫資源的使用效率,但若對這種并發操作不加限制就會破壞資料的完整性和一致性問題,
由于資料庫作業的基本單位是事務,針對事務并發操作中的各類問題,SQL 標準提出了事務的隔離級別概念,
事務的隔離級別:
并發操作雖然可以改善系統的資源利用率和短事務的回應時間,但是在運行中必須對并發事務加以控制,否則會引發一些問題,SQL92 標準對這些情況進行了分類,以及提出了解決辦法,
由于一個事務可能包含多個 SQL 陳述句,SQL 陳述句是順序執行的,T1 和 T2 兩個事務在一個資料庫上并發執行,可能有如下型別的問題:
讀“臟”資料(Dirty Read)
事務 T1 更新了一個資料,并且在 T1 提交或者回滾前,另外一個事務T2讀取了那個資料,如果 T1 這個時候回滾,那么T2就讀取了一個未提交的虛假的值,即“臟”資料,
不可重復讀(Non-Repeatable 或 Fuzzy Read)
事務 T1 讀取了一個資料,這個時候另外一個事務 T2 修改或者洗掉了這個資料并且提交了,如果 T1 嘗試再讀取一次這個資料,就會發現再次讀到的資料與之前不一致或不存在,
幻象讀(Phantom Read)
事務 T1 讀取了若干個滿足某個查詢條件的資料,這個時候事務 T2 創建了一個資料恰好也滿足 T1 的這個查詢條件,如果這個時候 T1 再次根據這個查詢條件進行讀取,它會發現會多出了部分資料,
很顯然,高并發度帶來了資料的不一致,這些情況一些是用戶不愿意見到,一些則是無法接受的,用戶需要在高并發帶來的高性能和資料的一致性之間做取舍,SQL92 標準提出了事務隔離級別,來解決上面的問題,
| 隔離級別 | 讀臟資料 | 不可重復讀 | 讀幻象資料 |
|---|---|---|---|
| 讀未提交(Read uncommitted) | 可能 | 可能 | 可能 |
| 讀已提交(Read committed) | 不可能 | 可能 | 可能 |
| 可重復的讀(Repeatable read) | 不可能 | 不可能 | 可能 |
| 可串行化(Serializable) | 不可能 | 不可能 | 不可能 |
四個隔離級別從上到下對事務執行的并發程度進行了不同程度的限制,更加嚴格的限制在帶來更好的資料一致性的同時,也會損失更多并發帶來的高性能,
實際使用中,隔離級別并不是越高就越好,大多數情況下應用并不需要很高的資料一致性,相反的,在多用戶環境下,更強調的是并發度,所以綜合考慮選取一個折中的辦法往往能達到最優的效果,
KingbaseES向用戶提供兩種隔離級別:讀已提交(Read committed)和可串行化(Serializable),這一點與 Oracle 一致,
讀已提交 (Read committed)
READ COMMITTED 是 KingbaseES 默認的事務隔離級別,在運行在該隔離級別的事務中,查詢陳述句只能看到該查詢開始執行之前提交的資料,而不會看到任何未提交的資料或查詢執行期間并發的其它事務提交的資料,但是該查詢可以看到本事務中查詢之前執行的資料更新, 在 READ COMMITTED 隔離級別下,對于事務 T1 中的更新和洗掉陳述句,與查詢陳述句相同,只能看到陳述句開始執行時提交的資料行,但是,這些資料行可能已經被同時并發的另一個事務 B 更新,在這種情況下,事務 T1 將等待事務 T2 回滾或提交,如果事務 T2 回滾,則事務 T1 在原來的資料上繼續更新,如果事務 T2 提交了,將分兩種情況,1):如果事務 T2 洗掉了該行,則事務 T1 忽略該行,2):如果事務 T2 對該行進行了更新,則事務 T1 判斷該行的新值是否還滿足條件,如果滿足條件,則事務 T1 在新資料行上進行更新,如果不滿足條件,則忽略該行, 在 READ COMMITTED 隔離級別下,同一個事務的不同查詢看到的可能是不同的資料,因此會出現不可重復讀的問題,這種隔離級別對于大多數的應用已經能夠滿足要求,但有些應用需要提供更加嚴格的資料一致性, 為了避免同樣的查詢得到不同的結果,在 READ COMMITTED 隔離級別下,應用程式在同一事務內應該盡量避免重復的查詢,
可串行化 (Serializable)
SERIALIZABLE 提供了更加嚴格的事務隔離級別,在該事務隔離級別下,事務并發執行,其結果與某個串行執行順序的結果完全相同, 在運行在 SERIALIZABLE 隔離級別的事務中,查詢陳述句只能看到該事務開始執行之前已經提交的資料,而不會看到任何未提交的資料或事務執行期間,并發的其它事務提交的資料,但是該查詢可以看到本事務中查詢之前執行的資料更新, 在 SERIALIZABLE 隔離級別下,對于事務 T1 中更新和洗掉陳述句,與查詢陳述句相同,只能看到事務開始執行時提交的資料行,但是,這些資料行可能已經被同時并發的另一個事務 T2 更新(事務 T2 開始的時間在事務 T1 前),在這種情況下,事務 T1 將等待事務 T2 回滾或提交,如果事務 T2 回滾,則事務 T1 在原來的資料上繼續更新,如果事務 T2 提交了,則事務 T1 就會出錯回滾,因為一個串行事務不能修改在該事務開始后被其它事務修改的資料, SERIALIZABLE 隔離級別可以確保每個事務看到一個完全一致的資料,但是當出現并發更新時,后更新的事務必須回滾,只能在之前的更新提交后再重新執行, 在 SERIALIZABLE 隔離級別下,應用程式如果碰到更新陳述句回滾,應該重執行更新陳述句所在的整個事務,
有關事務隔離級別的設定請參見 SET TRANSACTION 語法描述, KingbaseES還提供引數 deadlock_timeout 來設定等鎖的時間,解決事務并發操作長期進行鎖等待的問題,
并發控制的實作
KingbaseES在多用戶環境的并發訪問,是通過多版本并發控制和封鎖機制共同實作的,
多版本并發控制
多版本并發控制,即 MVCC(Multi-version concurrency control),對于表里的某個一行 R,多版本并發控制通過每個寫 R 的操作建立 R 的一個新版本,當執行一個讀 R 的操作時,針對操作所在的事務,系統選擇 R 的一個正確版本來進行操作,多版本并發控制的一個顯著好處是讀操作和寫操作并不互斥,例如:如果用戶 A 希望讀取表 T 上的所有資料,而此時用戶 B 正在更新表 T 上的某行資料 r,對于多版本并發控制系統,B 用戶的更新操作對于 r 生成新的版本r(i)進行修改,而不是直接修改修改資料,用戶 A 讀操作同樣獲取一個版本的資料r(j),所以利用區分版本的方式,用戶 A 不必等待 B 的完成, 這里的版本概念也稱作快照(snapshot),一個快照就是在某個時刻的資料庫映像,比如,當事務開始時,系統為對應的時間點的資料生成一個快照,在這個快照中包含的資料十分關鍵,可能包含了那個時刻未提交的事務所產生的資料,還可能包含了那個時刻已經提交的事務產生的資料,換句話說一些資料在這個快照中是可見的,另一些是不可見的,毫無疑問,這影響到了資料的一致性, 可以用快照對資料的可見性,定義資料庫的隔離級別,
讀已提交 (Read committed)
當一個事務隔離級別為讀已提交時,在事務里每個 SQL 陳述句開始時,按規則生成一個快照,對于還沒有提交的資料,認為不可見,否則可見,
可串行化 (Serializable)
當一個事務隔離級別為可串行化時,事務開始時生成一個快照,如果在這個事務開始時還沒有提交的資料,認為它們不可見,否則可見, 多版本控制帶來的巨大好處是最大可能的支持并發的查詢操作,即使修改資料時也不會阻塞讀,
5.5.2.2. 封鎖
除了多版本并發控制,封鎖機制也是實作并發訪問的必不可少的手段, KingbaseES使用鎖控制用戶對資料庫物件,包括:表、頁面、元組、事務、非表物件(函式,觸發器等)的并發訪問,
| 編號 | 鎖 模式(LOCKMODE) | 對應操作 | 與之沖突的模式 |
|---|---|---|---|
| 1 | AccessShareLock | SELECT | 8 |
| 2 | RowShareLock | SELECT FOR UPDATE | 7,8 |
| 3 | RowExclusiveLock | INSERT, UPDATE, DELETE | 5,6,7,8 |
| 4 | ShareUp dateExclusiveLock | VACUUM | 4,5,6,7,8 |
| 5 | ShareLock | CREATE INDEX | 3,4,6,7,8 |
| 6 | Shar eRowExclusiveLock | like ExclusiveLock, but allows ROW SHARE | 3,4,5,6,7,8 |
| 7 | ExclusiveLock | blocks ROW SHARE | 2,3,4,5,6,7,8 |
| 8 | Ac cessExclusiveLock | DROP TABLE, ALTER TABLE | 全部 |
如果一個物件被加上了一種模式的鎖,那么其他用戶如果想加上和此模式相沖突的鎖,就會發生沖突,這個用戶必須等待,直到加上的鎖被釋放,
KingbaseES 支持用戶手動對表加鎖,詳細資訊請查看 LOCK 語法描述,
兩到多個事務相互爭用資源時,可能發生死鎖,KingbaseES 支持自動檢測死鎖,并且自動處理,
例如:事務 T1 已經獲得表 A 上的排它鎖(如成功更新表 A 上的列 a:update A set a = 1;),事務T2 已經獲得表 B 上的排它鎖(如成功更新表 B 行的列 a:update B set a = 1;),現在 T1 申請表 B 上的排它鎖(如嘗試更新表 B 上的列 a:update B set a = 1;),由于沖突,發生鎖等待,這時 T2 申請表 A 上的排它鎖(如嘗試更新表 A 上的列 a:update A set a = 1;),也沖突,形成死鎖,這時 KingbaseES 檢測到 T1 和 T2 發生死鎖,強制回滾 T2 ,解決死鎖,
六、實體體系結構:
實體結構
KingbaseES 資料庫管理系統,由資料庫檔案和KingbaseES實體組成,
資料庫檔案
資料庫檔案為存盤用戶資料以及元資料的一組磁盤檔案, 元資料為描述資料庫結構、配置和控制有關的資訊,
KingbaseES 實體
包含若干對存盤的資料進行操作的資料庫服務行程,還包括分配和管理記憶體,統計各種資訊,以及實作各種協調作業的后臺行程,一臺設備上,可以同時運行多個實體, 實體注冊成實體服務后,會有唯一的名字標志一個實體, 一個 KingbaseES 實體在作業系統上表現為一個 KingbaseES 行程,它可以由控制器啟動,也可以單獨用命令列啟動, 一個 KingbaseES 實體管理多個邏輯上的資料庫,啟動一個 KingbaseES 實體后,使用客戶端可以訪問到這個實體管理的任意一個資料庫,
KingbaseES 實體的結構以及和資料庫檔案的關系可以表示為:

圖 6.1.15 KingbaseES 實體和資料庫檔案
以下是 KingbaseES 實體的詳細介紹,
資料庫服務行程是多行程結構
KingbaseES 資料庫服務行程,稱該行程為一個“KingbaseES 資料庫實體”, 在一個資料目錄只能同時啟動一個實體,不同的資料目錄可以同時以不同的埠,手動啟動為不同的實體,
KingbaseES實體采用多行程架構,因此一個實體中會包含多個行程,這些行程按照功能的不同可以分為后臺行程和服務行程兩類:
后臺行程
KingbaseES 主行程
主行程負責統一管理各服務行程和其他后臺行程, 該行程負責啟動服務行程和其他后臺行程,并且在子行程退出的時候做清理作業, 該行程負責分發來自作業系統的信號到各子行程,系統退出時,主行程負責發送信號通知各子行程退出,然后再停止自己,
后臺寫行程
在這個行程中,共享緩沖池上的臟頁會逐漸定期地寫入持久存盤(例如HDD、SSD),
檢查點行程
用來執行檢查點程序,
自動vacuum行程
會定期地在服務器上執行vacuum,
WAL日志寫行程
這個行程周期性地將WAL緩沖區上的WAL資料寫入和重繪到持久存盤,
統計行程
在此行程中,會收集sys_stat_activity和sys_stat_database等統計資訊,
日志寫行程
寫日志執行緒負責將日志緩沖區中的日志頁面寫出到日志檔案中,
歸檔行程
歸檔行程負責將日志檔案歸檔到指定的位置,
服務行程
KingbaseES 用服務行程來處理連接到資料庫服務的客戶端請求, 對于每個客戶端的連接,KingbaseES主行程接收到客戶端連接后,會為其創建一個新的服務行程, 該行程負責實際處理客戶端的資料庫請求,連接斷開時退出,
記憶體管理
KingbaseES 統一管理實體所用的記憶體資源,配置引數 shared_buffers 決定了資料庫實體使用多少記憶體,當系統啟動時,資料庫實體向作業系統申請一塊大記憶體(大小由 shared_buffers 決定)作為共享記憶體,在這之后各個行程對記憶體資源的使用都在這塊記憶體里操作,
KingbaseES 對于共享記憶體的使用主要可以分為以下幾部分:
資料頁面快取
在記憶體里快取資料頁面,shared_buffers 越大,在記憶體里保存的資料頁面就越多,相同條件下操作資料時進行的 IO 操作更少,
日志頁面快取
日志緩沖區,操作資料時產生的日志都放在這個緩沖區上,由寫日志執行緒和服務執行緒刷到磁盤, 引數 wal_buffers 設定日志頁面快取大小,
排序和連接運算使用的快取
服務器對元組進行排序或者連接運算時,需要用到記憶體快取資料,如果所需的運算還需更大的空間,KingbaseES 會借助于臨時檔案完成, 引數 work_mem 設定每個服務行程排序和連接運算使用的快取大小,
鎖快取
多執行緒并發操作會用到鎖,KingbaseES 從共享記憶體開辟獨立的記憶體空間用于存放鎖資訊, 鎖快取的大小由總的共享記憶體大小決定,
臨時分配的記憶體
服務器在處理資料流程中,用于臨時存放資料所使用的記憶體,也從共享記憶體里分配, KingbaseES 對于共享記憶體的使用通常是可配置的,詳細資訊請參考 記憶體,
七、后臺作業行程:
KingbaseES可以被擴展用來在獨立行程中運行用戶提供的代碼,
此行程將被kingbase啟動、停止和監控,這使它們的生命期與服務器的狀態緊密聯系,這些行程具有選項可以掛接上KingbaseES的共享記憶體區域,并且可以從內部連接到資料庫,它們也可以連續地運行多個事務,就像一個正常的被客戶端連接的服務器行程,同樣,通過鏈接到libkci,它們可以連接到服務器并像一個正常客戶端應用作業,
通過將模塊名放在shared_preload_libraries中,可以在KingbaseES被啟動時初始化后臺作業者,
一個希望運行后臺作業者的模塊需要通過在其_SYS_init()中呼叫RegisterBackgroundWorker(BackgroundWorker *worker)來注冊它,
也可以在系統啟動后通過呼叫函式RegisterDynamicBackgroundWorker(BackgroundWorker *worker, BackgroundWorkerHandle **handle)來啟動后臺作業者,
與只能在kingbase內呼叫的RegisterBackgroundWorker不同,必須從一個常規后端呼叫RegisterDynamicBackgroundWorker,
typedef void (*bgworker_main_type)(Datum main_arg);
typedef struct BackgroundWorker
{
char bgw_name[BGW_MAXLEN];
char bgw_type[BGW_MAXLEN];
int bgw_flags;
BgWorkerStartTime bgw_start_time;
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
char bgw_library_name[BGW_MAXLEN];
char bgw_function_name[BGW_MAXLEN];
Datum bgw_main_arg;
char bgw_extra[BGW_EXTRALEN];
int bgw_notify_pid;
} BackgroundWorker;
| 引數 | 描述 |
|---|---|
| bgw_name 和 bgw_type | bgw_name和bgw_type是要被用在日志訊息、行程串列和類似環境中的字串, 對于同種型別的所有后臺作業者,bgw_type應該相同,這樣才可能將行程串列 中的這些作業組分組,另一方面,bgw_name可以包含有關特定行程的額外資訊 (通常,bgw_name中的字串在某種程度上也會包含型別,但沒有嚴格要求), |
| bgw_flags | 一個按位與的位掩碼,用于指示模塊想要的能力,可能的值是: |
| BGWORKER _SHMEM _ACCESS | 請求共享記憶體訪問,沒有共享記憶體使用權的作業者不能訪問任何的KingbaseES 共享資料結構,例如重量級或者輕量級鎖、共享緩沖區以及該作業者本身想要創 建和使用的任何自定義資料結構, |
| BGWORKER _BACKEND _DATABASE _CONNE CTION | 請求建立資料庫連接的能力,這樣它后面可以通過建立起的連接運行事務和查詢, 一個使用BGWORKER_BACKEND_DATABASE_CONNECTION來連接一個資料庫 的后臺作業者也必須使用BGWORKER_SHMEM_ACCESS掛接到共享記憶體,否則作業 者啟動將會失敗, |
| bgw_start _time | 服務器狀態,在該狀態中kingbase會啟動該行程,它可以是 BgWorkerStart_KingbaseStart(在kingbase本身完成初始化之后立即啟動, 這種行程不能使用資料庫連接)、BgWorkerStart_ConsistentState(當一個 熱后備中達到一個一致性狀態之后立即啟動,允許行程連接到資料庫并運行只讀查 詢)和BgWorkerStart_RecoveryFinished(在系統進入到正常讀寫狀態后立即 啟動)之一,注意后兩種值在服務器不是一個熱后備的情況下是等同的,注意這種 設定僅僅表示何時啟動行程,當一個不同狀態到達時它們不會停止, |
| bgw_restart _time | 是在崩潰情況下kingbase啟動行程之前等待的時間間隔,以秒計,它可以是任何 正值,或者BGW_NEVER_RESTART,表示在出現崩潰后不重啟行程, |
| bgw_library _name | 是應該在其中定位后臺作業者初始入口點的庫名稱,所指的庫將被作業者行程動態 載入并且bgw_function_name將被用來標識要呼叫的函式,如果從核心代碼載入 一個函式,必須被設定為"kingbase", |
| bgw_func tion_name | 一個動態載入庫中的一個函式名,該函式將被用作一個新后臺作業者的初始入口點, |
| bgw_main _arg | 后臺作業者主函式的Datum引數,這個主函式應該有一個單一的Datum型別的引數, 并且回傳void,bgw_main_arg將被作為引數傳遞,此外,全域變數 MyBgworkerEntry指向注冊時傳入的BackgroundWorker結構的一份拷貝,作業者 會發現檢查這個結構會很有用, |
| bgw_extra | 可以包含要傳遞給后臺作業者的額外資料,與bgw_main_arg不同,這個資料 不會被作為一個引數傳遞給作業者的主函式,而是按照上面所述通過MyBgworkerEntry 來訪問, |
| bgw_notify _pid | 一個KingbaseES后端行程的PID,當后臺作業者行程啟動或者退出時,kingbase 會向這個PID所指的行程發送SIGUSR1,對于在kingbase啟動時注冊的作業者,它應 該為0;或者注冊該作業者的后端不希望等待該作業者啟動時,它也應該為0,否則, 它應該被初始化為MyProcPid, |
運行起來后,行程可以通過呼叫BackgroundWorkerInitializeConnection(char *dbname, char *username)或者BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid)來連接資料庫,這使得該行程可以使用SPI介面運行事務和查詢,
如果dbname為NULL或者dboid為InvalidOid,該會話沒有連接到任何特定資料庫,但共享的目錄可以被訪問,
如果username為NULL或者useroid為InvalidOid,該行程將以在initdb階段創建的資料庫管理員賬號運行,
如果BGWORKER_BYPASS_ALLOWCONN被指定為flags,可以繞過該限制連接不允許用戶連接的資料庫,在每一個后臺行程中,只能呼叫兩者之一,并且只能呼叫一次,所以不可能切換資料庫,
當控制到達后臺作業者的主函式時,信號初始會被阻塞,并且必須被它解除阻塞,這是為了允許行程自定義它的信號處理器,在新行程中可以通過呼叫BackgroundWorkerUnblockSignals來解除對信號的阻塞,還可以通過呼叫BackgroundWorkerBlockSignals來阻塞信號,
如果一個后臺作業者的bgw_restart_time被配置為BGW_NEVER_RESTART,或者它退出時的退出碼為0,又或者它是被TerminateBackgroundWorker所終止,它將會被kingbase在退出時自動解除注冊,否則,它將在等待通過bgw_restart_time配置的時間段之后被重新啟動,或者在kingbase因為一次后端失敗重新初始化集簇時立刻被重啟,需要臨時禁止執行的后端應該使用可中斷的休眠而不是退出,這可以通過呼叫WaitLatch()實作,呼叫該函式時要確保WL_POSTMASTER_DEATH標志被設定,并且驗證在kingbase本身被終止的緊急情況下產生的快速退出回傳碼,
當一個后臺作業者通過RegisterDynamicBackgroundWorker函式注冊時,后端可以執行該注冊以獲得有關該作業者的狀態資訊,希望這樣做的后端應該把一個BackgroundWorkerHandle *的地址作為第二個引數傳遞給RegisterDynamicBackgroundWorker,如果作業者被成功地注冊,這個指標將被用一個非透明句柄初始化,它之后會被傳遞給GetBackgroundWorkerPid(BackgroundWorkerHandle *,pid_t *)或者TerminateBackgroundWorker(BackgroundWorkerHandle *),GetBackgroundWorkerPid可以被用來測驗作業者的狀態:回傳值為BGWH_NOT_YET_STARTED表示該作業者還未被kingbase啟動;BGWH_STOPPED表示它已經被啟動但是不再運行;而BGWH_STARTED表示它正在運行,在最后一種情況下,PID也將被通過第二個引數回傳,TerminateBackgroundWorker導致kingbase發送SIGTERM給作業者(如果它在運行),并且在它不再運行時盡快解除注冊,
在某些情況下,一個注冊后臺作業者的行程可能希望等待該作業者啟動起來,實作方式是:將bgw_notify_pid初始化成MyProcPid并且接著把注冊時得到的BackgroundWorkerHandle *傳遞給WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle,pid_t *)函式,這個函式將阻塞直到kingbase已經嘗試啟動該后臺作業者,或者直到kingbase死亡,如果后臺作業者正在運行,回傳值將是BGWH_STARTED,并且其PID將被寫入到所提供的地址,否則,回傳值將是BGWH_STOPPED或者BGWH_POSTMASTER_DIED,
行程也可以等待一個后臺作業者關閉,方法是使用WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)函式并且傳入注冊時得到的BackgroundWorkerHandle *,這個函式將阻塞直至后臺作業者退出或者kingbase死掉,當后臺作業者退出時,回傳值是BGWH_STOPPED,如果kingbase死掉則會回傳BGWH_POSTMASTER_DIED,
如果一個后臺作業者通過服務器編程介面(SPI)用NOTIFY命令發送異步通知,在提交外層事務之后它應該顯式地呼叫ProcessCompletedNotifies,這樣通知才能被發送出去,如果一個后臺作業者通過SPI使用LISTEN注冊為接收異步通知,它將記錄那些通知,但是對于作業者來說沒有程式化的方式可以攔截以及回應那些通知,
src/test/modules/worker_spi模塊包含了一個實體,它展示了一些有用的技巧,
注冊的后臺作業者的最大數量由max_worker_processes限制,
【本文正在參與炫“庫”行動-人大金倉征文大賽】
CSDN
https://marketing.csdn.net/p/98bd30353e7cb998b6070a89e8b91edb
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/301471.html
標籤:其他
