Identifying the blocking Lock

In one of our production DB we are experiencing huge bottlenecks due to locks. I am using OEM lock monitor to detect and identify the problematic lock. I am trying this out randomly as OEM list all the blocking locks. . Most times I am not able to analyse the problematic locks because of support calls from production. I just have time to kill the sessions and get the platform ready. Is there a script that I can use to identify the session that is blocking other sessions ? How do we do analysis during situations like this? At least I am interested in finding the root cause of the problem so we request the developers to fix it.
- BMP

&1 --><sid of any session>.if the sid provided is waiting for other sessions, it will show you the blocking session id.
Try this one (Not tested):
SELECT bs.username "Blocking User", bs.username "DB User",
ws.username "Waiting User", bs.SID "SID", ws.SID "WSID",
bs.sql_address "address", bs.sql_hash_value "Sql hash",
bs.program "Blocking App", ws.program "Waiting App",
bs.machine "Blocking Machine", ws.machine "Waiting Machine",
bs.osuser "Blocking OS User", ws.osuser "Waiting OS User",
bs.serial# "Serial#",
DECODE (wk.TYPE,
'MR', 'Media Recovery',
'RT', 'Redo Thread',
'UN', 'USER Name',
'TX', 'Transaction',
'TM', 'DML',
'UL', 'PL/SQL USER LOCK',
'DX', 'Distributed Xaction',
'CF', 'Control FILE',
'IS', 'Instance State',
'FS', 'FILE SET',
'IR', 'Instance Recovery',
'ST', 'Disk SPACE Transaction',
'TS', 'Temp Segment',
'IV', 'Library Cache Invalidation',
'LS', 'LOG START OR Switch',
'RW', 'ROW Wait',
'SQ', 'Sequence Number',
'TE', 'Extend TABLE',
'TT', 'Temp TABLE',
wk.TYPE
) lock_type,
DECODE (hk.lmode,
0, 'None',
1, 'NULL',
2, 'ROW-S (SS)',
3, 'ROW-X (SX)',
4, 'SHARE',
5, 'S/ROW-X (SSX)',
6, 'EXCLUSIVE',
TO_CHAR (hk.lmode)
) mode_held,
DECODE (wk.request,
0, 'None',
1, 'NULL',
2, 'ROW-S (SS)',
3, 'ROW-X (SX)',
4, 'SHARE',
5, 'S/ROW-X (SSX)',
6, 'EXCLUSIVE',
TO_CHAR (wk.request)
) mode_requested,
TO_CHAR (hk.id1) lock_id1, TO_CHAR (hk.id2) lock_id2
FROM Gv$lock hk, v$session bs, v$lock wk, v$session ws
WHERE hk.BLOCK = 1
AND hk.lmode != 0
AND hk.lmode != 1
AND wk.request != 0
AND wk.TYPE(+) = hk.TYPE
AND wk.id1(+) = hk.id1
AND wk.id2(+) = hk.id2
AND hk.SID = bs.SID(+)
AND wk.SID = ws.SID(+)
AND (bs.username IS NOT NULL)
AND (bs.username <> 'SYSTEM')

Similar Messages

  • Kill the Blocker

    Hi all,
    11.2.0.1
    We have been long bothered by a blocking process that prevents our batch process to successfully complete during midnight.
    This script helped me to identify the blocker, but did not provide the serial#r for killing the process.
    select distinct s1.username ||'@'|| s1.machine ||'(INST=' || s1.inst_id ||' SID= '|| s1.sid ||')
    is blocking '|| s2.username || '@' || s2.machine || ' (INST=' || s1.inst_id||' SID='||s2.sid ||')'    
    AS blocking_status, s2.program,s3.sql_id, s3.sql_text from gv$lock l1, gv$session s1, gv$lock l2, gv$session s2, v$sql s3
        where s1.sid=l1.sid
        and s2.sid=l2.sid
        and l1.block=1
        and l2.request >0
        and l1.id1=l2.id1
        and l2.id2=l2.id2
        and s2.sql_id = s3.sql_id;
    It this regard, to prove that I am not "lazy" I am revising the script and tell me if it correct by testing at your respective db.
    Here is my revised script:
    select distinct 'alter system kill session '||''''||s1.sid||','||s1.serial#||',@'||s1.inst_id||'''' from gv$lock l1, gv$session s1, gv$lock l2, gv$session s2, v$sql s3
        where s1.sid=l1.sid
        and s2.sid=l2.sid
        and l1.block=1
        and l2.request >0
        and l1.id1=l2.id1
        and l2.id2=l2.id2
        and s2.sql_id = s3.sql_id;
    Please check it it will kill the right process?
    Thanks a lot,
    zxy

    yxes2013 wrote:
    You did not check it
    You did not even noticed the redundant conditions which Nicolas has observed.
        and l2.id2=l2.id2
    Please check if it can be removed or there has been substitute or overwritten conditions missing?
    Thanks
    Troll.

  • Monitoring blocking Locks

    Hi
    This question relates to monitoring blocking locks on a 9.2.0.5 2 node RAC
    Origionally I have been monitoring bocking locks with every 5 mins using the following query:
    "select * from dba_blockers"
    I have recently implemented monitoring via grid control this is running an out of the box metric every 5 mins, the sql behind it is as follows:
    "SELECT blocking_sid, num_blocked
    FROM ( SELECT blocking_sid, SUM(num_blocked) num_blocked
    FROM ( SELECT l.id1, l.id2,
    MAX(DECODE(l.block, 1, i.instance_name||'-'||l.sid,
    2, i.instance_name||'-'||l.sid, 0 )) blocking_sid,
    SUM(DECODE(l.request, 0, 0, 1 )) num_blocked
    FROM gv$lock l, gv$instance i
    WHERE ( l.block!= 0 OR l.request > 0 ) AND
    l.inst_id = i.inst_id
    GROUP BY l.id1, l.id2)
    GROUP BY blocking_sid
    ORDER BY num_blocked DESC)
    WHERE num_blocked != 0 "
    Now.. At one point today the alert using "select * from dba_blockers" fired where as the out of the box metric from gird control did not fire.... alert duration was around 5 - 10 mins
    At first i simply assumed that this could have been a brief lock and due to both 5 min intervals being out of sync, the lock had shown and cleared before the grid control interval run.
    now im a little more curious.
    Is there any significan difference in what these 2 different SQL's will alert on, I was under the impression that DBA_BLOCKERS was simply querying a number of joined views, and Oracle had decided to use V$lock for their out of the box metric as it was more efficient.
    Any comments welcome
    Thanks

    Just to prove that the SQL is correct I have constrcuted a demo for you...
    SQL> create table t (a char(1));
    Table created.
    SQL> insert into t values ('z');
    1 row created.
    SQL> commit;
    in session 1 ---->
    select * from t where a='z' for update;
    ==================================================================
    in session 2 ---->
    update t set a='x' where a='z';
    (session simply hangs)
    ==================================================================
    in session 3 ------>
    SQL> select * from dba_blockers;
    HOLDING_SESSION
    48
    SQL>
    SQL> SELECT blocking_sid, num_blocked
    FROM ( SELECT blocking_sid, SUM(num_blocked) num_blocked
    FROM ( SELECT l.id1, l.id2, MAX(DECODE(l.block, 1, i.instance_name||'-'||l.sid,
    2, i.instance_name||'-'||l.sid, 0 )) blocking_sid,
    SUM(DECODE(l.request, 0, 0, 1 )) num_blocked
    FROM gv$lock l, gv$instance i
    WHERE ( l.block!= 0 OR l.request > 0 ) AND
    l.inst_id = i.inst_id
    GROUP BY l.id1, l.id2)
    GROUP BY blocking_sid
    ORDER BY num_blocked DESC)
    WHERE num_blocked != 0;
    2 3 4 5 6 7 8 9 10 11 12
    BLOCKING_SID NUM_BLOCKED
    RAC1-48 1
    So back to the origional question,
    I am using both these queries from different monitors on my prod syystem, both running on 5 minute intervals, " select * from dba_blockers" fired where as the above query - querying gv$lock did not fire.
    Origionaly i assumed that the blocking lock may have simply lasted 3t0 seconds, and due the 5 minute monitor intervals of each metric not being in sync, ... "select * from dba_blockers" may have picked up the lock, then the query selecting from gv$lock ran 2 mins later by which time the lock had disapeared.
    -Can anyone suggest any other reasons other than this why one monitor (select * from dba_blockers) picked up the lock and the other (gv$lock) didnt?
    Thanks

  • Blocking Locks - What Was Likely Going On?

    I had a blocking lock yesterday that showed up in OEM under Cluster Database --> Cluster Database Locks. The blocking lock was a row exclusive (RX) table lock that was blocking 175 other sessions that were listed under the blocking lock as having requested row share (RS) locks. It was an hour before I found out about this problem.
    Two questions:
    1.] The "Oracle Database Concepts 10gR2" book, Table 13-13, states that a row exclusive (RX) table lock can be obtained as a result of INSERT, UPDATE or DELETE DML and that in RX mode share lock modes are not permitted (which is why I had 175 blocked sessions). Does this mean that a user must have been doing a long running (1 hour plus) INSERT, UPDATE or DELETE or is there another more likely cause that I'm not aware of?
    2.] The only ways I know of to request a row share lock (of which 175 were blocked due to the RX lock) is by using:
    LOCK_TABLE <table name> IN SHARE MODE;
    LOCK_TABLE <table name> IN SHARE EXCLUSIVE MODE;
    LOCK_TABLE <table name> IN EXCLUSIVE MODE;
    I can't imagine a user doing any of these commands so is there another more likely reason that 175 row share (RX) locks were being requested (and blocked)?
    Thanks for any insight you can offer. I ended up killing the session that held the RX lock and that resolved the problem but I'd like to better understand what was happening.

    1.] The "Oracle Database Concepts 10gR2" book, Table
    13-13, states that a row exclusive (RX) table lock
    can be obtained as a result of INSERT, UPDATE or
    DELETE DML and that in RX mode share lock modes are
    not permittedThat table shows that RS (mode 2) is permitted while RX lock is held.
    Did you mean to say that sessions were waiting on a S mode (4) lock?
    This could indicate that update/delete was attempted on a parent table and that dependend table was lacking an index on fk column. (may answer your q.2)

  • Blocking locks encountered while splitting partitions in 11g

    Background: I've taken over administration of a database that has several date-range partitioned tables that, suffering from a lack of proper administration, have not had their MAXVALUE partition split into the requisite monthly partitions, in almost a year. As a result, in some cases the MAXVALUE partition has 10 million rows (the monthly partitions should average 750K rows).
    My understanding is that the syntax I am using to perform the split, should allow for on-line access to the tables while the split is being performed. Here is my syntax without the actual table names:
    ALTER TABLE owner.table_name
    SPLIT PARTITION MAXVALUE AT
    (TO_DATE(' 2012-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
    INTO (PARTITION PART201201
    TABLESPACE tablespace
    PCTFREE 10
    INITRANS 1
    MAXTRANS 255,
    PARTITION MAXVALUE) update indexes;
    Problem: In attempting to split the MAXVALUE partition into monthly partitions while the database is on-line and accessible, I see application sessions being blocked by my split session.
    So, is my understanding above incorrect? Is there some additional syntax that I am missing? Or, are the blocking locks I'm seeing merely transient in nature, and can be ignored? The server I'm running on is not very "beefy", and the split is taking quite a while to run.
    Any assistance would be appreciated.

    >
    Background: I've taken over administration of a database that has several date-range partitioned tables that, suffering from a lack of proper administration, have not had their MAXVALUE partition split into the requisite monthly partitions, in almost a year. As a result, in some cases the MAXVALUE partition has 10 million rows (the monthly partitions should average 750K rows).
    My understanding is that the syntax I am using to perform the split, should allow for on-line access to the tables while the split is being performed.
    Problem: In attempting to split the MAXVALUE partition into monthly partitions while the database is on-line and accessible, I see application sessions being blocked by my split session.
    So, is my understanding above incorrect? Is there some additional syntax that I am missing? Or, are the blocking locks I'm seeing merely transient in nature, and can be ignored? The server I'm running on is not very "beefy", and the split is taking quite a while to run.
    >
    DML that modifies the table cannot be performed on the table while the split is ongoing.
    Your bigger problem is that you are using the WRONG method for your use case. If you repeatedly split the MAXVALUE partition you will be repeatedly copying and moving the same ultimate MAXVALUE data over and over again.
    DBMS_REDEFINITION is one of your options. But since I just answered this same question 3 days ago see my reply in this thread for a more thorough discussion of your options.
    Re: Which is the Best method to Split Partition

  • Blocking Locks monitoring in 12c cloud control

    Ours is a 11.2 4 node RAC environment, and to check for blocking locks i run a sql script. I want to monitor the blocking locks in the system and if there are any locks for more than say 10 minutes then send out a mail to a group to look into it.
    We have 12c cloud control setup, my question is if there is a way to setup alerting/monitoring via 12c for checking blocking locks on all nodes and send out email notifications if there are any. I am not much familiar with 12c, please let me know and if its possible let me know the steps to set it up.

    Resolved by removing and re-adding the target...

  • Identify the table used in payables

    Hey there,
    I can identify the block, column and value in Oracle Payables using Select Help->Diagnostics->Examine.
    My question is given the BLOCK name that it returns is it possible to identify what the underlying TABLES/VIEWS are used to make the BLOCK?
    Thanks!
    Jonathan

    Change the Block so it reads as SYSTEM.
    Then select last query from the field LOV.
    This should bring up a query for the block.

  • How to find out the reason for blocking locks?

    PB Application try to create data in ASE 12.5. With this operation, there are sql, sp, trigger involved. Most of the it is okay. With lock of sleeping or sync sleeping lock. User wait for a short time to get the result.
    but some time, there are blocking lock.
    If spid for the app is 1. then looks like this app also generate another spid, say it is 2. and 2 is blocking by 1. spid 1 holding lock!
    then all user is frozen because of spid 1 holding lock!!!  How to figure it out the reason for blocking locks?

    Thanks, Mark. Yes, sp_lock, sp_who, ... are common tool I used.
    I found out one case like:
    I have a SP which call a View for data.
    When I run this SP, suppose the sipd is 1. then it will create another spid 2 because of access view and it gone very quick. This cause spid 1 block spid 2 within a short time.
    If the are many user run the app, the app will be  frozen and everyone is waiting. Finally it release, no dead lock, but the performance is not acceptable.
    That why I have this question.

  • Is it possible to have the Grid Server send an alert for blocking locks?

    All,
    We are deploying a new custom application. I'm the DBA. Our development team wants to be alerted if any processes in this new application are being blocked for more than 30 seconds. I believe that I can setup an notification from the Grid Control to alert me if more than 1 process is waiting but I'm not sure about the ability to alert when a blocking lock is occurring for more than a period of time.
    Does anyone know if this is possible? Or , can anyone give me some points on how I might write a custom notification?
    Thanks in advance.
    John

    OEM provides this metric out of the box though if you wanted to limit the check to a specific type of lock, or application you would have to write your own UDM (User Defined Metric) which is a trivial task. The minimum time interval is minutes but I assume you could use 0.25 minutes to check every 15 seconds, and be notified if it repeats twice (so this would be 2 repeated alarms over 30 seconds and match your criteria, correct?).
    Check the documentation for creating a UDM if you choose to go that route.
    Hope this helps.

  • How to identify the locks in oracle db objects? i dont have access to check

    How to identify the locks in oracle db objects? i dont have access to check the v$lock or v$ objects. i dont have dba access. what are the symptoms for table, row or objects lock? how v guess it would be lock?
    Thanks in advance friends..

    I believe you will have to call your DBA on the phone in that case.
    You can query something with a select ... for update nowait.
    If it raises an exception you can handle it within a when section.
    -- Running in one session
    SQL> create table t1 as select 1 col1 from dual;
    Table created
    SQL> select * from t1 for update nowait;
          COL1
             1
    SQL>
    -- now running in a different session
    SQL> select * from t1 for update nowait;
    select * from t1 for update nowait
    ORA-00054: resource busy and acquire with NOWAIT specified
    SQL> set serveroutput on
    SQL>
    SQL> DECLARE
      2    CURSOR cur1 IS
      3      SELECT col1 FROM t1 FOR UPDATE NOWAIT;
      4    v_col1 NUMBER;
      5    locking_error EXCEPTION;
      6    PRAGMA EXCEPTION_INIT(locking_error, -00054);
      7  BEGIN
      8    OPEN cur1;
      9  EXCEPTION
    10    WHEN locking_error THEN
    11      dbms_output.put_line('Busted locking my rows!');
    12  END;
    13  /
    Busted locking my rows!
    PL/SQL procedure successfully completed
    SQL> Now, surely you won't be able to tell anything else other than there was something locked there.
    But none of the details you would find in the views.

  • How to identify the device is locked or not?

    how to identify the iphone is locked or not

    Call AppleCare, give them the model and serial number and ask them if it is locked and if yes, which cell carrier it is locked with.

  • Identifying the process or user that has a lock on a folder or file

    In Windows Server 2008, it was easy to identify the user that had a lock on a folder or file. As a last resort, you could always log off that user to release a lock.
    In Windows Server 2012 R2, as far as my limited understanding, it is more difficult to identify which user or process has a lock on a folder or file. Is there a MS or third party technique or tool to achieve this?
    I looked at the third party tool called Unlocker, but I think that that does not work on network drives.
    Many thanks.
    Keith
    R K Howard

    Hi Keith,
    This is bit difficult in GUI.
    As mentioned by Mandy, try powershell
    Use below to get all the open files:
    Get-SMBOpenFile | flFileId              SessionId           Path                ShareRelativePath   ClientComputerName  ClientUserName
    4415226382229       4415226380377       C:\ClusterStorag... VM4\Virtual Mach... 192.168.102.14      Contoso\Contoso-HV2$
    4415226382237       4415226380385       C:\ClusterStorag... VM4\VIRTUAL MACH... 192.168.102.14      Contoso\Contoso-HV2$
    Identify the interested path and note the 'FileId', ClientComputerName (Is the user Workstation IP)
    Use below cmdlet to identify if Locks(1) is Enabled on that path not.
    Get-SmbOpenFile -FileId 4415226383569 | Select-Object -Property *ClientComputerName    : 192.168.102.14
    ClientUserName        : Contoso\Contoso-HV2$
    ClusterNodeName       : Contoso-FS2
    ContinuouslyAvailable : True
    Encrypted             : False
    FileId                : 4415226383569
    Locks                 : 1
    Path                  : C:\ClusterStorage\Volume2\VMS\VM4.VHDX
    Once you find the correct FileId, use below command to ping and find the workstation name having the Lock,
    ping -a <IP address>
    There are few more cmdlets that you might be interested in.
    Get-SMBConnection | fl
    Get-SMBSession | fl
    References:
    Get-SmbOpenFile
    http://technet.microsoft.com/en-us/library/jj635701.aspx
    Regards,
    Satyajit
    Please“Vote As Helpful”
    if you find my contribution useful or “MarkAs Answer” if it does answer your question. That will encourage me - and others - to take time out to help you.

  • Identifying the procecure/function that has locked a table (or a resource)

    Sometimes, I have a procedure failing saying that a table is locked (yes, I know, it could have been written to diligently wait for it to become available). Is there any system table from where I can figure out which procedure has locked a table and which procedures are waiting to access it, and in what order? I am trying to figure out who are the resource hogs here, and what resources are most hogged.
    Thanks,
    Regards,
    Srini

    Hi Keith,
    This is bit difficult in GUI.
    As mentioned by Mandy, try powershell
    Use below to get all the open files:
    Get-SMBOpenFile | flFileId              SessionId           Path                ShareRelativePath   ClientComputerName  ClientUserName
    4415226382229       4415226380377       C:\ClusterStorag... VM4\Virtual Mach... 192.168.102.14      Contoso\Contoso-HV2$
    4415226382237       4415226380385       C:\ClusterStorag... VM4\VIRTUAL MACH... 192.168.102.14      Contoso\Contoso-HV2$
    Identify the interested path and note the 'FileId', ClientComputerName (Is the user Workstation IP)
    Use below cmdlet to identify if Locks(1) is Enabled on that path not.
    Get-SmbOpenFile -FileId 4415226383569 | Select-Object -Property *ClientComputerName    : 192.168.102.14
    ClientUserName        : Contoso\Contoso-HV2$
    ClusterNodeName       : Contoso-FS2
    ContinuouslyAvailable : True
    Encrypted             : False
    FileId                : 4415226383569
    Locks                 : 1
    Path                  : C:\ClusterStorage\Volume2\VMS\VM4.VHDX
    Once you find the correct FileId, use below command to ping and find the workstation name having the Lock,
    ping -a <IP address>
    There are few more cmdlets that you might be interested in.
    Get-SMBConnection | fl
    Get-SMBSession | fl
    References:
    Get-SmbOpenFile
    http://technet.microsoft.com/en-us/library/jj635701.aspx
    Regards,
    Satyajit
    Please“Vote As Helpful”
    if you find my contribution useful or “MarkAs Answer” if it does answer your question. That will encourage me - and others - to take time out to help you.

  • How to dump block and identify the bytes stored for each column

    SQL> select header_file, header_block
    2 from dba_segments
    3 where segment_name = 'APARTMENTS';
    HEADER_FIL HEADER_BLO
    4 1692
    1 row selected.
    SQL> alter system dump datafile 4 block 1693;
    Statement processed.
    How can I see the dump block and identify the bytes stored for each column?
    tab 0, row 0, @0x73b
    tl: 125 fb: H-FL lb: 0x1 cc: 4
    col 0: [25]
    52 65 64 77 6f 6f 64 20 53 68 6f 72 65 73 20 41 70 61 72 74 6d 65 6e 74 73
    col 1: [20] 00 54 00 01 02 08 00 00 00 01 00 00 00 01 00 00 00 00 1b 8d
    col 2: [53]
    00 54 00 01 02 0c 00 00 00 01 00 00 00 01 00 00 00 00 1b 8e 00 21 09 00 00
    00 00 00 00 11 00 00 00 00 00 01 45 6d 65 72 67 65 6e 63 79 20 44 65 74 61
    69 6c 73
    col 3: [20] 00 54 00 01 01 08 00 00 00 01 00 00 00 01 00 00 00 00 1b 8f

    SQL> select header_file, header_block
    2 from dba_segments
    3 where segment_name = 'APARTMENTS';
    HEADER_FIL HEADER_BLO
    4 1692
    1 row selected.
    SQL> alter system dump datafile 4 block 1693;
    Statement processed.
    How can I see the dump block and identify the bytes stored for each column?
    tab 0, row 0, @0x73b
    tl: 125 fb: H-FL lb: 0x1 cc: 4
    col 0: [25]
    52 65 64 77 6f 6f 64 20 53 68 6f 72 65 73 20 41 70 61 72 74 6d 65 6e 74 73
    col 1: [20] 00 54 00 01 02 08 00 00 00 01 00 00 00 01 00 00 00 00 1b 8d
    col 2: [53]
    00 54 00 01 02 0c 00 00 00 01 00 00 00 01 00 00 00 00 1b 8e 00 21 09 00 00
    00 00 00 00 11 00 00 00 00 00 01 45 6d 65 72 67 65 6e 63 79 20 44 65 74 61
    69 6c 73
    col 3: [20] 00 54 00 01 01 08 00 00 00 01 00 00 00 01 00 00 00 00 1b 8f

  • Using OleDbDataAdapter Update with InsertCommands and getting blocking locks on Oracle table

    The following code snippet shows the use of OleDbDataAdapter with InsertCommands.  This code is producing many inserts on the Oracle table and is now suffering from contention... all on the same table.  How does the OleDbDataAdapter produce
    inserts from a dataset... what characteristics do these inserts inherent in terms of batch behavior... or do they naturally contend for the same resource. 
    oc.Open();
    for (int i = 0; i < xImageId.Count; i++)
    // Create the oracle adapter using a SQL which will not return any actual rows just the structure
    OleDbDataAdapter da =
       new OleDbDataAdapter("SELECT BUSINESS_UNIT, INVOICE, ASSIGNMENT_ID, END_DT, RI_TIMECARD_ID, IMAGE_ID, FILENAME, BARCODE_LABEL_ID, " +
       "DIRECT_INVOICING, EXCLUDE_FLG, DTTM_CREATED, DTTM_MODIFIED, IMAGE_DATA, PROCESS_INSTANCE FROM sysadm.PS_RI_INV_PDF_MERG WHERE 1 = 2", oc);
    // Create a data set
    DataSet ds = new DataSet("documents");
    da.Fill(ds, "documents");
    // Loop through invoices and write to oracle
    string[] sInvoices = invoiceNumber.Split(',');
    foreach (string sInvoice in sInvoices)
        // Create a data set row
        DataRow dr = ds.Tables["documents"].NewRow();
        ... map the data
        // Populate the dataset
        ds.Tables["documents"].Rows.Add(dr);
    // Create the insert command
    string insertCommandText =
        "INSERT /*+ append */ INTO PS_table " +
        "(SEQ_NBR, BUSINESS_UNIT, INVOICE, ASSIGNMENT_ID, END_DT, RI_TIMECARD_ID, IMAGE_ID, FILENAME, BARCODE_LABEL_ID, DIRECT_INVOICING, " +
        "EXCLUDE_FLG, DTTM_CREATED, DTTM_MODIFIED, IMAGE_DATA, PROCESS_INSTANCE) " +
        "VALUES (INV.nextval, :BUSINESS_UNIT, :INVOICE, :ASSIGNMENT_ID, :END_DT, :RI_TIMECARD_ID, :IMAGE_ID, :FILENAME,  " +
        ":BARCODE_LABEL_ID, :DIRECT_INVOICING, :EXCLUDE_FLG, :DTTM_CREATED, :DTTM_MODIFIED, :IMAGE_DATA, :PROCESS_INSTANCE)";
    // Add the insert command to the data adapter
    da.InsertCommand = new OleDbCommand(insertCommandText);
    da.InsertCommand.Connection = oc;
    // Add the params to the insert
    da.InsertCommand.Parameters.Add(":BUSINESS_UNIT", OleDbType.VarChar, 5, "BUSINESS_UNIT");
    da.InsertCommand.Parameters.Add(":INVOICE", OleDbType.VarChar, 22, "INVOICE");
    da.InsertCommand.Parameters.Add(":ASSIGNMENT_ID", OleDbType.VarChar, 15, "ASSIGNMENT_ID");
    da.InsertCommand.Parameters.Add(":END_DT", OleDbType.Date, 0, "END_DT");
    da.InsertCommand.Parameters.Add(":RI_TIMECARD_ID", OleDbType.VarChar, 10, "RI_TIMECARD_ID");
    da.InsertCommand.Parameters.Add(":IMAGE_ID", OleDbType.VarChar, 8, "IMAGE_ID");
    da.InsertCommand.Parameters.Add(":FILENAME", OleDbType.VarChar, 80, "FILENAME");
    da.InsertCommand.Parameters.Add(":BARCODE_LABEL_ID", OleDbType.VarChar, 18, "BARCODE_LABEL_ID");
    da.InsertCommand.Parameters.Add(":DIRECT_INVOICING", OleDbType.VarChar, 1, "DIRECT_INVOICING");
    da.InsertCommand.Parameters.Add(":EXCLUDE_FLG", OleDbType.VarChar, 1, "EXCLUDE_FLG");
    da.InsertCommand.Parameters.Add(":DTTM_CREATED", OleDbType.Date, 0, "DTTM_CREATED");
    da.InsertCommand.Parameters.Add(":DTTM_MODIFIED", OleDbType.Date, 0, "DTTM_MODIFIED");
    da.InsertCommand.Parameters.Add(":IMAGE_DATA", OleDbType.Binary, System.Convert.ToInt32(filedata.Length), "IMAGE_DATA");
    da.InsertCommand.Parameters.Add(":PROCESS_INSTANCE", OleDbType.VarChar, 10, "PROCESS_INSTANCE");
    // Update the table
    da.Update(ds, "documents");

    Here is what Oracle is showing as blocking locks and the SQL that has been identified with each of the SIDS.  Not sure why there is contention.  There are no triggers or joined tables in this piece of code.
    Here is the SQL all of the SIDs below are running:
    INSERT INTO sysadm.PS_RI_INV_PDF_MERG (SEQ_NBR, BUSINESS_UNIT, INVOICE, ASSIGNMENT_ID, END_DT, RI_TIMECARD_ID, IMAGE_ID, FILENAME, BARCODE_LABEL_ID, DIRECT_INVOICING, EXCLUDE_FLG, DTTM_CREATED, DTTM_MODIFIED, IMAGE_DATA, PROCESS_INSTANCE) VALUES (SYSADM.INV_PDF_MERG.nextval,
    :BUSINESS_UNIT, :INVOICE, :ASSIGNMENT_ID, :END_DT, :RI_TIMECARD_ID, :IMAGE_ID, :FILENAME, :BARCODE_LABEL_ID, :DIRECT_INVOICING, :EXCLUDE_FLG, :DTTM_CREATED, :DTTM_MODIFIED, :IMAGE_DATA, :PROCESS_INSTANCE)
    SID 1452 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1 is blocking SID 1150 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1
    SID 1452 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1 is blocking SID 1452 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1
    SID 1452 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1 is blocking SID 1156 (BTSUSER,biztprdi,BTSNTSvc64.exe) in instance FSLX3
    SID 1452 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1 is blocking SID 6 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX2
    SID 1452 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1 is blocking SID 1726 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX2
    SID 1452 (BTSUSER,BIZTPRDI,BTSNTSvc64.exe) in instance FSLX1 is blocking SID 2016 (BTSUSER,biztprdi,BTSNTSvc64.exe) in instance FSLX2

Maybe you are looking for