|
曾今有件事情讓我記憶猶新,那年剛來(lái)攜程不久,馬上就被安排寫(xiě)一個(gè)接口,供企鵝公司調(diào)用他們員工的差旅信息,然后我就三下五除二的給寫(xiě)好 了,上線之后,大概過(guò)了一個(gè)月。。。DBA那邊報(bào)告數(shù)據(jù)庫(kù)出現(xiàn)大量鎖超時(shí),并且及時(shí)根據(jù)sql的來(lái)源將email發(fā)到了我們部門(mén),指出sql讀取時(shí)間過(guò)長(zhǎng), 并且缺少nolock,影響了大量機(jī)票訂單入庫(kù),然后我就拿著sql去生產(chǎn)環(huán)境跑了下,22s。。?;ú痢?。。項(xiàng)目上線時(shí)間太久,版本已經(jīng)不存在了,無(wú)法 回滾。。。原本準(zhǔn)備撤下接口。。??戳讼鲁废陆涌诟由蟦olock時(shí)間相差不多,最后決定先加上nolock,發(fā)布緊急單。。。然后再優(yōu)化,DBA那邊暫 時(shí)做手工解鎖,發(fā)上去后,最后就是損失XXXX訂單。。。定級(jí)為三級(jí)事件。然后就是追責(zé),當(dāng)然這個(gè)責(zé)任只能有老大們?nèi)コ袚?dān)了,出了這次由我引發(fā)的 事件,我得思考了,出了事情對(duì)我不見(jiàn)得全是壞事,起碼這次會(huì)讓我銘記如心,想想也搓,來(lái)攜程之前根本就不會(huì)關(guān)注要不要給select指定nolock,這其 中也包括自己沒(méi)遇到過(guò)大數(shù)據(jù)吧,也包括自己的能力有限,只知道有鎖這個(gè)玩意,細(xì)說(shuō)的話就啥也不知道了,后來(lái)才知道攜程有個(gè)規(guī)則,就是很多業(yè)務(wù)產(chǎn) 線所寫(xiě)的select都必須指定nolock,懂一點(diǎn)的人可能會(huì)說(shuō)nolock可以提升性能,如果你這樣說(shuō),確實(shí)是這樣,因?yàn)閿?shù)據(jù)庫(kù)的鎖是有96字節(jié)開(kāi)銷(xiāo)的,沒(méi)了 鎖,也就沒(méi)有你在profile中看到accquired和released痙攣了,當(dāng)你看完我的事件之后,你可能會(huì)意識(shí)到,性能提升不是最關(guān)心的,最關(guān)心就是不要出現(xiàn) 死鎖,鎖等待。。。好了,言歸正傳,下面我們看看到底在數(shù)據(jù)庫(kù)中可以指定多少個(gè)鎖???
一:到底可以指定多少個(gè)鎖 這個(gè)問(wèn)題有意思,我們不需要記,只要你裝一個(gè)SQL Prompt,有了這個(gè)神器,你就知道到底有多少個(gè)?如下圖: 1 DROP TABLE dbo.Person 2 CREATE TABLE Person(ID INT IDENTITY,NAME CHAR(4000) DEFAULT 'xxxxx') 3 INSERT INTO dbo.Person DEFAULT VALUES 4 go 6
一眼掃下去,還是蠻多的,不過(guò)你要注意了,那些所謂的XXXLock才是我們需要關(guān)注的,根據(jù)上面的圖,我們大概把鎖分個(gè)類(lèi)。。。 粒度鎖:PAGLOCK, TABLOCK, TABLOCKX, ROWLOCK, NOLOCK 模式鎖:HOLDLOCK, UPDLOCK, XLOCK 接下來(lái)我從粒度鎖說(shuō)起: 1. NOLOCK 都說(shuō)nolock是無(wú)鎖模式的,那到底是怎樣的無(wú)鎖呢???到這篇為止,你應(yīng)該知道,如果不加nolock,我們的表,數(shù)據(jù)頁(yè)是附加IS鎖的,那接 下來(lái)我用profile看下兩者有什么區(qū)別。
從上圖中,你會(huì)看到加上nolock之后,object上面附加了Sch-S鎖,這個(gè)鎖叫做“架構(gòu)穩(wěn)定鎖”,很簡(jiǎn)單就是sql編譯時(shí)附加的一把鎖,目的就是 防止在編譯時(shí),有其他連接修改表結(jié)構(gòu),而這個(gè)鎖只與Sch-M鎖沖突,與其他鎖都兼容,這說(shuō)明什么?說(shuō)明其他連接鎖住了記錄也沒(méi)關(guān)系,我的 nolock不跟他們打交道,這樣的話,就可能會(huì)讀到臟數(shù)據(jù),不過(guò)沒(méi)關(guān)系,攜程的很多業(yè)務(wù)是容許臟數(shù)據(jù)的,畢竟比鎖等待,死鎖要強(qiáng)得多,再說(shuō) nolock讀到了其他連接未修改或者未提交的數(shù)據(jù),這個(gè)概率也比較低,就算遇到了也沒(méi)關(guān)系,一般不會(huì)招來(lái)客訴的,客人或許再刷下頁(yè)面,數(shù)據(jù) 或許就正確了,對(duì)不對(duì)。。。
2.TABLOCK 這個(gè)還是比較見(jiàn)名識(shí)義的,就是附加在table上的鎖,也就是表鎖了,很恐怖的。。。下面我舉個(gè)Update的例子,看看前后對(duì)比。
在上面你有沒(méi)有看到,X鎖已經(jīng)附加到OBJECT上面去了。。。這樣的話,其他連接就動(dòng)不了這個(gè)Object了,只能等待。。。
3. PAGLOCK 看了名字你應(yīng)該也知道,就是附加到頁(yè)面這個(gè)級(jí)別的鎖,我也舉一個(gè)Update的例子。 1 BEGIN TRAN 2 UPDATE dbo.Person SET NAME='aaaaa' WHERE ID=6 3 4 BEGIN TRAN 5 UPDATE dbo.Person WITH(PAGLOCK) SET NAME='bbbbb' WHERE ID=4
從上面兩個(gè)圖中,你應(yīng)該可以看到,原來(lái)附加到RID上面的U鎖,由于PagLock的提升,現(xiàn)在要附加到Page上面了,這個(gè)就是所謂的數(shù)據(jù)頁(yè)鎖。
4.TABLOCKX, ROWLOCK 這兩個(gè)我就不細(xì)說(shuō)了,TABLOCKX就是直接附加在table上的X鎖,你可以通過(guò)select看一下。
ROWLOCK的話,默認(rèn)情況下就是ROWLOCK,比如默認(rèn)的Update,你會(huì)發(fā)現(xiàn)RID上被附加的U鎖,這個(gè)就是行鎖。
5.UPDLOCK 這個(gè)鎖還是蠻有意思的,它就是update鎖,如果你select下,它會(huì)呈現(xiàn)update的鎖痙攣效果。
6. XLOCK 知道了UPDLOCK鎖,我想XLOCK你也應(yīng)該明白了。。。它就是delete鎖,即排他鎖,我可以讓select帶上排他鎖。
7.HOLDLOCK 最后一個(gè)我也沒(méi)鬧明白,據(jù)說(shuō)是讓語(yǔ)句在整個(gè)事務(wù)中持有鎖,然后我就用select和update調(diào)試一下。 1 SELECT * FROM dbo.Person(HOLDLOCK) 2 UPDATE dbo.Person WITH(HOLDLOCK) SET NAME='bbbbb' WHERE ID=4
從圖中可以看到,HOLDLOCK不管是在select還是Update中,都是對(duì)表持有鎖,沒(méi)心情研究了,明天可以回家了。。。留給大家觀察吧。
最后祝大家新年愉快,闔家歡樂(lè),我也終于在年前完成了這個(gè)系列,也祝賀祝賀自己。 |
|
|
來(lái)自: 咸咸咸咸魚(yú)干 > 《鎖知識(shí)》