SQL Server有4中隔離模式,和多種鎖。我就簡單地整理一下心得體會,如有錯誤,敬請指正。
前言
隔離模式和鎖有差別,大家千萬不要搞混。隔離模式是規範了併發控制行爲,而鎖是控制鎖定的粒度。但是兩者都會對你應用系統的併發法產生重大影響。缺省是read committed隔離模式和行級鎖(ROWLOCK)。
不同數據庫間,在這方面,有很多差別,也有共同的地方。這些表面現象其實在於體系架構上的差別。
需要指出的一點是:我們不要去判斷這種差別孰優孰劣的問題,因爲不同數據庫產品都有自己的指標。尤其用編程上的方便來判斷是很幼稚的。作爲應用系統,應該是在編程開發上應該去適應數據庫,而不是讓數據庫來適應編程開發。因爲數據庫的選型方案是更本不會考慮編程的方便與否。很多業務邏輯控制問題應該在系統設計上考慮,不能只依靠數據庫系統的鎖定機制來解決你應用系統的邏輯問題。
Read committed模式
這是SQL Server缺省,也是大家最常用的一種。也是很多用過ORACLE人感覺不適應的地方。
Example:
Session 1
begin tran
insert into T1 values(1,'Allan')
Session 2
select * from T1
嗯?怎麼回事,被掛住了。ORACLE中可不會,我看不到1,'ALLAN'的這條記錄不就好了。
其實這就是oracle和sql server在這一點上的差別。ORACLE採用了ROLLBACK的機制,保證了在READ COMMITTED模式下行記錄鎖定不會影響其他事務的讀取(更新還是會被LOCK住的)。因此,ORACLE提供了更強的併發度。顯然,SQL SERVER簡化了這個架構,自然就只能這樣了。
SQL Server在READ COMMITTED模式下,一個事物的查詢語句是不會忽略其他事務未提交的數據(如果你的查詢條件包括了其他事務爲提交的數據),SQL SERVER將讓你等待其他提交,從而保證數據一致性,顯然併發度比ORACLE低。如果出現了等待情況,大家可以根據這個標準來判斷。
但是,兩個事務同時更新一條記錄或者插入主鍵相同的記錄的話,都會有一個等待,SQL Server和ORACLE都是這樣的。
那麼下面讓我用例子來仔細說明一下:
測試表如下:
測試表如下:
c1 c2 c3
----------- --------------------- --------------------
1 200.5000 Hellen
2 129.1400 Hellen
3 288.9700 Allan
SESSION 1:
BEGIN TRANSACTION DELETE FROM test where c1=1 |
SESSION 2:
select * from test
此時被掛住,因爲包括了c1=1的記錄,sql server當然要求你等待。
如果我不選c1=1的記錄呢,自然就不會被waitting了。
SESSION3:
select * from test where c1=2 SELECT * FROM test where c1=3 c1 c2 c3 c1 c2 c3 (所影響的行數爲 1 行) |
沒有被掛起,一切很好。
此時,還可以發現一個很有趣,很容易迷惑你的現象。
SESSION 4
select * from test where c1<>1
結果也被掛住了,好像ROWLOCK出了“問題”?不要急,原來由於我這個表Test建了主鍵(c1字段)。我認爲這是由於update,delete操作引起了索引上行的lock。
而此時,如果執行select * from test where c1>1是沒有問題的。
那麼,我們只要強制跳過聚集索引的索引頁和索引葉節點頁(數據頁)中行鎖定的部分。
select * from test with(FASTFIRSTROW) where c1<>1
果然就一切OK。
因此,對於很多現象,我們需要進一步地去思考和去解迷。
下面,我們通過sp_lock查看來在說明一下
通過sp_lock查看:
spid dbid ObjId IndId Type Resource Mode Status ------ ------ ----------- ------ ---- ---------------- -------- ------ ------------------------------------ 53 7 789577851 1 PAG 1:126 IX GRANT 53 7 789577851 1 KEY (010086470766) X GRANT 53 7 789577851 1 PAG 1:127 IX GRANT 53 7 789577851 2 KEY (090041892960) X GRANT 53 7 789577851 0 TAB IX GRANT |
(1) id 789577851就是表Test,可以查詢sysobjects。
(2) 關於TAB的IX,是表結構的意向排他鎖 。此時,如果你執行ALTER TABLE命令來改變表結構(會對錶結構上X鎖)是會被掛住 的。
(3) PAG是頁鎖,就是索引頁鎖,此時爲什麼會有兩個呢?顯然1:126是索引樹的中間頁節點頁面,而1:127是葉節點頁,也就是數據頁(聚集索引的表存儲結構)。因此,任何對索引頁上X鎖的操作都會被掛住,而上IX,S不會,SQL Server會進一步判斷行級鎖。此時,可以通過select * from Test with(paglock) where c2=2測試。
(4) KEY (010086470766) ,KEY (090041892960) 的兩個X最明顯了,就是行級獨佔鎖。一個是索引中間頁上的行級鎖,一個是葉節點(數據頁)上的行級鎖。
這就是SQL Server最常用的read committed隔離模式的情況,下次繼續討論read uncommitted隔離模式。