你们好,欢迎回到性能调优培训。上个星期我经过讨论悲观并发模式拉开了第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)。请继续关注!