為應對突發的數據庫請求流量、資源消耗過高的語句訪問以及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選項進行限流。
  • 限流結果
    一條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設置的最大并發度而執行失敗。

  • 示例

    假設需要創建一條名為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。

刪除限流規則

說明 被刪除的限流規則會立即失效,此時該規則下等待隊列中的SQL語句全部會被正常執行。
  • 刪除指定限流規則:
    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查詢。
關閉慢SQL限流觸發器

刪除由SLOW_SQL_CCL GO創建的限流觸發器,會同時刪除由限流觸發器創建的限流規則。語法如下:

SLOW_SQL_CCL BACK
查看慢SQL限流觸發器
  • 語法
    SLOW_SQL_CCL SHOW
  • 示例

    plan_cache和ccl_rules里以模版ID作為join key的一次inner join。

    查看限流情況
調整慢SQL的閾值
  • SLOW_SQL_CCL GO語句中設置SLOW_SQL_TIME參數的值。
  • 在一鍵開啟SQL限流之前,設置用戶變量SLOW_SQL_TIME。如下:
    SLOW_SQL_CCL GO;
  • 在控制臺上設置系統參數SLOW_SQL_TIME
說明 后面的設置方式會被前面的設置方式所覆蓋。