1
我有一個存儲過程,如果行鍵不存在,則將行插入表中。它看起來像這樣:我的選擇插入程序中是否需要鎖定提示?
create proc EmployeeInsertIfNotExists
(@id int, @name varchar(50))
as
begin
SET XACT_ABORT ON
begin transaction
if not exists(select * from tbl where id = @id)
insert into tbl(id, name)
values(id, name)
commit transaction
end
這個存儲過程實際上只是兩個語句,一個select和一個可能的插入。我在一個事務中使用了兩個語句,以便在它們之間不會發生任何異常。 id
列是主鍵,所以我想確保我不插入兩次相同的ID。
我的問題是:這是否足以防範問題的預防措施?我是否需要在選擇語句中加入任何提示?如果是這樣,我需要HOLDLOCK, TABLOCKX
?這是我的新材料。
編輯:建議答案
create proc EmployeeInsertIfNotExists
(@id int, @name varchar(50))
as
begin
SET XACT_ABORT ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin transaction
if not exists(select * from tbl where id = @id)
insert into tbl(id, name)
values(id, name)
commit transaction
end
那麼我需要將我的程序更改爲我粘貼的第二個程序嗎?我可以通過使用merge'語句完全避免事務嗎? – user2023861
是的,你的第二個版本應該可以工作。不,合併不是原子的。它具有與原始版本相同的問題。 –
這是對你正在嘗試做的事情的矯枉過正。可序列化會傷害(殺死?)你機器的性能。如果id對它有一個唯一的約束,那麼將保證沒有其他人可以在該列中插入多於一個的鍵值。您可以從proc返回一個指示插入失敗的值,並且可以使用另一個鍵值再次嘗試。 –