这篇文章源于在PL/SQL领域非常有建树的专家:Steven Feuerstein 的推荐。

于是突发奇想,将该篇文章翻译成了中文。如果通过我的努力,确实让一些朋友有所收获,我将非常荣幸。

文章开始:

之前我的一些文章中,曾经建议通过使用11g中提供的FLASHBACK的数据归档功能而直接替换日志信息表(journalling tables)。即我们已经不再需要针对某些专门表中的记录,我们需要持续跟踪记录所有的改变和被改变之前的记录状态(可以参考如下链接 http://technology.amis.nl/blog/2453/oracle-11g-total-recall-flashback-in-the-hands-of-database-designers-and-application-developers-at-last-and-the-end-of-journalling-tables)。通过Flashbck的数据归档功能不但可以减少编程工作,而且通过该功能可以大幅提升DML操作的性能,同时又可获得许多的方便的功能。例如:Flashback Queries可以直接地象SQL查询一样查询历史数据,甚至通过使用dbms_flashback包,我们可以使用相同的应用程序和相同的查询操作去检索过去某个时间点的数据。

在之前的不太长的时间,Flashback有许多功能上的限制,而使得其基本上不能记录那些已经存有历史数据但结构又发生变化的表。随着11GR2在这些方面作的改进,绝大多数的限制都已经取消了,并且象增加、重命名以及删除字段和限制这样的对于表的DDL操作以已经可以实现。

另外一个导致日志表可以消失的原因,就是通过Flashback的Flashback Queries操作,可以得到一些重要的附加信息。何时(DML操作的时间戳)和操作信息(操作类型和原数据信息),这些信息可以很好的知道,操作者到底导致了怎样的变化。而这些在一个部门内的监管是非常重要的。过去,习惯使用数据库用户就是真实用户去提交交易。但是当今业界使用多层服务组件和WEB应用通过池化连接数据库,而造成数据库用户往往不是操作的真实用户。对于最终用户的操作通常(或者应该这样)通过sys_context(‘userenv’, ‘client_identifier’)可以获得,通过设置dbms_session.set_identifier() 或者直接使用连接(例如:JDBC)。对于我们的日志而言,我们需要记录或筛选真实的执行人和客户身份。

这篇文章描述了记录和后督交易时客户身份信息的方法。

标准的数据库审计工具(Standard Database Audit Facilities)  

象其他一些人一样,我也不得不使用,我不甚熟悉的ORACLE数据库自带的审计功能。但让使用不够深入。但是,当试图检查过去某些数据库交易信息的时候,总是能够自然的想到使用使用审计功能。并且这种方法确实让我得到了我需要的信息:每个交易的操作记录,并且通过交易号(transactionid)可以关联到闪回的历史数据查询。这些数据会包含用户身份和执行的所有操作。Oralce数据库的审计可以进行许多种不同操作。从每种对象类型的建立、授权更新和执行操作,到每个数据库用户执行的操作甚至非法的对象。但是因为审计会产生大量的记录数据,而致使我们不得不定期清理这些历史数据。通常这些周期只能都是非常短暂的。为了记录交易历史,我尝试通过日志表转而使用审计功能。并且我需要确定审计的等级--那些操作和那些对象(是否还包含用户?)现在,我需要使用FLASHBAKC功能协助,就像我参考的那些文档,并且我需要确保每个针对EMP表的DML操作都必须被记录。这就意味着,下面的SQL开启审计功能:

  1. AUDIT INSERT, UPDATE, DELETE ON SCOTT.EMP

为了审计功能,我假设一个web应用,这个应用可以让真是的最终用户修改数据。在数据库中执行如下操作:设置用户身份,应用程序需要执行:

  1. begin
  2. dbms_session.set_identifier('TheRealUser');
  3. end;

进行下一个DML操作:

  1. update emp
  2. set      sal = sal + 100
  3. where  job ='CLERK'

当交易被提交后,EMP使用了新的值,而原有的值成为了历史数据。这些历史数据,可以通过Flashback Versions Query被我们查询。

  1. select ename
  2. ,      sal
  3. ,      versions_xid
  4. ,      VERSIONS_STARTTIME
  5. ,      VERSIONS_ENDTIME
  6. from   emp VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE
  7. where  job = 'CLERK'

结果集如下:

  1. ENAME      SAL    VERSIONS_XID     VERSIONS_STARTTIME           VERSIONS_ENDTIME
  2. ---------- ------ ---------------- -------------------------    -------------------------
  3. ADAMS      1405   07001E00A9040000 06-FEB-11 08.12.09.00 AM     06-FEB-11 08.42.13.00 AM
  4. ADAMS      1505   04000E0088040000 06-FEB-11 08.42.13.00 AM
  5. ADAMS      1400                                                 06-FEB-11 08.12.09.00 AM
  6. JAMES      1255   07001E00A9040000 06-FEB-11 08.12.09.00 AM     06-FEB-11 08.42.13.00 AM
  7. JAMES      1355   04000E0088040000 06-FEB-11 08.42.13.00 AM
  8. JAMES      1250                                                 06-FEB-11 08.12.09.00 AM
  9. MILLER     1605   07001E00A9040000 06-FEB-11 08.12.09.00 AM     06-FEB-11 08.42.13.00 AM
  10. MILLER     1705   04000E0088040000 06-FEB-11 08.42.13.00 AM
  11. MILLER     1600                                                 06-FEB-11 08.12.09.00 AM
  12. SMITH      1105   07001E00A9040000 06-FEB-11 08.12.09.00 AM     06-FEB-11 08.42.13.00 AM
  13. SMITH      1205   04000E0088040000 06-FEB-11 08.42.13.00 AM
  14. SMITH      1100                                                 06-FEB-11 08.12.09.00 AM

很显然,这些记录的数据中没有修改数据人的信息。但是,配合之前开启的审计追踪功能,我可以关联Flashback的Versions Query与 USER_OBJECT_AUDIT试图,找到更多的执行人(WHO)的数据信息:

  1. select ename
  2. ,      sal
  3. ,      uat.client_id
  4. ,      uat.os_username
  5. ,      uat.userhost
  6. ,      uat.username
  7. ,      uat.scn
  8. ,      versions_xid
  9. ,      VERSIONS_STARTTIME
  10. ,      VERSIONS_STARTSCN
  11. ,      VERSIONS_ENDTIME
  12. ,      VERSIONS_ENDSCN
  13. from   emp VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE eh
  14. join
  15. user_audit_trail uat
  16. on ( eh.versions_xid = uat.transactionid)
  17. where  job = 'CLERK'
  18. order
  19. by     ename, versions_starttime

结果集显示客户身份(client identifier)信息与实际的操作用户不符。

  1. ENAME  SAL  CLIENT_ID    OS_USERNAME USERHOST USERNAME SCN      VERSIONS_XID     VERSIONS_STARTTIME       VERSIONS_STARTSCN
  2. ---------- ---------------------- ---------------------------------------------------------------- ------------------------
  3. ADAMS  1505 TheRealUser  demo        xp-vm    SCOTT    2200769  04000E0088040000 06-FEB-11 08.42.13.00 AM 2200778
  4. JAMES  1355 TheRealUser  demo        xp-vm    SCOTT    2200769  04000E0088040000 06-FEB-11 08.42.13.00 AM 2200778
  5. MILLER 1705 TheRealUser  demo        xp-vm    SCOTT    2200769  04000E0088040000 06-FEB-11 08.42.13.00 AM 2200778
  6. SMITH  1205 TheRealUser  demo        xp-vm    SCOTT    2200769  04000E0088040000 06-FEB-11 08.42.13.00 AM 2200778

注意:如果我想通过flash的versions query找到开启审计之前的历史数据,需要使用左外联接在我们的查询中。

  1. select ename
  2. ,      sal
  3. ,      uat.client_id
  4. ,      uat.os_username
  5. ,      uat.userhost
  6. ,      uat.username
  7. ,      uat.scn
  8. ,      versions_xid
  9. ,      VERSIONS_STARTTIME
  10. ,      VERSIONS_STARTSCN
  11. ,      VERSIONS_ENDTIME
  12. ,      VERSIONS_ENDSCN
  13. from   emp VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE eh
  14. left outer join
  15. ( select uat.*
  16. ,      row_number() over (partition by transactionid order by extended_timestamp) rn
  17. from   user_audit_trail uat
  18. ) uat
  19. on ( eh.versions_xid = uat.transactionid)
  20. where  job = 'CLERK'
  21. and    rn = 1
  22. order
  23. by     ename, versions_starttime

现在,我已经介绍了一个嵌套SQL,如何通过一个查询将user_audit_trail所有交易都查询出来,而不是通过一个交易一个查询的方式进行检索。

这个方法确实非常简单。因为,我们可以象轻松开启审计信息那样开启每张表的Flashback功能。

但是这里却有一个审计开销缺点。首先是性能问题,因为对于每条被“触碰”到的记录,都会触发日志信息记录,同时存储在系统审计表SYS.AUD$中的数据量将是非常惊人的。因为审计将会收集所有用户和对象的操作。审计信息存储表需要周期性清除。注意,清理可以有选择行的指定某个对象或者操作。

为了简化标准的审计跟踪功能,我们可以构建一个JOB,周期性地从 sys.aud$表中抽取我们需要的记录信息,并构建自己需要的交易历史。因为审计机制会完整的记录每个交易的DML操作语句但我们只是需要每个交易的单个记录,我们可以通过整合针对每个交易记录的审计信息,达到大幅降低交易历史数据量的目的。交易历史表可以象如下:

  1. create table transaction_history
  2. ( transaction_id    varchar2(100) not null
  3. , client_identifier varchar2(200)
  4. , os_user           varchar2(200)
  5. , scn               number
  6. , transaction_start_timestamp     timestamp default systimestamp
  7. , db_user           varchar2(100)
  8. , application_info  varchar2(2000)
  9. )

从审计跟踪表中抽取交易历史数据操作:

  1. insert into transaction_history
  2. ( transaction_id
  3. , client_identifier
  4. , os_user
  5. , scn
  6. , transaction_start_timestamp
  7. , db_user
  8. )
  9. select uat.transactionid
  10. ,      uat.client_id
  11. ,      uat.os_username
  12. ,      uat.scn
  13. ,      uat.extended_timestamp
  14. ,      uat.username
  15. from   ( select uat.*
  16. ,      row_number() over (partition by transactionid order by extended_timestamp) rn
  17. from   user_audit_trail uat
  18. ) uat
  19. where  rn = 1
  20. and    transactionid is not null

对于审计跟踪(可能需要部分清理)和交易历史表(可能不能全部更新),我们可以将两者结合来构建基于EMP表的交易历史记录。

  1. select ename
  2. ,      sal
  3. ,      versions_xid
  4. ,      nvl(th.client_identifier, uat.client_id) client_id
  5. ,      nvl(th.os_user, uat.os_username) os_user
  6. ,      uat.userhost userhost
  7. ,      nvl(th.db_user, uat.username) db_user
  8. ,      nvl(th.scn,uat.scn) scn
  9. ,      VERSIONS_STARTTIME
  10. ,      VERSIONS_STARTSCN
  11. ,      VERSIONS_ENDTIME
  12. ,      VERSIONS_ENDSCN
  13. from   emp VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE eh
  14. left outer join
  15. ( select uat.*
  16. ,      row_number() over (partition by transactionid order by extended_timestamp) rn
  17. from   user_audit_trail uat
  18. ) uat
  19. on ( eh.versions_xid = uat.transactionid)
  20. left outer join
  21. transaction_history th
  22. on ( eh.versions_xid = th.transaction_id)
  23. where  job = 'CLERK'
  24. and    uat.rn = 1
  25. order
  26. by     ename, versions_starttime

注意:查询可以部分的结合审计跟踪信息和我们自己的交易历史表在一个试图中。

上面提及的大概方法给我们提供一个针对标准应用构建日志表的思路。在这个举例中,我们并没有建立触发器。简单地开启针对某些表DML操作的审计跟踪,配以这些表的flashback归档数据,就足以构建我们的日志信息。在后续的文章中将会更为详细的介绍。

当然,如果我们要实际构建这样的日志信息也许还有一个难点需要克服,即关于DBA的审计,尤其是对于标准审计特性,对于DBA和对于应用开发人员的日志记录,我们的应用往往是没有考虑的(但是,我们需要他或她也去建立flashback的归档数据)。

在未来的文章中,我将会讨论看似相似的问题:跟踪交易历史的方法和通过flashback归档数据收集全面的日志信息。

----EOF 译文完。

原文链接:

http://technology.amis.nl/blog/10911/database-transaction-recorder-adding-who-to-when-and-what-to-make-flashback-take-over-from-journalling-tables

Thanks Lucas Jellema -:)

本文转自Be the miracle!博客51CTO博客,原文链接http://blog.51cto.com/miracle/499942如需转载请自行联系原作者

Larry.Yue

数据库交易记录--如何添加审计信息到闪回归档数据以替换操作日志表相关推荐

  1. oracle数据库归档闪回,[Oracle]Oracle的闪回归档

    Oracle的闪回归档 场景需求,由于管理数据库的一些核心表,在实施初期会有人为误删除的问题.Oracle 11gR2提供了闪回归档的特性,可以保证不用RMAN来恢复误删除的数据.实践如下: 1.创建 ...

  2. 视频教程-赵强老师:Oracle数据库从10g到11g(16)闪回-Oracle

    赵强老师:Oracle数据库从10g到11g(16)闪回 毕业于清华大学,拥有超过13年的工作经验. Oracle认证讲师,拥有6年以上授课经验.精通Oracle数据库.中间(Weblogic)和大数 ...

  3. java 银行管理系统怎么储存账户信息_银行管理系统 实现用户注册 登录 存、取款 交易记录查询和修改用户信息等功能...

    ========= 项    目   介   绍======== 银行账户管理系统 本项目主要实现用户注册 登录 存.取钱和修改用户信息功能. 用户信息的存储和获取通过集合和IO输入输出流实现. 存钱 ...

  4. 用aspect在springboot中记录操作日志至数据库的详细过程

    代码来自若依管理系统的后台,我截取的其中用于记录操作日志的部分 1.切面 2.操作日志表 3.spring工具类 4.客户端工具类 异步工厂(产生任务用) 异步任务管理器 5.服务层 6.控制层 1. ...

  5. 井通区块链API接口介绍02-挂单类+交易记录+交易效果

    本节介绍井通区块链的挂单接口和交易记录接口. 井通区块链是一个原生支持多资产,原生支持多资产之间相互交易的底层区块链系统,因此用户可以直接在链上挂单,用一种资产 交换另外一种资产,价格和数量可以自由定 ...

  6. Oracle 数据库闪回

    Oracle 数据库闪回 一.闪回技术的7个特性 二.Oracle 数据库的4种SCN 1.系统检查点 SCN 2.数据文件 SCN 3.结束 SCN 4.数据文件头 SCN 三.闪回操作 1.查询闪 ...

  7. 如何使用SpringBoot AOP 记录操作日志、异常日志?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:咫尺的梦想_w cnblogs.com/wm-dv/ ...

  8. JAVA记录操作日志步骤

    项目地址:https://gitee.com/Selegant/logs-demo.git 说明 系统日志不论是在日常的管理还是维护中都会起到很大的作用,但是在日志的记录中通常会存在很多的问题 日志记 ...

  9. SpringBoot AOP 记录操作日志、异常日志

    使用SpringBoot AOP 记录操作日志.异常日志 我们在做项目时经常需要对一些重要功能操作记录日志,方便以后跟踪是谁在操作此功能.在操作某些功能时也有可能会发生异常,但是每次发生异常要定位原因 ...

  10. AOP实现操作日志记录

    一.设计: 操作日志记录 根据业务场景 一般是需要记录下数据修改更新的日志,查询类可以忽略. 所以需要对指定的某些方法进行记录.这块希望可以结合注解灵活操作,对于注解的方法进行日志记录 操作日志表设计 ...

最新文章

  1. 链表问题8——将单向链表按某值划分成左边小、中间相等、右边大的形式(进阶)
  2. mysql 生产实践_mysql-主从复制
  3. Visio对象插入Word后周围空白过大
  4. Java 技术篇-使用poi开源jar包实现读取excel实例演示,poi-3.17.jar获取
  5. 介绍一种导入文件夹中图片数据集的方法
  6. Jedis Cluster源码分析
  7. [洛谷P1439]排列LCS问题
  8. android 请求网络异步载入
  9. ros(6) service server编程实现
  10. php计时器每过24小时结果加一倍,单片机时钟24小时慢了21.5秒 如何修改初值校正呢?...
  11. Silverlight学习之贪吃蛇游戏
  12. 一个前端小白的成长之路(序)
  13. 嵌入式开发(一):嵌入式开发新手入门
  14. 浙江大学机械系制造所2010届毕业生…
  15. VS2017如何设置C++11?
  16. 微信小程序版本更新后提示用户更新
  17. Android Kotlin + 协程 + Retrofit + MVVM优雅的实现网络请求(简洁!!!!)
  18. layui实现导航栏目
  19. 计算机毕业设计之java+javaweb的大学生勤工助学管理系统
  20. JeecgBoot 技术架构

热门文章

  1. c fun函数求n个整数的平均值_OOP 面向对象编程:由 C 到 C++
  2. Abp框架 Abp中使用Redis
  3. Layer单选框非空校验注意
  4. PHP使用 uEditor富文本编辑器
  5. 路径中,连续多个目录分隔符不影响,仍按照一个处理
  6. configure: error: no usable zlib; please install zlib devel package or equivalent m
  7. 文字处理技术:页面布局时,有两个方向
  8. 分析华为毕昇JDK8:类数据共享CDS有效果,幅度很小
  9. LINUX(CENTOS)下载编译nload
  10. 未解决:火狐浏览器提示不安全的链接