PostgreSQL觸發器,日志審計小神器
最近遇到的項目問題,審計日志記錄不夠詳細,比如某用戶編輯了某台設備,只記錄了用戶操作的設備名、操作時間、登錄用戶和登錄IP,至於設備其他屬性編輯前和編輯后的信息就沒有更詳細的對比了,審計粒度不夠細,顯然是不能讓客戶滿意的,秉承客戶滿意優先原則,只好技術加持一波了。
實際客戶想要記錄的更多,涉及的業務屬性比較廣,返本溯源,我們決定在數據庫層面解決,以期能最少的改動業務代碼。
利用PostgreSql觸發器在源表數據發生變化的時候准備一張對應表進行備份記錄,把變化數據就像提交svn一樣插入到歷史表中,如圖

解決方案有了,但其實還存在一個問題觸發器只在數據庫內部運行,如何記錄是當前是哪個登錄用戶對數據源進行的變更還是個問題,經過一位大佬的指導,可以利用PostgreSql的會話變量解決,簡單的測試代碼如下

打印結果

這樣就可以利用數據庫會話變量的特性,在每一次的數據庫變更前,先將全局操作pid關聯到用戶uid為一張表,而變更的時候,將將全局操作pid插入到歷史數據表中,這樣通過唯一的全局操作pid就可以關聯查詢出是哪個用戶的操作了。
於是解決方案圖變為

開心的代碼實現
創建審計主表

創建審計歷史表

創建用戶id和操作id關聯表

在用戶進行數據操作變更的postgresql連接時,我們都先將數據庫全局變量插入到operation_log表中,將當前登錄的用戶id與這次變更操作綁定在一起,這個可以封裝在web框架層實現。
創建觸發器
觸發器函數定義了觸發器被觸發后執行的操作,下面列一下觸發器函數中可以使用的變量,例子中的 OLD,就表示觸發操作的舊數據行,詳細如下:
l NEW:INSERT、UPDATE 操作觸發的行級觸發器中存儲的新的數據行,
l OLD:INSERT、UPDATE 操作觸發的行級觸發器中存儲的的數據行,
l TG_OP:代表當前觸發器監聽到的操作類型,數據類型為 text,內容為 INSERT、UPDATE、DELETE、TRUNCATE。

小結
本文只是大概如何利用PostgreSql觸發器對用戶行為進行詳細日志審計,旨在提供一個觸發器記錄數據源變更和web框架結合的思路,希望對你有所幫助,如果你有更好的解決方案可以留言告訴我哦
PS:如果文章對你有價值,歡迎點個推薦。
