58

有人可以幫助我理解何時使用SNAPSHOT隔離級別超過SQL Server中的READ COMMITTED SNAPSHOT?已提交的快照VS快照隔離級別

據我所知,在大多數情況下READ COMMITTED SNAPSHOT的作品,但不知道什麼時候進行SNAPSHOT隔離。

感謝

+1

難怪命名事物是計算機科學中最困難的事情。很高興你發佈了這個問題。 – RBT 2016-08-24 06:44:17

+1

只需添加 - 「READ_COMMITTED_SNAPSHOT」是一個數據庫級選項,而「Snapshot」是可應用於特定會話或事務的隔離級別。 – RBT 2016-08-24 06:51:45

回答

69

READ COMMITTED SNAPSHOT不樂觀的讀取和寫入悲觀。相比之下,SNAPSHOT做樂觀的讀取和樂觀的寫入。

對於大多數需要行版本控制的應用程序,Microsoft建議使用READ COMMITTED SNAPSHOT

閱讀此優秀的Microsoft文章:Choosing Row Versioning-based Isolation Levels。它解釋了兩種隔離級別的好處和成本。

這裏還有一個更徹底的一個: http://msdn.microsoft.com/en-us/library/ms345124(SQL.90).aspx

+2

這看起來不正確。請參閱http://dba.stackexchange.com/a/54681/52708。 – 2015-01-29 01:15:20

10

Isolation levels table

請參見下面的例子:

提交讀快照

更改數據庫屬性如下

ALTER DATABASE SQLAuthority 
SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE 
GO 

會議1次

USE SQLAuthority 
GO 
BEGIN TRAN 
UPDATE DemoTable 
SET i = 4 
WHERE i = 1 

會議2

USE SQLAuthority 
GO 
BEGIN TRAN 
SELECT * 
FROM DemoTable 
WHERE i = 1 

結果 - 查詢在第二節展示舊值(1,ONE),因爲當前事務未提交。這也是避免阻塞並讀取已提交數據的方法。

會議1

COMMIT 

會議2

USE SQLAuthority 
GO 
SELECT * 
FROM DemoTable 
WHERE i = 1 

結果 - 查詢在第二場演出沒有行,因爲排在會話1.更新,因此,我們再次看到了承諾數據。

快照隔離級別

這是新的隔離級別,這是可以從SQL Server 2005起。對於此功能,應用程序需要進行更改,因爲它必須使用新的隔離級別。

使用以下更改數據庫設置。我們需要確保數據庫中沒有交易。

ALTER DATABASE SQLAuthority SET AllOW_SNAPSHOT_ISOLATION ON 

現在,我們還需要使用下面

會議1

USE SQLAuthority 
GO 
BEGIN TRAN 
UPDATE DemoTable 
SET i = 10 
WHERE i = 2 

會議2

SET TRANSACTION ISOLATION LEVEL SNAPSHOT 
GO 
USE SQLAuthority 
GO 
BEGIN TRAN 
SELECT * 
FROM DemoTable 
WHERE i = 2 

Result-改變連接的隔離級別即使我們h ave將值改爲10,我們仍然會在會話2(2,TWO)中看到舊的記錄。

現在,讓我們在會議上提交事務1次

會議1

COMMIT 

讓我們回到會話2,然後再次運行選擇。

會議2

SELECT * 
FROM DemoTable 
WHERE i = 2 

我們仍然可以看到記錄,因爲會話2已聲明與快照隔離事務。除非我們完成交易,否則我們不會看到最新的記錄。

會議2

COMMIT 
SELECT * 
FROM DemoTable 
WHERE i = 2 

現在,我們不應該看到的行作爲它已經更新。

見:SQL AuthoritySafari Books Online

+1

這個答案比所選答案更好。 – jyao 2017-05-25 23:50:29

0

仍然具有現實意義,從比爾的意見,我讀更多和做筆記,可能是別人有用。

默認情況下,單個語句(包括「SELECT」)在「提交」數據(READ COMMITTED)上工作,問題是:他們是否在等待數據「空閒」並阻止他人在讀取時工作?

設置通過右鍵單擊數據庫「屬性 - >選項 - >其他」:

併發/封閉:讀取已提交快照在 [默認關閉,應該是]:

  • 使用SNAPSHOT進行選擇(讀取),不要等待其他人,也不要阻止他們。無代碼變化
  • 影響操作
  • ALTER DATABASE SET READ_COMMITTED_SNAPSHOT [ON | OFF]
  • SELECT姓名,is_read_committed_snapshot_on FROM SYS。數據庫

一致性:允許快照隔離 [默認關閉,值得商榷 - OK關閉]:

  • 允許客戶機請求在不同SQL語句(交易)快照。
  • 代碼必須要求「交易」快照(如SET TRANSACTION ...)
  • ALTER DATABASE SET ALLOW_SNAPSHOT_ISOLATION [ON | OFF]
  • SELECT名字,is_read_committed_snapshot_on FROM sys.databases中

正題:讀取提交快照和允許快照隔離之間的另一個不是。它們是兩種快照,並且可以單獨打開或關閉,允許快照隔離更像是一個高級主題。允許快照隔離允許代碼進一步控制快照域。

如果您考慮一行,默認情況下系統沒有副本,所以如果其他人正在寫入,讀者必須等待,如果有其他人正在讀取,作者也必須等待 - 行必須一直鎖定。啓用「提交讀取提交快照」激活數據庫以支持「快照副本」以避免這些鎖定。

散漫上...

在我看來「讀取已提交快照,」應該是「真」的任何正常MS SQLServer的數據庫,它是一個過早的優化,這船「FALSE」默認。

但是,我被告知一行鎖越來越差,不僅因爲您可能在表中尋址多行,而且因爲在SQL Server中,行鎖使用「塊」級鎖實現(鎖定存儲器關聯的隨機行並且存在一個閾值,其中多個鎖觸發表鎖定 - 可能會在忙數據庫中阻塞問題的風險下進行更「樂觀」的性能優化。

1

未對快照中可能發生的可怕「快照更新衝突」異常進行討論,但未提供「快照讀取已提交」,沒有比較快照和快照讀取已提交完成。

簡而言之,快照隔離會在事務的開始處檢索已提交數據的快照,然後對讀取和寫入操作使用樂觀鎖定。如果在嘗試提交事務時發現某些其他內容更改了某些相同的數據,則數據庫將回滾整個事務並在調用代碼中引發導致快照更新衝突異常的錯誤。這是因爲事務影響的數據版本在事務結束時與開始時不同。致力於

快照讀不存在這個問題,因爲它使用鎖定在寫入(悲觀寫),它在每個語句的統計獲得的所有已提交數據的快照版本信息。

發生快照更新衝突發生在快照和不快照讀取已提交的可能性是兩者之間的一個非常顯着的區別。