|
|
|
|
公众号矩阵

SQL Server优化:SQL Server中Nolock关键字的用法

SQL Server没创建一个查询,都相当于创建一个查询会话,在不同的查询分析器里面进行的查询操作,可能会影响别的查询会话。

作者: 郝光明 来源: IT技术分享社区|2021-10-13 06:49

1、为什么SQL Server有NOLOCK关键字?

SQL Server没创建一个查询,都相当于创建一个查询会话,在不同的查询分析器里面进行的查询操作,可能会影响别的查询会话。比较典型的一个例子,如果你正在使用事务执行某一张表的插入或者操作而没有正确关闭事务的情况下,会造成别的会话针对该数据表的查询都会处于阻塞的状态,从而不能完成查询的操作。这个时候有两个解决方案,第一种查询到阻塞的会话id然后杀掉该会话id,第二种可以使用WITH(NOLOCK)关键字忽略掉阻塞的会话直接查询出结果。

简单来说NOLOCK关键字的作用是防止查询的时候被别的会话阻塞,从而顺利完成查询的操作。

2、SQL Server有NOLOCK有什么问题

使用NOLOCK关键字可以避免阻塞造成无法查询出数据,但使用该关键字会有造成数据脏读的可能。下面举个例子:

2.1 创建数据表

  1. CREATE TABLE [dbo].[userInfo] ( 
  2.   [id] varchar(32) COLLATE Chinese_PRC_CI_AS  NOT NULL
  3.   [userName] nvarchar(30) COLLATE Chinese_PRC_CI_AS  NULL
  4.   [birthday] [dbo].[birthday]  NULL
  5.   CONSTRAINT [PK__userInfo__3213E83F0505C75D]  
  6.   PRIMARY KEY CLUSTERED ([id]) 
  7. WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
  8.  IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)   
  9. ON [PRIMARY
  10. )   
  11. ON [PRIMARY
  12. GO 
  13. INSERT INTO [dbo].[userInfo] ([id], [userName], [birthday]) 
  14.  VALUES ('123', N'小明''2005-01-02 12:30:00.000'); 
  15. INSERT INTO [dbo].[userInfo] ([id], [userName], [birthday]) 
  16.  VALUES ('125', N'小孙''2005-01-02 12:30:00.000'); 

2.2 创建时候 会话id 为58 开启事务 不关闭事务

  1. begin tran  
  2. insert into userInfo (id,userName,birthday) 
  3. values ('127','小张','2015-01-02 12:30:00.000'
  4. --commit tran 

2.3 当前会话(58)还可以查询出数据

事务还没有提交 此时数据还在内存中,未保存到数据库当中。

  1. select * from userInfo 

2.4 新建一个查询会话 当前新建的id是51

  1. select * from userInfo; 
  2. select * from userInfo WITH(NOLOCK); 

2.5 杀掉58会话进程

  1. declare @spid  int  
  2. Set @spid  = 58 --锁表进程 
  3. declare @sql varchar(1000) 
  4. set @sql='kill '+cast(@spid  as varchar
  5. exec(@sql) 

3、NOLOCK使用场景

针对那些被频繁操作(插入、更新、删除)的表,使用NOLOCK是非常比较适合的,但要考虑到脏读的情况。

  • 不经常修改的数据表,省掉锁定表的时间来大大加快查询速度。
  • 数据量非常大的数据表,可以考虑牺牲数据安全性来提升查询的效率;
  • 允许出现脏读现象的业务逻辑,对数据完整性要求比较严格的场景不适合,比如电商、银行等系统。
  • 当使用NoLock时,它允许阅读那些已经修改但是还没有结束事务的数据。因此要考虑transaction事务数据的实时完整性时,不建议使用。

4、nolock和with(nolock)的区别

三种查询写法

  1. SELECT * FROM A NOLOCK; 
  2. SELECT * FROM A (NOLOCK); 
  3. SELECT * FROM A WITH(NOLOCK); 
  • SQL Server 2005版本中,只支持with(nolock)关键字
  • with(nolock)的写法非常容易再指定索引
  • 跨数据库服务器查询语句时不能用with (nolock) 只能用nolock,同数据服务器查询时 两者都可以用-- SQL Server 2008版本之后建议采用WITH(NOLOCK)写法。

5、表解锁脚本

  1. -- 查询被锁表 
  2. select request_session_id   spid 
  3. ,OBJECT_NAME(resource_associated_entity_id) tableName    
  4. from   sys.dm_tran_locks where resource_type='OBJECT'
  5. --参数说明 spid   锁表进程 ;tableName   被锁表名 
  6. -- 解锁语句 需要拿到spid然后杀掉缩表进程 
  7. declare @spid  int  
  8. Set @spid  = 57 --锁表进程 
  9. declare @sql varchar(1000) 
  10. set @sql='kill '+cast(@spid  as varchar
  11. exec(@sql) 

本文转载自微信公众号「IT技术分享社区」,可以通过以下二维码关注。转载本文请联系IT技术分享社区公众号。

个人博客网站:https://programmerblog.xyz

【编辑推荐】

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区
  2. Java、Golang项目基于kubernetes集群CICD实践案例【Gitlab工具链】
  3. 除了备份,这些远程办公的安全工具你都有吗?
  4. Windows11Upgrade 小工具:让你轻松绕过限制升级Windows 11
  5. Facebook封杀“取消所有关注”工具背后的开发者
  6. Weakpass:一款功能强大的在线字典生成工具
【责任编辑:武晓燕 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO官微