473,383 Members | 1,762 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Row Locking

I'm trying to create a stored procedure to grab a record from a table and update the record.

Expand|Select|Wrap|Line Numbers
  1. declare val integer;
  2. select COL2 into val from TAB1 where COL1 = 777;
  3. update TAB1 set COL2 = COL2 + 1;
But, I fear this will allow anyone to run over the procedure and get the same COL2 value before I update the record. I hear using "lock table in exclusive mode" would be a bad thing to do. What can I do?
Feb 13 '09 #1
6 6194
Assuming that you only wish to update COL2 for the rows where COL1 = 777 then, in order of preference:
  1. UPDATE TAB1 SET COL2 = COL2+1 WHERE COL1 = 777; SELECT COL2 - 1 INTO VAL FROM TAB1 WHERE COL1 = 777;
  2. SELECT COL2 into val from TAB1 where COL1 = 777 WITH RS; UPDATE TAB1 SET COL2 = COL2+1 WHERE COL1 = 777;

Advantages are:
  1. Takes X row locks on all changed rows first so no-one else can change the row you are selecting.
  2. Takes a Next Key Share lock on the row retrieved and this prevents others from changing this row.

If you want to update all the rows in the table, then LOCK TABLE IN EXCLUSIVE MODE is probably your best choice as otherwise the UPDATE statement will take a row lock on every row in the table (same effect but less efficient).
Feb 14 '09 #2
You're right I forgot to put in where COL1 = 777 in my update statement. The forum won't let me edit the first post to correct my mistake...

Oh, I wish it was that easy with those statements. I have to do some processing of the COL2 value before I do the update so #1 would not work. Sorry I didn't explain it better.

Would #2 prevent reading from this record for others? What I fear is that after I read from the record and while I'm processing the value, someone else reads the record and now we both have that same COL2 value.
Feb 14 '09 #3
First up, you won't be able to prevent users reading with UNCOMMITTED READ. To stop others reading as well as writing you will need an exclusive row lock. In theory this can be done in 3 ways:
  1. SELECT COL2 INTO val1 FROM TAB1 WHERE COL1 = 777 WITH RS USE AND KEEP EXCLUSIVE LOCKS
  2. UPDATE TAB1 SET COL2 = COL2 WHERE COL1 = 777
  3. UPDATE TAB1 SET COL2 = COL2+1 WHERE COL1 = 777

Interestingly although these all take and hold X row locks, only the last of these actually blocks reads; seems DB2 is trying to be clever and realising that the data isn't actually changing and reading through the X lock. So you might want to do the last option before selecting the data and then undoing the change with the real value after processing.

I should also have mentioned the traditional approach:

Expand|Select|Wrap|Line Numbers
  1. DECLARE CURSOR X FOR 
  2.    SELECT COL2 from TAB1 where COL1 = 777 FOR UPDATE OF COL2;
  3. OPEN CURSOR X;
  4. FETCH X INTO val1;
  5. ...process val1
  6. UPDATE X SET COL2=val1 WHERE CURRENT OF X;
  7. CLOSE X;
  8.  
Used to be the only way to do this in the past but a lot more code change for you.
Feb 15 '09 #4
(option #1 doesn't compile for me so it must be for a different system).

I'm trying to test the row lock with a waiting loop immediately doing one of the above and running a select statement separately to read the row to see if its locked. The select has no problem reading the record. Do you know what I'm doing wrong?

Expand|Select|Wrap|Line Numbers
  1. create procedure sp_test
  2. language SQL
  3. begin
  4.   declare v_counter integer default 0;
  5.   update tab1 set col2 = col2 + 1 where col1 = 777;
  6.  
  7.   aloop:
  8.   loop
  9.     set v_counter = v_counter + 1;
  10.     if v_counter = 5000000 then
  11.       leave aloop;
  12.     end if;
  13.   end loop aloop;
  14. end
  15.  
Expand|Select|Wrap|Line Numbers
  1. create procedure sp_test
  2. language SQL
  3. begin
  4.   declare v_counter integer default 0;
  5.   declare val integer;
  6.   declare c1 cursor for select col2 from tab1 where col1 = 777;
  7.   open c1;
  8.   fetch c1 into val;
  9.  
  10.   aloop:
  11.   loop
  12.     set v_counter = v_counter + 1;
  13.     if v_counter = 5000000 then
  14.       leave aloop;
  15.     end if;
  16.   end loop aloop;
  17. end
  18.  
Feb 17 '09 #5
Two things come to mind:
  • The procedure names are the same. Therefore the "read" procedure is actually being run twice.
  • Your isloation level is Uncommitted Read. Change your select statement to add WITH CS to confirm this as this will override your default isolation level

INcidentally, when I rename the second procedure and run the two I get a lock wait as expected.
Feb 18 '09 #6
After some testing with your recommendations, I've found that "for update of COL2" worked, and then I slapped on "with cs" for good measure. Thanks a lot; I've learned a lot.

Oddly, using just "for update" won't block and nor will just "with cs", but "for update of col2" apparently will do it.

Expand|Select|Wrap|Line Numbers
  1. declare v_counter integer default 0;
  2. declare val integer;
  3. declare c1 cursor for select col2 from tab1 where col1 = 777
  4. for update of col2 with cs;
  5. open c1;
  6. fetch c1 into val;
Feb 18 '09 #7

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: Michael Chermside | last post by:
Ype writes: > For the namespaces in Jython this 'Python internal thread safety' > is handled by the Java class: > > http://www.jython.org/docs/javadoc/org/python/core/PyStringMap.html > > which...
3
by: Ryan | last post by:
I have a problem with record locking / blocking within an application. The app is quite straight forward. Written in Delphi 5 using BDE to access a SQL 7 database (Win2K server). Every so often...
9
by: john smile | last post by:
Hi All, I want to lock 2 tables on 2 servers using TABLOCKX hint. These tables function as semaphores in my application. It means when the tables are locked then other users will not be able to...
16
by: Nid | last post by:
How do I do row-level locking on SQL Server? Thanks, Nid
10
by: McFly Racing | last post by:
Thread Locking In Static Methods I have the need for a Log Manger class that has static methods. Normally I would use the lock statement or a Monitor statement both of which take a...
15
by: z. f. | last post by:
Hi, i have an ASP.NET project that is using a (Class Library Project) VB.NET DLL. for some reason after running some pages on the web server, and trying to compile the Class Library DLL, it...
7
by: Shak | last post by:
Hi all, I'm trying to write a thread-safe async method to send a message of the form (type)(contents). My model is as follows: private void SendMessage(int type, string message) { //lets...
0
by: xpding | last post by:
Hello, I have a class MyEmbededList contains a generic dictionary, the value field is actually the MyEmbededList type as well. There is another class need to access and manipulate a list of...
0
by: Cindy Huyser | last post by:
I have an Access 2000 database behind a threaded Java application that that can have have concurrent access to the same table (but not the same record). The database is set up for shared access...
1
by: Paul H | last post by:
I have an Employees table with the following fields: EmployeeID SupervisorID Fred Bob Bob John Bob Mary Bill Bill I have created a self join in...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.