當資料庫面臨高並發或特定SQL消耗過多資源時,RDS PostgreSQL提供的SQL限流功能可通過限制SQL並發數,保障資料庫穩定運行。該功能適用於防止惡意攻擊以及控制資源使用(如備份、監控)等情境,以避免因個別SQL語句引發資料庫整體效能下降或服務中斷。
前提條件
注意事項
計費說明
此功能免費。
建立和刪除外掛程式
通過控制台建立和刪除外掛程式
訪問RDS執行個體列表,在上方選擇地區,然後單擊目標執行個體ID。
在左側導覽列單擊外掛程式管理。
在外掛程式概覽頁面中,找到rds_ccl外掛程式,並單擊安裝。

您也可以在管理外掛程式頁面,搜尋rds_ccl外掛程式,並單擊操作列的安裝。
在彈出的視窗中選擇目標資料庫和高許可權帳號後,單擊安裝,將外掛程式安裝至目標資料庫。
當執行個體的狀態由實例維護中變為运行中時,表示外掛程式已成功安裝。
在管理外掛程式頁面的已安裝外掛程式頁簽,單擊目標外掛程式操作列的卸載,卸載目標外掛程式。
通過SQL命令建立和刪除外掛程式
請使用高許可權帳號執行如下命令。
建立外掛程式
CREATE EXTENSION rds_ccl;刪除外掛程式
DROP EXTENSION rds_ccl;
使用樣本
請使用高許可權帳號執行如下命令。
建立SQL限流規則
使用情境
該函數只能在主執行個體中調用,用於建立一個SQL限流規則。
文法
文法一:根據設定的SQL語句進行限流。
SELECT rds_add_ccl_rule( query_string varchar, node_tag int, max_concurrency int, max_waiting int, is_enabled boolean, comment varchar, -- 可選 search_path varchar -- 可選 );文法二:根據設定的query_id進行限流。
SELECT rds_add_ccl_rule_with_query_id( query_id bigint, node_tag int, max_concurrency int, max_waiting int, is_enabled boolean, query_string varchar, -- 可選 comment varchar, -- 可選 search_path varchar -- 可選(1.2及之後版本支援) );
參數解釋
參數 | 類型 | 說明 |
query_string | varchar | 需要限流的SQL語句。 配置時,使用 例如: 該函數根據query_string取值計算query_id,再根據query_id匹配同類SQL進行限流。query_id的更多資訊,請參見query_id簡介。 |
query_id | bigint | 需要限流的SQL語句的query_id,更多資訊,請參見query_id簡介。 |
node_tag | int | 限流的節點。
說明 建立SQL限流規則函數中,此參數僅表示規則可應用的範圍,不會自動在唯讀執行個體中生效。如果您想要此規則在唯讀執行個體中發揮SQL限流作用,需要手動載入,具體操作,請參見載入SQL限流規則。 |
max_concurrency | int | 限制此類SQL的最大並發數。 取值範圍:0~100000 |
max_waiting | int | 限制此類SQL的最大等待數,超過設定上限時,新的SQL會導致PostgreSQL核心觸發ABORT,終止並復原事務。 取值範圍:0~100000 |
is_enabled | boolean | 該規則是否生效。
|
comment | varchar | 規則描述。 |
search_path | varchar | 目標限流SQL運行時的模式搜尋路徑(search_path),如果配置為空白字串( |
注意事項
在文法一中,comment和search_path如果不配置,可以填寫為空白字串(
''),如果配置為NULL,則函數不會進行任何操作而直接返回。在文法二中:
query_string和comment如果不配置,可以填寫為空白字串(
''),如果配置為NULL,則函數不會進行任何操作而直接返回。如果同時配置了query_id和query_string,AliPG核心將以query_id為準進行SQL限流。
該函數會返回ccl_id,ccl_id是當前資料庫下限流規則的唯一標識。
SQL樣本
在主執行個體的ccl_test資料庫中,有資料表ccl_tbl,建立SQL限流規則:
對所有的
SELECT * FROM ccl_tbl語句(假設其query_id=1)進行限流。最多允許3條此類SQL並發執行。
最多允許2個此類SQL等待。
規則建立成功後立即生效。
文法一:
SELECT rds_add_ccl_rule( $$SELECT * FROM ccl_tbl;$$, -- 待限流的SQL語句,使用$$包裹 1, -- 僅限制主執行個體 3, -- 最多允許3條此類SQL並發執行 2, -- 最多允許2個此類SQL等待 true, -- 規則立即生效 'limit constant select', -- 規則描述 '' -- 使用預設的search_path );文法二:
SELECT rds_add_ccl_rule_with_query_id( 1, -- 待限流的SQL語句的query_id 1, -- 僅限制主執行個體 3, -- 最多允許3條此類SQL並發執行 2, -- 最多允許2個此類SQL等待 true, -- 規則立即生效 '' -- SQL語句的文本,本樣本不填寫 'limit constant select', -- 規則描述 'public' -- search_path );
查詢SQL限流規則
使用情境
該命令可以在主執行個體或唯讀執行個體中使用,用於查詢已建立的SQL限流規則。
文法
查看當前執行個體中所有庫下的SQL限流規則:
SELECT * FROM rds_enabled_ccl_rule;說明此命令查詢結果中,由於顯示限制,query_string和comment的資訊會被截斷,只顯示前200個字元,如果需要查看完整資訊,請使用
SELECT * FROM rds_show_current_db_ccl_rule();命令。1.2及之後版本rds_ccl的支援返回
search_path。
查詢當前資料庫下的所有SQL限流規則:
SELECT * FROM rds_show_current_db_ccl_rule();
使SQL限流規則生效
使用情境
該函數只能在主執行個體中調用,適用於以下情境:
如果建立SQL限流規則時,is_enabled參數配置為false,則可以使用此函數使規則生效。
使失效的規則再次生效。
文法
SELECT rds_enable_ccl_rule(ccl_id int);參數解釋
參數 | 類型 | 說明 |
ccl_id | int | SQL限流規則ID,如何查詢SQL限流規則ID,請參見查詢SQL限流規則。 |
注意事項
無
SQL樣本
SELECT rds_enable_ccl_rule(1);載入SQL限流規則
使用情境
該函數可以在主執行個體或唯讀執行個體中調用,用於載入SQL限流規則,只有被載入的規則才會發揮SQL限流作用。
適用於以下情境:
主執行個體:
建立SQL限流規則時,如果is_enabled配置為true,則規則會自動載入到主執行個體,無需手動調用。
建立SQL限流規則時,如果is_enabled配置為false,調用
rds_enable_ccl_rule函數使規則生效時,規則會自動載入到主執行個體,無需手動調用。如果主執行個體重啟,則需要手動調用此函數,載入規則。
唯讀執行個體:
如果需要規則在唯讀執行個體發揮作用,則需要在主執行個體建立規則(node_tag配置為2或3)後,再在唯讀執行個體中調用此函數,手動載入規則。
文法
SELECT rds_load_ccl_rule(ccl_id int);參數解釋
參數 | 類型 | 說明 |
ccl_id | int | SQL限流規則ID,如何查詢SQL限流規則ID,請參見查詢SQL限流規則。 |
注意事項
只有在主執行個體中調用
rds_add_ccl_rule函數建立了SQL限流規則,且node_tag配置為2或3時,才能在唯讀執行個體中載入規則。失效的規則無法被載入,如果唯讀執行個體需要載入某條失效的規則,請先在主執行個體中使其生效,具體方法,請參見使SQL限流規則生效。
SQL樣本
SELECT rds_load_ccl_rule(1);變更SQL限流規則
使用情境
該函數只能在主執行個體中調用,用於變更SQL限流規則中的最大並發數和最大等待數。
文法
SELECT rds_update_ccl_rule(
ccl_id int,
new_max_concurrency int,
new_max_waiting int
);參數解釋
參數 | 類型 | 說明 |
ccl_id | int | SQL限流規則ID,如何查詢SQL限流規則ID,請參見查詢SQL限流規則。 |
new_max_concurrency | int | 變更後最大並發數。
|
new_max_waiting | int | 變更後最大等待數。
|
注意事項
更新SQL限流規則後,規則立即生效。
當前僅支援變更SQL限流規則中的最大並發數和最大等待數。
SQL樣本
SELECT rds_update_ccl_rule(
2, -- ccl_id
4, -- 新的最大並發數為4
5 -- 新的最大等待數為5
);使SQL限流規則失效
使用情境
該函數只能在主執行個體中調用,用於使某條SQL限流規則失效,該規則不再發揮SQL限流作用。
如果要使指定的規則生效,請參見使SQL限流規則生效。
文法
使指定SQL限流規則失效:
SELECT rds_disable_ccl_rule(ccl_id int);使當前庫下的所有SQL限流規則失效:
SELECT rds_disable_all();
參數解釋
參數 | 類型 | 說明 |
ccl_id | int | SQL限流規則ID,如何查詢SQL限流規則ID,請參見查詢SQL限流規則。 |
注意事項
失效的規則無法被載入,如果唯讀執行個體需要載入某條失效的規則,請先在主執行個體中使其生效,具體方法,請參見使SQL限流規則生效。
使SQL限流規則失效時,會自動將規則從主執行個體卸載,該規則不再發揮SQL限流作用。
SQL樣本
SELECT rds_disable_ccl_rule(1);卸載SQL限流規則
使用情境
該函數可以在主執行個體或唯讀執行個體中調用,用於卸載SQL限流規則,被卸載的規則不會再發揮SQL限流作用。
適用於以下情境:
主執行個體:
如果在主執行個體中調用了
rds_disable_ccl_rule或rds_disable_all函數使規則失效,規則將自動從主執行個體卸載,無需手動調用。如果在主執行個體調用了
rds_del_ccl_rule函數刪除規則,規則將自動從主執行個體卸載,無需手動調用。您也可以手動調用此函數,將規則從主執行個體卸載。
唯讀執行個體:
如果不希望某條規則在唯讀執行個體發揮限流作用,可以在唯讀執行個體中手動調用此函數。
文法
SELECT rds_unload_ccl_rule(ccl_id int, db_name varchar default '');參數解釋
參數 | 類型 | 說明 |
ccl_id | int | SQL限流規則ID,如何查詢SQL限流規則ID,請參見查詢SQL限流規則。 |
db_name | varchar | 預設為空白字串,表示當前資料庫。您也可以指定其他資料庫,將其他資料庫下的SQL限流規則卸載。 |
注意事項
規則卸載後,不再發揮SQL限流作用,如需再次使用,需要重新載入,更多資訊,請參見載入SQL限流規則。
SQL樣本
SELECT rds_unload_ccl_rule(1,'');刪除SQL限流規則
使用情境
該函數只能在主執行個體中調用,用於刪除某條SQL限流規則。規則刪除時,自動從主執行個體卸載。
文法
SELECT rds_del_ccl_rule(ccl_id int);參數解釋
參數 | 類型 | 說明 |
ccl_id | int | SQL限流規則ID,如何查詢SQL限流規則ID,請參見查詢SQL限流規則。 |
注意事項
無。
SQL樣本
SELECT rds_del_ccl_rule(1);返回結果:
rds_del_ccl_rule
----------------------
-7851264404688445170
(1 row)返回結果為query_id。
如果規則不存在,則刪除報錯。
附錄
query_id簡介
query_id是PostgreSQL中SQL的特殊標識,同類SQL的query_id相同。
例如:
-- 以下兩個sql的query_id相同 SELECT * FROM tbl WHERE a = 1; SELECT * FROM tbl WHERE a = 2;query_id包含有SQL中對象的資訊(即oid資訊),不同資料庫下的同名表不是同一個對象,不同schema下的同名表也不是同一個對象。所以相同的SQL,如果其包含的查詢對象不同,那麼query_id就不相同。
如果是SQL中的訪問對象的是全域表,或是全域函數,query_id相同。
樣本1:
pg_database為全域表,在不同資料庫中查詢query_id相同。ccl_test資料庫中執行如下語句:
SELECT rds_get_query_id($$SELECT * FROM pg_database;$$);返回結果:
rds_get_query_id ---------------------- -8733244708994363681 (1 row)ccl_test2資料庫中執行如下語句:
SELECT rds_get_query_id($$SELECT * FROM pg_database;$$);返回結果:
rds_get_query_id ---------------------- -8733244708994363681 (1 row)
樣本2:
pg_sleep為全域函數,在不同資料庫中查詢query_id相同。ccl_test資料庫中執行如下語句:
SELECT rds_get_query_id($$SELECT pg_sleep(1);$$);返回結果:
rds_get_query_id -------------------- 440101247839410938 (1 row)ccl_test2資料庫中執行如下語句:
SELECT rds_get_query_id($$SELECT pg_sleep(1);$$);返回結果:
rds_get_query_id -------------------- 440101247839410938 (1 row)
調用函數情境下,當參數類型變化或是有無FROM子句時,query_id會發生變化。
例如,同樣調用
pg_sleep函數,不同情況下返回query_id結果不同。無FROM子句:
SELECT rds_get_query_id($$SELECT pg_sleep(1);$$);返回結果:
rds_get_query_id -------------------- 440101247839410938 (1 row)有FROM子句:
SELECT rds_get_query_id($$SELECT * FROM pg_sleep(1);$$);返回結果:
rds_get_query_id ---------------------- -3404018605099167039 (1 row)參數類型變化:
select rds_get_query_id($$SELECT * FROM pg_sleep(1.0);$$);返回結果:
rds_get_query_id --------------------- 3073869725037049158 (1 row)