欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡(jiǎn)單介紹SQL Server中的自旋鎖

 更新時(shí)間:2015年07月27日 08:59:17   作者:Visitors  
本文主要分為兩大部分,第1部分討論了為什么SQL Server需要實(shí)現(xiàn)自旋鎖,第2部分討論了對(duì)SQL Server的自旋鎖如何進(jìn)行故障排除,需要的朋友可以參考下

為什么我們需要自旋鎖?
用閂鎖同步多個(gè)線程間數(shù)據(jù)結(jié)構(gòu)訪問(wèn),在每個(gè)共享數(shù)據(jù)結(jié)構(gòu)前都放置一個(gè)閂鎖沒(méi)有意義的。閂鎖與此緊密關(guān)聯(lián):當(dāng)你不能獲得閂鎖(因?yàn)槠渌艘呀?jīng)有一個(gè)不兼容的閂鎖拿到),查詢就會(huì)強(qiáng)制等待,并進(jìn)入掛起(SUSPENDED)狀態(tài)。查詢?cè)趻炱馉顟B(tài)等待直到可以拿到閂鎖,然后就會(huì)進(jìn)入可執(zhí)行(RUNNABLE)狀態(tài)。對(duì)于查詢執(zhí)行只要沒(méi)有可用的CPU,查詢就一直在可執(zhí)行(RUNNABLE)狀態(tài)。一旦CPU有空閑,查詢會(huì)進(jìn)入運(yùn)行(RUNNING)狀態(tài),最后成功獲取到閂鎖,用它來(lái)保護(hù)訪問(wèn)的共享數(shù)據(jù)結(jié)構(gòu)。下圖展示了SQLOS對(duì)協(xié)調(diào)線程調(diào)度實(shí)現(xiàn)的狀態(tài)機(jī)。

因?yàn)樘嚓P(guān)聯(lián)的閂鎖,對(duì)“忙碌”數(shù)據(jù)結(jié)構(gòu)使用閂鎖保護(hù)沒(méi)有意義。因此SQL Server實(shí)現(xiàn)所謂自旋鎖(Spinlocks)。自旋鎖就像一個(gè)閂鎖,存儲(chǔ)引擎使用的一個(gè)輕量級(jí)同步對(duì)象,用來(lái)同步對(duì)共享數(shù)據(jù)結(jié)構(gòu)線程訪問(wèn)。和閂鎖的主要區(qū)別是你積極等待自旋鎖——不離開CPU。在自旋鎖上的“等待”總會(huì)發(fā)生在運(yùn)行(RUNNING)狀態(tài)的CPU。在你閉合循環(huán)里旋轉(zhuǎn)直到獲得自旋鎖。這就是所謂的忙碌等待(busy wait)。自旋鎖的最大優(yōu)點(diǎn)是當(dāng)查詢?cè)谧孕i上等待時(shí),不會(huì)涉及到上下文切換。另一方面忙碌等待浪費(fèi)CPU周期,其他查詢也許能對(duì)它們更有效的使用。

為了避免太多的CPU周期浪費(fèi),SQL Server 2008 R2及后續(xù)版本實(shí)現(xiàn)所謂的指數(shù)補(bǔ)償機(jī)制(exponential backoff mechanism),那里在CPU上一些時(shí)間的休眠后,線程停止旋轉(zhuǎn)。在線程進(jìn)入休眠期間,增加了嘗試獲得自旋鎖的超時(shí)。這個(gè)行為可以降低對(duì)CPU性能的影響。

(補(bǔ)充說(shuō)明:Spinlock中文可以稱為自旋鎖。它是一個(gè)輕量級(jí)的,用戶態(tài)的同步對(duì)象,和critical section類似,但是粒度比前者小多了。它主要用來(lái)保護(hù)某些特定的內(nèi)存對(duì)象的多線程并發(fā)訪問(wèn)。Spinlock是排他性的。一次只能一個(gè)線程擁有。

Spinlock的設(shè)計(jì)目標(biāo)是非常快和高效率。Spinlock內(nèi)部如何工作呢?它首先試圖獲得某個(gè)對(duì)象的鎖,如果目標(biāo)被其它線程占有,就在那里輪詢(spin)一定時(shí)間。如果還得不到鎖,就sleep一小會(huì),然后繼續(xù)spin。反復(fù)這個(gè)過(guò)程直到得到對(duì)象的占有權(quán)。)

自旋鎖與故障排除
對(duì)自旋鎖故障排除的主要DMV是 sys.dm_os_spinlock_stats。這個(gè)DMV里返回的每一行都代表SQL Server里的一個(gè)自旋鎖。SQL Server 2014實(shí)現(xiàn)了262個(gè)不同自旋鎖。我們來(lái)詳細(xì)看下這個(gè)DMV里的各個(gè)列:

name:自旋鎖名稱
collision:當(dāng)嘗試訪問(wèn)保護(hù)的數(shù)據(jù)結(jié)構(gòu)時(shí),被自旋鎖阻塞的線程次數(shù)
spins:在循環(huán)里嘗試獲得自旋鎖的自旋鎖線程次數(shù)
spins_per_collision:旋轉(zhuǎn)和碰撞之間的比率
sleep_time:因?yàn)橥吮芫€程休眠時(shí)間
backoffs:為了其他線程在CPU上繼續(xù),線程退避次數(shù)
在這個(gè)DMV里最重要的列是backoffs,對(duì)于特定的自旋鎖類型,這列告訴你退避發(fā)生頻率。高頻率的退避會(huì)屈服于CPU消耗引起SQL Server里的自旋鎖競(jìng)爭(zhēng)(Spinlock Contention)。我就見過(guò)一個(gè)32核的SQL Server服務(wù)器,CPU運(yùn)行在100%而不進(jìn)行任何工作——典型的自旋鎖競(jìng)爭(zhēng)癥狀。

對(duì)自旋鎖問(wèn)題進(jìn)行故障排除你可以使用擴(kuò)展事件提供的sqlos.spinlock_backoff。當(dāng)退避(backoff)發(fā)生時(shí),就會(huì)觸發(fā)這個(gè)擴(kuò)展事件。如果你捕獲了這個(gè)事件,你還要保證你使用非常好的選擇性謂語(yǔ),因?yàn)樵赟QL Server里退避會(huì)經(jīng)常發(fā)生。一個(gè)好的謂語(yǔ)可以是特定的自旋鎖類型,通過(guò)剛才提到的DMV你已經(jīng)看到。下列代碼給你展示了如何創(chuàng)建這樣的擴(kuò)展事件會(huì)話。


 -- Retrieve the type value for the LOCK_HASH spinlock.
 -- That value is used by the next XEvent session
 SELECT * FROM sys.dm_xe_map_values
 WHERE name = 'spinlock_types'
 AND map_value = 'LOCK_HASH'
 GO
 
 -- Tracks the spinlock_backoff event
 CREATE EVENT SESSION SpinlockContention ON SERVER 
 ADD EVENT sqlos.spinlock_backoff
(
 ACTION
 (
  package0.callstack
 )
  WHERE
 (
  [type] = 129 -- <<< Value from the previous query
 )
) 
ADD TARGET package0.histogram
 (
  SET source = 'package0.callstack', source_type = 1
 )
 GO

從代碼里可以看到,這里我在調(diào)用堆棧(callstack)上使用了直方圖(histogram)目標(biāo)來(lái)bucktize。因此對(duì)于特定的自旋鎖,你可以可能到SQL Serve里生成的最高退避(backoffs)代碼路徑。你甚至可以通過(guò)啟用3656跟蹤標(biāo)記(trace flag)來(lái)標(biāo)識(shí)調(diào)用堆棧。這里你可以看到來(lái)自這個(gè)擴(kuò)展會(huì)話的輸出:

sqldk.dll!XeSosPkg::spinlock_backoff::Publish+0x138
sqldk.dll!SpinlockBase::Sleep+0xc5
sqlmin.dll!Spinlock<129,7,1>::SpinToAcquireWithExponentialBackoff+0x169
sqlmin.dll!lck_lockInternal+0x841
sqlmin.dll!XactWorkspaceImp::GetSharedDBLockFromLockManager+0x18d
sqlmin.dll!XactWorkspaceImp::GetDBLockLocal+0x15b
sqlmin.dll!XactWorkspaceImp::GetDBLock+0x5a
sqlmin.dll!lockdb+0x4a sqlmin.dll!DBMgr::OpenDB+0x1ec
sqlmin.dll!sqlusedb+0xeb
sqllang.dll!usedb+0xb3
sqllang.dll!LoginUseDbHelper::UseByMDDatabaseId+0x93
sqllang.dll!LoginUseDbHelper::FDetermineSessionDb+0x3e1
sqllang.dll!FRedoLoginImpl+0xa1b
sqllang.dll!FRedoLogin+0x1c1
sqllang.dll!process_request+0x3ec
sqllang.dll!process_commands+0x4a3
sqldk.dll!SOS_Task::Param::Execute+0x21e
sqldk.dll!SOS_Scheduler::RunTask+0xa8
sqldk.dll!SOS_Scheduler::ProcessTasks+0x279
sqldk.dll!SchedulerManager::WorkerEntryPoint+0x24c
sqldk.dll!SystemThread::RunWorker+0x8f
sqldk.dll!SystemThreadDispatcher::ProcessWorker+0x3ab
sqldk.dll!SchedulerManager::ThreadEntryPoint+0x226

使用提供調(diào)用堆棧,不難找出自旋鎖競(jìng)爭(zhēng)發(fā)生的地方。在那個(gè)指定的笤俑堆棧里競(jìng)爭(zhēng)發(fā)生在LOCK_HASH自旋鎖類型里,它是保護(hù)鎖管理器的哈希表。每次在鎖管理器里加鎖或解鎖被執(zhí)行時(shí),自旋鎖必須在對(duì)應(yīng)的哈希桶里獲得。如你所見,在調(diào)用堆棧里,當(dāng)從XactWorkspacelmp類調(diào)用GetSharedDBLockFromLockManager函數(shù)時(shí),自旋鎖被獲得。這表示當(dāng)競(jìng)爭(zhēng)到數(shù)據(jù)庫(kù)時(shí),共享數(shù)據(jù)庫(kù)鎖被嘗試獲取。最后在用很高的退避(backoffs)的LOCK_HASH自旋鎖里,這屈服于自旋鎖競(jìng)爭(zhēng)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • SQL Server 日期和時(shí)間的內(nèi)部存儲(chǔ)過(guò)程

    SQL Server 日期和時(shí)間的內(nèi)部存儲(chǔ)過(guò)程

    在SQL Server的內(nèi)部存儲(chǔ)中,日期和時(shí)間不是以字符串的形式存儲(chǔ)的,而是使用整數(shù)來(lái)存儲(chǔ)的。這篇文章主要介紹了SQL Server 日期和時(shí)間的內(nèi)部存儲(chǔ),需要的朋友可以參考下
    2019-12-12
  • sqlserver中幾種典型的等待

    sqlserver中幾種典型的等待

    在最近的幾次sqlserver問(wèn)題的排查中,總結(jié)了sqlserver幾種典型的等待類型,類似于oracle中的等待事件,如果看到這樣的等待類型時(shí)候能夠迅速定位問(wèn)題的根源,下面通過(guò)一則案例來(lái)把這些典型的等待處理方法整理出來(lái)
    2016-05-05
  • 安裝SQL?Server2019詳細(xì)教程(推薦!)

    安裝SQL?Server2019詳細(xì)教程(推薦!)

    SQL Server數(shù)據(jù)庫(kù)是Microsoft開發(fā)設(shè)計(jì)的一個(gè)關(guān)系數(shù)據(jù)庫(kù)智能管理系統(tǒng)(RDBMS),現(xiàn)在是全世界主流數(shù)據(jù)庫(kù)之一,下面這篇文章主要給大家介紹了關(guān)于安裝SQL?Server2019詳細(xì)教程,需要的朋友可以參考下
    2022-11-11
  • SQL日期的計(jì)算合集

    SQL日期的計(jì)算合集

    在SQL Server中,時(shí)間和日期是常見的數(shù)據(jù)類型,也是數(shù)據(jù)處理中重要的一部分,本文將介紹SQL Server中一些常用的時(shí)間和日期函數(shù),以及它們的用法和示例,感興趣的可以了解一下
    2023-10-10
  • sql server使用公用表表達(dá)式CTE通過(guò)遞歸方式編寫通用函數(shù)自動(dòng)生成連續(xù)數(shù)字和日期

    sql server使用公用表表達(dá)式CTE通過(guò)遞歸方式編寫通用函數(shù)自動(dòng)生成連續(xù)數(shù)字和日期

    CTE是在內(nèi)存中準(zhǔn)備好數(shù)據(jù),而不是每次一條往返服務(wù)器和客戶端一次。如果需要再插入到臨時(shí)表的話就是全部數(shù)據(jù)一次性插入。 這篇文章主要介紹了sql server使用公用表表達(dá)式CTE通過(guò)遞歸方式編寫通用函數(shù)自動(dòng)生成連續(xù)數(shù)字和日期 ,需要的朋友可以參考下
    2019-07-07
  • Sql Server:多行合并成一行,并做分組統(tǒng)計(jì)的兩個(gè)方法

    Sql Server:多行合并成一行,并做分組統(tǒng)計(jì)的兩個(gè)方法

    Sql Server:多行合并成一行,并做分組統(tǒng)計(jì)的兩個(gè)方法,需要的朋友可以參考一下
    2013-02-02
  • sqlserver中查詢橫表變豎表的sql語(yǔ)句簡(jiǎn)析

    sqlserver中查詢橫表變豎表的sql語(yǔ)句簡(jiǎn)析

    SQL 查詢橫表變豎表是我工作遇到過(guò)得情況,總結(jié)下來(lái)。如果有遇到這種情況的話可以參考下
    2012-05-05
  • SQLServer2019安裝教程圖文詳解

    SQLServer2019安裝教程圖文詳解

    這篇文章主要介紹了SQLServer2019安裝教程圖文詳解,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • sqlserver下Kill 所有連接到某一數(shù)據(jù)庫(kù)的連接

    sqlserver下Kill 所有連接到某一數(shù)據(jù)庫(kù)的連接

    可以通過(guò)下面代碼Kill所有連接到某一數(shù)據(jù)庫(kù)的所有連接
    2010-05-05
  • SQL?Server單表數(shù)據(jù)查詢舉例詳解

    SQL?Server單表數(shù)據(jù)查詢舉例詳解

    在最近的學(xué)習(xí)中,我發(fā)現(xiàn)對(duì)于我們編程的人員來(lái)說(shuō),數(shù)據(jù)是非常重要的,因?yàn)槲覀冊(cè)诰幊痰臅r(shí)候,每分每秒每刻都在與數(shù)據(jù)進(jìn)行打交道,下面這篇文章主要給大家介紹了關(guān)于SQL?Server單表數(shù)據(jù)查詢的相關(guān)資料,需要的朋友可以參考下
    2023-04-04

最新評(píng)論