[20130701]db link与事务.txt
昨天帮别人修复数据库,安全起见,我先启动read only模式,叫他们检查一些相关数据是否正常,但是在程序界面上出现:
ORA-16000: database open for read-only access。
我跟踪发现执行的实际上通过db_link访问远程数据库的语句,不是dml语句(注:实际上执行dml,发生的事务也在远端,不在本地)。按
照这个道理如果数据库在只读的情况下,是不能访问远端的数据库的。
google 发现如下链接:
我回来后在我的机器做一次测试,发现在11g与10g下存在不同。这也解开了我在生产系统看到的一些奇怪情况。
1.建立测试环境:
SQL> @ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
--建立db_link,并验证是否正确。
CREATE PUBLIC DATABASE LINK "TESTB.COM"
CONNECT TO SCOTT
IDENTIFIED BY
USING '192.168.XXX.YYY:1521/orcl';
--启动数据库到read only模式:
SQL> select open_mode from v$database ;
OPEN_MODE
--------------------
READ ONLY
2.开始测试:
$ cat viewredo.sql
SELECT b.NAME, a.statistic#, a.VALUE
FROM v$mystat a, v$statname b
WHERE b.NAME IN ('redo size', 'redo wastage','user commits') AND a.statistic# = b.statistic#;
SQL> @viewredo
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 6 0
redo size 178 0
redo wastage 183 0
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
no rows selected
SQL> select sysdate from dual@testb.com;
SYSDATE
-------------------
2013-07-01 09:42:28
--奇怪,居然成功!
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
no rows selected
SQL> @viewredo
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 6 0
redo size 178 0
redo wastage 183 0
--在11G下没有回滚段产生,没有redo产生。
SQL> select dbms_transaction.local_transaction_id() x from dual ;
X
------------------------------
65535.0.599562215
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC STATUS XID
---------- ---------- ---------- ---------- ---------- ---------- ---------------- ----------------
-1 0 599562215 0 0 0 IDLE FFFF0000E797BC23
SQL> select * from FLASHBACK_TRANSACTION_QUERY where xid=hextoraw('FFFF0000E923393B');
no rows selected
SQL> @viewredo
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 6 0
redo size 178 0
redo wastage 183 0
--奇怪,执行select dbms_transaction.local_transaction_id() x from dual ;为什么会有事务回滚段。
--但是注意看xid*的信息很奇怪,XIDUSN=-1,UBAFIL,UBABLK,UBAREC都是0,按照这个信息,是不应该分配回滚段的。
-- 也就是并没有分配使用回滚段。这样应该也没有产生redo日志。
SQL> select * from dba_rollback_segs where segment_id=-1 ;
no rows selected
SQL> rollback ;
Rollback complete.
SQL> select dbms_transaction.local_transaction_id() x from dual ;
X
------------------------------
--可以发现在11G(只读模式下)下通过db_link访问远端,没有redo size产生,不会报错。
3.在10G下测试,由于各种原因,我无法设置数据库在read only模式,不过还是能看出问题:
SQL> ver.sql
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
SQL> column name format a30
SQL> @viewredo.sql
NAME STATISTIC# VALUE
------------------------------ ---------- ----------
user commits 4 0
redo size 134 0
redo wastage 136 0
SQL> select sysdate from dual@mid ;
SYSDATE
-------------------
2013-07-01 11:27:58
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC STATUS XID
---------- ---------- ---------- ---------- ---------- ---------- ---------------- ----------------
5 67 414045 0 0 0 ACTIVE 050043005D510600
SQL> @viewredo.sql
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 4 0
redo size 134 340
redo wastage 136 0
--很明显在10g下,要通过db_link访问远端数据库,要使用回滚段并且会产生redo。但是注意看UBAFIL,UBABLK,UBAREC都是0.
SQL> select * from FLASHBACK_TRANSACTION_QUERY where xid=hextoraw('050043005D510600');
XID START_SCN START_TIMESTAMP COMMIT_SCN COMMIT_TIMESTAMP LOGON_USER UNDO_CHANGE# OPERATION TABLE_NAME TABLE_OWNER ROW_ID UNDO_SQL
---------------- ---------- ------------------- ---------- ------------------- ---------- ------------ ---------- ---------- ----------- ---------------
050043005D510600 9672478702 2013-07-01 11:27:58 XXXX 1 BEGIN
--这个也是我们生产系统看到的情况。
4.在10G下如何实现不产生日志呢?可以设置回话事务的read only,来避免这个情况。不过估计没人会这么做!
SQL> @ver.sql
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
SQL> set transaction read only;
Transaction set.
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
no rows selected
SQL> @viewredo.sql
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 4 0
redo size 134 0
redo wastage 136 0
SQL> select sysdate from dual@mid ;
SYSDATE
-------------------
2013-07-01 11:42:00
SQL> @viewredo.sql
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 4 0
redo size 134 0
redo wastage 136 0
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
no rows selected
SQL> select dbms_transaction.local_transaction_id() c20 from dual ;
C20
--------------------
5.25.414049
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC STATUS XID
---------- ---------- ---------- ---------- ---------- ---------- ---------------- ----------------
5 25 414049 0 0 0 ACTIVE 0500190061510600
5.回到11G,打开到read write模式:
SQL> select open_mode from v$database ;
OPEN_MODE
--------------------
READ WRITE
SQL> @viewredo
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 6 0
redo size 178 724
redo wastage 183 0
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
no rows selected
SQL> select sysdate from dual@testb.com;
SYSDATE
-------------------
2013-07-01 12:04:05
SQL> select XIDUSN,XIDSLOT,XIDSQN,UBAFIL,UBABLK,UBAREC,STATUS,xid from v$transaction;
XIDUSN XIDSLOT XIDSQN UBAFIL UBABLK UBAREC STATUS XID
---------- ---------- ---------- ---------- ---------- ---------- ---------------- ----------------
9 13 15788 0 0 0 ACTIVE 09000D00AC3D0000
SQL> @viewredo
NAME STATISTIC# VALUE
-------------------- ---------- ----------
user commits 6 0
redo size 178 980
redo wastage 183 0
SQL> select dbms_transaction.local_transaction_id() x from dual ;
X
------------------------------
9.13.15788
SQL> select * from FLASHBACK_TRANSACTION_QUERY where xid=hextoraw('09000D00AC3D0000');
XID START_SCN START_TIMESTAMP COMMIT_SCN COMMIT_TIMESTAMP LOGON_USER UNDO_CHANGE# OPERATION TABLE_NAME TABLE_OWNER ROW_ID UNDO_SQL
---------------- ---------- ------------------- ---------- ----------------- ---------- ------------ ---------- ---------- ----------- ------ --------
09000D00AC3D0000 3237659553 2013-07-01 12:04:04 SCOTT 1 BEGIN
--可以发现一样产生日志!
总结:
DBLINK是远程连接到其他数据库进行访问,这个会涉及到一个事务的关系。但是在11g在read only模式下使用dblink是没有问题的。