資料列版本控管 SnapShot Isolation VS Read Committed Snapshot(二)
在資料列版本控管 SnapShot Isolation VS Read Committed Snapshot(一)中我們有談到
SQL在2005版後提供『資料列版本控管(Row Version)』有兩種。
1. 「快照集隔離(Snapshot Isolation)」
2. 「讀取認可快照(Read Committed Snapshot)」
在SnapShot Isolation VS Read Committed Snapshot(一)中我們已經先介紹過快照集隔離
(Snapshot Isolation),而本篇就來針對讀取認可快照(Read Committed Snapshot)簡介一下
步驟一、我們先將資料庫的ALLOW_SNAPSHOT_ISOLATION設為OFF並開啟
READ_COMMITTED_SNAPSHOT,執行完語法後我們檢視一下SYS.DATABASES
看看資料庫設定值是否正確(如下圖所示)
步驟二、開啟另一個ID為52的Session,我們利用DBCC USEROPTIONS指令來檢視這一
個Session的設定值。其中要看的部分就是如下圖紅色圈選處Isolation Level,我們可以知
道這一個Session的預設Isolation Level就是Read Committed Snapshot。
步驟三、我們先Select 出目前EmployeeID=1的FirstName,該欄位資料為ROCK。然後開啟
交易並將該筆資料的FirstName改為CAREY(如下圖紅色圈選處),且不Commit此交易。
步驟四、我們開啟一個新的Session,其ID為53。我們利用此Session來
Select EmployeeID=1的資料,看看是否會因為步驟三的Update的交易沒
有Commit而導致Blocking情形。測試結果如下圖,我們並沒有被Blocking
且可以順利取得資料,欄位資料為ROCK而不是CAREY,因為異動為
CAREY的交易尚未被Commit。
步驟五、我們將步驟三的Update交易Commit掉,讓FirstName欄位資料正式變更為CAREY。
步驟六、我們回到Session 53,這一次我們開啟交易然後同樣Select EmployeeID=1的資料
。如下圖所示回傳內容是CAREY了,同樣的我們先不要Commit這一個交易。
步驟七、我們回到Session 52,並將資料由CAREY異動為DANIEL,並且Commit交易。
此時EmployeeID=1的FirstName欄位內容已被變更為DANIEL(如下圖所示)。
步驟八、我們回到步驟六尚未Commit交易的Session 53並且加入一個DML命令,
UPDATE Employees SET FirstName=’ROCK’WHERE EmployeeID=1來異動該筆資料
,看看是否會跟SNAPSHOT ISOLATION一樣因為資料內容已被另一個Session異動過
而發生錯誤呢 ? 由下圖結果看來我們也成功地將資料內容改為ROCK,並不會像
SNAPSHOT ISOLATION一樣產生錯誤。
小結 :
不論是「快照集隔離(Snapshot Isolation)」,或「讀取認可快照(Read Committed Snapshot)」,
都能避免掉 SQL Server 預設的交易隔離等級 Read Committed。可大幅降低Blocking及Deadlock
的發生,但這樣的做法會大量使用到TempDB,因此TempDB的優化會是另一個重要的課題。
而兩種做法對於資料列版本控管方式並不相同,因此請依據自身商業邏輯來選擇適當的方法。
讀取認可快照(Read Committed Snapshot)基本不必修改程式碼即可套用,而快照集隔離
(Snapshot Isolation)則須注意Update的問題。
參考資料來源
我是ROCK
rockchang@mails.fju.edu.tw