MySQL觸發器之審計功能

MySQL觸發器的用處還是非常多地,關鍵看業務需要,曾經給大家介紹過基於存儲引擎MEMORY加觸發器的應用場景之一剖析。通過閱讀本文,將會告訴大家:觸發器的語法知識、觸發器的限制、審計案例分析和實現,將逐一講解。

  語法

CREATE 
  [DEFINER = { user | CURRENT_USER }] 
  TRIGGER trigger_name trigger_time trigger_event 
  ON tbl_name FOR EACH ROW trigger_stmt

  DEFINER:指定觸發器的創建者,默認爲登錄mysqld服務器的賬號信息;

  trigger_name:觸發器的名稱,要符合mysql對待數據庫對象命名的規範;

  trigger_time:觸發表上的觸發器語句體執行的時間:行更新前還是行更新後,2個選項值:

  BEFOR or AFTER;

  tbl_name:指定觸發器是對應那一個數據庫對象:表的;

  trigger_stmt:爲觸發器內部可執行的語句體;

  觸發器限制

  •   擁有觸發器的數據庫對象必須爲實體表,不能爲臨時表或視圖;
  •   MyISAM、MEMORY、InnoDB等常用存儲引擎都支持觸發器功能;
  •   觸發器支持INSERT類操作:INSERT、LOAD DATA、REPLACE;
  •   觸發器支持UPDATE操作;
  •   觸發器支持DELETE操作,但是不支持DROP TABLE 、TRUNCATE操作;
  •   處發起能支持字句:INSERT INTO … ON DUPLICATE KEY UPDATE …;
  •   一個數據庫中的對象表,不能對同一觸發事件有2個或以上的觸發器同時響應;
  •   一個數據庫中不能有同名的觸發器程序;
  •   觸發器無法顯示調用執行,也無法像函數或存儲過程一樣顯示地傳遞參數;
  •   通過關鍵字OLD.column_name獲得的值不能通過SET命令修改,但是關鍵字NEW獲得的值能通過SET NEW.column_name=VALUE方式修改;
  •   觸發器的處理部分不能含有事務的關鍵字,例如:COMMIT、ROLLBACK等;
  •   創建了觸發器的表,若支持事務,則觸發器也會受事務執行成功還是失敗的影響,且觸發器程序執行成功還是失敗,也會影響事務的執行是成功還是失敗;若不支持事務,則也無法支持事務的回滾操作;

  審計案例

  有一張存儲車輛收費信息的表t_car,因業務要求,程序要有對該表的數據修改權限,爲此需要審計對該表上數據的記錄值修改信息,以備查詢、跟蹤。表t_car結構:

CREATE TABLE t_car( 
  `ID` INT UNSIGNED NOT NULL AUTO_INCREMENT, 
  `car_number` VARCHAR(45) DEFAULT ” COMMENT ‘車牌號’, 
  `card_number` VARCHAR(45) DEFAULT ” COMMENT ‘卡片編號’, 
  `pay` DECIMAL(6,1) DEFAULT 0 COMMENT ‘金額’, 
  PRIMARY KEY(`id`) 
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  審計存儲的內容:

  修改前pay字段的值;

  修改後pay字段的值;

  記錄被修改的時間;

  登陸數據庫服務器修改數據的ip地址、帳號信息;

  爲此審計表的結構爲:

CREATE TABLE t_record( 
  `ID` INT UNSIGNED NOT NULL AUTO_INCREMENT, 
  `username` VARCHAR(45) DEFAULT ” COMMENT ‘登錄mysql的用戶名’, 
  `client_ip` VARCHAR(45) DEFAULT ” COMMENT ‘遠程訪問mysql服務器的客戶端ip地址’, 
  `update_Before` VARCHAR(45) DEFAULT ” COMMENT ‘修改前的金額’, 
  `update_After` VARCHAR(45) DEFAULT ” COMMENT ‘修改後的金額’, 
  `gmt_create` TIMESTAMP NOT NULL DEFAULT ’0000-00-00 00:00:00′ COMMENT ‘創建時間’, 
  PRIMARY KEY (`id`) 
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  我們可以使用觸發器記錄所有用戶對錶t_car,進行UPDATE操作修改數據的行爲進行記錄,觸發器語句體:

DELIMITER $$ 
  CREATE TRIGGER tri_t_car BEFORE UPDATE ON t_car FOR EACH ROW 
  BEGIN 
  IF NEW.pay<>OLD.pay THEN 
  INSERT INTO t_record(username,client_ip,update_Before,update_After,gmt_create)
  VALUES(SUBSTRING_INDEX(USER(),’@',1),SUBSTRING_INDEX(USER(),’@',-1),OLD.pay,NEW.pay,NOW()); 
  END IF; 
  END $$ 
  DELIMITER ;

  測試:

  測試用例的數據生成語句:

INSERT INTO t_car(car_number,card_number,pay) 
VALUES(SUBSTRING(RAND(),3,20),SUBSTRING(RAND(),3,10),SUBSTRING(RAND(),3,3)), 
(SUBSTRING(RAND(),3,20),SUBSTRING(RAND(),3,10),SUBSTRING(RAND(),3,3)), 
(SUBSTRING(RAND(),3,20),SUBSTRING(RAND(),3,10),SUBSTRING(RAND(),3,3)); 

root@localhost : test 11:14:49> SELECT * FROM t_car; 
+—-+—————–+————-+——-+ 
| ID | car_number      | card_number | pay   | 
+—-+—————–+————-+——-+ 
|  1 | 933606902075565 | 4065322181  | 231.0 | 
|  2 | 939605452064057 | 0025060456  | 193.0 | 
|  3 | 96105140723386  | 2241153588  | 237.0 | 
+—-+—————–+————-+——-+ 
3 rows in set (0.00 sec)

  修改目標表數據的測試語句:

  UPDATE t_car SET pay=100.5 WHERE ID=1;

  查詢審計信息存儲的表:

root@localhost : test 11:15:51> SELECT * FROM t_record; 
+—-+———-+———–+—————+————–+———————+ 
| ID | username | client_ip | update_Before | update_After | gmt_create          | 
+—-+———-+———–+—————+————–+———————+ 
|  1 | root     | localhost | 231.0         | 100.5        | 2011-07-08 11:15:51 | 
+—-+———-+———–+—————+————–+———————+ 
1 row in set (0.00 sec)

  可以看到需要審計的信息,都已經存儲到對應的審計表中,到此觸發器實現審計功能的需求就完整實現了。

  總結

  觸發器的用處非常多,關鍵是要結合業務場景使用,本文給大家介紹瞭如何使用觸發器實現數據庫的審計功能;我們還可以藉助觸發器實現2張表之間的數據同步問題,配合MEMORY引擎可以解決該存儲引擎缺陷:數據無法持久化,從而增強MEMORY引擎的使用場景;我們也可以利用觸發器實現異地,甚至跨國界多數據庫節點之間的數據同步業務需求,後續篇章給大家介紹,某著名電子商務公司利用觸發器,加應用程序實現多數據節點之間的數據同步問題。

原文出處:http://www.mysqlops.com/2011/07/08/mysql-trigger-audit.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章