天天看點

2.0解析系列 | OceanBase 2.0——第一款支援“存儲過程”的原生分布式資料庫引言價值和意義實作機制相容性分布式調試包總結和展望

OB君:本文是 “OceanBase 2.0 技術解析系列” 的第八篇文章,今天我們來說說2.0版本最标志性、最不得不提的新特性——存儲過程。在為數不多的原生分布式資料庫中,OceanBase 2.0是第一款支援存儲過程功能的産品。本文将為你深入剖析2.0中存儲過程的功能特性和實作機制。更多精彩歡迎關注OceanBase公衆号持續訂閱本系列内容!

引言

PL/SQL(存儲過程)是一種程式語言,叫做過程化SQL語言(Procedural Language/SQL),從Ada語言發展而來。PL/SQL是關系資料庫對SQL語句的擴充,在普通SQL語句的基礎上增加了程式設計語言的特點,把資料操作和查詢語句組織在PL/SQL的過程化代碼中,通過邏輯判斷、循環等操作實作複雜的功能。

使用PL/SQL可以編寫具有很多進階功能的程式,能夠把業務邏輯封裝在資料庫内部,提供更好的抽象和安全性,同時減少了網絡的互動,并且調用更快,進而提升整體性能。

目前無論是商業資料庫還是開源産品幾乎都在一定程度上支援類似PL的功能,但是采用的規範标準不盡相同。使用最廣泛的是Oracle的PL/SQL,最早在1989年釋出,文法基于Ada語言。

除此之外還有SQL Server的T-SQL,PostgreSQL的PL/pgSQL等。SQL标準中的SQL/PSM(SQL/Persistent Stored Modules)定義了存儲過程中使用的PL,但是Oracle的PL/SQL已經成為了事實上的規範。MySQL采用的是SQL/PSM标準,但是并非100%相容。OceanBase 2.0目前的PL以相容MySQL為主體,MySQL沒有的功能參照Oracle實作。

MySQL和PostgreSQL的PL都采用解釋執行方式,從實作角度來說,解釋執行比編譯執行更容易實作,也更易于控制。但是理所當然的,解釋執行比編譯執行性能相對較差。

Oracle 9.x之前的PL也是解釋執行(Interpreted Compilation)的,從9.x開始,Oracle提供了編譯執行(Native Compilation),SQL/PL首先被翻譯為C語言代碼,然後調用C編譯器編譯為機器碼,編譯後的程式存在動态連結庫中,運作時執行器直接裝載調用動态連結庫中編譯好的函數。

根據Oracle自己的說明,編譯後的程式比解釋執行性能提升1.05到2.4倍。具體提升的程度取決于程式的特性。因為SQL語句本身還是解釋執行的,是以如果PL的主體是程式控制邏輯,那麼提升效果會很明顯,而如果PL的主體是SQL語句,那麼PL的性能提升不會顯著。另外Oracle的PL調試功能隻支援解釋執行方式。

編譯執行是一個趨勢,目前除了PL之外,很多資料庫也紛紛在嘗試把SQL引擎改寫為編譯執行,包括MemSQL、HANA、PostgreSQL等。OceanBase PL采用編譯執行的方式,使用LLVM生成native code,并直接把機器碼裝載到程式段執行,無需依賴外部C編譯器和生成動态連結庫。

無論解釋執行還是編譯執行,目前的商業資料庫都隻支援單機,OceanBase在分布式環境下在關系資料庫裡支援了完整的PL/SQL功能,這在業界尚屬首次。

價值和意義

1. 降低RT

PL對于業務最直接的價值就是降低業務的RT。假如某個業務邏輯裡面一條完整的執行鍊路平均有200條SQL,也就是應用需要和資料庫互動200次。在同機房的情況下網絡開銷大約需要0.5ms,如果把200次互動省掉,那麼就可以節約100ms的RT。當然,事實上因為業務有自身的邏輯,不可能全部邏輯都可以用PL/SQL來實作,是以這200次互動不可能全部省掉,但是即便省下一半,也會有大約50ms的RT提升。

2. 節省資源

減少網絡互動除了減少RT,另一個直接的效果是減少了網絡的資料傳輸和網絡開銷。假如某個網際網路業務的網絡開銷平均是30%,也就是說30%的CPU都花在了網絡的收發和解析上。如果說幾十個ms的RT對整個鍊路來說比例不那麼顯著的話,30%的CPU資源節省縮省下的機器可是以億計的真金白銀,而把這些機器資源換算成系統處理能力也将是驚人的。

3. 提高吞吐率

事實上利用PL/SQL帶來的網絡開銷的節省隻是表面,更深層次的是,因為每個事務的RT縮短,每個事務在資料庫核心所搶占臨界區的時間縮短,使得系統的CPU使用率獲得大幅提升,整個吞吐量也随之提高。這種提升不止在資料庫核心存在,對業務的應用邏輯同樣有幫助。CPU使用率的提升所獲得價值同樣也是億級規模的。

4. 提升穩定性和可靠性

目前的網際網路分布式業務多是單元化部署,應用和資料庫部署在同機房,并且在大多數情況下都是機房内通路,一旦發生故障導緻某個資料庫的資料不可通路,OceanBase會自動切換通路其他副本,與此同時應用也必須随之切走,否則同機房的資料庫通路将變成跨機房甚至跨城通路,網絡開銷也将由原來的每次0.5ms變成2ms,甚至達到7ms~30ms。對于單次來說這不算什麼,但是在幾百條SQL的加成下就可觀了。

巨大的網絡延遲會對整個業務系統造成嚴重影響,甚至拖垮整個系統。而利用了PL/SQL之後,這些問題都将不複存在,業務将不再和資料庫強綁定,計算和計算的分離成為可能,整個系統的可靠性獲得提升。

同時,OceanBase的設計對于網絡要求相對比較高,叢集内部通信以及内部流程邏輯也都可以利用PL/SQL實作,這不僅提升能夠内部通信的效率,同時也使得資料庫核心的核心代碼充分簡化,減少出錯路徑,提升穩定性。

并且部分業務邏輯改為PL後,業務的代碼将會減少,業務開發流程也會相對簡化,同時提供更好的抽象和安全性。

實作機制

1. 架構結構

圖1給出了OceanBase PL Engine工作的調用關系圖。PL引擎(PL Engine)和SQL引擎(SQL Engine)可以互互相動,SQL可以直接通路PL引擎,比如在一個SQL語句中使用了使用者自定義函數。PL引擎可以通過SPI接口通路SQL引擎,比如在PL裡進行表達式計算和執行SQL語句。

2.0解析系列 | OceanBase 2.0——第一款支援“存儲過程”的原生分布式資料庫引言價值和意義實作機制相容性分布式調試包總結和展望

圖1:PL Engine工作調用關系

2.PL Engine

PL Engine由六個子產品組成:Parser、Resolver、Code Generator、Compiler、Executor和PL Cache,其中Parser、Resolver、Code Generator和Compiler構成了一個完整的PL編譯流程。如圖2所示。

  • Parser

    文法解析器,用于分析PL文法生成文法樹(ParseTree)。PL引擎和SQL引擎各自實作了單獨的Parser,但是兩個Parser盡量不做備援的工作。一個查詢串進入Observer首先進入PL Parser解析,如果發現是SQL語句則交由SQL引擎解析。

  • Resolver

    Resolver用于進行語義分析,例如檢查變量作用域、靜态SQL中資料對象的Schema等,并為每一條PL語句生成對應的AST結構以及全局的FunctionAST結構。FunctionAST存儲了PL定義的基本資訊和生成的全局符号表、全局标簽表、全局異常表等資訊。每一條語句的AST裡面則記錄了指向這些全局表的邏輯資訊。

  • Code Generator

    對于解釋執行來說,AST已經足夠。但是對于編譯執行,需要對AST進行進一步的翻譯,這一步是使用LLVM提供的接口,把AST樹翻譯成IR中間碼的過程。IR碼可以輸出,以核對檢驗翻譯過程是否正确。

  • Compiler

    通過JIT把IR碼生成機器碼的過程,輸出為PLFunction結構。

  • Executor

    PL的執行器,根據編譯出的PLFunction,和輸入參數構造執行環境,調用函數指針,得到函數結果。

  • PL Cache

    PL Cache存在的目的是為了避免每一次都重新編譯PL,提升PL的執行效率。是以對于匿名塊(Anonymous Block)沒有Cache的必要。

PL Cache是一個hash表,通過Key(Procedure或Function的ID)查找到Value(PLFunction),并通過通路Schema檢查PLFunction的有效性,如果失效則趁機删除。

PL Cache是PL Engine的内部機制,PL Engine對外提供統一的通過ID執行Procedure或Function的接口,外部不必關心PL的緩存機制,隻需通過PL Engine對象執行PL即可。

2.0解析系列 | OceanBase 2.0——第一款支援“存儲過程”的原生分布式資料庫引言價值和意義實作機制相容性分布式調試包總結和展望

圖2:PL Engine子產品組成

PL Engine根據ID在PL Cache查找是否有編譯好的PLFunction,如果有則進一步檢查Version是否可用。如果PL Cache中沒有可用的PLFunction,則調用編譯流程進行編譯,編譯後的結果緩存在PL Cache,并交給Executor執行。

最終編譯出的結果是一段二進制代碼的記憶體位址,Executor将這段記憶體位址轉成一個函數指針,并傳入執行參數和執行環境運作得到結果。

3.編譯執行

編譯執行比解釋執行的優勢毋庸贅言,OceanBase 也是采用把存儲過程編譯為機器碼的方式進行執行,但是和Oracle實作不同的是,OceanBase采用JIT技術,無需依賴外部C編譯器和生成動态連結庫。采用這一技術方案,有如下優點:

  1. 無需研究體系結構相關的複雜的機器碼生成,就可以獲得編譯執行的效果;生成LLVM IR比生成彙編簡單很多,且自然擁有了考慮跨平台能力;
  2. LLVM提供的成熟的優化子產品都是基于LLVM IR的,clang等項目中對優化器的改進都可以直接被我們受益;
  3. 用JIT技術在Observer内直接控制生成編譯後的代碼,比Oracle采用的在資料庫外部編譯器編譯結合動态連結庫裝載的方式在可控性,性能,可維護性各方面都有優勢;
  4. PL的編譯執行可以和SQL表達式及部分physical operator甚至是整個查詢計劃采用編譯執行相結合,擷取整體性能的提升。

圖3給出了PL 編譯的工作流程。Parser、Resolver和Code Generator三個子產品完成了編譯器的前端(Frontend)工作,實作從PL文本到中間碼(LLVM IR)的轉換過程。Compiler子產品完成了Pass和後端(Backend)的工作,把中間碼經過Pass流程優化,并生成實際的機器碼。

2.0解析系列 | OceanBase 2.0——第一款支援“存儲過程”的原生分布式資料庫引言價值和意義實作機制相容性分布式調試包總結和展望

圖3:PL編譯工作流程

這種架構下,對于實作PL/SQL語言來說,大量的工作是實作一個前端,即Parser、Resolver和Code Generator三個子產品,而對于Compiler可以調用LLVM提供的接口實作。

相容性

各大資料庫支援的PL都各有不同。目前最廣泛使用的Oracle PL/SQL語言最早在1989年釋出,文法基于Ada語言。PostgreSQL的PL/pgSQL,SQL Server的T-SQL等語言都各不相同。SQL标準中的SQL/PSM (SQL/Persistent Stored Modules)定義了存儲過程中使用的PL,但遺憾的是主流資料庫廠商并沒有全心支援。

像PL/pgSQL一樣,MySQL采用了SQL/PSM标準,但是并非100%相容。OceanBase 提供MySQL和Oracle兩種相容模式,PL/SQL也同樣既可以使用Mysql的用法,也可以選擇Oracle相容模式,基于Mysql或者Oracle的PL的代碼可以一行不改的遷移到OceanBase運作。

分布式

OceanBase天然的分布式特性決定PL的執行也是分布式的,PL的解析、編譯和執行都在某一個Observer上完成,當PL裡涉及到SQL互動時,會通過SPI調用SQL Engine,由SQL Engine執行SQL語句,如果該SQL語句是一個分布式的,那麼自然而然會進行分布式執行。

OceanBase選擇存儲過程裡通路的第一張表的資料所在的節點編譯和執行PL,這是為了盡量使得PL對資料的通路都是LOCAL的。如果無法确定所通路資料所在的節點,則随機選取一個節點。

當分布式執行的SQL調用了PL函數時,PL函數可能會在多個Observer上編譯執行,每個Observer上保證在相同的環境參數下進行編譯,進而編譯出的PL具有相同的行為。

調試

調試是程式設計語言的基本需求,是以事實上Mysql這樣不支援調試的PL/SQL是不具備大規模應用的基礎的。

業界實作PL的調試功能都隻在解釋執行模式支援,Oracle的編譯執行模式不支援調試。OceanBase隻有一種編譯執行模式,支援在編譯模式進行調試,并且是在分布式的環境下進行調試。目前支援的調試功能包括設定斷點(b)、檢視斷點(info b)、檢視變量(p)、檢視堆棧(bt)、單步運作(s)、進入函數(s)、繼續(c)等等,通訊方式采用類似Oracle的方式,建立一個資料庫連接配接來調試另一個連接配接,調試指令用文本指令,不發明新的通訊協定,并通過包的形式對外提供接口。

分布式調試是分布式環境下實作PL/SQL的難點,當PL分布式執行時,使用者的調試線程連到其中一個節點,該節點需要再和其他分布式執行節點建立調試連接配接并傳輸指令和資料。

Mysql沒有包(Package),OceanBase提供和Oracle完全相容的包機制,使用者在Oracle上建立的包可以一行不改的遷移到OceanBase上建立和運作。

但是Oracle的系統包目前OceanBase還沒有全部支援,這也将成為今後一段時間我們要做的工作之一。在有了PL/SQL的基礎能力支援和Package的機制之後,其餘的系統包可以根據需要快速實作。

總結和展望

從OceanBase誕生的第一天起,團隊的目标就不是想做一個資料庫隻給自己用,而是要做一個通用資料庫真的去推動整個社會的進步,能夠讓整個社會的生産力發生變化。

随着螞蟻金服的開放賦能,OceanBase也開始服務外部客戶,金融行業的很多客戶以前都有很大一部分業務是使用Oracle開發,并且大量使用了PL/SQL,這種現狀在非金融行業中更為普遍,而這也成為了Oracle綁在客戶身上最重要的一條鎖鍊。OceanBase要為客戶提供比Oracle更可靠、更高成本效益的服務,PL/SQL是必須邁過去的一道門檻。這道門檻很難邁,而一旦邁過去,就會形成OceanBase的重要優勢。

另一方面,雖然網際網路公司目前的現狀是普遍都不使用PL/SQL進行業務開發,但是難掩其對業務的巨大價值,PL不僅能夠降低RT,提高資源使用率,提升系統吞吐率、穩定性和可靠性,同時也是服務使用者,尤其是傳統行業客戶的重要基礎。在這一方面螞蟻金服走在網際網路行業前列,已經開始在内部嘗試利用PL/SQL的優勢來解決業務的問題。

OceanBase提供了同時相容Mysql和Oracle兩種模式的PL/SQL,并利用LLVM實作其編譯執行的核心引擎,使得PL控制邏輯本身性能能夠達到Oracle相當的水準。而且OceanBase是業界第一個真正意義上支援分布式PL的商業産品,并提供完善和相容的調試機制。與此同時OceanBase還提供了完備的包機制。

未來除了進一步完善Oracle相容的系統包之外,還需要繼續優化PL/SQL的性能。與此同時,我們也會在更多内部業務中推廣使用PL/SQL,為業務創造巨大的價值,并在提供給外部客戶使用之前做好技術沉澱和産品錘煉。

加入OceanBase 2.0技術交流群

— 想了解更多OceanBase 2.0新特性?

— 想與螞蟻金服OceanBase的一線技術專家深入交流?

掃描下方二維碼聯系小編,快速加入OceanBase技術交流群!

2.0解析系列 | OceanBase 2.0——第一款支援“存儲過程”的原生分布式資料庫引言價值和意義實作機制相容性分布式調試包總結和展望