Solved

How to select only unlocked rows

Posted on 2006-07-07
7
1,325 Views
Last Modified: 2007-11-27
I have a long-running transaction that runs concurrently from multiple sessions.  Each transaction needs to update a randomly selected row from a table of 100 rows.  It needs to do this without waiting for the other transactions to release their update locks.  In other words, it needs to randomly select for update any of the rows which is not locked for update by another transaction.  If all the rows are locked, it's ok to fail with a resource busy error, however, if any row is not locked, then I want to select one of them for update (don't care which one).

As it stands now, the application does a "Select  random_row for update NOWAIT", but the incidence of resource busy errors has become unacceptable.  I can remove the NOWAIT, but then the delay waiting for resources to free up is unacceptable.

Any ideas?          
0
Comment
Question by:dqmq
  • 4
  • 2
7 Comments
 
LVL 14

Expert Comment

by:sathyagiri
ID: 17063551
If your transaction is in PL/SQL

you could have something like

declare
var_rowid rowid;
var_col1 table1.col1%type;
var_col2 table1.col2%type;
cursor c is select rowid,col1,col2 from table1;
NOWAIT_EXCEPT EXCEPTION;
PRAGMA EXCEPTION INIT(NOWAIT_EXCEPT , -00054);
BEGIN
FOR I IN C
LOOP
SELECT col1 into VAR_COL1 FROM TABLE1 WHERE ROWID = I.ROWID FOR UPDATE NO WAIT;
EXCEPTION
WHEN NOWAIT_EXCEPT THEN
CONTINUE;
END;
END LOOP;
END:


0
 
LVL 14

Accepted Solution

by:
sathyagiri earned 350 total points
ID: 17063570
made some syntax errors above, here's the corrected version
declare
var_rowid rowid;
var_col1 table1.col1%type;
var_col2 table1.col2%type;
cursor c is select rowid,col1,col2 from table1;
NOWAIT_EXCEPT EXCEPTION;
PRAGMA EXCEPTION INIT(NOWAIT_EXCEPT , -00054);
BEGIN
FOR I IN C
LOOP
BEGIN
SELECT col1 into VAR_COL1 FROM TABLE1 WHERE ROWID = I.ROWID FOR UPDATE NO WAIT;
// Update transaction here;

EXCEPTION
WHEN NOWAIT_EXCEPT THEN
DBMS_OUTPUT.PUT_LINE('Unable to lock' || rowid);
END;
END LOOP;
END:

0
 
LVL 19

Assisted Solution

by:actonwang
actonwang earned 150 total points
ID: 17063711
>>the incidence of resource busy errors has become unacceptable.  I can remove the NOWAIT, but then the delay waiting for resources to free up is unacceptable.

you can create a function to procedure to hide the error message. for example , you can create a function as:

create or replace function getRow
return rowid
as
  ret rowid;
  cursor c is select rowid from test1;
begin
  for rec in c loop
    begin
      select rowid into ret from test1 where rowid = rec.rowid for update nowait;
      exit;
      exception
         when others then
           null;
    end;
  end loop;

  return ret;
end;
/
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 
LVL 19

Expert Comment

by:actonwang
ID: 17063717
then you can use this function as:

(1) in pl/sql block:
     declare
         rid rowid;
     ..
     begin
         rid := getRow;
     ...        
         update <table> set ... where rowid = rid;
         commit;
     end;

(2) in sql*plus:
     variable rid varchar2(20);

     exec :rid := getrow;

     update <table> set ... where rowid = :rid;


Acton
0
 
LVL 19

Expert Comment

by:actonwang
ID: 17063720
>>cursor c is select rowid from test1;
>>select rowid into ret from test1 where rowid = rec.rowid for update nowait;

     replace "test1" by your own table name.
0
 
LVL 42

Author Comment

by:dqmq
ID: 17082962
Thank you both for the suggestions. Since both use essentially the same technique, I am splitting points with most going to sathyagiri. Partly that's for being first, but also because I don't particularly like the "when others then null" handler.

BTW, I am grading 'B' because neither solution addresses the case where all rows are locked and neither really selects randomly from the unlocked rows.  But, I have since figured out those details. Also, I oversimplified and didn't mention that there really are more than 100 rows in the table, but only 100 are qualified for update based on a "where" condition. The truely complicating factor is when a row changes between the open cursor and the select for update such that it no longer qualifies for the update.  So it is necessary to re-assert the where condition on the select for update and handle no_data_found similar to a locked row.
0
 
LVL 19

Expert Comment

by:actonwang
ID: 17087368
for random, it is easy to implement and I forgot to put it in. I guess you already get it.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Note: this article covers simple compression. Oracle introduced in version 11g release 2 a new feature called Advanced Compression which is not covered here. General principle of Oracle compression Oracle compression is a way of reducing the d…
Have you ever had to make fundamental changes to a table in Oracle, but haven't been able to get any downtime?  I'm talking things like: * Dropping columns * Shrinking allocated space * Removing chained blocks and restoring the PCTFREE * Re-or…
This video shows setup options and the basic steps and syntax for duplicating (cloning) a database from one instance to another. Examples are given for duplicating to the same machine and to different machines
Video by: Steve
Using examples as well as descriptions, step through each of the common simple join types, explaining differences in syntax, differences in expected outputs and showing how the queries run along with the actual outputs based upon a simple set of dem…

912 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now