首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

使用触发器来审计表的DML、DDL操作

编程知识
2024年08月07日 22:11

最近帮客户排查某问题时,因为怀疑应用对某张配置表有变更,所以需要对这张表的所有操作进行审计。

原本Oracle对某张表的审计是非常方便的,一条命令就可以实现,也不需要费心自定义审计表。

-- 启用对表DEPT的插入、更新和删除操作的审计
AUDIT INSERT, UPDATE, DELETE ON DEPT BY ACCESS;

-- 查看对DEPT表的所有审计记录
SELECT * FROM DBA_AUDIT_TRAIL WHERE OBJ_NAME = 'DEPT';

-- 停用对表DEPT的审计
NOAUDIT INSERT, UPDATE, DELETE ON DEPT;

但不幸的是,因为客户当前环境已经把默认开启的audit_trail给关闭了。(默认开启,默认值是DB,关闭就是NONE)
笔者已经在实验环境验证过:

  • 1.audit_trail必须开的情况下,对表进行审计才会有记录;
  • 2.audit_trail是静态参数,如果修改,需要重启数据库才可以生效。

尤其注意要检查这个参数的设置情况,因为这里比较坑的一点是,上述审计命令,即便你关了这个参数,开启表审计的命令执行也并不会报错,只是实际上无法记录。

相信大家都知道,生产环境的重启申请流程非常麻烦,因此只能用手工的方式,比如自定义触发器的方式来监控这张表的DML操作。

还好因为这个配置表正常情况下,并不会被频繁修改,所以使用触发器也不会带来什么性能问题。

下面就进入到hands-on环节,我们模拟下这个客户的需求,假设dept这张表:

-- 创建示例表DEPT
CREATE TABLE dept (
    deptno NUMBER(2) PRIMARY KEY,
    dname VARCHAR2(14),
    loc VARCHAR2(13)
);

-- 插入示例数据到DEPT表
INSERT INTO dept VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO dept VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO dept VALUES (40, 'OPERATIONS', 'BOSTON');

commit;

针对dept表建立触发器如下:

-- CREATE TABLE
CREATE TABLE dml_audit(
modiy_time DATE, 
table_name VARCHAR2(30), 
deptno NUMBER(2), 
modiy_type VARCHAR2(14), 
dname VARCHAR2(14), 
loc VARCHAR2(13)
);

CREATE OR REPLACE TRIGGER dept_trg
BEFORE INSERT OR DELETE OR UPDATE ON dept
FOR EACH ROW
BEGIN
  IF inserting THEN 
    INSERT INTO dml_audit (modiy_time, table_name, deptno, modiy_type, dname, loc) 
    VALUES (sysdate, 'dept', :NEW.deptno, 'insert', :NEW.dname, :NEW.loc);
  END IF;
  
  IF deleting THEN 
    INSERT INTO dml_audit (modiy_time, table_name, deptno, modiy_type, dname, loc) 
    VALUES (sysdate, 'dept', :OLD.deptno, 'delete', :OLD.dname, :OLD.loc);
  END IF;

  IF updating THEN 
    INSERT INTO dml_audit (modiy_time, table_name, deptno, modiy_type, dname, loc) 
    VALUES (sysdate, 'dept', :OLD.deptno, 'update_before', :OLD.dname, :OLD.loc);
    
    INSERT INTO dml_audit (modiy_time, table_name, deptno, modiy_type, dname, loc) 
    VALUES (sysdate, 'dept', :NEW.deptno, 'update_after', :NEW.dname, :NEW.loc);
  END IF;
END;
/

测试下,确认delete、insert、update都可以监测到:

08:17:58 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO2> select * from dml_audit;

no rows selected

Elapsed: 00:00:00.02
08:18:05 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO2> delete from dept where deptno=10;

1 row deleted.

Elapsed: 00:00:00.22
08:18:41 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO2> INSERT INTO dept VALUES (10, 'ACCOUNTING', 'NEW YORK');

1 row created.

Elapsed: 00:00:00.00
08:18:56 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO2> update dept set LOC='China' where deptno=40;

1 row updated.

Elapsed: 00:00:00.04
08:19:25 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO2> select * from dml_audit;

MODIY_TIME	   TABLE_NAME			      DEPTNO MODIY_TYPE     DNAME	   LOC
------------------ ------------------------------ ---------- -------------- -------------- -------------
07-AUG-24	   dept 				  10 delete	    ACCOUNTING	   NEW YORK
07-AUG-24	   dept 				  10 insert	    ACCOUNTING	   NEW YORK
07-AUG-24	   dept 				  40 update_before  OPERATIONS	   BOSTON
07-AUG-24	   dept 				  40 update_after   OPERATIONS	   China

Elapsed: 00:00:00.01

是否万事大吉了呢?

其实不是,因为客户问题是怀疑这个表有被改动,而改动其实不仅仅局限于DML操作。

我们假设一种极端场景,如果一个操作是将这张表drop后重建,然后插入一样的数据。

这样的场景,仅靠上面的触发器就无法记录到。因为表被drop时,对应的触发器也会被删除。
因为触发器是依赖于表存在的对象,当表被删除时,触发器也会失去作用的对象。

比如有这样一个init的脚本,功能是直接对配置表进行了drop删除然后重新创建初始化数据:

@init

那要如何做才能监控到这种极端情况呢?
也不难,再建立一个针对DDL的触发器,如果对dept表有ddl操作也记录到指定日志表。

-- 创建审计表
CREATE TABLE ddl_audit (
    event_time  TIMESTAMP,
    username    VARCHAR2(30),
    userhost    VARCHAR2(30),
    object_type VARCHAR2(30),
    object_name VARCHAR2(30),
    action      VARCHAR2(30)
);

-- 创建 DDL 触发器
CREATE OR REPLACE TRIGGER ddl_trigger
AFTER CREATE OR DROP ON SCHEMA
DECLARE
    v_username    VARCHAR2(30);
    v_userhost    VARCHAR2(30);
BEGIN
    SELECT USER, SYS_CONTEXT('USERENV', 'HOST') INTO v_username, v_userhost FROM DUAL;

    IF ORA_DICT_OBJ_NAME = 'DEPT' THEN
        INSERT INTO ddl_audit (
            event_time, username, userhost, object_type, object_name, action
        ) VALUES (
            SYSTIMESTAMP, v_username, v_userhost, ORA_DICT_OBJ_TYPE, ORA_DICT_OBJ_NAME, ORA_SYSEVENT
        );
    END IF;
END;
/

这样,如果真有这种DDL操作,也可以审计到,但需要注意,这个DDL的触发器的影响相对要大些,非必要情况先不要建。定位完问题后,及时删掉。

08:26:49 PRIMARY @DB0913_9DF_IAD -> JINGYU @DEMO2> select * from ddl_audit;

EVENT_TIME		       USERNAME        USERHOST        OBJECT_TYPE		      OBJECT_NAME     ACTION
------------------------------ --------------- --------------- ------------------------------ --------------- ------------------------------
07-AUG-24 08.25.11.885875 AM   JINGYU	       demo	       TABLE			      DEPT	      DROP
07-AUG-24 08.25.12.167304 AM   JINGYU	       demo	       TABLE			      DEPT	      CREATE
07-AUG-24 08.25.59.989356 AM   JINGYU	       demo	       TABLE			      DEPT	      DROP
07-AUG-24 08.26.00.061629 AM   JINGYU	       demo	       TABLE			      DEPT	      CREATE

Elapsed: 00:00:00.01

可以看到,这样触发器的方式,虽然比审计笨重,但也可以实现对表无论是DDL还是DML的跟踪记录,有了这些操作痕迹,自然就方便客户去进一步排查问题了。

From:https://www.cnblogs.com/jyzhao/p/18348050/shi-yong-chu-fa-qi-lai-shen-ji-biao-dedmlddl-cao-z
本文地址: http://shuzixingkong.net/article/891
0评论
提交 加载更多评论
其他文章 七牛云私有空间图片上传、下载
导航 引言 总体思路 七牛云相关的配置文件 获取七牛云上传token 相关类定义 核心代码实现 获取七牛云图片下载链接 公开空间 私有空间 核心代码实现 结语 参考 引言 我们在成长,代码也要成长。 多媒体图片在各种网站、小程序和app中应用广泛,同时也大大增强了用户体验。 随着云服务的兴起,越来越
七牛云私有空间图片上传、下载 七牛云私有空间图片上传、下载
莽撞闯荡的6周年,也就是弹指一挥间
6年也就是弹指一挥间,时间过得飞快。6年前的明天,也就是2018年的8月8日,我离开了服务12年的腾讯开始探索自己的梦想-参见《回顾4180天在腾讯使用C#的历程,开启新的征途》。到今天,已经整整走过了6年,这6年还是围绕着C# 开展业务和活动。在这个6周年的特殊日子,总感觉要说些什么,但想说的话又
SpringBoot项目中HTTP请求体只能读一次?试试这方案
问题描述 在基于Spring开发Java项目时,可能需要重复读取HTTP请求体中的数据,例如使用拦截器打印入参信息等,但当我们重复调用getInputStream()或者getReader()时,通常会遇到类似以下的错误信息: 大体的意思是当前request的getInputStream()已经被调
SpringBoot项目中HTTP请求体只能读一次?试试这方案 SpringBoot项目中HTTP请求体只能读一次?试试这方案 SpringBoot项目中HTTP请求体只能读一次?试试这方案
再探GraphRAG:如何提升LLM总结能力?
本文对GraphRAG的灵感来源、能力透视、应用场景都做了比较优秀的解读,同时也对图技术的应用价值做了深入探讨,相信会给大家带来不一样的收获。
再探GraphRAG:如何提升LLM总结能力? 再探GraphRAG:如何提升LLM总结能力? 再探GraphRAG:如何提升LLM总结能力?
Golang在整洁架构基础上实现事务
这篇文章在 go-kratos 官方的 layout 项目的整洁架构基础上,在微服务架构下,实现优雅的数据库事务操作。
Golang在整洁架构基础上实现事务 Golang在整洁架构基础上实现事务 Golang在整洁架构基础上实现事务
升级JDK时涉及的工作任务
JDK版本升级,通常引入新的语言特性、新的API,废弃一些API,从而导致一些不兼容的现象。 因此在升级产品使用的JDK版本时,通常有如下考虑: 新产品包括新建设的项目以及刚启动不久的项目,使用高版本的JDK。 对于生命周期中间的产品,依据人力预算和团队的技能,决策是否升级。 对于进入生命周期尾部的
《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态(出现、移除、显示和隐藏)
1.简介 在我们日常工作中进行UI自动化测试时,保证测试的稳定性至关重要。其中一个关键方面是正确地定位和操作网页中的元素。在网页中,元素可能处于不同的状态,有些可能在页面加载完成之前不在DOM中,需要某些操作后才会出现,而其他元素可能一直存在于DOM中,但最初处于隐藏状态,需要通过操作才能使其出现进
《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态(出现、移除、显示和隐藏) 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态(出现、移除、显示和隐藏) 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态(出现、移除、显示和隐藏)
博客园自救之产品开发小建议
继上次 博客园直播方向运营建议之后,我又冒出了一个小建议, 毕竟作为博客园精神股东,开动我脑洞,我也义不容辞责任 博客园的产品形式是博客文章, 拓展路径有两条,一条是 文章的分类,一条的是文章的内容 分类的控制权在博客园,可拓展性强 内容的控制权在文章作者,可获站性弱 所以更多的拓展方向在分类 软件