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

原本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的跟踪记录,有了这些操作痕迹,自然就方便客户去进一步排查问题了。

使用触发器来审计表的DML、DDL操作的更多相关文章

  1. MySql修改数据表的基本操作(DDL操作)

    1.查看数据库的基本语句:show databases; 2.选择相应的数据库进入语法:use 数据库名; 3.查看数据库中的表语法:show tables; 4.查看表的基本结构语句:desc 表名 ...

  2. 数据库级别DDL操作监控审计、数据库触发器/服务器触发器

    关键词:数据库触发器/服务器触发器  ,数据库级别DDL操作监控审计,禁止修改登录名密码 [1]数据库级别DDL操作监控审计 转自2012示例库,只能数据库级别,不能实例级别 use database ...

  3. 创建日志表记录DML操作和DDL操作

    创建一个日志表,记录dept表的DML操作 create table dept_log(logid number,type varchar2(50),logdate date,deptno numbe ...

  4. 15. DML, DDL, LOGON 触发器

    触发器可以理解为由特定事件触发的存储过程, 和存储过程.函数一样,触发器也支持CLR,目前SQL Server共支持以下几种触发器: 1. DML触发器, 表/视图级有效,可由DML语句 (INSER ...

  5. oracle触发器update本表数据

    功能: 1. 允许/限制对表的修改 2. 自动生成派生列,比如自增字段 3. 强制数据一致性 4. 提供审计和日志记录 5. 防止无效的事务处理 6. 启用复杂的业务逻辑 开始 create trig ...

  6. MySQL 大表在线DML神器--pt-online-schema-change

    一个朋友问我在线对大表进行ddl操作,如何做能尽量避免主从延迟以及不影响在线dml操作呢?我想到一个开源的pt-online-schema-change工具,测试了吧,效果还可以. pt-online ...

  7. mysql DML DDL DCL

    DML(data manipulation language):  它们是SELECT.UPDATE.INSERT.DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言  D ...

  8. MySQL InnoDB 修改表列Online DDL

    概述 一般来说数据库结构一经设计,不能轻易更改,因为更改DDL(Data Definition Language)操作代价很高,所以在进行数据库结构设计时需要谨慎. 但是业务发展是未知的,特别是那些变 ...

  9. ORACLE中如何查找定位表最后DML操作的时间小结

    在Oracle数据库中,如何查找,定位一张表最后一次的DML操作的时间呢? 方式有三种,不过都有一些局限性,下面简单的解析.总结一下. 1:使用ORA_ROWSCN伪列获取表最后的DML时间 ORA_ ...

  10. 查询表DML和DDL操作的最后时间

    查询test表DML操作的最后时间的语句: select max(ora_rowscn),to_char(scn_to_timestamp(max(ora_rowscn)),'yyyy-mm-dd h ...

随机推荐

  1. maven和gradle环境变量配置及idea相关的设置

    1.maven 环境变量添加之后,重新打开cmd窗口,验证是否配置成功. idea   File >> Settings idea配置之后的验证: 2.gradle 环境变量添加之后,重新 ...

  2. 社会工程学——进行IP追踪

    如果目标对象有一个公开的邮箱,可以往这个邮箱地址发试探性的Email,然后看看该邮件是否有[回信],从而了解对象是否在线.(注:这招是社会工程学的基本伎俩) 说一个稍微高级点的邮件技巧--[不依赖回信 ...

  3. 在Xcode编写我们的quick help

    程序环境 Xcode 13.2.1 "写代码要经常写注释."虽然很多人不以为然,但是在使用Xcode的时候,我们在写注释的时候稍微注意一下格式的话,Xcode会给我们带来额外的正反 ...

  4. git 有用配置汇总

    背景 git config的不同级别,每一个级别覆盖上一级别的配置,所以.git/config的配置变量会覆盖/etc/gitconfig中的配置变量 git config --system #为整个 ...

  5. Markdown 文章 跳转

    背景 在查阅一些文档的时候,一些比较优秀博客在文章中是带有目录的,点击就会跳转到指定的锚点. 在本人的某些文章中,也想尝试这样的效果. 做法 实现这样的效果有2种做法(不同之处在于 超链接的写法不同) ...

  6. 开源免费的专注于建立大型个人知识库推荐-Trilium Notes

    Trilium Notes是一个分层的笔记应用程序,专注于建立大型个人知识库. 支持相当丰富的 markdown,包括 mermaid 和 latex,而且即时渲染,和 typora 一样.支持代码类 ...

  7. 使用PHP实现字符串的上标和下标,比如:M²和Log₂FC

    要在PHP中实现字符串的上标和下标效果,并直接在命令行或网页中正确显示,你可以分别使用Unicode转义序列或HTML实体来表示上标(UPER)和下标(SUB)字符.对于打印到网页的情况,可以使用HT ...

  8. 说说XXLJob分片任务实现原理?

    XXL Job 是一个开源的分布式任务调度平台,其核心设计目标是开发迅速.学习简单.轻量级.易扩展的分布式任务调度框架. 这两天咱们开发的 AI Cloud 项目中,也使用到了 XXL Job 来执行 ...

  9. oeasy教您玩转vim - 44 - # 综合练习

    ​ 综合练习 回忆上节课内容 上次我们学到了各种的替换模式 r,替换当前光标的字符 R,进入替换模式 ~,改变大小写 这次来个综合练习吧! 我们这次要完成这样一个任务 我们有的时候需要写日志 Syst ...

  10. SQL Server调用OLE对象

    T-SQL 中是可以调用 OLE 的,将这一功能应用到触发器.存储过程等对象中,SQL Server 运用变得更贴近我们的功能,更加满足我们的需要. T-SQL 中有七个存储过程是围绕本节内容进行的, ...