第二章 技術背景與相關研究
2.3 語句結構剖析工具
國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
19
表的詮釋欄位。
2.3 語句結構剖析工具
在 SQL 語句轉換成以 Extension Table Layout 邏輯表達的 SQL 語句過程中,必 需先取得 SQL 語句中的語句元素,以圖 2.10 為例,其 UPDATE 語句是由資料表 名稱(CourseInfo)、更新欄位以及其更新欄位數值(Days = ‘Tue’, Time =
‘D56’)、WHERE 條件式(CourseName = ‘軟體工程’)這三項語句元素所構成 的。本研究將採用 JSqlParser 來協助系統工具進行語句結構剖析的動作。
JSqlParser 可以在 Java 程式中進行 SQL 語句的結構剖析並將其結構內容轉 換成一種階層式的 Java 類別,並以 vistor pattern 的方式去操作這些 Java 類 別。下圖 2.10 是一個 JSqlParser 對 SQL 語句進行剖析的程式碼範例。
圖 2.10 JSqlParser 對 SQL 語句進行剖析的程式碼範例
以圖 2.10 程式碼為例,圖中名為 sql 的 String 物件是即將進行結構剖析 的 SQL 語句(line 1),首先,建立一個名為 pm 的 CCJSqlParserManager 物 件(line 2)。接下來,藉由 parse()函式對名為 sql 的 String 物件進行語句
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
20
結構剖析,同時,將剖析後獲得的語句元素存放在名為 updatestmt 的 Update 類別物件中(line 4)。最後,透過 getColumn()、getExpressions()、
getTable()以及 getWhere()這四個 getter 函式(line 7-13)來取得所需的 語句元素,包含更改欄位(例如:[Days,Time])、更改欄位數值(例如:[‘Tue’,
’D56’])、資料表名稱(例如:CourseInfo)以及 Where 條件式的內容(例如:
CourseName=‘軟體工程’),並將取得的資訊儲存在 columns、expressions、
table 以及 where 這四個變數中以協助後續的語句轉換動作。
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
21
第三章 系統設計
基於多租戶技術的概念,在租戶資源共享的情況下,也要讓租戶以自助的方式 去客製化其資源,所以,本研究在租戶共享資料庫的前提下,以提供租戶適度 地客製化其資料表綱要的能力納入主要的設計考量,另外,由於採用 Extension Table Layout 的概念進行設計,因此,也可以提升軟體開發人員統一管理租戶 的共有欄位以及其資料的能力。本系統工具透過改寫 JDBC 的部分 API 去攔截軟 體開發人員所撰寫的 SQL 語句;接下來,將攔截到的 SQL 語句交給 JSqlParser 進行結構剖析以獲得語句元素;再來,重組獲得的語句元素,將 SQL 語句從一 租戶一資料表寫法轉換成以 Extension Table Layout 邏輯表達的 SQL 語句;最 後,將轉換後的 SQL 語句在資料庫中執行以進行資料表綱要的建立、更改或是 資料的增刪修改以及查詢等動作。本章節將針對系統設計的部分進行詳細地解 說,包含了系統設計理念、系統設計考量、系統流程以及系統實作方法。
3.1 系統設計理念
現今的多租戶應用程式之資料層級大部份是以 Private Table Layout 的概念去 設計,雖然可以提供租戶客製化其資料表綱要的能力,但此種方式容易造成軟 體開發人員在多租戶應用程式維運上的不便,倘若開發一個新服務的過程中,
需要修改已存在的資料表綱要,則軟體開發人員要逐一針對每個租戶的資料表 綱要(schema)進行修改,當租戶的數量或是受影響的資料表綱要(schema)逐漸 增加,這無非是一個很費時的工程。相較之下,採用 2.2.3 小節 Extension Table
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
22
Layout 的概念更符合多租戶應用程式之資料層級的需求,其所提出的共有欄位、
私有欄位概念可以提升軟體開發人員統一管理租戶的共有欄位以及其資料的能 力;除此之外,亦可以讓租戶建立私有欄位,也意味著滿足租戶適度地客製化 欄位的需求。
但是,當資料以 Extension Table Layout 的資料存放方式儲存,會讓軟體 開發人員在撰寫 SQL 語句時,為了配合實際資料存放方式而無法採用一租戶一 資料表寫法撰寫 SQL 語句,造成軟體開發人員在開發上的困難。
為了解決上述採用 Extension Table Layout 的概念對軟體開發人員所造成 的困難,本研究實作一套系統工具將 SQL 語句從一租戶一資料表寫法轉換成以 Extension Table Layout 邏輯表達的 SQL 語句,讓軟體開發人員可以沿用一租 戶一資料表的 SQL 語句邏輯對以Extension Table Layout 的資料存放方式儲存 的資料進行增刪修改。
因此,在應用程式的部分,軟體開發人員透過 JDBC 的 API 以標準的 SQL 語 句邏輯撰寫 SQL 語句來表達其所要對資料庫進行的動作,同時,設定 TenantId 讓本系統工具知道其所要執行 SQL 語句的對象(租戶)。透過語句轉換機制的處 理,產生以 Extension Table Layout 邏輯表達的 SQL 語句並在資料庫上執行,
完成軟體開發人員原先所要達到的目的。(圖 3.1)
圖 3.1 採用本系統工具的運作模式
‧
(schema)不盡相同。採用 Extension Table Layout 其所提出的私有欄位概念讓 租戶針對各自的需求新增、修改以及刪除其獨有的私有欄位為本研究所強調的” 份是以 Private Table Layout 的概念去進行設計,此種開發方式雖然直覺、簡 單,但當租戶的數量逐漸增加,資料表的數量也隨之增加,此時,軟體開發人 員在多租戶應用程式的維運上需要花費更多的成本。雖然 Extension Table‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
24
Layout 無法減少租戶數量增加,資料表數量增加的問題,但其所提出的共有欄 位、私有欄位的概念,可以提供一套有效管理方式讓軟體開發人員能夠統一對 所有租戶資料表中的共有欄位進行增刪修改,因此,降低軟體開發人員在多租 戶應用程式開發以及維運上所需花費的時間成本。
3.3 系統流程
關於系統流程,主要可以分成三個階段(圖 3.2),首先,透過改寫 JDBC 的部分 API 去攔截軟體開發人員所撰寫的 SQL 語句,接下來,將 SQL 語句經由 JSqlParser 進行結構剖析,再來,從其剖析結果取得語句元素以協助系統工具以 Extension Table Layout 的邏輯進行語句轉換,最後,將轉換後的語句回傳至 JDBC 並在資 料庫中執行,影響各別租戶的資料表綱要(schema)或是資料。
圖 3.2 系統工具進行語句轉換流程圖
第一階段,如圖 3.3 所示,建立一個新類別-Multitenantstatement,此 類別去繼承原先在 JDBC 中扮演實際執行 SQL 語句以及回傳查詢結果角色的 Statement 類別(此 Statement 類別已實作 JDBC 中的 Statement 介面)。在 Multitenantstatement 類別中,基於 1.2 小節所提到的多租戶技術的開發概念,
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
25
除了既有的類別成員之外,額外增加了一個類別成員-TenantId,透過此類別 成員(TenantId)去辨識此 SQL 語句的執行對象(租戶)。
圖 3.3 Multitenantstatement 類別繼承關係圖:
藉由此類別協助系統工具取得租戶的識別碼-TenantId
圖 3.4 系統工具攔截軟體開發人員所撰寫的 SQL 語句程式碼範例
如何攔截到軟體開發人員所撰寫的 SQL 語句。站在軟體開發人員的角度,
以圖 3.4 為例,首先,會先建立與資料庫的連線(line 1-3),緊接著,建立一 個新的 Multitenantstatement 物件取代原先 Statement 物件的位置,扮演實際
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
26
執行 SQL 語句以及回傳查詢結果的角色(line 5),接下來,撰寫其所要執行的 SQL 語句(line 6),最後,利用 setTenantId()設定執行的對象(租戶),透過 executeUpdate()去執行 SQL 語句。
從圖 3.4 以及圖 3.5 清楚知道系統工具藉由 executeUpdate()攔截到軟 體開發人員所撰寫的 SQL 語句(圖 3.4 的 line 8),接下來,將 SQL 語句利用 If -Else 去判斷其語句型態(圖 3.5 的 line 6),根據判斷結果將 SQL 語句進行不 同型態的語句轉換。
第二階段,將 SQL 語句轉換成以 Extension Table Layout 邏輯表達的 SQL 語句之前,必需先透過 JSqlParser 去進行語句結構剖析,從其剖析結果獲得進 行語句轉換時所需的語句元素。最後,將取得的語句元素以 Extension Table Layout 邏輯進行重組。
第三階段,將上一階段轉換後所產生的語句傳回 executeUpdate()並在 資料庫中執行,影響個別租戶的資料表綱要(schema)或是資料。
圖 3.5 executeUpdate()的虛擬碼
3.4 系統實作方法
在上一章節說明了系統工具如何利用改寫 JDBC 的部分 API 去攔截軟體開發人員
‧
轉換時所需的語句元素。緊接著,本章節將詳細地解釋如何依據 Extension Table Layout 邏輯進行各種型態的語句轉換。3.4.1 Extension Table Layout 概念實作
在 2.2.3 小節中提到 Extension Table Layout 的概念是將所有租戶的共有欄位 提出後放置在一個共用資料表中,同時,所有租戶屬於共有欄位的欄位資料也 都存放在該共用資料表中。另外,為了滿足租戶客製化欄位的需求,替每個租 戶建立其存放私有欄位(即客製化欄位)資料的私有資料表。接下來的部分,將 了解如何實現 Extension Table Layout 所提出的共有欄位、私有欄位概念在多 租戶應用程式之資料層級設計。
在多租戶應用程式的開發過程中,資料層級的部分,軟體開發人員會依照 應用程式的需求設計一套資料表集合,以開發一個多租戶(此範例的租戶定義為 學校)選課系統為例,假定目前有 Nccu、Fju 以及 Tku 三間學校(租戶)使用這個 多租戶選課系統,根據 Extension Table Layout 所提出的概念,首先,軟體開 發人員會透過 CREATE 語句去建立三個存放所有學校共有欄位資料的共用資料表,
分別是用來存放所有學校學生共有欄位資料的 StudentInfoCommonFields、所有 學校課程共有欄位資料的 CourseInfoCommonFields 以及記錄所有學校學生選課 記錄共有欄位資料的 SelectCourseCommonFields。接下來,為了讓每個學校(租 戶)可以依據各自需求適度地客製化其資料表綱要(schema),本系統工具增加了 一個名為 CREATE EXTENSION TABLE 的語句去協助軟體開發人員建立存放學校(租 戶)其私有欄位(客製化欄位)資料的私有資料表集合,另外,藉由 ALTER 語句讓 每個學校(租戶)對其所擁有的私有資料表綱要(schema)進行欄位的增刪修改,
此一動作意味著私有欄位的增刪修改,同時,也代表著租戶擁有客製化欄位的
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
28
能力。
除此之外,由於 Extension Table Layout 會將資料表欄位拆成共有欄位、
私有欄位,共有欄位的資料存放在共用資料表中;私有欄位的資料則存放在各 租戶各自擁有的私有資料表中。為了協助系統工具進行後續的語句轉換,所以,
必須額外記錄各個共用資料表、私有資料表的欄位名稱資訊(不包含詮釋欄位名 稱)在 Columns_Metadata Table 中。
圖 3.6 是 Columns_Metadata Table 的欄位資訊存放格式。Columns_Metadata Table 主要記錄了實際在資料庫中,每個資料表所存在的欄位名稱,但不包含詮 釋欄位名稱(TenantId、Row)。
圖 3.6 Columns_Metadata Table 的欄位資訊存放格式:每一列以實際資料表名稱開頭,
以逗點分隔逐一記錄其所存在的欄位名稱(不包含詮釋欄位:TenantId、Row)
3.4.2 CREATE 語句的轉換、CREATE EXTENSION TABLE 的設計與實作
為了實現共有欄位的概念,軟體開發人員可以撰寫 CREATE 語句建立存放所有租 戶共有欄位資料的共用資料表;另外,CREATE EXTENSION TABLE 語句則是協助 軟體開發人員建立每個租戶各自擁有的私有資料表集合。
為了實現共有欄位的概念,軟體開發人員可以撰寫 CREATE 語句建立存放所有租 戶共有欄位資料的共用資料表;另外,CREATE EXTENSION TABLE 語句則是協助 軟體開發人員建立每個租戶各自擁有的私有資料表集合。