Question

I have a table of chalets where a chalet is referenced by an account...

CHALET
------
int ChaletId PK
int Berth

ACCOUNT
-------
int AccountId PK
int ChaletId FK

The chalets start off un-referenced. When a user buys a chalet the code needs to find an unreferenced chalet and assign it to a newly created account. I think that the returned chalet needs to have an UPDLOCK on it until the account that will reference it has been commited in order to stop a concurrent shopper from being assigned the same chalet.

How can I write the SELECT that fetches a chalet? I was thinking something like this..

SELECT * FROM CHALET WITH (UPDLOCK) c
LEFT JOIN ACCOUNT a
ON c.ChaletId = a.ChaletID
WHERE a.ChaletID is null
AND Berth = 4

I think the problem is that if this query is being run concurrently then one query might lock half of one table and another might lock the other half and a dead lock would ensure. Is there a way around this? For example, is it possible to lock the selected chalet rows in the same orders?

Cheers, Ian.

Was it helpful?

Solution

Would (UPDLOCK, ROWLOCK, READPAST) do what you need?

OTHER TIPS

I think you are trying to use SQL Concurrency locking when you really need your application to handle provisional reservations.

  • Create a flag column or separate table of the reservations that are in-flight.
  • Make all your other queries exclude items that are in the process of being reserved.
  • In the case of a rollback, you would need to unwind that reservation.

try

SELECT * FROM CHALET WITH (UPDLOCK, HOLDLOCK) c
LEFT JOIN ACCOUNT a
ON c.ChaletId = a.ChaletID
WHERE a.ChaletID is null
AND Berth = 4

But why oh why are you not using an identity property for this kind of stuff instead of trying to roll your own?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top