February 8, 2005 at 1:51 pm
G'Day all,
This is a greatly simplified version of a common, real world problem. The actual select statement is significantly more complex. I know of at least three ways to solve the issue. Extreme performance is mandatory, as this proc is potentially called hundreds of times per second. This is almost a textbook problem, but interestingly enough, the textbooks differ on the right solution.
PROBLEM: The following proc is not multi-user safe as written. Two users making a request at the same time can receive the same result. Periodically, two users call the proc at exactly the same time and receive the same value which is a really, really bad thing. The table size is not huge - perhaps on the order of 300,000 to 500,000 rows.
So much for the problem statement. I would like your thoughts on the "best" way to make it multi-user safe. Please remember to include "why" your suggestion is the best one. Your thoughts?
CREATE TABLE tblName (RowID int,
Color VARCHAR(10),
RowIsUsed INT DEFAULT 0)
GO
INSERT INTO tblName (RowID, Color)
SELECT 1, 'RED'
UNION
SELECT 2, 'ORANGE'
UNION
SELECT 3, 'YELLOW'
UNION
SELECT 4, 'GREEN'
UNION
SELECT 5, 'BLUE'
UNION
SELECT 6, 'INDIGO'
UNION
SELECT 7, 'VIOLET'
GO
CREATE PROCEDURE GetColor
@OutRowID INT OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @Error INT,
@RowCount INT
SET @Error = 0
SELECT @OutRowID = (SELECT TOP 1 RowID FROM tblName WHERE RowIsUsed = 0)
SELECT @Error = @@ERROR
IF @Error <> 0 RETURN @Error
IF @OutRowID IS NULL RETURN -1
UPDATE tblName SET RowIsUsed = 1 WHERE RowID = @OutRowID
SELECT @Error = @@ERROR, @RowCount = @@ROWCOUNT
IF @Error <> 0 OR @RowCount <> 1 OR @RowCount IS NULL
RETURN -2
END
GO
DECLARE @MyRowID VARCHAR(10)
EXEC GetColor @MyRowID OUTPUT
SELECT @MyRowID
EXEC GetColor @MyRowID OUTPUT
SELECT @MyRowID
UPDATE tblName SET RowIsUsed = 0
GO
February 8, 2005 at 4:28 pm
I believe what you are needing is the "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE" at the beginning of your Stored Procedure. By doing it this way, you are preventing anyone from reading the data whilst there are updates or inserts to the dataset. Remember that concurrency is at an all time low when you use this Isolation Level!
Have a look at BOL for syntax & Info.
February 9, 2005 at 12:28 am
how about using transactions to get isolation ?
Offcourse everything has a price !
CREATE PROCEDURE GetColor
@OutRowID INT OUTPUT
AS
BEGIN
-- print statements added for debugging
SET NOCOUNT ON
declare @trancount int
set @trancount = @@trancount
print @trancount
begin tran
DECLARE @Error INT,
@RowCount INT
SET @Error = 0
SELECT @OutRowID = (SELECT TOP 1 RowID FROM tblName with (holdlock) WHERE RowIsUsed = 0)
SELECT @Error = @@ERROR
IF @Error <> 0
begin
print 'A-A'
print @@trancount
if @trancount <> @@trancount
begin
commit tran -- rollback would also have impact to the
-- calling application
end
RETURN @Error
end
IF @OutRowID IS NULL
begin
print 'B-B'
print @@trancount
if @trancount <> @@trancount
begin
commit tran -- rollback would also have impact to the
-- calling application
end
RETURN -1
end
UPDATE tblName SET RowIsUsed = 1 WHERE RowID = @OutRowID
SELECT @Error = @@ERROR, @RowCount = @@ROWCOUNT
print 'C-C'
print @@trancount
if @trancount <> @@trancount
begin
print 'final commit in this proc'
commit tran -- rollback would also have impact to the
-- calling application
end
IF @Error <> 0 OR @RowCount <> 1 OR @RowCount IS NULL
begin
print 'D-D'
print @@trancount
RETURN -2
end
END
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data/code to get the best help[/url]
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
February 9, 2005 at 1:49 am
i guess what u r trying to ask, tht 2 people have the same records and each one updates records, then there wud be a probelm is int?
wht u actually asked is 2 people geting the same resultselt, ya let them get it , its not a problem
u can handle this thing at the client level, see u can add a column in a table which will store the latest updated data & time. then while saving the data
u can check the column value in the table with the resultset value in that column (for any change)
if there is a diference in it,
u will come to know that this row has been editited by some 1 else and u can stop the update for a particular row or inform the user of the changes made,or do the needful thing.
see if u want to boost the perfomance, u can improve the perfomance by using command object in ado and compiling and storing the compiled query in the clients memory.
thats possible in Ado
seting the isolation level to serilizable is not a very
advisiable way to do it, becoz that will lock the entire table, and the users will get a hangup system, and they will come shouting to u.
<a href="http://www.websolsoftware.com"> For IT jobs click here</a>
*Sukhoi*[font="Arial Narrow"][/font]
February 9, 2005 at 9:22 am
Thanks all for the good thinking so far. Comments follow:
Sukhio: Suppose that instead of colors, the actual data is a bank account number being assigned to a new customer. Having two different customers get the same account number would be a really, really bad thing. The proc must guarantee that one and only one user receives a specific result.
Trigger: The transaction approach is safe, but performance is terrible.
Alzdba: Same comment as trigger.
One tweak to the proc will help to ensure that only one person gets the row.
UPDATE tblName
SET RowIsUsed = 1
WHERE RowID = @OutRowID
AND RowIsUsed <> 1
This will cause the update to fail for the second caller and return an error to the calling routine. There is an error handler in the calling routine that will continue trying to get a result when errors occur. The simultaneous read happens rarely, and this may be "good enough".
Again, I open it up to the community for comments.
Thanks for your thoughts, and have a great day!
Wayne
February 9, 2005 at 11:12 pm
u should have mentiond thats they no 2 persons will get the same resultset
<a href="http://www.websolsoftware.com"> For IT jobs click here</a>
*Sukhoi*[font="Arial Narrow"][/font]
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply