EOS 數據庫結構詳解
在 EOS 中,智能合約執行完畢後,所佔用的內存會釋放。程序中的全部變量都會丟失。若是智能合約裏要持久地記錄信息,好比遊戲智能合約要記錄每位用戶遊戲記錄,本次合約執行完畢後數據不能丟失,就須要將數據存儲到 EOS 數據庫中。與數據庫交互的 API 被官方稱爲 Persistence API,中文能夠叫作持久化 API。下圖說明了 EOS 智能合約在執行 Action 時,與數據庫的交互過程。git
爲了方便智能合約與 EOS 數據庫的交互,EOS 仿造了 Boost 庫中的 Multi-Index Containers
,開發了 C++ 類:eosio::multi_index(如下簡稱
multi_index`),中文能夠叫作多索引列表類。github
multi_index
頭文件地址:
https://github.com/EOSIO/eos/...數據庫
在 EOS 見證人硬盤中,爲每一個帳戶都預留了數據庫空間(大小與代幣持有量有關),每一個帳戶名下能夠創建多個數據表。智能合約沒法直接操做存儲在見證人硬盤中的數據表,須要使用multi_index
做爲中間工具(或者叫容器),每一個multi_index
實例都與一個特定帳戶的特定數據表進行交互(取決於實例化時的參數)。EOS智能合約與EOS數據庫的數據交互以下圖所示。segmentfault
multi_index
是一個很是方便的數據庫交互容器,能夠存儲任何 C++ 數據類型。每個multi_index
都至關於傳統數據庫的一個數據表(table),但將傳統數據庫的行與列的形式改成了單純的列。也就是說multi_index
是一個線性排列的表,只有一列,每一行都只存儲一個對象。可是通常來講multi_index
存儲的對象都是結構體或者類,裏面含有多個成員變量,因此multi_index
存儲數據的靈活性也是不亞於傳統數據庫的。windows
咱們使用官方的「汽車維修店」示例,咱們創建一個數據表,儲存每一個汽車維修店客戶的帳戶名、保養時間、車輛里程。那麼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
數據結構。數據結構
首先,每一個數據表要有一組主鍵,主鍵必須是無符號 64 位整數類型(64-bit integer),這就是上面的service_rec
結構體中第一個變量爲uint64_t
類型的緣由。在數據表中,全部的對象就是按照主鍵升序排列的,小的在前,大的在後。主鍵能夠是有意義的,也能夠是沒有意義的,讓系統產生一個在這個數據表中沒有被使用的主鍵便可。爲了設置主鍵,咱們須要在以前的service_rec
結構體添加一個叫作primary_key()
的成員函數函數的返回值爲主鍵。dom
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
索引。
multi_index
是如何操做數據表中的每一個對象的呢?答案是 Iterators(迭代器)。你們能夠搜索 「C++ 迭代器」或者設計模式中的「迭代器模式」來了解迭代器的設計思路。在 EOS 數據庫中,我更願意將迭代器比喻爲一個「電梯」,在整個數據表中上下穿梭。全部對數據的操做必須經過迭代器完成。典型的數據修改過程是這樣的:首先使用迭代器的find()
方法,在特定的索引中尋找須要的數據,好比在車主用戶名索引中尋找某個用戶。迭代器會移動到須要的數據對象上。而後就可使用迭代器的modify()
方法修改當前迭代器對應的數據。下圖爲迭代器指向用戶 Sue 的狀況。
本篇文章介紹了 EOS 數據庫的基本結構,之後的文章會詳細介紹 EOS 數據庫使用實戰,敬請期待。
圓方圓學院聚集大批區塊鏈名師,打造精品的區塊鏈技術課程。 在各大平臺都長期有優質免費公開課,歡迎報名收看。
公開課地址:https://ke.qq.com/course/345101