distributed transaction,找到线索了

最近放松了学习,整理一下之前关于dbkink query 的一篇文章:

"带dblinkquery会起一个transaction吗?"

我觉得会,但是一直找不到相关的技术细节。

PL/SQL Developer的sql window中做distributed query时,commit 和rollback是高亮显示的,但是后来发现在command window中执行,commit 和rollback 却没有高亮。

 

现在终于发现有比较好的分析了:

 

http://dbsnake.com/2009/07/distributed-transaction.html

 

"带dblinkquery会起一个transaction吗?"

 

PL/SQL Developercommand window中执行一个带dblinkquery后,PL/SQL Developer的工具栏上的标识transaction的按钮'commit'和'rollback'没有高亮显示呢?"。

----在PL/SQL Developercommand window中执行一个transaction的时候,如果没有commit或者rollback,其工具栏上的标识transaction的按钮'commit'和'rollback'是一直会高亮显示的。

 

可以试了一下,的却是这样的。

 

下面是一些实验步骤:

 

不用PL/SQL Developercommand window了,直接用sqlplus,开两个session,分别为session 1session 2

 

先在session 1中删除表uplbth中的一条记录:

Session 1

SQL> delete from uplbth where ubtbth='HPCAN081200010';

 

已删除1行。

 

接着在session 2中也做同样的删除动作,只不过在执行删除前先执行一个带dblinkquery语句:

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 Developercommand window中做同样的事情,session 2就会一直等待session 1

 

我感觉这是因为在session 2中执行"select count(*) from uplbth@caipratest"的时候PL/SQL Developer人为的commit了一下。

 

好了,我们来做一个10046验证一下。

打开一个PL/SQL Developercommand 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 ct=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,并且这个transactionread only的。

 

但我并没有从trace文件中看到显式的commit语句,估计是PL/SQL Developerbegin :id := sys.dbms_transaction.local_transaction_id; end;做了这样的事情。
 
 
 
关于begin :id := sys.dbms_transaction.local_transaction_id; end;
 
 
SELECT   /*+ ORDERED */
         sql_text
    FROM v$sqltext a
   WHERE (a.hash_value, a.address) IN (
            SELECT DECODE (sql_hash_value,
                           0, prev_hash_value,
                           sql_hash_value
                          ),
                   DECODE (sql_hash_value, 0, prev_sql_addr, sql_address)
              FROM v$session b
             WHERE  b.SID=&sid) 
ORDER BY piece ASC;
 
如果只是select, 得到的结果就是
begin :id := sys.dbms_transaction.local_transaction_id; end;
 
如果是DML, 没有commit,或者rollback,得到的结果是:
 
begin sys.dbms_output.get_line(line => :line, status => :status); end;
 
 
还没有找到更详细的解释,似乎PL/SQL Developer中 的SESSION就会是这样的,用SQLPLUS调用的话,就能查询到正确的结果。
 
那么问题来了sys.dbms_transaction.local_transaction_id;是干什么的呢?
 
TOM 大师有简单的论述:
 
Q:
 to uniquely identify a
transaction with the introducton of automatic undo management mode in Oracle9i. And if we could still user the following query to get (rbs, slot, seq) and compare it with the
result (xidusn, xidslot, xidsqn) from v$transaction.

select username, v$lock.sid,
trunc(id1/power(2,16)) rbs,
bitand(id1,to_number('ffff','xxxx'))+0 slot,
id2 seq, lmode, request, block
from v$lock, v$session
where v$lock.type='TX'
and v$lock.sid=v$session.sid
and v$session.username=USER
 
A:
ops$tkyte@ORA920> select dbms_transaction.local_transaction_id from dual;

LOCAL_TRANSACTION_ID
-----------------------
13.36.60919

ops$tkyte@ORA920> select XIDUSN, XIDSLOT,XIDSQN from v$transaction;

    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
        13         36      60919


but yes, it would work with UNDO tablespaces since they are just rollback segments in disguise.  
 
这么看来这个
begin :id := sys.dbms_transaction.local_transaction_id; end;
就是得到和transaction相关的值,但问题又来了,select操作并不会产生这个值。
 
SQL>  alter session set isolation_level=serializable;

Session altered.

SQL> select * from t;

         X
----------
         1

SQL> SELECT dbms_transaction.local_transaction_id FROM dual;

LOCAL_TRANSACTION_ID
--------------------------------------------------------------------------------
16.81.7410

/* So far so good -- I am in the transaction */
SQL> commit;

Commit complete.

SQL> alter session set isolation_level=read committed;

Session altered.

SQL> select * from t;

         X
----------
         1

SQL> SELECT dbms_transaction.local_transaction_id FROM dual;

LOCAL_TRANSACTION_ID
--------------------------------------------------------------------------------

/* How come ? I am not in a transaction ? Or a transaction running in the READ COMMITTED mode is
not quite a transaction */

SQL> commit;

Commit complete.
 
session  isolation_level设置成serializable,就生成了 transaction相关信息,而此时commit和rollback 又高亮了,这说明已经用到回归段了。
 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/781883/viewspace-700169/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/781883/viewspace-700169/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值