From:Steve Adams
Date:27-Mar-2001 14:24
Subject:   Deadlock waiting for shared locks on TX enqueues

No, the shared lock that you would wait for in the case of a missing foreign key index would be a table lock (TM enqueue). In this case you are waiting for another transaction to complete (TX enqueue). This is not a row-level locking issue either, because the sessions would be waiting for an X mode lock in that case. There are several reasons that I have encountered that can cause sessions to wait for a shared lock on a TX enqueue. In order of frequency they are ...

  1. ITL entry shortages: If a session needs to update a row in a block, but finds that all the available transaction slots in the block header are in use by uncommitted transactions, and that there is not enough free space in the block to dynamically create an additional ITL slot, then it will wait for one of the transactions using the existing transaction slots to complete. The transaction that it chooses to wait for is the Oracle process id of its controlling process modulo the number of transaction slots in the block.
  2. Constraint validation: If a session needs to make a change that in combination with an uncommitted change in another transaction would violate a unique or referential integrity constraint should both transactions be committed, then it must wait for the other transaction to complete.
  3. Bitmap index entry locks: If a session needs to make a change to an index entry in a bitmap index, but finds that another transaction has changed that index entry but not yet committed, then it must wait for that transaction to complete.
From the information in your trace file I cannot eliminate any of these options, so I'll leave it up to you to figure out which is most likely in your environment.

I've used your missing_fk_indexes script with much success since we have a lot of processes running against our database in parallel. After indexing the foreign keys it eliminated all of our deadlocks. Recently though, we've been getting the following deadlock and I can't for the life of me figure out why the insert statement is trying to get a shared lock.

Current SQL statement for this session:
insert into ENGINE.RESPONSE (ID,RESPONSEDATA_ID,RESPONSETYPE_ID,VALUE) values ( :1 , :2 , :3 , :4 )

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-0002000d-00000118        11       9     X              8      15           S
TX-0007002f-0000011a         8      15     X             11       9           S

Rows waited on:
Session 15: no row
Session 9: no row
I've run your missing_fk_indexes script and we don't have any unindexed foreign keys that I'm aware of. Wouldn't the shared lock in this case imply a missing fk index?