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


TiDB是Google F1的開源實現;

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

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

自 Google F1開始,數據庫被分成了兩類:

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

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

在看TiDB源碼之前, 再簡單回顧一下TiDB的結構:

 

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

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

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

因為篇幅所限, 這里只介紹一下大體流程; 讓我們對數據庫的實現有一個簡單的認識;

假設我們在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 中的;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM