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中,都是对表持有锁,没心情研究了,明天能够回家了。。。留给你们观察吧。

 

最后祝你们新年愉快,阖家欢乐,我也终于在年前完成了这个系列,也祝贺祝贺本身。