你們好,歡迎回到性能調優培訓。上個星期我經過討論悲觀併發模式拉開了第5個月培訓的序幕。今天咱們繼續,討論下樂觀併發模式(Optimistic Concurrency)。html
樂觀併發模式自SQL Server 2005後引入,並基於行版本控制(Row Versioning)原則。行版本控制背後的想法是讀操做(SELECT查詢)再也不須要得到共享鎖(Shared Lock)。不去等待直到成功得到共享鎖(Shared Lock),讀操做是返回行前一個提交的版本。老的,前一個版本被存儲在所謂的版本存儲(Version Store)裏,這個在TempDb裏永駐。寫操做(UPDATE,DELETE語句)明確複製老版本到版本存儲,新版本中含一個指針指向versionstore裏面舊行。下圖詮釋了這個概念。數據庫
增長這個指針的一個反作用是每一個記錄會增長額外的14 bytes。這會帶來:併發
另外,你也要按需計劃和大小TempDb,由於你會引入額外的I/O,在默認配置下會帶來競爭問題。如今讓咱們看看SQL Server提供給你的2個新的樂觀隔離級別(optimistic isolation levels)。性能
自SQL Server 2005起,關係引擎提供2個新的樂觀隔離級別,它們是基於上一部分討論過的行版本控制概念。學習
咱們來詳細看下這2個隔離級別。RCSI提供你基於快照語句級別的隔離。換句話說,SQL Server總會返回你在語句開始前有效的版本。它是提交讀隔離級別(Read Committed Isolation Level)的樂觀實現。所以使用這個隔離級別你會有不可重複讀(Non-Repeatable Reads)。 spa
1 ALTER DATABASE AdventureWorks2012 SET READ_COMMITTED_SNAPSHOT ON 2 GO 3 4 -- Check if RCSI is now enabled 5 SELECT name,is_read_committed_snapshot_on 6 FROM sys.databases 7 WHERE database_id = DB_ID('AdventureWorks2012') 8 GO
RCSI的一個好處是對數據庫/應用程序自己它是徹底透明的:你重要在數據庫上啓用它,而後對於每一個查詢新的默認隔離級別是讀提交快照隔離(Read Committed Snapshot Isolation)。所以經過對指定數據庫啓用RCSI,你能夠克服鎖和阻塞問題,即便死鎖問題也很容易。下面代碼顯示了對於給出的數據庫如何啓用RCSI:scala
對於你SELECT查詢,若是你想有重複讀(Repeatable Reads)的樂觀方式,你可使用快照隔離(Snapshot Isolation (SI))隔離級別。快照隔離提供你開箱即用(out of box)的重複讀,這就是說你總拿到在你事務開始前有效的行版本。遺憾的是快照隔離並不徹底透明:版本控制
下面代碼向你展現了對於指定的數據庫,如何啓用快照隔離(Snapshot Isolation),如何請求這個新的隔離級別。指針
1 -- Enable Snapshot Isolation (SI) 2 ALTER DATABASE AdventureWorks2012 SET ALLOW_SNAPSHOT_ISOLATION ON 3 GO 4 5 -- Check if SI is now enabled 6 SELECT name, snapshot_isolation_state, snapshot_isolation_state_desc 7 FROM sys.databases 8 WHERE database_id = DB_ID('AdventureWorks2012') 9 GO 10 11 USE AdventureWorks2012 12 GO 13 14 -- Setting the Isolation Level to Snapshot Isolation 15 SET TRANSACTION ISOLATION LEVEL SNAPSHOT 16 GO
今天你學習了自SQL Server 2005起支持的2個樂觀隔離級別。提交讀快照隔離(Read Committed Snapshot Isolation (RCSI))提供你基於語句級別的隔離,快照隔離(Snapshot Isolation (SI))提供你基於事務級別的隔離,由於2個隔離級別使在永駐在TempDb裏的版本存儲,對於TempDb你須要仔細計劃和指定標準。code
下週我會談下SQL Server 裏鎖和阻塞發生的問題:鎖升級(Lock Escalations)。請繼續關注!