|
|
Question : T-SQL Best Practices: Locking rows
|
|
Scenario: I have a table, SALES, with millions of rows. 100 staff are using an application that queries the table for the next "priority" sale they must review. As they are accessing the table concurrently and with the same priority criteria, there is potential that they will simultaneously grab the same record at the same time.
Worth noting that while they're doing this, any number of other staff outside of these 100 are also running reports/updates/etc against the same table.
Table structure (dummied down): SALES: SaleID (INT, Unique nonclustered index), UserAssigned (VARCHAR, NULL), SaleStatus (VARCHAR, NOT NULL, can be "OPEN" or "CLOSED"), Priority (INT)
What I want to do is something in the order of, via a stored procedure,
************************************************ CREATE PROCEDURE spGetSale ( @USER VARCHAR(30) ) AS BEGIN DECLARE @ID INT SET @ID = 0 SET NOCOUNT ON BEGIN TRAN /* Find the next, highest priority, available sale to review */ SELECT TOP 1 @ID = SaleID FROM SALES WHERE SaleStatus = 'OPEN' AND ISNULL(UserAssigned, '') = '' ORDER BY PRIORITY DESC
IF (@ID >= 1) BEGIN /* Found one, give it to the user */ UPDATE SALES SET UserAssigned = @User WHERE SaleID = @ID END COMMIT TRAN SET NOCOUNT OFF
SELECT @ID /* Application needs to know which ID was assigned, it knows how to handle zero */ END ************************************************
I had some success during testing using the hints WITH (XLOCK, ROWLOCK, READPAST) in the initial select statement, but I'm not SQL-savvy enough to anticipate all the repurcussions to this.
This strikes me as a rather common transaction. What would a "best practices" solution be?
PS. I forget why, but I really do want to do it in seperate steps, select and update.
Thanks kindly
|
Answer : T-SQL Best Practices: Locking rows
|
|
Yes, that's the point. In other SQL variants, the equivalent syntax is Select...For Update.
|
|
|
|
|