Skip to Main Content
  • Questions
  • oracle parameter distributed_locked_tiemeout?

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, lys.

Asked: November 12, 2008 - 12:09 am UTC

Last updated: March 27, 2013 - 3:10 pm UTC

Version: 10.2.1

Viewed 10K+ times! This question is

You Asked

hi,
I am getting an application error: ORA-02049: timeout: distributed transaction waiting for lock
error? How do I keep the ORA-02049 from happening?how to modify this parameter?


and Tom said...

you modify that parameter in the same exact way you modify *any* parameter.

You read about it, you see if it is session modifiable, instance modifiable and so on. For this one:

ops$tkyte%ORA11GR1> exec print_table( q'|select * from v$parameter where name = 'distributed_lock_timeout'|' );
.NUM                          : 1092
.NAME                         : distributed_lock_timeout
.TYPE                         : 3
.VALUE                        : 60
.DISPLAY_VALUE                : 60
.ISDEFAULT                    : TRUE
.ISSES_MODIFIABLE             : FALSE
.ISSYS_MODIFIABLE             : FALSE
.ISINSTANCE_MODIFIABLE        : FALSE
.ISMODIFIED                   : FALSE
.ISADJUSTED                   : FALSE
.ISDEPRECATED                 : FALSE
.ISBASIC                      : FALSE
.DESCRIPTION                  : number of seconds a distributed transaction
waits for a lock
.UPDATE_COMMENT               :
.HASH                         : 842900040
-----------------

PL/SQL procedure successfully completed.



It cannot be modified online, so you would update your init.ora or spfile and restart with a larger value.

To keep the error from happening, you would set this parameter higher than the longest amount of time you are ever willing to wait.

Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

A reader, November 12, 2008 - 8:09 pm UTC

thanks a lot !

question on ORA-02049

JMFT, March 14, 2013 - 6:00 pm UTC

{code}
We have the dblink pm from DB2 to DB1

In DB1:


SQL> create table test02049 as select * from user_objects where rownum<3;

Table created.

SQL> select object_name from test02049;

OBJECT_NAME
-----------------------------------------------------------------------------------
ACCOUNT
ACTIVITYCODEHIERARCHY

SQL> 

In DB2:

SQL> select object_name from test02049@pm;

OBJECT_NAME
--------------------------------------------------------------------------------------
ACCOUNT
ACTIVITYCODEHIERARCHY


SQL> -- session one
SQL> update test02049@pm set object_name ='new_obj1' where object_name ='ACCOUNT';

1 row updated.

SQL> 

We did not make the commit nor rollback

open second session on DB2

SQL> -- session two
SQL> update test02049@pm set object_name ='new_obj2'  where object_name ='ACCOUNT';
update test02049@pm set object_name ='new_obj2'  where object_name ='ACCOUNT'
*
ERROR at line 1:
ORA-02049: timeout: distributed transaction waiting for lock
ORA-02063: preceding line from PM

Before the second session got time out. 

In DB1:

SQL> @vlockb

USERNAME          SID   SERIAL# TYPE     CTIME HELD       REQ             ID1      ID2
--------------- ----- --------- ---- --------- ---------- ---------- -------- --------
PRIVUSER         2836      3669 TX          21 Exclusive  None         917504  1325382
PRIVUSER         2881     53329 TX          18 None       Exclusive    917504  1325382

-- we have the blocker 2836, and the requester 2881

SQL> l
  1  SELECT SN.Username, M.Sid, SN.SERIAL#,   M.Type, m.ctime,
  2  DECODE(M.Lmode, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row
  3  Excl.', 4, 'Share', 5, 'S/Row Excl.', 6, 'Exclusive',  LTRIM(TO_CHAR(Lmode,'990'))) Lmode,
  4  DECODE(M.Request, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row Excl.', 4, 'Share', 5, 'S/Row E
  5  LTRIM(TO_CHAR(M.Request, '990'))) Request,
  6  M.Id1, M.Id2
  7  FROM V$SESSION SN
  8  , V$LOCK M
  9  WHERE
 10  (SN.Sid = M.Sid and M.Request ! = 0)
 11  or (SN.Sid = M.Sid and M.Request = 0 and Lmode != 4 and (id1, id2)
 12  in (select S.Id1, S.Id2 from V$LOCK S where Request != 0 and S.Id1
 13  = M.Id1 and S.Id2 = M.Id2) )
 14* order by Id1, Id2, M.Request

we want to check out the sql by the blocker:

SQL> @showsql
Enter value for sid_or_null: 2836
old   6: and sid = NVL('&sid_or_null',sid)
new   6: and sid = NVL('2836',sid)

no rows selected

-- We found none.

Then check on the requester:

SQL> /
Enter value for sid_or_null: 2881
old   6: and sid = NVL('&sid_or_null',sid)
new   6: and sid = NVL('2881',sid)

USERNAME            SID SQL_TEXT
--------------- ------- ------------------------------------------------------------
PRIVUSER           2881 UPDATE "TEST02049" "A1" SET "OBJECT_NAME" = :"SYS_B_0" WHERE
                         "A1"."OBJECT_NAME"=:"SYS_B_1"


SQL> 
SQL> l
  1  select username, sid, sql_text
  2  from
  3  v$sql sql,
  4  v$session sess
  5  where sql.address = sess.sql_address
  6* and sid = NVL('&sid_or_null',sid)
SQL> 

why we did not see the sql from the blocker?

{code}

Tom Kyte
March 25, 2013 - 9:39 am UTC

2836 isn't executing any SQL, it *has* executed sql, but it isn't currently executing any.


and even if it were executing sql - that wouldn't tell you "this is the sql you are looking for" - it would be some arbitrary bit of sql that session decided to be executing at that moment in time. it wouldn't be the blocking sql (it would be HIGHLY unusual for it to be the blocking sql, that would imply the block sql runs for a really really long time to still be around).

Heck, the sql that "blocked" you might not even be in the shared pool anymore.

the blocking query

A reader, March 26, 2013 - 10:14 am UTC

>>>Heck, the sql that "blocked" you might not even be in the shared pool anymore. <<<
it might be in the shared pool if the size is big enough?
Tom Kyte
March 27, 2013 - 3:10 pm UTC

right, it might be, it might not be. so what? I was just pointing that out to you - you were trying to see it in v$session and I reminded you that "it might not exist on this planet anymore"

the fact remains that the blocking session isn't actively executing that sql, so you won't see it using methods that show actively executing sql - which is what you were doing.

you can see the blocked sql obviously - because they are active and you are using a query to see actively executed sql.

you cannot see the blocking sql that way, in fact you cannot see the blocking sql at all - because as far as we are concerned - there is no such concept.

You could look in v$open_cursor - on the chance the application still has it open, but it won't show you the culprit sql, it would only show you sql that MIGHT be the culprit.

You could use ASH, but it would have had to of been a longish running sql statement to be captured by ASH - and even then, it would only be a candidate - you would not be able to tell if that sql was THE sql.

there is no such concept to us as a blocking query, there is just the fact that this session has a lock on a row and these other sessions, that just happen to be executing a particular sql statement, are blocked by that row lock.

We don't know or track the sql that locked a specific row.


even if you had sql_trace enabled, you would just have a file full of sql that MIGHT be the culprit, you would be able to look at the sql and figure out (because you can read it and tell which ones modify the table in question) what sql MIGHT be the culprit, but you wouldn't be able to 100% identify it (unless there was only one modifying sql statement in the lot of them of course)

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library