对一些相对不怎么敏感的数据,不需要太及时性的数据,不需要占锁。
要在SQL Server中执行查询而不占用锁,可以采取以下几个策略:
1、使用NOLOCK提示: 最直接但风险较高的方法是在查询中使用WITH (NOLOCK)提示。这样,SQL Server会在读取数据时不获取共享锁,从而避免阻塞其他事务的写操作。但是,这可能导致读取“脏读”(未提交的数据)或重复读取(因并发修改而被删除或更改的数据)。因此,这个选项通常仅推荐用于只读查询,尤其是报表或数据分析场景,并且能接受数据可能不完全准确的风险。
SELECT * FROM YourTable WITH (NOLOCK)
此策略不要认为数据库库不会产生任何锁。实质上,使用了WITH(NOLOCK)后,数据库依然对该表对象生成Sch-S(架构稳定性)锁以及DB类型的共享锁,不要认为不会被其它会话阻塞,依然可能会产生Schema Change Blocking
2、 快照隔离级别: 更安全的做法是将数据库或会话的事务隔离级别设置为快照隔离(SNAPSHOT)。在快照隔离下,查询不会阻塞其他事务,也不会被其他事务阻塞,因为每个事务看到的是数据的一个快照版本,而不是实际的行锁。不过,这会增加版本存储的需求。设置会话级别的快照隔离:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
3、 使用READ_COMMITTED_SNAPSHOT: 启用数据库的READ_COMMITTED_SNAPSHOT选项,使得在读取已提交隔离级别下执行的查询也能像快照隔离一样不阻塞。这样可以在不改变应用程序代码的情况下减少锁争用。
-- 启用数据库的事务快照隔离级别
ALTER DATABASE YourDatabaseName
SET ALLOW_SNAPSHOT_ISOLATION ON;
--设置数据库为SINGLE_USER模式,减少锁定时间
ALTER DATABASE YourDatabaseName SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE YourDatabaseName SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE YourDatabaseName SET READ_COMMITTED_SNAPSHOT ON
ALTER DATABASE YourDatabaseName SET MULTI_USER
SELECT
name AS DatabaseName,
is_read_committed_snapshot_on,
CASE
WHEN snapshot_isolation_state = 0 THEN 'OFF'
WHEN snapshot_isolation_state = 1 THEN 'ON'
WHEN snapshot_isolation_state = 2 THEN 'IN_TRANSITION_TO_ON'
WHEN snapshot_isolation_state = 3 THEN 'IN_TRANSITION_TO_OFF'
ELSE 'UNKNOWN'
END AS SnapshotIsolationStateDesc
FROM
sys.databases
WHERE
name = DB_NAME(); -- 查询当前数据库,如果需要检查所有数据库,可以删除此条件或替换为具体的数据库名
设置方法 参考文章 如何修改数据库的快照隔离级别_read committed snapshotison为1-CSDN博客