I am currently developing an online Auction system using ASP.NET 3.5 and SQLServer 2008. I have reached the point in development where I need to ensure that my system sensibly handles the concurrency issue which may arise when:
Two people – Geraldine and John – want to bid on the same auction item which is currently going for £50. Geraldine enters a bid of £55 and John enters a bid of £52. The system now has two copies of the page ‘submit_bid.aspx’ running; each copy of the page checks to see that their bid is high enough, they both see that it is, and they submit the bids. If John’s bid goes through first then the auction item price is currently £55 and a moment later it’s being replaced by a bid of £52.
What I need to do is to lock the auction item row until the current bid price is updated before allowing any other bidder to check the current bid price and placing a new bid.
My question is: what is the best practice way for doing this using T-SQL and / or ADO.NET?
I currently have an AuctionItem table which has the following fields (plus other fields I haven’t included for brevity):
AuctionItemID INT
CurrentBidPrice MONEY
CurrentBidderID INT
I have performed some research and come up with the following T-SQL (pseudocode-ish):
@Bid MONEY
@AuctionItemID INT
BEGIN TRANSACTION
SELECT @CurrentBidPrice = CurrentBidPrice
FROM AuctionItem
WITH (HOLDLOCK, ROWLOCK)
WHERE AuctionItemID = @AuctionItemID
/* Do checking for end of Auction, etc. */
if (@Bid > @CurrentBidPrice)
BEGIN
UPDATE AuctionItem
SET CurrentBidPrice = @Bid
WHERE AuctionItemID = @AuctionItemID
END
COMMIT TRANSACTION
I have also read that if I include the SET LOCK_TIMEOUT I can also reduce the number of failed concurrent updates. For example:
SET LOCK_TIMEOUT 1000
…will make a concurrent update wait for 1000 milliseconds for a lock to be released. Is this best practice?
I followed Alex K’s suggestion above and implemented a ‘Bid History’. Works a treat. Thanks Alex K.