|
自定义事务用: PRAGMA AUTONOMOUS_TRANSACTION 来控制;
很多朋友,为了在“复杂” 的程序里做一些“自由”的处理;“不由自主”的用上了 自制事务,或嵌套事务;
我倾向于使用 savepoint 的方法,做一个局部回滚点;
大部分时候,是能够解决问题的;
但是有的程序,已经很复杂了,为了快刀斩乱麻,只能用自制事务来处理;
下面我用几个例子讲一下陷阱;
例子1:
- declare xx varchar2(200);
- procedure reglog
- as
- PRAGMA AUTONOMOUS_TRANSACTION;
- begin
- update okform a set a.CAPTION='44445' where a.FORMCLASSNAME='TfrmPro1d';
- --这里必须写 commit 或 rollack,否者也会报错
- end;
- begin
- reglog;
- end;
复制代码 执行失败,提示:
ORA-06519: 检测到活动的独立的事务处理, 已经回退
ORA-06512: 在 line 11
ORA-06512: 在 line 15
说明:凡是在自制事务里,只要做了有效的DML操作,就必须要有内部提交或回滚;
例子2:
先查询: select CAPTION from OKFORM a where a.FORMCLASSNAME='TfrmProd'
得到 : CAPTION的值为 : 变化前;
然后执行:
- declare xx varchar2(200);
- procedure reglog
- as
- PRAGMA AUTONOMOUS_TRANSACTION;
- begin
- select a.CAPTION into xx from OKFORM a where a.FORMCLASSNAME='TfrmProd';
- dbms_output.put_line(xx); --得到:变化前
- end;
- begin
- update okform a set a.CAPTION='变化后' where a.FORMCLASSNAME='TfrmProd';
- select a.CAPTION into xx from OKFORM a where a.FORMCLASSNAME='TfrmProd';
- dbms_output.put_line(xx); --得到:变化后
- reglog;
- end;
复制代码 说明:你会奇怪的发现,自制事务里select的数据 仿佛是一个独立会话中读取的数据;
它在整个事务里是一个独立的王国,不受未提交的数据影响;
例子3:
- declare xx varchar2(200);
- procedure reglog
- as
- PRAGMA AUTONOMOUS_TRANSACTION;
- begin
-
- update okform a set a.CAPTION='44445' where a.FORMCLASSNAME='TfrmProd';
-
- COMMIT;
- end;
- begin
- update okform a set a.CAPTION='333' where a.FORMCLASSNAME='TfrmProd';
- reglog;
-
- end;
-
复制代码 执行失败,提示:
ORA-00060: 等待资源时检测到死锁
ORA-06512: 在 line 8
ORA-06512: 在 line 15
说明:第2个例子已经知道,自制事务类似于1个独立会话; 所以该例子中,两个相同记录的更新,全局的在前,自制的在后,那么必然因为两个会话同时一起操作同一个记录,而造成死锁;
所以,关键要了解自制事务本质上是个大的会话内部的一个小的独立会话, 这样你就会留意到可能发生的陷阱;
当然,从我的角度讲,简约设计,能不用自制事务,还是少用;
|
|