曾今有件事情讓我記憶猶新,那年剛來攜程不久,馬上就被安排寫一個接口,供企鵝公司調用他們員工的差旅資訊,然後我就三下五除二的給寫好
了,上線之後,大概過了一個月。。。dba那邊報告資料庫出現大量鎖逾時,并且及時根據sql的來源将email發到了我們部門,指出sql讀取時間過長,
并且缺少nolock,影響了大量機票訂單入庫,然後我就拿着sql去生産環境跑了下,22s。。。花擦。。。項目上線時間太久,版本已經不存在了,無法
復原。。。原本準備撤下接口。。。看了下撤下接口跟加上nolock時間相差不多,最後決定先加上nolock,釋出緊急單。。。然後再優化,dba那邊暫
時做手工解鎖,發上去後,最後就是損失xxxx訂單。。。定級為三級事件。然後就是追責,當然這個責任隻能有老大們去承擔了,出了這次由我引發的
事件,我得思考了,出了事情對我不見得全是壞事,起碼這次會讓我銘記如心,想想也搓,來攜程之前根本就不會關注要不要給select指定nolock,這其
中也包括自己沒遇到過大資料吧,也包括自己的能力有限,隻知道有鎖這個玩意,細說的話就啥也不知道了,後來才知道攜程有個規則,就是很多業務産
線所寫的select都必須指定nolock,懂一點的人可能會說nolock可以提升性能,如果你這樣說,确實是這樣,因為資料庫的鎖是有96位元組開銷的,沒了
鎖,也就沒有你在profile中看到accquired和released痙攣了,當你看完我的事件之後,你可能會意識到,性能提升不是最關心的,最關心就是不要出現
死鎖,鎖等待。。。好了,言歸正傳,下面我們看看到底在資料庫中可以指定多少個鎖???
一:到底可以指定多少個鎖
這個問題有意思,我們不需要記,隻要你裝一個sql prompt,有了這個神器,你就知道到底有多少個?如下圖:
一眼掃下去,還是蠻多的,不過你要注意了,那些所謂的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的例子。
從上面兩個圖中,你應該可以看到,原來附加到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調試一下。
從圖中可以看到,holdlock不管是在select還是update中,都是對表持有鎖,沒心情研究了,明天可以回家了。。。留給大家觀察吧。