SQL Server 2008 R2 (Data Center edition – I think)
I have a very specific requirement for the database.
I need to insert a row marked with timestamp [ChangeTimeStamp]. Timestamp value is passed as a parameter. Timestamp has to be unique.
Two processes can insert values at the same time, and I happen to run into duplicate key insertion once in a while. To avoid this, I am trying:
declare @maxChangeStamp bigint
set transaction isolation level read committed
begin transaction
select @maxChangeStamp = MAX(MaxChangeTimeStamp) from TSMChangeTimeStamp
if (@maxChangeStamp > @changeTimeStamp)
set @maxChangeStamp = @maxChangeStamp + 1
else
set @maxChangeStamp = @changeTimeStamp
update TSMChangeTimeStamp
set MaxChangeTimeStamp = @maxChangeStamp
commit
set @changeTimeStamp = @maxChangeStamp
insert statment
- REPEATABLE READ – causes deadlock
- READ COMMITTED – causes duplicate key inserts
@changeTimeStamp is my parameter.
TSMChangeTimeStamp holds only one value.
If anyone has a good idea how to solve this I will appreciate any help.
Inside the transaction, the SELECT statement will acquire a shared lock if the mode is not READ COMMITTED or snapshot isolation. If two processes both start the SELECT at the same time, they will both acquire a shared lock.
Later, the UPDATE statement attempts to acquire an exclusive lock (or update lock). Unfortunately, neither one can acquire an exclusive lock, because the other process has a shared lock.
Try using the
WITH (UPDLOCK)table hint on the SELECT statement. From MSDN:For example:
Note that update locks may be promoted to a table lock if there is no index for your table (Microsoft KB article 179362).
Explicitly requesting an XLOCK may also work.
Also note your UPDATE statement does not have a WHERE clause. This causes the UPDATE to lock and update every record in the table (if applicable in your case).