有朋友问我"带dblink的query会起一个transaction吗?"
我说会呀。
他接着问"那为什么我在PL/SQL Developer的command window中执行一个带dblink的query后,PL/SQL Developer的工具栏上的标识transaction的按钮'commit'和'rollback'没有高亮显示呢?"。
----我们知道,当你在PL/SQL Developer的command window中执行一个transaction的时候,如果你没有commit或者rollback,其工具栏上的标识transaction的按钮'commit'和'rollback'是一直会高亮显示的。
我试了一下,还真是这样。
不可能呀,在我印象里,带dblink的query一定会起一个distributed transaction的。
我来证明给大家看。
不用PL/SQL Developer的command window了,直接用sqlplus,开两个session,分别为session 1和session 2。
先在session 1中删除表uplbth中的一条记录:
Session 1:
SQL> delete from uplbth where ubtbth='HPCAN081200010';
已删除 1 行。
接着在session 2中也做同样的删除动作,只不过在执行删除前先执行一个带dblink的query语句:
Session 2:
SQL> select count(*) from uplbth@caipratest;
COUNT(*)
----------
36
SQL> delete from uplbth where ubtbth='HPCAN081200010';
delete from uplbth where ubtbth='HPCAN081200010'
*
第 1 行出现错误:
ORA-02049: timeout: distributed transaction waiting for lock
在session 2大概等待了一分钟后,oracle这里报错ORA-02049,这就是最好的证明,如若"select count(*) from uplbth@caipratest"不起一个distributed transaction的话,session 2是会一直等待下去的。
这里为什么会等待一分钟,是因为distributed_lock_timeout的值是60(这也是默认值)。
好了,我们这里再来看一下为什么在PL/SQL Developer的command window中做同样的事情,session 2就会一直等待session 1?
我感觉这是因为在session 2中执行"select count(*) from uplbth@caipratest"的时候PL/SQL Developer人为的commit了一下。
好了,我们来做一个10046验证一下。
打开一个PL/SQL Developer的command window,执行"select count(*) from uplbth@caipratest",执行完了看一下产生的trace文件:
XCTEND rlbk=1, rd_only=1
WAIT #0: nam='SQL*Net message to dblink' ela= 1 driver id=675562835 #bytes=1 p3=0 obj#=-1 tim=31020960699684
WAIT #0: nam='SQL*Net message from dblink' ela= 436 driver id=675562835 #bytes=1 p3=0 obj#=-1 tim=31020960700143
WAIT #0: nam='SQL*Net message to client' ela= 0 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=31020960700211
WAIT #0: nam='SQL*Net message from client' ela= 16592 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=31020960716827
=====================
PARSING IN CURSOR #1 len=61 dep=0 uid=56 oct=47 lid=56 tim=31020960716966 hv=356401299 ad='78651b38'
begin :id := sys.dbms_transaction.local_transaction_id; end;
在产生的trace文件里,我们看到了XCTEND rlbk=1, rd_only=1,这表示"select count(*) from uplbth@caipratest"已经用到了回滚段了,也就是产生了一个transaction,并且这个transaction是read only的。
有朋友问我"带dblink的query会起一个transaction吗?"
我说会呀。
他接着问"那为什么我在PL/SQL Developer的command window中执行一个带dblink的query后,PL/SQL Developer的工具栏上的标识transaction的按钮'commit'和'rollback'没有高亮显示呢?"。
我记得带dblink的查询,在plsql里commit,rollback是会高亮显示的~可能是不同PLSQL版本做了不同的处理,像你说的现在版本的PLSQL自己给加了COMMIT吧.
PL/SQL Developer里可以自己设置是否auto commit,但一般来说,这个auto commit只是针对sql window中执行的DML语句,对于command window是无效的。也就是说不管你是否设置了auto commit,当你在command window中执行DML语句的时候是始终需要手工执行commit或者rollback的。所以这里我觉得很奇怪,我明明没有commit,但PL/SQL Developer自己在这里就commit了。我用的PL/SQL Developer的版本是6.05,很老的版本了。
远邦,祝我今天上午10点半交规的考试能过吧。我这几天完全没有时间静下心来看交规的书,不知道今天上午的考试能否考过。
从下午写完这篇blog开始,一直到现在,强迫自己看完了1500道交规的题目,太枯燥了!
预祝你交规考试顺利通过!
我们那会考交规考试,每个人交了20块钱,老师在上面直接给大家念答案了.特有意思,呵呵
呵呵,太羡慕了,我上午过了。
恭喜恭喜,年中总结里的目标又实现了一件 ^_^