文章目錄
- 0.簡介
- 1.概念說明
- 2.tag的生成和存儲
- 2.1 tag合法性校驗
- 2.2 內存中存儲
- 2.3 持久化存儲
- 3.tag的觸發
0.簡介
在上一篇文章中中,我們介紹了PG中的兩種觸發器,即適合于DML的普通觸發器和對于DDL的事件觸發器,其中事件觸發器與常規的 DML 觸發器(響應行級別或語句級別操作)不同的地方在于事件觸發器在 DDL 操作的生命周期中觸發,觸發時執行用戶指定的存儲過程或函數,可以用于監控或限制數據庫結構的變更。 本文對于事件觸發器中細節進行進一步的說明,也就是tag的原理。
1.概念說明
在上一篇文章中說明了創建事件觸發器的語法,其中可以使用filter_variable指定觸發事件過濾器的條件,也就是tag,其基本作用是實現對于ddl細分類型的精準觸發,比如在建表時觸發可以帶上如下內容:
WHEN TAG IN (‘CREATE TABLE’)
2.tag的生成和存儲
2.1 tag合法性校驗
在創建事件觸發器中的語法可以看到其tag是以字符串形式存在的,那么就需要驗證其是否合法,其驗證函數如下:
/** Validate DDL command tags.*/
static void
validate_ddl_tags(const char *filtervar, List *taglist)
{ListCell *lc;foreach(lc, taglist){const char *tag = strVal(lfirst(lc));event_trigger_command_tag_check_result result;result = check_ddl_tag(tag);if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_RECOGNIZED)ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR),errmsg("filter value \"%s\" not recognized for filter variable \"%s\"",tag, filtervar)));if (result == EVENT_TRIGGER_COMMAND_TAG_NOT_SUPPORTED)ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),/* translator: %s represents an SQL statement name */errmsg("event triggers are not supported for %s",tag)));}
}
其中主要使用check_ddl_tag函數去檢查是否合法,主要包含兩步,一是直接比較字符串是否一致,二是比較是否是由支持的類型組合而成比如drop和event_trigger_support數組中的INDEX組合,其是否支持就是true。
2.2 內存中存儲
事件觸發器在內存中是以哈希表的形式存儲的,其中key是事件類型,value是觸發器構成的鏈表,那么在查找執行時就需要做兩次的過濾:一是對事件進行過濾,二是對于tag進行過濾,只執行都匹配的觸發器函數。
static HTAB *EventTriggerCache;
2.3 持久化存儲
在之前文章中對事件觸發器存儲的系統表是pg_event_trigger有過描述,此處主要介紹一下PG在后續版本對于tag的查找優化。因為tag是字符串且可能數量比較多,那么每次都進行全量的字符串匹配就會帶來很多額外的計算開銷,所以PG利用固定tag的index構建了bitmap,方便查找是否符合條件。
3.tag的觸發
tag觸發邏輯較為簡單,在事件觸發器的執行邏輯內部增加了一層相應的判斷,其查找函數為EventTriggerCommonSetup: