文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SQL Server 的 Nolock 到底是怎样的无锁

2024-12-13 15:12

关注

二、nolock 的原理

1. sql 阻塞还原

为了方便讲述,先创建一个 post 表,插个 6 条记录,参考代码如下:

CREATE TABLE post(id INT IDENTITY,content char(4000))
GO

INSERT INTO dbo.post VALUES('aaa')
INSERT INTO dbo.post VALUES('bbb')
INSERT INTO dbo.post VALUES('ccc');
INSERT INTO dbo.post VALUES('ddd');
INSERT INTO dbo.post VALUES('eee');
INSERT INTO dbo.post VALUES('fff');

这里为了简单我没有创建索引,所以会出现 Table Scan 的情况,毕竟生产环境下的sql也避免不了 Table Scan 和 Clustered Index Scan 的存在,接下来还原下阻塞场景,开启两个 session 会话, session1 为正在运行的 update 事务, session2 为一个简单的 select 操作,这种场景下会导致 session2 阻塞,参考代码如下:

BEGIN TRAN
UPDATE post SET content='xxxxx' WHERE id=3
SELECT * FROM post WHERE id=4

从图中可以看到,这个 select 已经阻塞 9 分钟了,那为什么会被阻塞呢?可以观察 SQLSERVER 内部的统计信息,比如锁相关的动态视图 sys.dm_tran_locks ,参考代码如下:

SELECT t.request_session_id,
CASE
WHEN t.resource_type = 'OBJECT' THEN
OBJECT_NAME(t.resource_associated_entity_id)
WHEN t.resource_associated_entity_id = 0 THEN
'/'
ELSE
OBJECT_NAME(p.object_id)
END AS resource_name,
index_id,
t.resource_type,
t.resource_description AS description,
t.request_mode AS mode,
t.request_status AS status
FROM sys.dm_tran_locks AS t
LEFT JOIN sys.partitions AS p
ON p.hobt_id = t.resource_associated_entity_id
WHERE t.resource_database_id = DB_ID()

从图中看,session55 准备在 1:489:0 这个槽位指向的记录上附加 S 锁时被阻塞,因为 1:489:0 已经被附加了 X 锁,很显然这个 X 锁是 update 给的。

上面给出的是一个 静态视图,为了方便显示动态视图,这里把 sql profile 开起来观察两个 session 给锁的过程,事件选择上如下所示:

将 sqlprofile 开启后,重新运行下刚才的两个会话,观察 profile 的走势,截图如下:

图中的注释已经说的非常清楚了,和 sys.dm_tran_locks 显示的一致,有了这些基础后接下来观察下如果加上 with (nolock) 会怎么样?

SELECT * FROM post(NOLOCK) WHERE id=4

你会发现结果是可以出来的,那为什么可以出来呢?继续观察下 profile 即可。

从 session 55 的 lock 输出来看,with(nolock) 会对 post 表附加 Sch-S 架构稳定锁,以及分区中的 堆或BTree 附加S锁, 而不再对 PAGE 附加任何锁了,所以就不存在阻塞的情况,但肯定会引起脏读。

到这里基本上就是 nolock 的底层玩法了吧,不过也有一个注意点,nolock 真的不会引发阻塞吗? 接下来我们好好聊一聊。

3. nolock 真的无视阻塞吗

从 sqlprofile 观察锁的走势图来看,nolock 只是在上限为 page 页级别上做到无视,但在 page 之上就无法做到了,比如你看到的 Sch-S,可能有些朋友要问了,为什么要加上 Sch-S 锁呢?其实很简单,在 query 的过程中一定要保持架构稳定嘛,不能在 query 的过程中,post 表突然被删了,这样大家多尴尬。

接下来也可以做个简单的测试。

----- session 1
BEGIN TRAN
TRUNCATE TABLE post;

----- session 2
SELECT * FROM post(NOLOCK) WHERE id=4

可以发现 nolock 查询也被阻塞了,原因就在于拿不到 post 表的 Sch-S 锁,因为 TRUNCATE 已经给 post 附加了 Sch-M 架构修改锁,那有没有数据支撑呢?继续用动态视图 sys.dm_tran_locks 观察便可。

三、总结

综上所述,nolock 也仅在 page 级别上畅通无阻,在某些情况下也会有阻塞情况的发生,由于无锁自然就会读到别的会话已修改但还未提交的记录,sqlserver 作为一个数据库应用程序,里面包含了大量的运行时统计信息,这些统计信息可以用 系统视图 和 动态视图 获取,完全可以基于它们做一个完善的 APM 监控。

来源:一线码农聊技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯