我们知道数据库的事务是一种单元操作要么操作全部成功要么操作全部失败在Oracle数据库中一个事务是从执行第一个数据管理语言(DML)语句开始直到执行一个COMMIT语句提交保存这个事务或者执行一个ROLLBACK语句放弃此次操作结束 事务的要么全部完成要么什么都没完成的特性会让将错误信息记入数据库表中变得很困难因为当事务失败重新运行时用来编写日志条目的INSERT语句还未完成 针对这种困境Oracle提供了一种便捷的方法即自治事务自治事务从当前事务开始在其自身的语境中执行它们能独立地被提交或重新运行而不影响正在运行的事务正因为这样它们成了编写错误日志表格的理想形式在事务中检测到错误时您可以在错误日志表格中插入一行并提交它然后在不丢失这次插入的情况下回滚主事务 因为自治事务是与主事务相分离的所以它不能检测到被修改过的行的当前状态这就好像在主事务提交之前它们一直处于单独的会话里对自治事务来说它们是不可用的然而反过来情况就不同了主事务能够检测到已经执行过的自治事务的结果 要创建一个自治事务您必须在匿名块的最高层或者存储过程函数数据包或触发的定义部分中使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句在这样的模块或过程中执行的SQL Server语句都是自治的 触发无法包含COMMIT语句除非有PRAGMA AUTONOMOUS_TRANSACTION标记但是只有触发中的语句才能被提交主事务则不行 列表展示了对一个简单但灵活的错误日志表格所作的CREATE TABLE和CREATE SEQUENCE语句
CREATE TABLE errorlog ( errorlog_id NUMBER logged_on TIMESTAMP DEFAULT SYSTIMESTAMP logged_by VARCHAR() DEFAULT USER num NUMBER num NUMBER num NUMBER text VARCHAR() text VARCHAR() text VARCHAR() );CREATE SEQUENCE errorlog_seq START WITH INCREMENT BY ;
列表是一个独立的存储过程用于更新错误日志表格
CREATE OR REPLACEPROCEDURE log_error ( n IN NUMBER:=NULL t IN VARCHAR:=NULL n IN NUMBER:=NULL t IN VARCHAR:=NULL n IN NUMBER:=NULL t IN VARCHAR:=NULL )IS PRAGMA AUTONOMOUS_TRANSACTION;BEGIN INSERT INTO errorlog (errorlog_id num num num text text text) VALUES (errorlog_seqNEXTVAL n n n t t t); COMMIT;END;
这个过程接受最多三个数字和三个文本变量然后将它们和时间戳以及调用过程的用户一起储存在表格中 假如你要测试这个过程就需要更新(UPDATE)或删除(DELETE)表格中的某些行这就引发了主事务然后执行存储过程将您选择的要记入日志的数据传递给它最后重新运行主事务选择(SELECT)错误日志表格你的日志条目依旧会在原位置