T-SQL——关于表提示:WITH(NOLOCK)
1.关于With(NOLOCK)
NOLOCK等价于:READUNCOMMITTED,即允许脏读。不发出共享锁来防止其他事务修改当前事务读取的数据,并且其他事务设置的排他锁不会阻止当前事务读取锁定的数据
用法:
SELECT * FROM TABLE WIHT(NOLOCK)
SELECT * FROM TABLE_A AS a WIHT(NOLOCK) LEFT JOIN TABLE_B AS b WIHT(NOLOCK) ON a.ID=b.ID
2.关于在视图上使用WITH(NOLOCK)
SELECT * FROM V_XXX WIHT(NOLOCK)
简而言之:查询视图的时候,使用WITH(NOLOCK),可以将该效果传递到视图中使用的表上面
In SQL Server 2005, all lock hints are propagated to all the tables and views that are referenced in a view. Also, SQL Server performs the corresponding lock consistency checks.
在 SQL Server 2005 中,所有锁提示都传播到视图中引用的所有表和视图。此外,SQL Server 还会执行相应的锁一致性检查。
但是需要注意:
If a table contains computed columns and the computed columns are computed by expressions or functions accessing columns in other tables, the table hints are not used on those tables. This means the table hints are not propagated. For example, a NOLOCK table hint is specified on a table in the query. This table has computed columns that are computed by a combination of expressions and functions that access columns in another table. The tables referenced by the expressions and functions do not use the NOLOCK table hint when accessed.
如果表包含计算列,并且计算列是通过访问其他表中的列的表达式或函数计算的,则不会在这些表上使用表提示。这意味着不会传播表提示。例如,在查询中的表上指定了 NOLOCK 表提示。此表具有计算列,这些列由表达式和函数的组合计算,这些表达式和函数访问另一个表中的列。表达式和函数引用的表在访问时不使用 NOLOCK 表提示。
3.关于WITH(NOLOCK)与WITH(READPAST)区分
- READPAST:指定数据库引擎不读取被其他事务锁定的行
1.创建一个测试表
CREATE TABLE [dbo].[ATestLock]
(
[Id] [BIGINT] PRIMARY KEY IDENTITY(1, 1) NOT NULL,
[Msg] [NVARCHAR](50) NOT NULL,
[CreateTime] [DATETIME] NOT NULL DEFAULT (GETDATE())
);
2.SSMS中打开一个会话,执行一个事务,不回滚不提交
BEGIN TRANSACTION;
INSERT INTO dbo.ATestLock(Msg)VALUES(N'Test');
--ROLLBACK TRANSACTION
3.SSMS中打开一个新的会话,执行下面语句
- 不加任何的表提示语句,则查询不到被锁定的行
SELECT * FROM dbo.ATestLock
--查询不到上面事务中插入的数据
- 使用WITH(NOLOCK),则查询到了被锁定的行
SELECT * FROM dbo.ATestLock WITH(NOLOCK);
--查询到了上面事务插入的数据
Id Msg CreateTime
------- ------------- -----------------------
1 Test 2024-09-27 11:04:05.603
- 使用WITH(READPAST),则查询不到被锁定的行
SELECT * FROM dbo.ATestLock WITH(READPAST);
--查询不到上面事务插入的数据
【BY THE WAY】:
- SQL SQL Identity的自增在事务回滚后仍然递增,上面的事务,最后执行了ROLLBACK,之后在插入数据可以发现自增ID是跳过了被回滚的记录ID。
回滚了事务,自增标识的值仍会继续递增,这是因为自增标识的递增是由DBMS中的内部机制负责的,而非由事务控制。
4.关于WITH(NOLOCK)产生架构锁
WITH(NOLOCK)会不会产生锁?
很多人误以为使用了WITH(NOLOCK)后,数据库库不会产生任何锁。实质上,使用了WITH(NOLOCK)后,数据库依然对该表对象生成Sch-S(架构稳定性)锁以及DB类型的共享锁。
简单的说:就是其他事务在修改表结构的时候,我们的查询使用WITH(NOLOCK)依旧会被其他事务阻塞