SQL Server-聚焦SNAPSHOT基於行版本隔離級別詳解(三十)


前言

上一篇SQL Server詳細講解了隔離級別,但是對基於行版本中的SNAPSHOT隔離級別仍未完全理解,本節再詳細講解下,若有疑義或不同見解請在評論中提出,一起探討。

SNAPSHOT行版本隔離級別

在SNAPSHOT隔離級別下,讀取者在讀取數據時, 它是確保獲得事務啟動時最近提交的可用行版本,這意味着,保證獲得的是提交后的讀取並且可重復讀取,以及確保獲得不是幻讀,類似於SERIALIZABLE級別中一樣,但是此隔離級別依賴於行版本,而不是使用共享鎖,要想在企業部署的SQL Server實例中允許事務以SNAPSHOT隔離級別工作,首先需要在查詢窗口執行以下代碼打開快照隔離級別。如下:

ALTER DATABASE TSQL2012 SET ALLOW_SNAPSHOT_ISOLATION ON

下面我們再用一個簡單的例子來詳細講解其過程。首先我們啟用上述SNAPSHOT隔離級別,然后查詢某個表的修改日期列,如下:

ALTER DATABASE AdventureWorks2012 SET ALLOW_SNAPSHOT_ISOLATION ON
GO

SELECT 
    ModifiedDate
FROM HumanResources.Shift

GO

如上是我們正常查詢出的修改日期列(ModifiedDate)。接下來我們創建兩個會話,一個是寫入會話(會話一),另外一個是查詢會話(會話二)來證明SNAPSHOT隔離級別的作用。

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

BEGIN TRAN
UPDATE HumanResources.Shift
SET ModifiedDate = GETDATE()

GO

我們設置寫入者的隔離級別為SNAPSHOT,然后更新其修改日期為當前日期,但是我們此時只是開啟了事務並未提交該寫入事務。與此同時我們再來創建一個查詢會話(會話二)來查詢修改日期列,如下查詢會話也未提交事務。

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

BEGIN TRAN
SELECT 
    ModifiedDate
FROM HumanResources.[Shift]

此時我們看到查詢出的修改日期依然是原始值並未進行修改,此時我們再來提交寫入者事務(會話一),在上述寫入者事務后面添加如下一句。

COMMIT TRAN

此時再來在會話二中查詢修改日期,結果依然是原始值,如下:

此時我們再來提交查詢事務(會話二),再來查詢,結果如下 

在上一篇僅僅只講述了最后結果的變化,並未敘述其中過程到底是怎樣的,請往下看。 

SNAPSHOT基於行版本隔離級別過程敘述

(1)會話一中開啟事務並更新修改日期列,但是並未提交會話一中的事務,換句話說,原始值將依然有效,所以SNAPSHOT(快照隔離級別)導致仍然可以讀取到原始值。

(2)會話二中開啟事務並讀取原始值,在這個階段中,數據庫引擎將創建一個讀取的行副本到tempdb臨時數據庫中,所以在會話二中的所有讀取事務都將從tempdb臨時數據庫中讀取。

(3)會話一提交了事務並將其修改的值儲存到了表中,注意,此時改變的值只是響應到了表中,而會話二中在tempdb臨時數據庫中副本依然保持不變。

(4)會話二再次讀取行時,此時將從tempdb臨時數據庫中去讀取且讀取到的依然是原始值,因為在會話二中還並未提交事務。

(5)會話二提交了事務,此時將銷毀在tempdb臨時數據庫中的副本,在此之后將無法再讀取原始值。

(6)會話二再次讀取行時,因為在提交事務之后在tempdb臨時數據庫中沒有行,所以現在將去表中獲取新行。

若我們在上述會話二中查詢並未開啟事務,這就意味着所有讀取將直接從表中讀取,同時將不會創建副本到tempdb臨時數據庫中,進一步講,此時將導致查詢阻塞,所以從這里我們知道開啟基於行版本的SNAPSHOT隔離級別將有利於減少死鎖情況的發生,提高並發性能。

總結 

本節我們再次很詳細講解了基於行版本的SNAPSHOT隔離級別的過程描述,總算是明白了基於行版本隔離級別的原理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM