【許曉笛】EOS 資料庫與持久化 API —— 架構

圓方圓區塊鏈發表於2018-11-20

EOS 資料庫結構詳解

在 EOS 中,智慧合約執行完畢後,所佔用的記憶體會釋放。程式中的所有變數都會丟失。如果智慧合約裡要持久地記錄資訊,比如遊戲智慧合約要記錄每位使用者遊戲記錄,本次合約執行完畢後資料不能丟失,就需要將資料儲存到 EOS 資料庫中。與資料庫互動的 API 被官方稱為 Persistence API,中文可以叫做持久化 API。下圖說明了 EOS 智慧合約在執行 Action 時,與資料庫的互動過程。

【許曉笛】EOS 資料庫與持久化 API —— 架構

為了方便智慧合約與 EOS 資料庫的互動,EOS 仿造了 Boost 庫中的 Multi-Index Containers,開發了 C++ 類:eosio::multi_index(以下簡稱 multi_index),中文可以叫做多索引列表類。

multi_index 標頭檔案地址: github.com/EOSIO/eos/b…

在 EOS 見證人硬碟中,為每個賬戶都預留了資料庫空間(大小與代幣持有量有關),每個賬戶名下可以建立多個資料表。智慧合約無法直接操作儲存在見證人硬碟中的資料表,需要使用multi_index作為中間工具(或者叫容器),每個multi_index例項都與一個特定賬戶的特定資料表進行互動(取決於例項化時的引數)。EOS智慧合約與EOS資料庫的資料互動如下圖所示。

【許曉笛】EOS 資料庫與持久化 API —— 架構

資料表

multi_index是一個非常方便的資料庫互動容器,可以儲存任何 C++ 資料型別。每一個multi_index都相當於傳統資料庫的一個資料表(table),但將傳統資料庫的行與列的形式改為了單純的列。也就是說multi_index是一個線性排列的表,只有一列,每一行都只儲存一個物件。但是一般來說multi_index儲存的物件都是結構體或者類,裡面含有多個成員變數,所以multi_index儲存資料的靈活性也是不亞於傳統資料庫的。

我們使用官方的“汽車維修店”示例,我們建立一個資料表,儲存每個汽車維修店客戶的賬戶名、保養時間、車輛里程。那麼multi_index資料表儲存的專案中,每個都是如下的結構體:

struct service_rec {
    uint64_t        pkey;           // 主鍵
    account_name    customer;       // 車主使用者名稱
    uint32_t        service_date;   // 維修保養時間
    uint32_t        odometer;       // 車輛里程
};
複製程式碼

在傳統資料庫中,需要建立一個 4 列的資料表,用來儲存每個使用者的這個 4 個資料,而multi_index的每個資料表只有一列,只儲存每個使用者的 service_rec 整個結構體即可。下圖為multi_index資料結構。

【許曉笛】EOS 資料庫與持久化 API —— 架構

多索引

首先,每個資料表要有一組主鍵,主鍵必須是無符號 64 位整數型別(64-bit integer),這就是上面的service_rec結構體中第一個變數為uint64_t型別的原因。在資料表中,所有的物件就是按照主鍵升序排列的,小的在前,大的在後。主鍵可以是有意義的,也可以是沒有意義的,讓系統產生一個在這個資料表中沒有被使用的主鍵即可。為了設定主鍵,我們需要在之前的service_rec結構體新增一個叫做primary_key()的成員函式函式的返回值為主鍵。

	auto	primary_key()const { return pkey; }
複製程式碼

這樣就將pkey這個變數設定成了主鍵。

multi_index從字面上看就是能使用多個索引的資料表。EOS 中,每個multi_index或者說每個資料表都可以設定最多16個索引。索引相當於使用特定的方式給資料表中的物件重新排序。比如在我們經常使用的 windows 檔案管理器中,可以按照檔名排序、按照檔案修改時間排序、按照檔案大小排序,這就有了3個索引。EOS 資料庫索引更加靈活,可以單獨按照結構體中的某個變數索引,也可以將變數之間的運算結果(函式輸出)進行索引。如果我們想使用車主使用者名稱進行索引,需要在結構體中新增一個get_customer()成員函式,函式的返回值為索引變數。

account_name    get_customer()const { return customer; }
複製程式碼

這樣就將customer這個變數設定成了資料表的一個索引,下圖右側為customer索引。

【許曉笛】EOS 資料庫與持久化 API —— 架構

迭代器

multi_index是如何運算元據表中的每個物件的呢?答案是 Iterators(迭代器)。大家可以搜尋 “C++ 迭代器”或者設計模式中的“迭代器模式”來了解迭代器的設計思路。在 EOS 資料庫中,我更願意將迭代器比喻為一個“電梯”,在整個資料表中上下穿梭。所有對資料的操作必須通過迭代器完成。典型的資料修改過程是這樣的:首先使用迭代器的find()方法,在特定的索引中尋找需要的資料,比如在車主使用者名稱索引中尋找某個使用者。迭代器會移動到需要的資料物件上。然後就可以使用迭代器的modify()方法修改當前迭代器對應的資料。下圖為迭代器指向使用者 Sue 的情況。

【許曉笛】EOS 資料庫與持久化 API —— 架構

本篇文章介紹了 EOS 資料庫的基本結構,以後的文章會詳細介紹 EOS 資料庫使用實戰,敬請期待。


相關文章和視訊推薦

【許曉笛】EOS 資料庫與持久化 API —— 實戰

圓方圓學院彙集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。 公開課地址:ke.qq.com/course/3451…

相關文章