create">heyf@VOUCHER>create or replace procedure proc_t1 2 as 3 v_cnt number; 4 begin 5 select count(*) into v_cnt from t2@A ; 6 execute immediate 'alter session close database link A'; 7 end; 8 /
* ERROR at line 1: ORA-02080: database link is in use ORA-06512: at "HEYF.PROC_T1", line 6 ORA-06512: at line 1
alter">heyf@VOUCHER>alter session close database link a; ERROR: ORA-02081: database link is not open
引出问题:
ERROR at line 1: ORA-02080: database link is in use
GOOGLE:
Why does it seem that a SELECT over a db_link requires a commit after execution ?
Because it does! When Oracle performs a distributed SQL statement Oracle reserves an entry in the rollback segment area for the two-phase commit processing. This entry is held until the SQL statement is committed even if the SQL statement is a query. If the application code fails to issue a commit after the remote or distributed select statement then the rollback segment entry is not released. If the program stays connected to Oracle but goes inactive for a significant period of time (such as a daemon, wait for alert, wait for mailbox entry, etc?) then when Oracle needs to wrap around and reuse the extent, Oracle has to extend the rollback segment because the remote transaction is still holding its extent. This can result in the rollback segments extending to either their maximum extent limit or consuming all free space in the rbs tablespace even where there are no large transactions in the application. When the rollback segment tablespace is created using extendable files then the files can end up growing well beyond any reasonable size necessary to support the transaction load of the database. Developers are often unaware of the need to commit distributed queries and as a result often create distributed applications that cause, experience, or contribute to rollback segment related problems like ORA-01650 (unable to extend rollback). The requirement to commit distributed SQL exists even with automated undo management available with version 9 and newer. If the segment is busy with an uncommitted distributed transaction Oracle will either have to create a new undo segment to hold new transactions or extend an existing one. Eventually undo space could be exhausted, but prior to this it is likely that data would have to be discarded before the undo_retention period has expired. Note that per the Distributed manual that a remote SQL statement is one that references all its objects at a remote database so that the statement is sent to this site to be processed and only the result is returned to the submitting instance, while a distributed transaction is one that references objects at multiple databases. For the purposes of this FAQ there is no difference, as both need to commit after issuing any form of distributed query.
CLOSE DATABASE LINK Clause
Specify CLOSE DATABASE LINK to close the database link dblink. When you issue a statement that uses a database link, Oracle creates a session for you on the remote database using that link. The connection remains open until you end your local session or until the number of database links for your session exceeds the value of the initialization parameter OPEN_LINKS. If you want to reduce the network overhead associated with keeping the link open, then use this clause to close the link explicitly if you do not plan to use it again in your session.
ORA-02080: database link is in use Cause: a transaction is active or a cursor is open on the database link given in the alter session close database link command. Action: commit or rollback, and close all cursors
从上面我们基本上能理解为什么会发生这个错误了.
因为 select count(*) into v_cnt from t2@A 的执行在本机产生了一个事务,但没有COMMIT或者ROLLBACK,这时如果要执行alter session close database link A;ORACLE认为还有事务在这个DBLINK上面,所以不能关闭这个DBLINK,于是就报ORA-02080: database link is in use 错误!
USN NAME ---------- ------------------------------ 4 _SYSSMU4$
@>alter system dump undo header '_SYSSMU4$';
System altered.
@>SELECT d.VALUE|| '/'|| LOWER (RTRIM (i.INSTANCE, CHR (0)))|| '_ora_'|| p.spid|| '.trc' trace_file_name 2 FROM (SELECT p.spid 3 FROM SYS.v$mystat m, SYS.v$session s, SYS.v$process p 4 WHERE m.statistic# = 1 AND s.SID = m.SID AND p.addr = s.paddr) p, 5 (SELECT t.INSTANCE 6 FROM SYS.v$thread t, SYS.v$parameter v 7 WHERE v.NAME = 'thread' 8 AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE))) i, 9 (SELECT VALUE FROM SYS.v$parameter WHERE NAME = 'user_dump_dest') d 10 ;
Oracle creates a session for you on the remote database using that link. The connection remains open until you end your local session or until the number of database links for your session exceeds the value of the initialization parameter OPEN_LINKS.