為應(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)行限流。
  • 限流結(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í)行失敗。

  • 示例

    假設(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
  • 示例
    使用如下命令查看當(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ī)則會立即失效,此時該規(guī)則下等待隊列中的SQL語句全部會被正常執(zhí)行。
  • 刪除指定限流規(guī)則:
    DROP CCL_RULE [ IF EXISTS ] `ccl_rule_name1` [, `ccl_rule_name2`, ...]
  • 刪除所有限流規(guī)則:
    CLEAR CCL_RULES