Sql Server之旅——終點站 nolock引起的三級事件的一些思考

  曾今有件事情讓我記憶猶新,那年剛來攜程不久,立刻就被安排寫一個接口,供企鵝公司調用他們員工的差旅信息,而後我就三下五除二的給寫好sql

了,上線以後,大概過了一個月。。。DBA那邊報告數據庫出現大量鎖超時,而且及時根據sql的來源將email發到了咱們部門,指出sql讀取時間過長,數據庫

而且缺乏nolock,影響了大量機票訂單入庫,而後我就拿着sql去生產環境跑了下,22s。。。花擦。。。項目上線時間過久,版本已經不存在了,沒法架構

回滾。。。本來準備撤下接口。。。看了下撤下接口跟加上nolock時間相差很少,最後決定先加上nolock,發佈緊急單。。。而後再優化,DBA那邊暫性能

時作手工解鎖,發上去後,最後就是損失XXXX訂單。。。定級爲三級事件。而後就是追責,固然這個責任只能有老大們去承擔了,出了此次由我引起的大數據

事件,我得思考了,出了事情對我不見得全是壞事,起碼此次會讓我銘記如心,想一想也搓,來攜程以前根本就不會關注要不要給select指定nolock,這其優化

中也包括本身沒遇到過大數據吧,也包括本身的能力有限,只知道有鎖這個玩意,細說的話就啥也不知道了,後來才知道攜程有個規則,就是不少業務產ui

線所寫的select都必須指定nolock,懂一點的人可能會說nolock能夠提高性能,若是你這樣說,確實是這樣,由於數據庫的鎖是有96字節開銷的,沒了spa

鎖,也就沒有你在profile中看到accquired和released痙攣了,當你看完個人事件以後,你可能會意識到,性能提高不是最關心的,最關心就是不要出現3d

死鎖,鎖等待。。。好了,言歸正傳,下面咱們看看到底在數據庫中能夠指定多少個鎖???調試

 

一:到底能夠指定多少個鎖

  這個問題有意思,咱們不須要記,只要你裝一個SQL Prompt,有了這個神器,你就知道到底有多少個?以下圖:

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

一眼掃下去,仍是蠻多的,不過你要注意了,那些所謂的XXXLock纔是咱們須要關注的,根據上面的圖,咱們大概把鎖分個類。。。

粒度鎖:PAGLOCK, TABLOCK, TABLOCKX, ROWLOCK, NOLOCK

模式鎖:HOLDLOCK, UPDLOCK, XLOCK

接下來我從粒度鎖提及:

1. NOLOCK

  都說nolock是無鎖模式的,那究竟是怎樣的無鎖呢???到這篇爲止,你應該知道,若是不加nolock,咱們的表,數據頁是附加IS鎖的,那接

下來我用profile看下二者有什麼區別。 

 

從上圖中,你會看到加上nolock以後,object上面附加了Sch-S鎖,這個鎖叫作「架構穩定鎖」,很簡單就是sql編譯時附加的一把鎖,目的就是

防止在編譯時,有其餘鏈接修改表結構,而這個鎖只與Sch-M鎖衝突,與其餘鎖都兼容,這說明什麼?說明其餘鏈接鎖住了記錄也不要緊,個人

nolock不跟他們打交道,這樣的話,就可能會讀到髒數據,不過不要緊,攜程的不少業務是允許髒數據的,畢竟比鎖等待,死鎖要強得多,再說

nolock讀到了其餘鏈接未修改或者未提交的數據,這個機率也比較低,就算遇到了也不要緊,通常不會招來客訴的,客人或許再刷下頁面,數據

或許就正確了,對不對。。。

 

2.TABLOCK

  這個仍是比較見名識義的,就是附加在table上的鎖,也就是表鎖了,很恐怖的。。。下面我舉個Update的例子,看看先後對比。

在上面你有沒有看到,X鎖已經附加到OBJECT上面去了。。。這樣的話,其餘鏈接就動不了這個Object了,只能等待。。。

 

3.  PAGLOCK

  看了名字你應該也知道,就是附加到頁面這個級別的鎖,我也舉一個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

從上面兩個圖中,你應該能夠看到,原來附加到RID上面的U鎖,因爲PagLock的提高,如今要附加到Page上面了,這個就是所謂的數據頁鎖。

 

4.TABLOCKX, ROWLOCK

   這兩個我就不細說了,TABLOCKX就是直接附加在table上的X鎖,你能夠經過select看一下。

ROWLOCK的話,默認狀況下就是ROWLOCK,好比默認的Update,你會發現RID上被附加的U鎖,這個就是行鎖。

 

5.UPDLOCK

 這個鎖仍是蠻有意思的,它就是update鎖,若是你select下,它會呈現update的鎖痙攣效果。

  

6. XLOCK

  知道了UPDLOCK鎖,我想XLOCK你也應該明白了。。。它就是delete鎖,即排他鎖,我可讓select帶上排他鎖。

 

7.HOLDLOCK

  最後一個我也沒鬧明白,聽說是讓語句在整個事務中持有鎖,而後我就用select和update調試一下。

1 SELECT * FROM dbo.Person(HOLDLOCK)
2 UPDATE dbo.Person WITH(HOLDLOCK) SET NAME='bbbbb' WHERE ID=4

從圖中能夠看到,HOLDLOCK不論是在select仍是Update中,都是對錶持有鎖,沒心情研究了,明天能夠回家了。。。留給你們觀察吧。

 

最後祝你們新年愉快,闔家歡樂,我也終於在年前完成了這個系列,也祝賀祝賀本身。

相關文章
相關標籤/搜索