Exclusive table (read) lock on Oracle 10g?

22,634

Solution 1

If you just want to prevent any other session from modifying the data you can issue

LOCK TABLE whatever
/

This blocks other sessions from updating the data but we cannot block other peple from reading it.

Note that in Oracle such table locking is rarely required, because Oracle operates a policy of read consistency. Which means if we run a query that takes fifteen minutes to run the last row returned will be consistent with the first row; in other words, if the result set had been sorted in reverse order we would still see exactly the same rows.

edit

If you want to implement a queue (without actually using Oracle's built-in Advanced Queueing functionality) then SELECT ... FOR UPDATE is the way to go. This construct allows one session to select and lock one or more rows. Other sessions can update the unlocked rows. However, implementing a genuine queue is quite cumbersome, unless you are using 11g. It is only in the latest version that Oracle have supported the SKIP LOCKED clause. Find out more.

Solution 2

   1. Lock table
   2. Read next item in queue
   3. Remove item from the queue
   4. Remove table lock

Under this model a lot of sessions are going to be doing nothing but waiting for the lock, which seems a waste. Advanced Queuing would be a better solution.

If you want a 'roll-your-own' solution, you can look into SKIP LOCKED. It wasn't documented until 11g, but it is present in 10g. In this algorithm you would do

   1. SELECT item FROM queue WHERE ... FOR UPDATE SKIP LOCKED
   2. Process item
   3. Delete the item from the queue
   4. COMMIT

That would allow multiple processes to consume items off the queue.

Solution 3

The TABLOCKX and HOLDLOCK hints you mentioned appear to be used for writes, not reads (based on http://www.tek-tips.com/faqs.cfm?fid=3141). If that's what you're after, would a SELECT FOR UPDATE fit your need?

UPDATE: Based on your update, SELECT FOR UPDATE should work, assuming all clients use it.

UPDATE 2: You may not be in a position to do anything about it right now, but this sort of problem is actually an ideal fit for something other than a relational database, such as AMQP.

Share:
22,634
Philippe Leybaert
Author by

Philippe Leybaert

.NET and mobile (Xamarin) developer. Maintainer and main contributor of the Iridium open source framework.

Updated on September 29, 2020

Comments

  • Philippe Leybaert
    Philippe Leybaert over 3 years

    Is there a way to exclusively lock a table for reading in Oracle (10g) ? I am not very familiar with Oracle, so I asked the DBA and he said it's impossible to lock a table for reading in Oracle?

    I am actually looking for something like the SQL Server (TABLOCKX HOLDLOCK) hints.

    EDIT:

    In response to some of the answers: the reason I need to lock a table for reading is to implement a queue that can be read by multiple clients, but it should be impossible for 2 clients to read the same record. So what actually happens is:

    1. Lock table
    2. Read next item in queue
    3. Remove item from the queue
    4. Remove table lock

    Maybe there's another way of doing this (more efficiently)?