发表于: 2008.06.07 23:59
分类: ORACLE
出处: http://yangtingkun.itpub.net/post/468/463933
---------------------------------------------------------------
简单记录一下Oracle延迟事务提交的特点。
在测试的时候发现,Oracle延迟事务如果提交时出现了错误,那么Oracle会自动回滚所以的操作。
SQL> CREATE TABLE T (ID NUMBER, NAME VARCHAR2(30));
表已创建。
SQL> CREATE INDEX IND_T_ID ON T(ID);
索引已创建。
SQL> ALTER TABLE T ADD CONSTRAINT PK_T_ID PRIMARY KEY (ID) DEFERRABLE;
表已更改。
首先建立一张表,并建立了可延迟约束的主键信息:
SQL> INSERT INTO T VALUES (1, 'A');
已创建 1 行。
SQL> INSERT INTO T VALUES (1, 'B');
INSERT INTO T VALUES (1, 'B')
*第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
默认情况下,不能插入违反约束条件的数据。不过通过启用延迟约束,可以使得约束的检查放到事务提交的时刻:
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (1, 'A');
已创建 1 行。
SQL> INSERT INTO T VALUES (1, 'A');
已创建 1 行。
SQL> INSERT INTO T VALUES (1, 'A');
已创建 1 行。
SQL> UPDATE T SET ID = ROWNUM;
已更新4行。
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 A
3 A
4 A
SQL> COMMIT;
提交完成。
由于启用了延迟约束,使得上面的SQL操作可以成功执行,Oracle只在COMMIT的时刻检查约束是否发生冲突。
不过上面展示的是延迟约束在提交时刻可以满足的情况,对于延迟约束在提交时刻仍然无法满足的情况,会发现Oracle回滚了整个事务。
SQL> SET CONSTRAINTS ALL DEFERRED;
约束条件已设置。
SQL> INSERT INTO T VALUES (5, 'B');
已创建 1 行。
SQL> INSERT INTO T VALUES (6, 'C');
已创建 1 行。
SQL> INSERT INTO T VALUES (4, 'D');
已创建 1 行。
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 A
3 A
4 A
5 B
6 C
4 D
已选择7行。
SQL> COMMIT;
COMMIT
*第 1 行出现错误:
ORA-02091: 事务处理已回退
ORA-00001: 违反唯一约束条件 (YANGTK.PK_T_ID)
SQL> SELECT * FROM T;
ID NAME
---------- ------------------------------
1 A
2 A
3 A
4 A
这其实并不难理解,对于COMMIT操作而言,要么执行成功,那么事务被提交,要么出现了错误,事务被回滚。但是用户使用延迟事务时,必须清楚,使用延迟事务并准备提交时,很可能会由于约束冲突而导致本事务所有的修改丢失。
而这种修改的丢失是没有办法避免的,即使设置了SAVEPOINT也没有意义,在延迟事务提交失败后,Oracle会选择回滚到整个事务的开始部分。











