ORA-00060: Deadlock Trace file query found but can we get its parameter values
As this ORA-00060 is quite famous and I too have analyzed it in past and have solved a few of them in past. In my case I have ensured there is no common update from multiple session, still the error was occurring, and for such solutions I have used to increase the initrans and frequent commit in the concurrent transactions have helped me to solve it. Now in another program again I saw the ORA-00060. Then I analyze the .trc file. There it is showing the merge query running from two session which is causing deadlock. This query has bind parameters. I wanted to know the values of this bind parameter. Because if by any bug if this binding parameter is same from the two session then it will be obvious that the two sessions are updating the same records, and eventually causing the deadlock. Where I am struggling is that I am not able to see any way to get the value of these bind parameter in the .trc file. The call stack trace in the .trc file does have some blocks but very difficult to figure out where and what is the value of this parameter when the deadlock graph was created. Does anyone know whether it is possible to get the bind parameter values from .trc file for the queries causing the deadlock? I have started putting the log in the code so that next time when it occurs I will get that from normal logs.
Deadlock graph: ------------Blocker(s)----------- ------------Waiter(s)------------
Resource Name process session holds waits serial process session holds waits serial TX-0012000B-0004A991-00000000-00000000 193 203 X 7643 195 583 S 11914 TX-000F000E-000871FC-00000000-00000000 195 583 X 11914 193 203 S 7643
The query (table/column names I have changed) is:
----- Information for waiting sessions -----
Session 203:
sid: 203 ser: 7643 audsid: 38682755 user: 151/SCHMEA1
...
pid: 193 O/S info: user: grid, term: UNKNOWN, ospid: 11010512
image: oracle@hostname
client details:
...
application name: JDBC Thin Client, hash value=2546894660
current SQL:
MERGE INTO TABLE_A TA USING ZPD_TABL2 ZPD ON (TA.COY=ZPD.COY AND TA.COL2=ZPD.COL2 AND TA.TRXNO=ZPD.TRXNO AND (TA.COL3 = ' ' OR TA.COL3 IS NULL OR TA.COL3 = 'I') AND ZPD.THREADNO=:B1 ) WHEN MATCHED THEN UPDATE SET TA.COL3 = 'Y', TA.USRPRF=:B3 , TA.JOBNM=:B2 , TA.DATIME=LOCALTIMESTAMP
Session 583:
sid: 583 ser: 11914 audsid: 38682758 user: 151/VM1DTA
...
pid: 195 O/S info: user: grid, term: UNKNOWN, ospid: 58064926
image: oracle@hostname
client details:
..
application name: JDBC Thin Client, hash value=2546894660
current SQL:
MERGE INTO TABLE_A TA USING ZPD_TABL2 ZPD ON (TA.COY=ZPD.COY AND TA.COL2=ZPD.COL2 AND TA.TRXNO=ZPD.TRXNO AND (TA.COL3 = ' ' OR TA.COL3 IS NULL OR TA.COL3 = 'I') AND ZPD.THREADNO=:B1 ) WHEN MATCHED THEN UPDATE SET TA.COL3 = 'Y', TA.USRPRF=:B3 , TA.JOBNM=:B2 , TA.DATIME=LOCALTIMESTAMP
----- End of information for waiting sessions -----
So if I get the value of THREADNO =:B1 (this bind parameter) value from .trc file then I can confirm whether these two merge from two sessions are updating the same records or not.
Solution 1:
One possible suspect constalation in your use case would be if the threadno
is not uniquely mapped to the join keys used in the MERGE
.
You may quickly check it with the query below - it should not return any row. If yes, you have a postential problem described later.
select COY, COL2, TRXNO, min(THREADNO), max(THREADNO)
from zpd_tabl2 zpd
group by COY, COL2, TRXNO
having count(distinct THREADNO) > 1;
Bind Variables Used in Dealock Statements
Well, the deadlock trace file contains some information
Peeked Binds
============
Bind variable information
position=1
datatype(code)=2
datatype(string)=NUMBER
precision=0
scale=0
max length=22
value=1
But this will not help you as it is the peeked value used while the statement was parsed.
Rows waited on
More usefull information is the rowid
of the rows caused the problem
Rows waited on:
Session 138: obj - rowid = 00012563 - AAASVjAARAAAACbAAB
(dictionary objn - 75107, file - 17, block - 155, slot - 1)
Session 12: obj - rowid = 00012563 - AAASVjAARAAAACbAAA
(dictionary objn - 75107, file - 17, block - 155, slot - 0)
The object_id
(here 75107) should point to your TABLE_A
and you can check the threadno
s that try to modify the problematic rows with the following query.
select a.rowid, a.COY, a.COL2, a.TRXNO , zpd.threadno
from table_a a
join zpd_tabl2 zpd
ON ( a.coy = zpd.coy
AND a.col2 = zpd.col2
AND a.trxno = zpd.trxno)
where a.rowid in ( 'AAASVjAARAAAACbAAB','AAASVjAARAAAACbAAA');
If you see at least four rows, that you suffer the threadno
problem stated in the beginning.
Reproducible Example
Note, I can't claim that this is exact your situation, but this is the simplest way how to get a deadlock you observed.
create table table_a as
select rownum coy, rownum col2, rownum trxno, ' ' col3, localtimestamp datime
from dual
connect by level <= 2;
create table zpd_tabl2 as
select rownum coy, rownum col2, rownum trxno, 1 threadno
from dual
union all
select rownum coy, rownum col2, rownum trxno, 2 threadno
from dual
union all
select 1+rownum coy, 1+rownum col2, 1+rownum trxno, 3 threadno
from dual
union all
select 1+rownum coy, 1+rownum col2, 1+rownum trxno, 4 threadno
from dual
;
- in Session 1 run the
MERGE
with pareter1
.
MERGE INTO table_a ta
USING zpd_tabl2 zpd ON ( ta.coy = zpd.coy
AND ta.col2 = zpd.col2
AND ta.trxno = zpd.trxno
AND ( ta.col3 = ' '
OR ta.col3 IS NULL
OR ta.col3 = 'I' )
AND zpd.threadno = :b1 )
WHEN MATCHED THEN UPDATE
SET ta.col3 = 'Y',
ta.datime = localtimestamp;
1 row merged
- in Session 2 run the
MERGE
with pareter4
1 row merged
- in Session 1 run the
MERGE
with pareter3
waiting
- in Session 2 run the
MERGE
with pareter1
waiting
- in Session 1
ORA-00060: deadlock detected while waiting for resource