資料列版本控管 SnapShot Isolation V.S Read Committed Snapshot ( 一 )

資料列版本控管 SnapShot Isolation V.S Read Committed Snapshot ( 一 )

 

 

斯斯有兩種,而SQL2005版後提供『資料列版本控管(Row Version)也有兩種。

 

1.「快照集隔離(Snapshot Isolation)

 

2.「讀取認可快照(Read Committed Snapshot)

 

 

開啟資料列版本控管功能的好處就是可以降低BlockingDeadlock的發生,其運作

 

方式就是會在tempdb建立一個快照讓單純執行查詢的Query直接去讀取Copy出來

 

Read Only的資料,而不會因為交易中資料尚未Commit而造成Blocking,讓其他單

 

純只是想SelectQuery全部處於等待,造成效能上的問題。

 

 

啟用「快照集隔離(Snapshot Isolation)」的語法為:

ALTER DATABASE DB SET ALLOW_SNAPSHOT_ISOLATION ON

 

啟用「讀取認可快照(Read Committed Snapshot)」的語法為:

ALTER DATABASE DB SET READ_COMMITTED_SNAPSHOT ON

 

 

這一篇我們先來LAB一下「快照集隔離(Snapshot Isolation)」的功能

 

 

 

步驟一、首先我們先建立一資料庫SnapShotTest並開啟資料庫「快照集隔離

 

(Snapshot Isolation)」功能(如下圖所示)

clip_image002_thumb

 

 

步驟二、開啟一個Session編號59,然後在這一個Session開啟交易去Update Employees

 

資料表中EmployeeID1的資料,將FirstName改為ROCK。記得先不要Commit此筆交易。

clip_image004_thumb

 

 

步驟三、我們再開一個ID 60 Session,然後Select EmployeeID1的那一筆資料。

 

如下圖所示,這一個Query會被Blocking住,而持續處於Waitting狀態。此時我們可

 

以知道即使我們有開啟資料庫的Snapshot Isolation,但是所有Session的預設Isolation

 

Level都還是Read Commit

clip_image006_thumb

 

 

步驟四我們在ID 60Session中加入SET TRANSACTION ISOLATION LEVEL

 

SNAPSHOT語法,讓這一個Session使用SnapshotIsolation Level(此時Session 59

 

 Update交易一樣尚未Commit)。我們同樣Select EmployeeID1的資料,會發

 

現可以順利取的資料而不會被Blocking住了。

clip_image008_thumb

 

 

 

步驟五我們回到Session 59中,將交易Commit掉,確認將EmployeeID1

 

FirstName欄位改成ROCK

 

clip_image010_thumb

 

 

 

步驟六我們到Session 60中,此時不用再重複執行SET TRANSACTION ISOLATION

 

LEVEL SNAPSHOT語法了,執行過一次後這一個SessionIsolation Level就固定為Snapshot

 

了。這一次我們開啟交易(Begin Tran)然後一樣執行Select EmployeeID1的語法。如下

 

圖所示,我們取得的資料FirstName欄位為ROCK,先不要將交易Commit

clip_image012_thumb

 

 

 

步驟七回到Session 59中,我們將EmployeeID1的資料FirstName改為CAREY

 

clip_image014_thumb

 

 

 

 

步驟八我們在步驟七已經將欄位內容改為CAREY並且Commit了。此時再回到

 

Session 60來,這裡開啟的交易還Commit掉,我們重複再執行Select EmployeeID

 

1的語法。會發現即使步驟七中資料修正過且Commit了,但在這裡我們取得的

 

欄位資料還是ROCK

clip_image016_thumb

 

 

 

步驟九此時我們再開一個SessionID 61。一樣設定Isolation LevelSnapshot

 

並開啟交易然後Select EmployeeID1FirstName欄位資料。如下圖所示Session 61

 

取得的欄位資料是CAREY了,我們也不要將Session 61的交易結束掉。

clip_image018_thumb

 

 

 

 

 

步驟十再次回到Session 59,並再一次將資料修改為DANIEL並且Commit交易。

 

clip_image020_thumb

 

 

 

步驟十一我們回到Session 61再執行一次Select語法(如下圖),會發現資料回傳值仍為

 

CAREYSession 60執行一次Select語法,資料回傳值仍為ROCK

clip_image022_thumb

 

由上述幾個步驟可以發現針對每一個開啟的交易(注意Session要將Isolation Level設為Snapshot)

 

SQL產生相對應的資料列版本。

 

 

實驗中各Session的版本資料如下表 :

 

Session ID

FirstName資料

資料來源

59

DANIEL

Real Data

60

ROCK

Snapshot

61

CAREY

Snapshot

 

 

 

  

步驟十二很重要須注意的一點,由於我們每一個Session都有其版本,因此實際的資料

 

也許已經被異動過好幾版了。Session 61中我們看見的資料是CAREY但實際上早被Session 59

 

改成DANIEL了,這時候我們如果在Session 61的交易中去Update EmployeeID1的資料是會

 

失敗的(如下圖所示)

clip_image024_thumb

 

 

小結 :

 

        啟動資料庫的ALLOW_SNAPSHOT_ISOLATIONON,其Session的預設Isolation Level

 

還是Read Commit必須在Session中執行SET TRANSACTION ISOLATION LEVEL SNAPSHOT

 

後將該SessionIsolation Level更改為Snapshot後才會有資料列版本控管(Row Version)』的

 

功能。而要注意的地方就是交易中的新增刪除修改須注意錯誤控制

 

 

 

我是ROCK

rockchang@mails.fju.edu.tw