SQL2005中的事務與鎖定(四)
------------------------------------------------------------------------
-- Author : HappyFlyStone
-- Date : 2009-10-04 09:00:00
-- Version: Microsoft SQL Server 2005 - 9.00.2047.00 (Intel X86)
-- Apr 14 2006 01:12:25
-- Copyright (c) 1988-2005 Microsoft Corporation
-- Enterprise Edition on Windows NT 5.2 (Build 3790: Service Pack 2)
-- 轉載請註明出處,更多請關注:http://blog.csdn.net/happyflystone
-- 關鍵字:隔離等級 鎖定 意外數據行爲 Lock Hint SnapShot
------------------------------------------------------------------------
起了一個早,也沒事幹,突然想起昨天沒有完成的任務,繼續上一篇沒說完的。
3、可重複讀(Repeatable Read)
概念回顧:可重複讀等級比已提交讀多了一個約定:所有的共享鎖定持續到事務結束,不是在讀取完數據就釋放。數據被設置了共享鎖定後其它進程只能進行查詢與增加不能更改,顯然這個級別的隔離對程序有了更高的要求,因爲可能因長時間的共享鎖定影響系統的併發性能,增加死鎖發生的機率。很顯然是解決了不可重複讀的意外行爲。
數據測試:
查詢一:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRAN
SELECT * FROM TA WHERE TCID = 1 --可重複查詢,並且讀不到未提交的數據
--COMMIT TRAN --Don't commit
SELECT @@SPID
/*
tcid Tcname
----------- --------------------
1 READ COMMITTED LOCK
(1 行受影響)
------
52
(1 行受影響)
*/
查詢二:
INSERT TA SELECT 9,'FF'
/*
(1 行受影響)
*/
SELECT * FROM TA-- WITH(UPDLOCK)
WHERE TCID = 1
/*
tcid Tcname
----------- --------------------
1 READ COMMITTED LOCK
(1 行受影響)
*/
UPDATE TA
SET TCNAME = 'READ COMMITTED REP'
WHERE TCID = 1
/*
--查詢一直進行中……被鎖定無結果
--修改數據設置了排它鎖定必須等到SPID=52的事務結束
*/
查詢三:
很顯然查詢三中的S,Is(共享及意向共享)鎖定一直沒消失,因爲查詢一的事務沒有結束,在查詢二里可以發現插入與讀取(包括在查詢一里再次select)是不影響的,並且讀取的是未修改前的數據。
4、快照(SnapShot)
概念回顧:這是SQL SERVER2005的新功能,啓用快照後所有的讀操作不再受其它鎖定影響,讀取的數據是通過行版本管制器讀取事務開始前邏輯確定並符合一致性的數據行版本。 這個級別隔離與已提交讀的行版管理器的差別僅是行版本管理器裏歷史版本數據多久。
測試數據:
查詢一:
ALTER DATABASE TESTCSDN
SET ALLOW_SNAPSHOT_ISOLATION ON
GO
SELECT * FROM TA WHERE TCID = 1 --OLD數據
BEGIN TRAN
UPDATE TA
SET TCNAME = 'SNAPSHOT'
WHERE TCID = 1
--COMMIT TRAN --Don't commit
SELECT @@SPID
/*
tcid Tcname
----------- --------------------
1 READ COMMITTED REP
(1 行受影響)
(1 行受影響)
------
52
(1 行受影響)
*/
查詢二:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
SELECT * FROM TA WHERE TCID = 1
/*
tcid Tcname
----------- --------------------
1 READ COMMITTED REP
(1 行受影響)
*/
查詢三:
exec sp_us_lockinfo
5、可串行化:
概念回顧:這是交易裏最健壯最嚴謹最高級別的隔離。通過索引鍵範圍完全隔離其它交易的干擾,此隔離和select與鎖定提示HOLDLOCK效果一樣。這個級別基本解決所有的意外行爲,顯而易見的是併發性能下降或系統資源的損耗上升。
測試數據:
查詢一:
DROP TABLE TB
GO
CREATE TABLE TB (ID INT Primary Key, COL VARCHAR(10))
GO
INSERT INTO TB SELECT 1,'A'
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT * FROM TB WHERE ID BETWEEN 1 AND 5--OLD數據
--COMMIT TRAN --Don't commit
SELECT @@SPID
/*
ID COL
----------- ----------
1 A
(1 行受影響)
------
52
(1 行受影響)
*/
查詢二:
SELECT * FROM TB WHERE ID = 1
/*
ID COL
----------- ----------
1 A
(1 行受影響)
*/
INSERT TB SELECT 2,'EE'
/*
--查詢一直進行中……被鎖定無結果
--修改數據設置了排它鎖定必須等到SPID=52的事務結束
*/
UPDATE TB
SET COL = 'SERIALIZABLE'
WHERE ID = 1
/*
--查詢一直進行中……被鎖定無結果
--修改數據設置了排它鎖定必須等到SPID=52的事務結束
*/
查詢三:
exec sp_us_lockinfo
可以明顯的發現出現大量的索引鍵範圍(RangeS-S……),確保在當前事務未結束之前另外的用戶進程無法在索引鍵範圍內插入數據,防此幼影意外行爲的發生。可串行化後,除了數據能查詢外,不可以修改、增加、刪除索引鍵範圍內的任意數據行,必須等到索引上的鎖定釋放。
結論:通過以的一些測試,我們知道通過隔離等級我們可以控制併發時意外行爲,在實際操作的過程中我們可以用激活事務來控制鎖的粒度、影響範圍,以達到控制併發機制下數據的邏輯正確及數據一致性。最後我們發現通過鎖定提示(LOCK HINTS)也可以改變表級鎖定類型、鎖定週期,達到和設置隔離等級類似的功能。
附錄:隔離等級與意外數據行爲
意外行爲 隔離等級 |
丟失更新 |
髒讀 |
不可 重複讀 |
幻影 |
併發模型 |
未提交讀 |
否 |
是 |
是 |
是 |
悲觀 |
已提交讀(鎖 定) |
否 |
否 |
是 |
是 |
悲觀 |
已提交讀(行版本) |
否 |
否 |
是 |
是 |
樂觀 |
可重複讀 |
否 |
否 |
否 |
是 |
悲觀 |
快照 |
否 |
否 |
否 |
否 |
樂觀 |
可串行化 |
否 |
否 |
否 |
否 |
悲觀 |
好,到目前爲止我們把事務相關的東西介紹得差不多了,並且在提前介紹了部分的鎖定,在下面的文章裏我們重點對鎖進行介紹。
請大家繼續關注我的blog: http://blog.csdn.net/happyflystone