Off late, I've been facing a lot of row lock contentions. The table in contention seems to be a particular table.
This is generally what happens –
- Developer 1 starts a transaction from Oracle Forms front end screen
- Developer 2 starts another transaction, from a different session using the same screen
~5 minutes in, the front end seems unresponsive. Checking sessions shows row lock contention. The "solution" that everyone throws around is to kill sessions :/
As a database developer
- What can be done to eliminate row lock contentions?
- Would it be possible to find out which line of a stored procedure is causing these row lock contentions
- What would be the general guideline to reduce/avoid/eliminate such problems which coding?
If this question feels too open-ended/insufficient information please feel free to edit/let me know – I'll do my best to add in some additional information.
The table in question is under a lot of inserts and updates, I'd say it's one of the most busiest tables. The SP is fairly complex – to simplify – it fetches data from various tables, populates it into work tables, a lot of arithmetic operations occur on the work table and the result of the work table is inserted/updated into the table in question.
The database version is Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – 64bit. The flow of logic is executed the same order in both the sessions, the transaction isn't kept open for too long ( or at least I think so), and the locks occur during active execution of transactions.
Update: The table row count is larger than I expected, at about 3.1 million rows. Also, after tracing a session I found that couple of update statements to this table are not utilizing the index. Why is it so – I'm not sure. The column referenced in the where clause is indexed. I'm currently rebuilding the index.
Best Answer
Not exactly but you can get the SQL statement causing the lock and in turn identify the related lines in the procedure.
The Oracle Concepts Guide section on locks says, "A row is locked only when modified by a writer." Another session updating the same row will then wait for the first session to
COMMIT
orROLLBACK
before it can continue. To eliminate the problem you could serialize the users, but here are some things that can reduce the problem perhaps to the level of it not being an issue.COMMIT
more frequently. EveryCOMMIT
releases locks, so if you can do the updates in batches the likelihood of another session needing the same row is reduced.UPDATE t1 SET f1=DECODE(f2,’a’,f1+1,f1);
should be rewritten as the more selective (read fewer locks)UPDATE t1 SET f1=f1+1 WHERE f2=’a’;
. Of course if the changing the statement will still lock the majority of rows in the table then the change will only have a readability benefit.BULK COLLECT ... FORALL
.UPDATE
and theCOMMIT
. For example, if the code sends an email after each update, consider queuing the emails and sending them after committing the updates.SELECT ... FOR UPDATE NOWAIT
orWAIT 2
. You can then catch the inability to lock the row and inform the user that another session is modifying the same data.