資料列版本控管 SnapShot Isolation V.S Read Committed Snapshot ( 一 )
斯斯有兩種,而SQL在2005版後提供『資料列版本控管(Row Version)』也有兩種。
1.「快照集隔離(Snapshot Isolation)」
2.「讀取認可快照(Read Committed Snapshot)」
開啟資料列版本控管功能的好處就是可以降低Blocking及Deadlock的發生,其運作
方式就是會在tempdb建立一個快照讓單純執行查詢的Query直接去讀取Copy出來
Read Only的資料,而不會因為交易中資料尚未Commit而造成Blocking,讓其他單
純只是想Select的Query全部處於等待,造成效能上的問題。
啟用「快照集隔離(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)」功能(如下圖所示)
步驟二、開啟一個Session編號59,然後在這一個Session開啟交易去Update Employees
資料表中EmployeeID為1的資料,將FirstName改為ROCK。記得先不要Commit此筆交易。
步驟三、我們再開一個ID 60的 Session,然後Select EmployeeID為1的那一筆資料。
如下圖所示,這一個Query會被Blocking住,而持續處於Waitting狀態。此時我們可
以知道即使我們有開啟資料庫的Snapshot Isolation,但是所有Session的預設Isolation
Level都還是Read Commit。
步驟四、我們在ID 60的Session中加入SET TRANSACTION ISOLATION LEVEL
SNAPSHOT語法,讓這一個Session使用Snapshot的Isolation Level(此時Session 59
的Update交易一樣尚未Commit)。我們同樣Select EmployeeID為1的資料,會發
現可以順利取的資料而不會被Blocking住了。
步驟五、我們回到Session 59中,將交易Commit掉,確認將EmployeeID為1的
FirstName欄位改成ROCK。
步驟六、我們到Session 60中,此時不用再重複執行SET TRANSACTION ISOLATION
LEVEL SNAPSHOT語法了,執行過一次後這一個Session的Isolation Level就固定為Snapshot
了。這一次我們開啟交易(Begin Tran),然後一樣執行Select EmployeeID為1的語法。如下
圖所示,我們取得的資料FirstName欄位為ROCK,先不要將交易Commit。
步驟七、回到Session 59中,我們將EmployeeID為1的資料FirstName改為CAREY。
步驟八、我們在步驟七已經將欄位內容改為CAREY並且Commit了。此時再回到
Session 60來,這裡開啟的交易還沒Commit掉,我們重複再執行Select EmployeeID
為1的語法。會發現即使步驟七中資料修正過且Commit了,但在這裡我們取得的
欄位資料還是ROCK。
步驟九、此時我們再開一個Session為ID 61。一樣設定Isolation Level為Snapshot
並開啟交易然後Select EmployeeID為1的FirstName欄位資料。如下圖所示Session 61
取得的欄位資料是CAREY了,我們也不要將Session 61的交易結束掉。
步驟十、再次回到Session 59,並再一次將資料修改為DANIEL並且Commit交易。
步驟十一、我們回到Session 61再執行一次Select語法(如下圖),會發現資料回傳值仍為
CAREY。而Session 60再執行一次Select語法,資料回傳值仍為ROCK。
由上述幾個步驟可以發現針對每一個開啟的交易(注意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 EmployeeID為1的資料是會
失敗的(如下圖所示)。
小結 :
啟動資料庫的ALLOW_SNAPSHOT_ISOLATION為ON,其Session的預設Isolation Level
還是Read Commit。必須在Session中執行SET TRANSACTION ISOLATION LEVEL SNAPSHOT
後將該Session的Isolation Level更改為Snapshot後才會有『資料列版本控管(Row Version)』的
功能。而要注意的地方就是交易中的新增、刪除、修改須注意錯誤控制。
我是ROCK
rockchang@mails.fju.edu.tw