為應對突發的數據庫請求流量、資源消耗過高的語句訪問以及SQL訪問模型的變化等問題,PolarDB-X提供了節點級別的SQL限流功能來限制造成上述問題的SQL執行,從而保證實例的持續穩定運行。本文介紹如何使用SQL限流功能。
創建限流規則
- 語法
CREATE CCL_RULE [ IF NOT EXISTS ] `ccl_rule_name` ON `database`.`table` TO '<usename>'@'<host>' FOR { UPDATE | SELECT | INSERT | DELETE } [ filter_options ] with_options filter_options: [ FILTER BY KEYWORD(‘KEYWORD1’, ’KEYWORD2’,…) ] [ FILTER BY TEMPLATE(‘template_id’) ] with_options: WITH MAX_CONCURRENCY = value1 [ , WAIT_QUEUE_SIZE = value2 ] [ , WAIT_TIMEOUT = value3 ] [ ,FAST_MATCH = { 0 , 1 }]
表 1. 參數說明 參數 是否必選 說明 限流規則匹配參數 `ccl_rule_name`
必選 限流規則的名稱。 說明 為避免名稱與SQL關鍵字沖突,建議在規則名稱前后各加一個反引號(`)。`database`.`table`
必選 數據庫和數據表的名稱,支持使用星號(*)表示任意匹配。 說明 為避免名稱與SQL關鍵字沖突,建議在庫表名稱前后各加一個反引號(`)。'<usename>'@'<host>'
必選 賬號名稱。其中Host部分支持用百分號(%)來表示任意匹配。 UPDATE | SELECT | INSERT | DELETE
必選 SQL語句類型。當前支持UPDATE、SELECT、INSERT和DELETE類型。 說明 每條限流規則僅支持傳入一種類型的SQL語句。[ filter_options ]
可選 過濾條件,支持包括如下兩種條件: - 關鍵詞(KEYWORD):查看限流規則時,關鍵詞列表會在查詢結果中被轉化為
["kwd1","kw2","kw3"...]
的字符串形式,最多支持512個字符。說明- 若關鍵字是SQL語句中的參數值,匹配時大小寫敏感。
- 若關鍵字是SQL語句中的其他詞,匹配時大小寫不敏感。
- 模版(TEMPLATE):模版編號是SQL日志中的
sql_code
值,該值是參數化后的SQL語句(SQL模版)以16進制表示的哈希值。您可以通過SHOW FULL PROCESSLIST和EXPLAIN命令查看模版編號。
限流規則行為控制參數 with_options
必選 WITH選項中支持如下4個參數來控制限流規則的行為: - MAX_CONCURRENCY:匹配到該限流規則的SQL語句的最大并發度,超過后進入等待隊列。
取值范圍:[0~231 - 1],默認值為0。
- WAIT_QUEUE_SIZE:超過并發度后的最大等待隊列長度。當等待隊列長度超過該值后,SQL語句將報錯。在隊列中的語句仍然占用了線程資源,排隊過多時也可能導致內存耗盡。
取值范圍:[0~231 - 1],默認值為0。
- WAIT_TIMEOUT:SQL語句在等待隊列中的最長等待時間,超過該等待時間后,SQL語句將報錯。
取值范圍:[0~231 - 1],單位為秒,默認值為600。
- FAST_MATCH:是否開啟Cache來加速匹配。開啟后,PolarDB-X會將模版編號作為Cache key的一部分,匹配結果作為value進行緩存,來加速匹配速度。
取值范圍:0表示關閉,1表示開啟,默認開啟。
說明- 創建限流規則時,需從上述4個行為控制參數中至少選擇一個傳入。
- 當MAX_CONCURRENCY為默認值(0)時,可能會使匹配到的所有SQL返回錯誤。此時,建議您顯式指定該參數為非0的值。
- PolarDB-X是分布式云原生數據庫,計算層由多個節點組成,因此每個節點的并發度之和是整個實例的并發數最大值。在負載不均衡的情況下,整個實例的受限制SQL并發數可能無法達到最大并發數。
說明 僅當一個SQL語句滿足所有的匹配參數條件時,才會根據該規則的WITH選項進行限流。 - 關鍵詞(KEYWORD):查看限流規則時,關鍵詞列表會在查詢結果中被轉化為
- 限流結果一條SQL匹配到該規則后,根據限流規則中WITH選項里配置的參數,會出現如下幾種結果:
- RUN(可運行)
若并發度還未達到最大并發度(即MAX_CONCURRENCY參數值沒有達到最大值),該SQL正常執行不會被限流。
- WAIT(等待中)
若并發度已經達到最大并發度,但等待隊列長度還未達到最大長度(即WAIT_QUEUE_SIZE參數值沒有達到最大值),該SQL進入等待狀態,直到進入可運行(RUN)狀態,或者等待超時(WAIT_TIMEOUT)狀態。
您可以通過如下命令查看由于匹配到限流規則而等待的SQL語句:SHOW FULL PROCESSLIST;
返回結果示例如下:+----+---------------+-----------------+----------+-------------------------------+------+-------+-----------------------+-----------------+ | ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | SQL_TEMPLATE_ID | +----+---------------+-----------------+----------+-------------------------------+------+-------+-----------------------+-----------------+ | 2 | polardbx_root | ***.*.*.*:62787 | polardbx | Query | 0 | | show full processlist | NULL | | 1 | polardbx_root | ***.*.*.*:62775 | polardbx | Query(Waiting-selectrulereal) | 12 | | select 1 | 9037e5e2 | +----+---------------+-----------------+----------+-------------------------------+------+-------+-----------------------+-----------------+ 2 rows in set (0.08 sec)
從上述查詢結果可以看出:SQL語句
select 1
由于限流規則selectrulereal
而處于等待(Waiting)狀態。 - WAIT_TIMEOUT(等待超時)
SQL語句進入等待狀態后,當等待時間超過最長等待時間(即WAIT_TIMEOUT參數值)時,該語句將會返回錯誤。
例如,設置了一條最長等待時間為10秒的限流規則,執行
SELECT sleep(11)
語句時會因為等待超時而報錯,示例如下:ERROR 3009 (HY000): [11a07e23fd800000][30.225.180.55:8527][polardbx]Exceeding the max concurrency 0 of ccl rule selectrulereal after waiting for 10060 ms
- KILL(結束)
并發度和等待隊列長度均已經達到最大值,客戶端將收到超過最大并發度的報錯,報錯信息中會包含匹配上的限流規則的名稱。
例如,在并發度和等待隊列長度均已經達到最大值后執行SELECT 1;
命令,會出現如下報錯:ERROR 3009 (HY000): [11a07c4425c00000][**.***.***.**:8527][polardbx]Exceeding the max concurrency 0 of ccl rule selectrulereal
上述結果表示:該SQL語句
SELECT 1;
由于超出了限流規則selectrulereal
設置的最大并發度而執行失敗。
- RUN(可運行)
- 示例
假設需要創建一條名為
selectrule
的規則,用于限制由'ccltest'@'%'
用戶發起的,包含cclmatched
關鍵字的,且對任意表執行SELECT操作的SQL語句,同時將最大并發度設置為10。規則創建語句如下:
CREATE CCL_RULE IF NOT EXISTS `selectrule` ON *.* TO 'ccltest'@'%' FOR SELECT FILTER BY KEYWORD('cclmatched') WITH MAX_CONCURRENCY=10;
查看限流規則
- 語法
- 查看指定限流規則
語法如下:
SHOW CCL_RULE `ccl_rule_name1` [, `ccl_rule_name2` ]
- 查看所有限流規則
語法如下:
SHOW CCL_RULES
- 查看指定限流規則
- 示例使用如下命令查看當前數據庫下所有的限流規則:
SHOW CCL_RULES \G
返回結果如下:*************************** 1. row *************************** NO.: 1 RULE_NAME: selectrulereal RUNNING: 2 WAITING: 29 KILLED: 0 MATCH_HIT_CACHE: 21374 TOTAL_MATCH: 21406 ACTIVE_NODE_COUNT: 2 MAX_CONCURRENCY_PER_NODE: 1 WAIT_QUEUE_SIZE_PER_NODE: 100 WAIT_TIMEOUT: 600 FAST_MATCH: 1 SQL_TYPE: SELECT USER: ccltest@% TABLE: *.* KEYWORDS: ["SELECT"] TEMPLATEID: NULL CREATED_TIME: 2020-11-26 17:04:08
表 2. 參數說明 參數 說明 NO. 匹配優先級,數字越小,優先級越高。 RULE_NAME 限流規則名稱。 RUNNING 匹配到該限流規則且正常執行的SQL語句數量。 WAITING 匹配到該限流規則且正在等待隊列里的查詢數量。 KILLED 匹配到該限流規則且被KILL的SQL語句數量。 MATCH_HIT_CACHE 匹配到該限流規則且命中Cache的SQL語句數量。 TOTAL_MATCH 匹配到該限流規則命中的總次數。 ACTIVE_NODE_COUNT 計算層中啟用了SQL限流的節點數。 MAX_CONCURRENCY_PER_NODE 每個計算節點的并發度。 WAIT_QUEUE_SIZE_PER_NODE 每個計算節點上等待隊列的最大長度。 WAIT_TIMEOUT SQL語句在等待隊列的最大等待時間。 FAST_MATCH 是否啟動緩存加速匹配速度。 SQL_TYPE SQL語句類型。 USER 用戶名。 TABLE 數據庫表。 KEYWORDS 關鍵詞列表。 TEMPLATEID SQL模版的編號。 CREATED_TIME 創建時間(本地時間),格式為 yyyy-MM-dd HH:mm:ss
。
刪除限流規則
- 刪除指定限流規則:
DROP CCL_RULE [ IF EXISTS ] `ccl_rule_name1` [, `ccl_rule_name2`, ...]
- 刪除所有限流規則:
CLEAR CCL_RULES
慢SQL限流觸發器
開啟慢SQL限流觸發器- 語法
SLOW_SQL_CCL GO [ SQL_TYPE [MAX_CONCURRENCY] [SLOW_SQL_TIME] [MAX_CCL_RULE]]
- 參數說明
- SQL_TYPE:取值為ALL,SELECT,UPDATE,INSERT,默認為SELECT。相同語句類型的命令,有更新作用。
- MAX_CONCURRENCY:默認值為CPU核數的一半。
- SLOW_SQL_TIME:默認值為系統參數SLOW_SQL_TIME的值。
- MAX_CCL_RULE:可創建限流規則的個數,默認值為1000。
- 執行過程
- 遍歷整個實例的session,識別出該語句類型慢SQL的TemlateId。
- 創建針對慢SQL的限流觸發器,名稱為:_SYSTEM_SLOW_SQL_CCL_TRIGGER_{SQL_TYPE}_。
- 傳遞慢SQL的TemplateId給限流觸發器,由限流觸發器創建限流規則。
- Kill所有該語句類型的慢TemplateId查詢。
刪除由SLOW_SQL_CCL GO
創建的限流觸發器,會同時刪除由限流觸發器創建的限流規則。語法如下:
SLOW_SQL_CCL BACK
查看慢SQL限流觸發器- 語法
SLOW_SQL_CCL SHOW
- 示例
plan_cache和ccl_rules里以模版ID作為join key的一次inner join。
- 在
SLOW_SQL_CCL GO
語句中設置SLOW_SQL_TIME參數的值。 - 在一鍵開啟SQL限流之前,設置用戶變量SLOW_SQL_TIME。如下:
SLOW_SQL_CCL GO;
- 在控制臺上設置系統參數SLOW_SQL_TIME。