I have a JDBC-based application which uses XA datasources and transactions which span multiple connections, connected to an Oracle database. The app sometimes needs to make some queries using join with a table from another (Oracle) server using a shared DbLink. The request works if I don't do it too often, but after 4 or 5 requests in rapid succession I get an error (ORA-02020 - too many links in use). I did some research, and the suggested remedy is to call "ALTER SESSION CLOSE DATABASE LINK ". If I call this request after the query that joins the DbLnk table, I get the error ORA-2080 (link is in use). If I call it before the query, I get ORA-2081 (link closed). Does this call do any good at all? The JDBC connection is closed long before the transaction commit (which is managed either by servlet or by EJB container, depending on the circumstances). I get the impression that when the connection closes, Oracle marks the link as closed, but it takes a minute or two for it to return to the pool of available links. I understand I could enlarge the pool of links (using the open_links property in the config file), but that won't guarantee that I won't have the same problem under a heavier load. Is there something I can do differently to get the dblinks to close more rapidly?
1 Answers
Any distributed SQL, even a select, will open a transaction that must be closed before you can close the database link. You need to either rollback or commit before you call ALTER SESSION CLOSE DATABASE LINK.
But it sounds like you've already got something else handling your transactions. If it's not possible to manually rollback or commit, you should try to increase the number of open links. The OPEN_LINKS parameter is the maximum number of links per session. The number of links you need isn't really dependent on the load, it should be based on the maximum number of distinct remote databases.
Edit:
The situation you describe in your comment shouldn't happen. I don't understand enough about your system to know what's really happening with the transactions. Anyway, if you can't figure out exactly what the system is doing maybe you can replace "alter session close database link" with a procedure like this:
create or replace procedure rollback_and_close_db_links authid current_user is
begin
rollback;
for links in (select db_link from v$dblink) loop
execute immediate 'alter session close database link '||links.db_link;
end loop;
end;
/
You'll probably need this grant:
grant select on v_$dblink to [relevant user];

- 34,999
- 6
- 74
- 132
-
Thanks for the response. It's sort of the response I was afraid I would get. It's a pain because the layer which handles the SQL generation is far from the layer which handles the transactions, but maybe I can find a not-too-ugly way to pass the close requests into a queue to be processed after commit or rollback (at least in the cases where it's not the container that manages the transactions). – aro_biz Feb 25 '11 at 10:16
-
Follow-up question: If the problem is that Oracle can't close the link until the transaction is closed, why does the call to close the link BEFORE the request also fail? It's not in the same transaction. Obviously it should fail if the link was not previously used, but if the link is used in transaction A, which is then committed, and then a minute later I try to close the link in a new transaction B before using the dblink again, why do I get an ORA-2081 (link is closed) error? – aro_biz Feb 25 '11 at 12:58
-
FTI, I just ran a test to see if queuing up the close request and calling it immediately after the commit would work, and it doesn't. I still get the ORA-02081 error. – aro_biz Feb 28 '11 at 10:27
-
The tip about the grant for v_$dblink is useful. Now I can query v$dblink right after I get the ORA-02020 (too many open links) error. Unfortunately, the table is absolutely empty. It's pretty weird. It's as though the dblinks get removed from the list but are not closed right away. – aro_biz Feb 28 '11 at 10:35
-
v$dblink only lists the database links open in your session. – Jon Heller Feb 28 '11 at 20:48
-
Just did a new test, and for me the limiting parameter is not OPEN_LINKS but OPEN_LINKS_PER_INSTANCE. – aro_biz Mar 03 '11 at 17:35