当前位置: 首页 > Oracle, oracle 10g, oracle 11g > 正文

验证DDL隐式提交

今天复习了下DDL的隐式提交,在执行DDL语句的时候,ORACLE为了保证事物的一致性,会对当前SESSION未提交的事务隐式提交,以保证DDL语句失败时的回滚位置,以下是DDL操作的伪代码。

从DDL的伪代码可以看到,在执行DDL操作时,首先会执行一个COMMIT操作,提交当前SESSION未提交的事务,然后才会处理DDL语句(DDL操作一般都是修改数据字典的DML操作),如果DDL语句正确执行,则提交,如果DDL语句执行失败,则回滚到第一个COMMIT的时间点,可见第一个COMMIT是为ORACLE提供的DDL失败时的回滚位置,也是为了不影响DDL之前的操作,可以通过以下两个实验来验证DDL操作的隐式提交。
实验一:DDL语句失败
实验表信息如下:

SESSION 1>select * from t_stream;
        ID CODE  IDENTIFIER
---------- ----- --------------------
         1 01    01-01-0001-000001
         2 02    02-01-0001-000001
         3 03    03-01-0001-000001
         4 04    04-01-0001-000001

打开2个SQLPLUS窗口,SESSION1和SESSION2,SESSION1执行DML操作后,不提交。

SESSION 1>insert into t_stream values (5,'05','05-01-0001-000001');
1 row created.

此时,由于SESSION1未提交,SESSION2查询不到这条记录。

SESSION 2>select * from t_stream;
        ID CODE  IDENTIFIER
---------- ----- --------------------
         1 01    01-01-0001-000001
         2 02    02-01-0001-000001
         3 03    03-01-0001-000001
         4 04    04-01-0001-000001

SESSION1执行DDL操作,建立一张已存在的表。

SQL> create table t_dbdream as select * from t_test;
create table t_dbdream as select * from t_test
             *
ERROR at line 1:
ORA-00955: name is already used by an existing object

虽然DDL操作失败,但是在执行DDL语句之前的COMMIT已经执行(DDL语法要正确,否则不会执行隐式提交),此时SESSION2可以查看到SESSION1之前插入的记录。

SESSION 2>select * from t_stream;
        ID CODE  IDENTIFIER
---------- ----- --------------------
         1 01    01-01-0001-000001
         2 02    02-01-0001-000001
         3 03    03-01-0001-000001
         4 04    04-01-0001-000001
         5 05    05-01-0001-000001

通过10046追踪日志中相关的信息。

insert into t_stream values (5,'05','05-01-0001-000001')
END OF STMT
PARSE #1:c=0,e=131,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1315862570391933
BINDS #1:
EXEC #1:c=2000,e=2056,p=0,cr=1,cu=4,mis=0,r=1,dep=0,og=1,tim=1315862570394101
WAIT #1: nam='SQL*Net message to client' ela= 2 driver id=1650815232 #bytes=1 p3=0
obj#=-1 tim=1315862570394208
*** 2012-09-12 17:48:02.099
WAIT #1: nam='SQL*Net message from client' ela= 9780944 driver id=1650815232
#bytes=1 p3=0 obj#=-1 tim=1315862580175186
XCTEND rlbk=0, rd_only=0

可以看到在INSERT语句之后,DDL操作触发了COMMIT操作,INSERT操作已经被提交。
实验一:DDL语句成功
还是之前的实验表T_STREAM

SESSION 1>select * from t_stream;
        ID CODE  IDENTIFIER
---------- ----- --------------------
         1 01    01-01-0001-000001
         2 02    02-01-0001-000001
         3 03    03-01-0001-000001
         4 04    04-01-0001-000001

同样是SESSION1和SESSION2操作,唯一区别是SESSION1运行的DDL语句成功运行。

SESSION 1>insert into t_stream values (5,'05','05-01-0001-000001');
1 row created.

此时,由于SESSION1未提交,SESSION2查询不到这条记录。

SESSION 2>select * from t_stream;
        ID CODE  IDENTIFIER
---------- ----- --------------------
         1 01    01-01-0001-000001
         2 02    02-01-0001-000001
         3 03    03-01-0001-000001
         4 04    04-01-0001-000001

SESSION1执行DDL操作,建立一张新表。

SESSION 1>create table t_dbdreams as select * from t_test;
Table created.

由于触发隐式提交,此时SESSION2可以查看到SESSION1之前插入的记录。

SESSION 2>select * from t_stream;
        ID CODE  IDENTIFIER
---------- ----- --------------------
         1 01    01-01-0001-000001
         2 02    02-01-0001-000001
         3 03    03-01-0001-000001
         4 04    04-01-0001-000001
         5 05    05-01-0001-000001

10046追踪日志相关信息如下:

insert into t_stream values (5,'05','05-01-0001-000001')
END OF STMT
PARSE #1:c=0,e=262,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1315856684369288
BINDS #1:
EXEC #1:c=1999,e=1523,p=0,cr=1,cu=4,mis=0,r=1,dep=0,og=1,tim=1315856684370856
WAIT #1: nam='SQL*Net message to client' ela= 2 driver id=1650815232 #bytes=1 p3=0
obj#=-1 tim=1315856684370932
*** 2012-09-12 16:07:45.814
WAIT #1: nam='SQL*Net message from client' ela= 20525585 driver id=1650815232
#bytes=1 p3=0 obj#=-1 tim=1315856704896560
XCTEND rlbk=0, rd_only=0

INSERT语句之后,DDL操作触发了COMMIT操作,INSERT操作已经被提交。

update tsq$ set blocks=:3,maxblocks=:4,grantor#=:5,priv1=:6,priv2=:7,priv3=:8
where ts#=:1 and user#=:2
insert into obj$(owner#,name,namespace,obj#,type#,ctime,mtime,stime,status,
remoteowner,linkname,subname,dataobj#,flags,oid$,spare1,spare2)values(:1,:2,:3,
:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16, :17)
insert into seg$ (file#,block#,type#,ts#,blocks,extents,minexts,maxexts,extsize,
extpct,user#,iniexts,lists,groups,cachehint,bitmapranges,hwmincr, spare1,
scanhint) values (:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,0,:16,
DECODE(:17,0,NULL,:17),:18)
insert into tab$(obj#,ts#,file#,block#,bobj#,tab#,intcols,kernelcols,clucols,
audit$,flags,pctfree$,pctused$,initrans,maxtrans,rowcnt,blkcnt,empcnt,avgspc,
chncnt,avgrln,analyzetime,samplesize,cols,property,degree,instances,dataobj#,
avgspc_flb,flbcnt,trigflag,spare1,spare6)values(:1,:2,:3,:4,decode(:5,0,null,
:5),decode(:6,0,null,:6),:7,:8,decode(:9,0,null,:9),:10,:11,:12,:13,:14,:15,
:16,:17,:18,:19,:20,:21,:22,:23,:24,:25,decode(:26,1,null,:26),decode(:27,1,
null,:27),:28,:29,:30,:31,:32,:33)
insert into col$(obj#,name,intcol#,segcol#,type#,length,precision#,scale,null$,
offset,fixedstorage,segcollength,deflength,default$,col#,property,charsetid,
charsetform,spare1,spare2,spare3)values(:1,:2,:3,:4,:5,:6,decode
(:5,182/*DTYIYM*/,:7,183/*DTYIDS*/,:7,decode(:7,0,null,:7)),decode(:5,2,decode
(:8,-127/*MAXSB1MINAL*/,null,:8),178,:8,179,:8,180,:8,181,:8,182,:8,183,:8,231,
:8,null),:9,0,:10,:11,decode(:12,0,null,:12),:13,:14,:15,:16,:17,:18,:19,:20)
END OF STMT
EXEC #3:c=1000,e=852,p=0,cr=2,cu=7,mis=0,r=1,dep=1,og=4,tim=1315856705104698
XCTEND rlbk=0, rd_only=0

在DDL语句触发的INSERT和UPDATE相关数据字典后,也执行了COMMIT,也就是上文DDL伪代码中的第二个COMMIT。

本文固定链接: http://www.dbdream.com.cn/2012/09/%e9%aa%8c%e8%af%81ddl%e9%9a%90%e5%bc%8f%e6%8f%90%e4%ba%a4/ | 信春哥,系统稳,闭眼上线不回滚!

该日志由 dbdream 于2012年09月12日发表在 Oracle, oracle 10g, oracle 11g 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 验证DDL隐式提交 | 信春哥,系统稳,闭眼上线不回滚!
关键字: , ,

验证DDL隐式提交:等您坐沙发呢!

发表评论

快捷键:Ctrl+Enter