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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

     这篇文章源于在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 INSERTUPDATEDELETE 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) 

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

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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
23天前
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
在9月20日2024云栖大会上,阿里云智能集团副总裁,数据库产品事业部负责人,ACM、CCF、IEEE会士(Fellow)李飞飞发表《从数据到智能:Data+AI驱动的云原生数据库》主题演讲。他表示,数据是生成式AI的核心资产,大模型时代的数据管理系统需具备多模处理和实时分析能力。阿里云瑶池将数据+AI全面融合,构建一站式多模数据管理平台,以数据驱动决策与创新,为用户提供像“搭积木”一样易用、好用、高可用的使用体验。
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
|
15天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
123 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
25天前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
85 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
22天前
|
关系型数据库 分布式数据库 数据库
云栖大会|从数据到决策:AI时代数据库如何实现高效数据管理?
在2024云栖大会「海量数据的高效存储与管理」专场,阿里云瑶池讲师团携手AMD、FunPlus、太美医疗科技、中石化、平安科技以及小赢科技、迅雷集团的资深技术专家深入分享了阿里云在OLTP方向的最新技术进展和行业最佳实践。
|
30天前
|
人工智能 Cloud Native 容灾
云数据库“再进化”,OB Cloud如何打造云时代的数据底座?
云数据库“再进化”,OB Cloud如何打造云时代的数据底座?
|
1月前
|
SQL 存储 关系型数据库
数据储存数据库管理系统(DBMS)
【10月更文挑战第11天】
97 3
|
15天前
|
SQL Oracle 关系型数据库
【赵渝强老师】Oracle的联机重做日志文件与数据写入过程
在Oracle数据库中,联机重做日志文件记录了数据库的变化,用于实例恢复。每个数据库有多组联机重做日志,每组建议至少有两个成员。通过SQL语句可查看日志文件信息。视频讲解和示意图进一步解释了这一过程。
|
1月前
|
SQL 存储 关系型数据库
添加数据到数据库的SQL语句详解与实践技巧
在数据库管理中,添加数据是一个基本操作,它涉及到向表中插入新的记录
|
1月前
|
SQL 监控 数据处理
SQL数据库数据修改操作详解
数据库是现代信息系统的重要组成部分,其中SQL(StructuredQueryLanguage)是管理和处理数据库的重要工具之一。在日常的业务运营过程中,数据的准确性和及时性对企业来说至关重要,这就需要掌握如何在数据库中正确地进行数据修改操作。本文将详细介绍在SQL数据库中如何修改数据,帮助读者更好
241 4
|
1月前
|
NoSQL 前端开发 MongoDB
前端的全栈之路Meteor篇(三):运行在浏览器端的NoSQL数据库副本-MiniMongo介绍及其前后端数据实时同步示例
MiniMongo 是 Meteor 框架中的客户端数据库组件,模拟了 MongoDB 的核心功能,允许前端开发者使用类似 MongoDB 的 API 进行数据操作。通过 Meteor 的数据同步机制,MiniMongo 与服务器端的 MongoDB 实现实时数据同步,确保数据一致性,支持发布/订阅模型和响应式数据源,适用于实时聊天、项目管理和协作工具等应用场景。
下一篇
无影云桌面