天天看點

OceanBase 源碼解讀(三):分區的一生

OceanBase 源碼解讀(三):分區的一生

引言

源碼是OceanBase的“方向盤”,本系列主要圍繞“源碼解讀”,通過文章闡述,幫助大家理清資料庫的内在本質。此前,帶你讀源碼第二篇《戳這裡回顧:

OceanBase源碼解讀(二):SQL的一生

》為大家介紹了OceanBase 資料庫中一條 SQL 的執行流程主路徑,包括接收、處理、傳回結果給用戶端的過程,探讨了OceanBase的SQL引擎子產品。

本文為 OceanBase 資料庫源碼解讀系列文章的第三篇,将主要為大家介紹 OceanBase  的存儲層像相關知識。

正文

假若分區是 OceanBase 的一等公民。一個表由一個或者若幹個分區組成,分區是 OceanBase 邏輯上水準可擴充概念和實體上資料組織的基本機關。分區是自包含的:每個分區有自己獨立的選舉和 leader,獨立的事務日志、資料存儲和索引。分區可大可小,一般大小在 G B量級,它可以被 RS 在多個節點之間排程以實作負載均衡。

每個分區有一個唯一辨別 OBPartitionKey,由租戶 id、表 id、分區 id 組成。從存儲層來說,每個節點就是存儲群組織這些 key 對應的分區副本,每個節點上可以有數萬個副本。副本有多種類型,比如隻讀副本與主副本之間不是通過 paxos 協定,而是異步消息同步事務日志。

OceanBase 源碼解讀(三):分區的一生
OceanBase 源碼解讀(三):分區的一生

storage/ob_partition_service.h 是存儲層的總入口,它對外提供了存儲層的所有 RPC 服務,如建立删除分區副本。實際上,它是每個節點上所有分區級接口的入口,包括事務控制接口、分區讀寫的接口等。

前面講過,建表和新增分區等 DDL 語句是由 RS 執行的,RS 在根據一定政策標明節點後,就會 RPC 調用這裡的 create_xxx。

從這個入口一層一層追下去,可以找到所有存儲結構。但存儲層内部有大量類似的接口,很容易混淆。每個分區都是一個“索引組織表”,索引結構是多層的 LSM-Tree。雖然是多層,但是有參數可以調整,盡量隻有記憶體裡的 memtable(見storage/memtable)和磁盤上的 major sstable(見 storage/blocksstable)兩層。每次 major compaction 的時候,memtable, minor sstable 的資料與原來的 major sstable 合并,産生新版本的 major sstable。在合并期間,可能有多個版本的 major sstable 同時提供服務。一個分區副本的多層存儲結構合起來,就是類 OBPartitionStore。

分析到這裡,大家還以為“分區是 OB 的一等公民”嘛嗎?其實PG 才是。此 PG 非彼 PG。PG,Partition Group,表示共享同一個事務日志流和 memtable 的“有緊密關系的”一組分區。外部一般不使用這個特性,一般一個 PG 裡面隻有一個分區,這就是為什麼這裡的存儲結構和操作對象會有奇怪的pg字首和 OBPGKey了。

為了表達誠意,獻上我畫的存儲結構相關類圖。

OceanBase 源碼解讀(三):分區的一生
OceanBase 源碼解讀(三):分區的一生

一圖勝千言。

OceanBase 源碼解讀(三):分區的一生
OceanBase 源碼解讀(三):分區的一生

sql/engine/table 是 SQL 實體執行計劃中執行表掃描的算子,它通過 ob_partition_service.h 的 table_scan 接口獲得一個疊代器(疊代結束要調用 revert_scan_iter),這就是存儲層提供的資料通路入口。還有 DML(sql/engine/dml)使用的insert_rows, delete_rows, update_rows和lock_rows 等接口。

當分區或表被删除的時候,OBPGPartition 及其所有包含的存儲結構将被删除。但是并非立即釋放資源,要等所有引用失效且資源不被使用時執行清理。

以上便是分區的一生。在後續的源碼解讀第四篇我們将會為大家解析OceanBase 資料庫事務的外部接口,敬請期待。