跟隨一條insert語句, 進入TiDB的源碼世界(上)

TiDB是Google F1的開源實現;mysql

TiDB實現了基於mvcc的樂觀鎖,在線表結構變動,基於時間戳的數據線性一致性,等等;git

爲了可靠性,TiDB和Oracle同樣,維護了百萬級別的自動化測試用例,跑在k8s搭建的集羣之上;github

自 Google F1開始,數據庫被分紅了兩類:算法

  一類是傳統sql,表明如Oracle,依賴於高速網絡和磁盤陣列來實現海量數據的擴容和數據的高可靠,成本及其高昂,大部分銀行都用了Oracle的系統;sql

  另外一類是NewSQL,表明如F1和TiDB,依賴於各類算法,使數據庫服務能運行在由廉價服務器搭建的集羣之上,一樣保證了海量數據的擴容和數據的高可靠;數據庫

在看TiDB源碼以前, 再簡單回顧一下TiDB的結構:服務器

 

本篇文章涉及的內容是上述橙色部分---TiDB-Server的代碼;網絡

TiDB-Server 是用go實現的,go的代碼組織很是友好, 相比之下, C++ 和 Java 的各類編譯腳本和代碼依賴倉庫管理很是複雜並且容易出錯;session

TiDB-Server編譯以後生成的可執行文件是 tidb-server, 能夠單獨運行, 沒有 tipd 和 tikv也能啓動,實際上代碼裏面對 tipd和tikv實現了mock;你能夠把 tidb-server理解成一個mysql-server;mvc

由於篇幅所限, 這裏只介紹一下大致流程; 讓咱們對數據庫的實現有一個簡單的認識;

假設咱們在mysql客戶端執行了一條insert語句---"insert into t1 values("zhangshan", 5000000);" ,這條語句是怎樣被TiDB-Server執行的呢? 

先看看mysql客戶端接入部分的代碼:

 

鏈接上來以後, 會讀取mysql客戶端數據, 按照mysql 客戶端服務端協議進行解析;

 

 注:咱們下面對代碼裏面的變量舉例時,用的都是這條sql---"insert into t1 values("zhangshan", 5000000);"

 咱們看看cc.dispatch的實現

 

 

query類型的sql在 clientConn.handleQuery 裏面處理:

 

 一連串調用以後來到了session.execute, 咱們看看實現:

 

 session.execute裏面作了這幾件事:

  1. 經過語法和詞法分析將sql解析爲抽象語法樹,生成一個InsertStmt結構體;

    語法分析和詞法分析使用的是go語言版的yacc和lex;

    tidb用了一個工具ebnf2y(EBNF文法轉 .y文件)將mysql的sql BNF文法轉爲了 parser.y,能夠參見 github.com\pingcap\parser\parser.y;

    值得一提的是,pingcap將sql解析器從tidb獨立出來,能夠方便的供其餘項目使用;

  2. 優化sql, 生成執行計劃;

    

  3. 執行sql;

    對於 insert 語句,將數據插入到 kv 中;

    tidb-server 中 mock kv 是直接把鍵值對保存在了 go 語言版的 leveldb 中;

 咱們看看Insert語句對應的結構體:

限於篇幅,暫時講到這裏,下篇咱們一塊兒進入 session.executeStatement 函數;

看 tidb 是怎樣將列數據編碼爲 kv,插入到 go leveldb 中的;

相關文章
相關標籤/搜索