Skip to content

SQL WITH(NOLOCK)

🏷️ SQL

虽然 SQL 文中所有的表都加了 WITH(NOLOCK),但发现线上该 SQL 文偶尔还是会报死锁。

看了 SQL Server 中 WITH (NOLOCK) 浅析 才知道 WITH(NOLOCK) 并不是不加任何锁。


开发人员喜欢在 SQL 脚本中使用 WITH(NOLOCK), WITH(NOLOCK) 其实是表提示(table_hint)中的一种。它等同于 READUNCOMMITTED 。具体的功能作用如下所示(摘自 MSDN):

  1. 指定允许脏读。不发布共享锁来阻止其他事务修改当前事务读取的数据,其他事务设置的排他锁不会阻碍当前事务读取锁定数据。允许脏读可能产生较多的并发操作,但其代价是读取以后会被其他事务回滚的数据修改。这可能会使您的事务出错,向用户显示从未提交过的数据,或者导致用户两次看到记录(或根本看不到记录)。有关脏读、不可重复读和幻读的详细信息,请参阅并发影响。

  2. READUNCOMMITTEDNOLOCK 提示仅适用于数据锁。所有查询(包括那些带有 READUNCOMMITTEDNOLOCK 提示的查询)都会在编译和执行过程中获取 Sch-S(架构稳定性)锁。因此,当并发事务持有表的 Sch-M(架构修改)锁时,将阻塞查询。例如,数据定义语言 (DDL) 操作在修改表的架构信息之前获取 Sch-M 锁。所有并发查询(包括那些使用 READUNCOMMITTEDNOLOCK 提示运行的查询)都会在尝试获取 Sch-S 锁时被阻塞。相反,持有 Sch-S 锁的查询将阻塞尝试获取 Sch-M 锁的并发事务。有关锁行为的详细信息,请参阅锁兼容性(数据库引擎)。

  3. 不能为通过插入、更新或删除操作修改过的表指定 READUNCOMMITTEDNOLOCK。SQL Server 查询优化器忽略 FROM 子句中应用于 UPDATEDELETE 语句的目标表的 READUNCOMMITTEDNOLOCK 提示。