­

SCTL 涅槃重生:投入 RAL 的懷抱

《DistSQL:像數據庫一樣使用 Apache ShardingSphere》一文中,PMC 孟浩然為大家介紹了 DistSQL 的設計初衷和語法體系,並通過實戰操作展示了一條 SQL 創建分佈式數據庫表的強大能力,展現了 Apache ShardingSphere 在新形態下的交互體驗。
近期,ShardingSphere 社區對 SCTL 語法和執行引擎進行了重構,使 SCTL 完全投入 DistSQL 語法體系的懷抱,將原 SCTL 功能融入到 RAL 語法中,使 ShardingSphere 管理語言更加統一。本文將帶領讀者深入了解這次重構的意義,並通過實例一一解析新的 RAL 語句,感受 ShardingSphere 讓用戶體驗更加美好的追求態度。

作者簡介

江龍滔
SphereEx 中間件研發工程師,Apache ShardingSphere Committer。 目前主要負責 DistSQL 及權限相關特性的設計和研發。
 
蘭城翔
SphereEx 中間件研發工程師,Apache ShardingSphere Contributor。 目前專註於 DistSQL 的設計和研發。

前情回顧:什麼是 RAL

RAL 是 DistSQL 語法的一個分類,DistSQL 包含了 RDL、RQL 和 RAL 這三種具體類型。
  • RDL(Resource & Rule Definition Language)負責資源和規則的創建、修改和刪除;
  • RQL(Resource & Rule Query Language)負責資源和規則的查詢和展現;
  • RAL(Resource & Rule Administration Language)提供對資源和規則的高級控制能力。

什麼是 SCTL

SCTL(ShardingSphere Control Language)是 Apache ShardingSphere 的控制語言,負責 Hint、事務類型切換、分片執行計劃查詢等增量功能的操作。
 
SCTL 包含以下語法:
語句
說明
sctl:set transaction_type=XX
修改當前連接的事務類型, 支持 LOCAL,XA,BASE。例:sctl:set transaction_type=XA
sctl:show transaction_type
查詢當前連接的事務類型
sctl:show cached_connections
查詢當前連接中緩存的物理數據庫連接個數
sctl:explain SQL
查看邏輯 SQL 的執行計劃,例:sctl:explain select * from t_order;
sctl:hint set PRIMARY_ONLY=true
針對當前連接,是否將數據庫操作強制路由到主庫
sctl:hint set DatabaseShardingValue=yy
針對當前連接,設置 hint 僅對數據庫分片有效,並添加分片值,yy:數據庫分片值
sctl:hint addDatabaseShardingValue xx=yy
針對當前連接,為表 xx 添加分片值 yy,xx:邏輯表名稱,yy:數據庫分片值
sctl:hint addTableShardingValue xx=yy
針對當前連接,為表 xx 添加分片值 yy,xx:邏輯表名稱,yy:表分片值
sctl:hint clear
針對當前連接,清除 hint 所有設置
sctl:hint show status
針對當前連接,查詢 hint 狀態,primary_only:true/false,sharding_type:databases_only/databases_tables
sctl:hint show table status
針對當前連接,查詢邏輯表的 hint 分片值

為何重構

1、SCTL 功能實現於 v3.1.0 時期[1],彼時 ShardingSphere 還沒有提出 DistSQL 的概念。如今,DistSQL 提供了功能更加豐富、概念更加統一的新 API,將 SCTL 的功能融入到 RAL 中,可以降低用戶的理解成本,避免為用戶帶來困惑。
 
2、SCTL 語法使用了特殊的前綴字符 sctl: 作為標識,在 SQL 執行時沒有經過 Parser 引擎,而是通過字符串前綴匹配的方式進行解析的。現在 DistSQL 已經實現了完整的解析流程,可以使用規範的語法解析器來處理輸入語句,減少特殊代碼。
 
3、尤其重要的是,原來的 SCTL 語法,有點不像真正的 SQL 語句。隨着 5.0.0 版本的發佈,ShardingSphere 已經推出了 DistSQL 這樣一套完整的資源和規則管理方式,ShardingSphere 控制語句也可以變得更像 SQL,因此,社區將 SCTL 語法重構提上了日程。

重構解析

經過 ShardingSphere 社區的精心設計和細緻討論,SCTL 語法將由新的 RAL 語法代替[2],前後變化如下表所示:
調整前
調整後
sctl:set transaction_type=XX
set variable transaction_type=XX
sctl:show transaction_type
show variable transaction_type
sctl:show cached_connections
show variable cached_connections
sctl:explain SQL
preview SQL
sctl:hint set PRIMARY_ONLY=true
set readwrite_splitting hint source = [auto / write]
sctl:hint set DatabaseShardingValue=yy
set sharding hint database_value = yy;
sctl:hint addDatabaseShardingValue xx=yy
add sharding hint database_value xx= yy;
sctl:hint addTableShardingValue xx=yy
add sharding hint table_value xx = yy
sctl:hint clear
clear [hint / sharding hint / readwrite_splitting hint]
sctl:hint show status
show [sharding / readwrite_splitting] hint status
sctl:hint show table status
歸入 【show sharding hint status】
下面讓我們對這些語句一一進行解析:
show variable transaction_type
查詢當前連接的事務類型
  • 輸入命令
mysql> show variable transaction_type;  
  • 輸出效果
+------------------+
| TRANSACTION_TYPE |
+------------------+
| LOCAL            |
+------------------+
set variable transaction_type
修改當前連接的事務類型,支持的類型有:LOCAL, XA, BASE(不區分大小寫)。
  • 輸入命令
mysql> set variable transaction_type=XA;
  • 輸出效果
a. 設置成功,響應 Query OK, 0 rows affected;
b. 再次執行 show variable transaction_type; 顯示事務類型已經改變為 XA;
 
show variable cached_connection
查詢當前連接中緩存的物理數據庫連接個數。
  • 輸入命令
mysql> show variable cached_connections;
  • 輸出效果
+--------------------+
| CACHED_CONNECTIONS |
+--------------------+
| 0                  |
+--------------------+
preview SQL
預覽實際 SQL。此處以讀寫分離場景為例,preview 語法支持任意 SQL 語句。
  • 輸入命令
mysql> preview select * from t_order;
  • 輸出效果
+-----------------+----------------------------------------------+
| datasource_name | sql                                          |
+-----------------+----------------------------------------------+
| read_ds_0       | select * from t_order ORDER BY order_id ASC  |
| read_ds_1       | select * from t_order ORDER BY order_id ASC  |
+-----------------+----------------------------------------------+
*註:以下為讀寫分離場景 Hint 示例,示例中使用了讀寫分離 + 分片的規則配置,配置如下:
rules:
- !READWRITE_SPLITTING
  dataSources:
    ds_0:
      writeDataSourceName: write_ds_0
      readDataSourceNames: 
        - read_ds_0
    ds_1:
      writeDataSourceName: write_ds_1
      readDataSourceNames: 
        - read_ds_1
- !SHARDING
  tables:
    t_order:
      actualDataNodes: ds_${0..1}.t_order
  defaultDatabaseStrategy:
    standard:
      shardingColumn: user_id
      shardingAlgorithmName: database_inline
  defaultTableStrategy:
    none:
  shardingAlgorithms:
    database_inline:
      type: INLINE
      props:
        algorithm-expression: ds_${user_id % 2}
show readwrite_splitting hint status
針對當前連接,查詢 readwrite_splitting 的 hint 狀態。
  • 輸入命令
mysql> show readwrite_splitting hint status;
  • 輸出效果
+--------+
| source |
+--------+
| auto   |
+--------+
set readwrite_splitting hint source
針對當前連接,設置讀寫分離的路由策略(自動路由或強制到寫庫)。
source 支持的類型有:AUTO , WRITE(不區分大小寫)
  • AUTO:讀寫分離自動路由
  • WRITE:強制路由到主庫
 
  • 輸入命令
mysql> set readwrite_splitting hint source=write;
  • 輸出效果
a. 設置成功,響應 Query OK, 0 rows affected;
b. 再次執行 show readwrite_splitting hint status; 顯示 source 值已經改變為 write;
c. 執行 preview select * from t_order; 能夠看到查詢 SQL 將會路由到主庫:
mysql> preview select * from t_order;
+-----------------+----------------------------------------------+
| datasource_name | sql                                          |
+-----------------+----------------------------------------------+
| write_ds_0      | select * from t_order ORDER BY order_id ASC  |
| write_ds_1      | select * from t_order ORDER BY order_id ASC  |
+-----------------+----------------------------------------------+
clear readwrite_splitting hint
針對當前連接,清除 readwrite_splitting 的 hint 設置。
  • 輸入命令
mysql> clear readwrite_splitting hint;
  • 輸出效果
a. 清除成功,響應 Query OK, 0 rows affected
b. 將 readwrite_splitting hint 的所有設置恢復到初始狀態,可通過 show readwrite_splitting hint status; 命令查看 clear 的結果。
*註:以下為分片場景 Hint 示例,分庫和分表均使用了 Hint 算法,使用的分片配置如下:
rules:
- !SHARDING
  tables:
    t_order_item:
      actualDataNodes: ds_${0..1}.t_order_item_${0..1}
      databaseStrategy:
        hint:
          shardingAlgorithmName: database_inline
      tableStrategy:
        hint:
          shardingAlgorithmName: table_inline
  shardingAlgorithms:
    database_inline:
      type: HINT_INLINE
      props:
        algorithm-expression: ds_${Integer.valueOf(value) % 2}
    table_inline:
      type: HINT_INLINE
      props:
        algorithm-expression: t_order_item_${Integer.valueOf(value) % 2}
show sharding hint status
針對當前連接,查詢 sharding 的 hint 狀態。
  • 輸入命令
mysql> show sharding hint status;
  • 輸出效果
以下是初始狀態的輸出值:
  • 驗證查詢路由,輸入命令
preview select * from t_order_item;
  • 輸出效果
此時沒有 hint 值,查詢使用全路由
set sharding hint database_value;
針對當前連接,設置 hint 僅對數據庫分片有效,並添加分片值 1。
  • 輸入命令
mysql> set sharding hint database_value = 1;
  • 輸出效果
a. 設置成功,響應 Query OK, 0 rows affected;
b. 執行 show sharding hint status; 顯示 t_order_item 表對應的 database_sharding_values 值為 ‘1’, 且 sharding_type 值更新為 ‘databases_only’;
c. 執行 preview select * from t_order_item; SQL 全部路由到 ds_1:
說明:根據 YAML 配置中的分片規則,當 database_value 設置為奇數時路由到 ds_1,設置為偶數時路由到 ds_0。
add sharding hint database_value;
針對當前連接,為表 t_order_item 添加分片值。
  • 輸入命令
mysql> add sharding hint database_value t_order_item = 5;
  • 輸出效果
a. 設置成功,響應 Query OK, 0 rows affected;
b. 執行 show sharding hint status; 顯示 t_order_item 表對應的 database_sharding_values 值為 ‘5’,且 sharding_type 值更新為 ‘databases_tables’;
c. 執行 preview select * from t_order_item; SQL 全部路由到 ds_1:
  • 再次輸入 add 命令,添加一個偶數值
mysql> add sharding hint database_value t_order_item = 10;
  • 輸出效果:
a. 添加成功,響應 Query OK, 0 rows affected;
b. 執行 show sharding hint status; 顯示 t_order_item 表對應的 database_sharding_values 值為 ‘5,10’:
c. 執行 preview select * from t_order_item; SQL 路由包含了 ds_0 和 ds_1:(因為 hint 值包含奇數和偶數,將目標數據源全部包含在內)
add sharding hint table_value;
針對當前連接,為表 t_order_item 添加分片值。
  • 輸入命令
mysql> add sharding hint table_value t_order_item = 0;
  • 輸出效果
a. 設置成功,響應 Query OK, 0 rows affected;
b. 執行 show sharding hint status; 顯示 t_order_item 表對應的 database_sharding_values 值為 ‘5,10’,table_sharding_values 的值為 ‘0’:
c. 執行 preview select * from t_order_item; 路由情況如下圖,每個庫只查詢 t_order_item_0:
說明:根據 YAML 配置中的分片規則,當 table_value 設置為奇數時路由到 t_order_item_1,設置為偶數時路由到 t_order_item_0。
add sharding hint database_value 類似,add sharding hint database_value 也可以設置多個 hint 值,以覆蓋更多的分片。
clear sharding hint
針對當前連接,清除 sharding 的 hint 設置。
  • 輸入命令
mysql> clear sharding hint;

輸出效果

a. 清除成功,響應 Query OK, 0 rows affected
b. 將 sharding hint 的所有設置恢復到初始狀態,可通過 show sharding hint status; 命令查看 clear 的結果。初始狀態如下:
clear hint
這是一個特殊的指令,包含 clear readwrite_splitting hintclear sharding hint 的能力,將讀寫分離和分片的 hint 值全部清除,回歸初始狀態。
  • 任意設置 hint 值,再執行命令
mysql> clear hint;
  • 輸出效果
a. 清除成功,響應 Query OK, 0 rows affected
b. 將 readwrite_splitting hint 和 sharding hint 的所有設置恢復到初始狀態,可通過 show readwrite_splitting hint status;show sharding hint status; 命令查看 clear 的結果。
 
*註:特別說明:若需使用 Hint 相關 DistSQL 功能,需要啟用 ShardingSphere-Proxy 的配置項 `proxy-hint-enabled`,說明信息請參考:

更多 RAL 語句

除了包含原有 SCTL 語句的功能,RAL 語句還提供彈性伸縮、實例熔斷、讀寫分離讀庫禁用這樣的實用管理功能,歡迎讀者前往官網閱讀詳細文檔,了解 RAL 的更多使用場景: //shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-proxy/distsql/syntax/ral/

結語

以上就是本次分享的全部內容,如果讀者對 Apache ShardingSphere 有任何疑問或建議,歡迎在 GitHub issue 列表提出,也可提交 Pull Request 參與到開源社區,也歡迎在中文社區中討論。
 
 
 
 
參考信息

歡迎關注公眾號第一時間了解咨訊