SQL server 2008 里面的 SPINLOCK
转自 http://blogs.msdn.com/b/apgcdsd/archive/2012/05/14/sql-server-2008-spinlock.aspx
什么是spinlock呢?
Spinlock中文可以称为自旋锁。它是一个轻量级的,用户态的同步对象,和critical section类似,但是粒度比前者小多了。它主要用来保护某些特定的内存对象的多线程并发访问。Spinlock是排他性的。一次只能一个线程拥有。
Spinlock的设计目标是非常快和高效率。Spinlock内部如何工作呢?它首先试图获得某个对象的锁,如果目标被其它线程占有,就在那里轮询(spin)一定时间。如果还得不到锁,就sleep一小会,然后继续spin。反复这个过程直到得到对象的占有权。
SQL server 2008 里面有150多个对象由spinlock提供并发访问保护。 你可以运行如下命令来看看spinlock的统计信息:
select * from sys.dm_os_spinlock_stats order by collisions desc
输出如下:
上面输出你可以看到SQL server的对象的spinlock的使用情况。上面是我的测试机的输出,和您的服务器的输出可能很不一样,因为负荷不一样。
有时候你想详细了解某个spinlock究竟是如何使用的呢?他的callstack又是如何的呢?一个方法你生成一些mini-dump,然后分析这些mini-dump。另外一个方法是使用xevent。 下面的脚本就是使用xevent来得到某类spinlock的callstack,从而可以获知SQL server内部spinlock的潜在性能瓶颈。
create event session lock_cachestore_spin on server
add event sqlos.spinlock_backoff (action (package0.callstack)
where type=141
)
add target package0.asynchronous_bucketizer
( set filtering_event_name='sqlos.spinlock_backoff',
source_type=1 ,
source='package0.callstack'
)
with (MAX_MEMORY=32MB )
go
DBCC traceon (3656, -1)
Go
alter event session lock_hash_spin on server state=start
--Wait for 30mins
waitfor delay '00:30:00'
select event_session_address, target_name, execution_count, CAST(target_data as XML)
from sys.dm_xe_session_targets
go
alter event session lock_cachestore_spin on server state=stop
drop event session lock_cachestore_spin on server
go
在我服务器上,我得到如下的callstack:
<value>XeSosPkg::spinlock_backoff::Publish+b1
SpinlockBase::Sleep+64
SpinlockBase::Backoff+7b
Spinlock<141,1,0>::SpinToAcquireOptimistic+b3
SOS_CacheStore::GetUserData+fb
OpenSystemTableRowset+d9
CMEDScanBase::Rowset+202
CMEDScan::StartSearch+336
CMEDCatYukonDR::FGetNextDatabase+83
DBMgr::AreAllDatabasesRecovered+f3
CheckServerRecovered+78
CSvrRecCheckTask::ProcessTskPkt+5
OnDemandTaskContext::ProcessTskPkt+1d2
SystemTaskContext::ExecuteFunc+13
SystemTaskEntryPoint+2db
OnDemandTaskContext::FuncEntryPoint+23
</Slot>