SQL WITH(NOLOCK)
🏷️ SQL
虽然 SQL 文中所有的表都加了 WITH(NOLOCK)
,但发现线上该 SQL 文偶尔还是会报死锁。
看了 SQL Server 中 WITH (NOLOCK) 浅析 才知道 WITH(NOLOCK)
并不是不加任何锁。
开发人员喜欢在 SQL 脚本中使用 WITH(NOLOCK)
, WITH(NOLOCK)
其实是表提示(table_hint)中的一种。它等同于 READUNCOMMITTED
。具体的功能作用如下所示(摘自 MSDN):
指定允许脏读。不发布共享锁来阻止其他事务修改当前事务读取的数据,其他事务设置的排他锁不会阻碍当前事务读取锁定数据。允许脏读可能产生较多的并发操作,但其代价是读取以后会被其他事务回滚的数据修改。这可能会使您的事务出错,向用户显示从未提交过的数据,或者导致用户两次看到记录(或根本看不到记录)。有关脏读、不可重复读和幻读的详细信息,请参阅并发影响。
READUNCOMMITTED
和NOLOCK
提示仅适用于数据锁。所有查询(包括那些带有READUNCOMMITTED
和NOLOCK
提示的查询)都会在编译和执行过程中获取 Sch-S(架构稳定性)锁。因此,当并发事务持有表的 Sch-M(架构修改)锁时,将阻塞查询。例如,数据定义语言 (DDL) 操作在修改表的架构信息之前获取 Sch-M 锁。所有并发查询(包括那些使用READUNCOMMITTED
或NOLOCK
提示运行的查询)都会在尝试获取 Sch-S 锁时被阻塞。相反,持有 Sch-S 锁的查询将阻塞尝试获取 Sch-M 锁的并发事务。有关锁行为的详细信息,请参阅锁兼容性(数据库引擎)。不能为通过插入、更新或删除操作修改过的表指定
READUNCOMMITTED
和NOLOCK
。SQL Server 查询优化器忽略FROM
子句中应用于UPDATE
或DELETE
语句的目标表的READUNCOMMITTED
和NOLOCK
提示。