Locking

使用事務寫入表而不鎖定

  • February 4, 2018

是否可以使用事務寫入數據庫表而不鎖定它?

我想對單個記錄中的單個欄位執行更新查詢,但以防萬一我的應用程序出現錯誤,我希望能夠將其回滾。該應用程序可能需要一兩秒鐘才能完成整個過程,所以我想防止它鎖定表,因為它是一個讀取量很大的表。從應用程序的角度來看,該欄位是微不足道的,所以我不在乎它是否有臟讀。

(我知道 SELECT 語句的 NOLOCK 和 READPAST ,但我不是在尋找解決方案。)

任何幫助表示讚賞。

是否可以使用事務寫入數據庫表而不鎖定它?

取決於你所說的“它”是什麼意思?鎖可以在不同的資源級別含義:行、頁、表、非聚集索引頁等。

如果您的意思是以上所有內容,那麼答案是否定的。同時,您可以避免鎖定某些資源,具體取決於您的事務範圍和要更新的記錄數。

我建議你閱讀這篇文章:

為什麼我們需要 SQL Server 中的 UPDATE 鎖?克勞斯·阿申布倫納

現在讓我們看一個使用 Adventureworks 數據庫的範例。為了模擬我在做什麼,你可以從這裡下載這個數據庫。

USE [AdventureWorks]
GO

--Making sure we are only updating one row
SELECT COUNT(0) FROM [Production].[Product]
WHERE ProductId=318

BEGIN TRAN
UPDATE [Production].[Product] 
   SET [Name]='ML Crankarm_modified' 
   WHERE ProductId=318
--ROLLBACK TRAN

由於我們正在使用BEGIN TRAN(顯式事務),我們可以檢查此會話持有什麼鎖。

SELECT 
 resource_type,
   resource_database_id,
   resource_associated_entity_id,
   request_mode,
   request_status,
   request_session_id
FROM sys.dm_tran_locks
WHERE request_session_id=59

在此處輸入圖像描述

查看這些鎖和鎖兼容性圖表,您應該能夠弄清楚您可以執行哪些選擇語句以及哪些語句會被阻塞。請記住,它也將由您的事務隔離級別決定。

例如,您在 object id 482100758 上具有 Intent Exclusive 鎖,這是 production.product 表本身,並且此鎖與共享鎖不兼容。因此,您不能從該表中選擇所有記錄。但是,如果您想選擇一個或多個沒有與共享鎖不兼容的鎖的記錄,您應該能夠選擇數據。

引用自:https://dba.stackexchange.com/questions/196991