咱們都知道Sqlserver爲了提升併發,容許樂觀隔離級別(讀提交快照,快照)以便讀與寫之間不阻塞.這裏有一個在Sqlserver2008R2 SP2 的熱補丁(CU11)下RCSI(讀提交快照)隔離級別下的異常.但願你們注意.sql
這裏我經過實例給你們呈現.數據庫
Code 測試數據 (Sql2008R2 sp2 cu11)session
create database testbug select @@VERSION --Microsoft SQL Server 2008 R2 (SP2) - 10.50.4302.0 (Intel X86) use testbug go create table testbug ( id int identity(1,1) primary key, str1 char(10) ) insert into testbug select 'aa' go 10000 ALTER DATABASE testbug SET READ_COMMITTED_SNAPSHOT ON with rollback immediate-------------修改庫隔離級別爲RCSI
開啓session 1,顯式事務update架構
begin tran ttt update testbug set str1='cc'
開啓session 2,select 將被阻塞.併發
select * from testbug ---將被阻塞
出乎意料,不是說好的樂觀隔離級別下讀與寫不阻塞嗎??ide
緣由分析高併發
咱們從DMV sys.dm_tran_locks中查看具體阻塞狀況如圖1-1測試
select * from sys.dm_tran_locks
圖1-1spa
原來查詢操做申請了IS鎖,這裏我能夠經過trace flag 1200驗證 如圖1-2code
DBCC TRACEON (3604,1200,-1)--------開啓鎖追蹤輸出
圖1-2
在其餘的數據庫版本中(這裏我測試了sql 2008R2 SP1,SP2,sql 2012 SP1)( 能夠拿上面的測試腳本生成數據)
select 操做實際申請的鎖sch-s架構共享鎖,這個鎖是和排他鎖(X)兼容的如圖1-3
圖1-3
鎖兼容實例如圖1-4(鎖兼容表)
圖1-4
注意測試完成後咱們關閉跟蹤標記
DBCC TRACEOFF (3604,1200,-1)
能夠看到在sql2008R2 CU11這個熱補丁下讀提交快照(RCSI)中同粒度下的讀寫會相互阻塞,這也違背了他提升併發的初衷,因此應該把它歸結爲異常.
影響版本:sql2008R2 SP2下 CU11,CU12,CU13熱補丁
後記:原來已經有人提出了此BUG,微軟將在接下來的版本(Sql2008R2SP3?)中解決此問題
https://connect.microsoft.com/SQLServer/feedback/details/914650/sql2008-r2-sp2-cu12-undermines-rcsi-by-making-select-statements-use-locks-instead-of-reading-row-versions
結語:在生產環境中咱們可能會須要須要補丁來提升咱們數據庫的效率及健壯性等.但在打補丁前須要問下本身,爲何打補丁? Sqlserver補丁分爲"SP","CU"兩個粒度,CU屬於及時調整修復,而SP是階段性添補.我我的的經驗是通常狀況只打SP補丁(從這個實例能夠看出,SP補丁通常很穩定:)),特殊需求下才打CU.