為應(yīng)對突發(fā)的數(shù)據(jù)庫請求流量、資源消耗過高的語句訪問以及SQL訪問模型的變化等問題,PolarDB-X 1.0提供了節(jié)點級別的SQL限流功能來限制造成上述問題的SQL執(zhí)行,從而保證實例的持續(xù)穩(wěn)定運行。本文介紹如何使用SQL限流功能。
前提條件
PolarDB-X 1.0實例版本需為5.4.12及以上。關(guān)于如何查看實例版本,請參見查看實例版本。
創(chuàng)建限流規(guī)則
- 語法
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. 參數(shù)說明 參數(shù) 是否必選 說明 限流規(guī)則匹配參數(shù) `ccl_rule_name`
必選 限流規(guī)則的名稱。 說明 為避免名稱與SQL關(guān)鍵字沖突,建議在規(guī)則名稱前后各加一個反引號(`)`database`.`table`
必選 數(shù)據(jù)庫和數(shù)據(jù)表的名稱,支持使用星號(*)表示任意匹配。 說明 為避免名稱與SQL關(guān)鍵字沖突,建議在庫表名稱前后各加一個反引號(`)。'<usename>'@'<host>'
必選 賬號名稱。其中Host部分支持用百分號(%)來表示任意匹配。 UPDATE | SELECT | INSERT | DELETE
必選 SQL語句類型。當(dāng)前支持UPDATE、SELECT、INSERT和DELETE類型。 說明 每條限流規(guī)則僅支持傳入一種類型的SQL語句。[ filter_options ]
可選 過濾條件,支持如下兩種條件: - 關(guān)鍵詞(KEYWORD):查看限流規(guī)則時,關(guān)鍵詞列表會在查詢結(jié)果中被轉(zhuǎn)化為
["kwd1","kw2","kw3"...]
的字符串形式,最多支持512個字符。說明- 若關(guān)鍵字是SQL語句中的參數(shù)值,匹配時大小寫敏感。
- 若關(guān)鍵字是SQL語句中的其他詞,匹配時大小寫不敏感。
- 模版(TEMPLATE):模版編號是SQL日志中的
sql_code
值,該值是參數(shù)化后的SQL語句(SQL模版)以16進(jìn)制表示的哈希值。您可以通過SHOW FULL PROCESSLIST和EXPLAIN命令查看模版編號。
限流規(guī)則行為控制參數(shù) with_options
必選 WITH選項中支持如下4個參數(shù)來控制限流規(guī)則的行為: - MAX_CONCURRENCY:匹配到該限流規(guī)則的SQL語句的最大并發(fā)度,超過后進(jìn)入等待隊列。
取值范圍:[0~231 - 1],默認(rèn)值為0。
- WAIT_QUEUE_SIZE:超過并發(fā)度后的最大等待隊列長度。當(dāng)?shù)却犃虚L度超過該值后,SQL語句將報錯。在隊列中的語句仍然占用了線程資源,排隊過多時也可能導(dǎo)致內(nèi)存耗盡。
取值范圍:[0~231 - 1],默認(rèn)值為0。
- WAIT_TIMEOUT:SQL語句在等待隊列中的最長等待時間,超過該等待時間后,SQL語句將報錯。
取值范圍:[0~231 - 1],單位為秒,默認(rèn)值為600。
- FAST_MATCH:是否開啟Cache來加速匹配。開啟后,PolarDB-X 1.0會將模版編號作為Cache key的一部分,匹配結(jié)果作為value進(jìn)行緩存,來加速匹配速度。
取值范圍:0表示關(guān)閉,1表示開啟,默認(rèn)開啟。
說明- 創(chuàng)建限流規(guī)則時,需從上述4個行為控制參數(shù)中至少選擇一個傳入。
- 當(dāng)MAX_CONCURRENCY為默認(rèn)值(0)時,可能會使匹配到的所有SQL返回錯誤。此時,建議您顯式指定該參數(shù)為非0的值。
- PolarDB-X 1.0是分布式云原生數(shù)據(jù)庫,計算層由多個節(jié)點組成,因此每個節(jié)點的并發(fā)度之和是整個實例的并發(fā)數(shù)最大值。在負(fù)載不均衡的情況下,整個實例的受限制SQL并發(fā)數(shù)可能無法達(dá)到最大并發(fā)數(shù)。
說明 僅當(dāng)一個SQL語句滿足所有的匹配參數(shù)條件時,才會根據(jù)該規(guī)則的WITH選項進(jìn)行限流。 - 關(guān)鍵詞(KEYWORD):查看限流規(guī)則時,關(guān)鍵詞列表會在查詢結(jié)果中被轉(zhuǎn)化為
- 限流結(jié)果一條SQL匹配到該規(guī)則后,根據(jù)限流規(guī)則中WITH選項里配置的參數(shù),會出現(xiàn)如下幾種結(jié)果:
- RUN(可運行)
若并發(fā)度還未達(dá)到最大并發(fā)度(即MAX_CONCURRENCY參數(shù)值),該SQL正常執(zhí)行不會被限流。
- WAIT(等待中)
若并發(fā)度已經(jīng)達(dá)到最大并發(fā)度,但等待隊列長度還未達(dá)到最大長度(即WAIT_QUEUE_SIZE參數(shù)值),該SQL進(jìn)入等待狀態(tài),直到進(jìn)入可運行(RUN)狀態(tài),或者等待超時(WAIT_TIMEOUT)狀態(tài)。
您可以通過如下命令查看由于匹配到限流規(guī)則而等待的SQL語句:mysql> SHOW FULL PROCESSLIST;
返回結(jié)果示例如下:+----+---------------+-----------------+----------+-------------------------------+------+-------+-----------------------+-----------------+ | 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)
從上述查詢結(jié)果可以看出:SQL語句
select 1
由于限流規(guī)則selectrulereal
而處于等待(Waiting)狀態(tài)。 - WAIT_TIMEOUT(等待超時)
SQL語句進(jìn)入等待狀態(tài)后,當(dāng)?shù)却龝r間超過最長等待時間(即WAIT_TIMEOUT參數(shù)值)時,該語句將會返回錯誤。
例如,設(shè)置了一條最長等待時間為10秒的限流規(guī)則,執(zhí)行
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(結(jié)束)
并發(fā)度和等待隊列長度均已經(jīng)達(dá)到最大值,客戶端將收到提示超過最大并發(fā)度的報錯,報錯信息中會包含匹配上的限流規(guī)則的名稱。
例如,在并發(fā)度和等待隊列長度均已經(jīng)達(dá)到最大值后執(zhí)行SELECT 1;
命令,會出現(xiàn)如下報錯:ERROR 3009 (HY000): [11a07c4425c00000][**.***.***.**:8527][polardbx]Exceeding the max concurrency 0 of ccl rule selectrulereal
上述結(jié)果表示:該SQL語句
SELECT 1;
由于超出了限流規(guī)則selectrulereal
設(shè)置的最大并發(fā)度而執(zhí)行失敗。
- RUN(可運行)
- 示例
假設(shè)需要創(chuàng)建一條名為
selectrule
的規(guī)則,用于限制由'ccltest'@'%'
用戶發(fā)起的,包含cclmatched
關(guān)鍵字的,且對任意表執(zhí)行SELECT操作的SQL語句,同時將最大并發(fā)度設(shè)置為10。規(guī)則創(chuàng)建語句如下:
CREATE CCL_RULE IF NOT EXISTS `selectrule` ON *.* TO 'ccltest'@'%' FOR SELECT FILTER BY KEYWORD('cclmatched') WITH MAX_CONCURRENCY=10;
查看限流規(guī)則
- 語法
- 查看指定限流規(guī)則
語法如下:
SHOW CCL_RULE `ccl_rule_name1` [, `ccl_rule_name2` ]
- 查看所有限流規(guī)則
語法如下:
SHOW CCL_RULES
- 查看指定限流規(guī)則
- 示例使用如下命令查看當(dāng)前數(shù)據(jù)庫下所有的限流規(guī)則:
mysql> SHOW CCL_RULES \G
返回結(jié)果如下:*************************** 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. 參數(shù)說明 參數(shù) 說明 NO. 匹配優(yōu)先級,數(shù)字越小,優(yōu)先級越高。 RULE_NAME 限流規(guī)則名稱。 RUNNING 匹配到該限流規(guī)則且正常執(zhí)行的SQL語句數(shù)量。 WAITING 匹配到該限流規(guī)則且正在等待隊列里的查詢數(shù)量。 KILLED 匹配到該限流規(guī)則且被KILL的SQL語句數(shù)量。 MATCH_HIT_CACHE 匹配到該限流規(guī)則且命中Cache的SQL語句數(shù)量。 TOTAL_MATCH 匹配到該限流規(guī)則的總次數(shù)。 ACTIVE_NODE_COUNT 計算層中啟用了SQL限流的節(jié)點數(shù)。 MAX_CONCURRENCY_PER_NODE 每個計算節(jié)點的并發(fā)度。 WAIT_QUEUE_SIZE_PER_NODE 每個計算節(jié)點上等待隊列的最大長度。 WAIT_TIMEOUT SQL語句在等待隊列的最大等待時間。 FAST_MATCH 是否啟動緩存加速匹配速度。 SQL_TYPE SQL語句類型。 USER 用戶名。 TABLE 數(shù)據(jù)庫表。 KEYWORDS 關(guān)鍵詞列表。 TEMPLATEID SQL模版的編號。 CREATED_TIME 創(chuàng)建時間(本地時間),格式為 yyyy-MM-dd HH:mm:ss
。
刪除限流規(guī)則
- 刪除指定限流規(guī)則:
DROP CCL_RULE [ IF EXISTS ] `ccl_rule_name1` [, `ccl_rule_name2`, ...]
- 刪除所有限流規(guī)則:
CLEAR CCL_RULES