导致阻塞的SQL Server SELECT语句

Nei*_*ell 17 sql-server performance blocking

我们正在使用带有巨大select语句的SQL Server 2005数据库(没有行版本控制),我们看到它阻止其他语句运行(看到使用sp_who2).我没有意识到SELECT语句可能导致阻塞 - 我有什么办法可以缓解这种情况吗?

Rem*_*anu 32

SELECT可以阻止更新.正确设计的数据模型和查询只会导致最小的阻塞而不是问题."通常"WITH NOLOCK提示几乎总是错误的答案.正确的答案是调整查询,使其不扫描大表.

如果查询不可用,则应首先考虑SNAPSHOT ISOLATION级别,其次应考虑使用DATABASE SNAPSHOTS,最后一个选项应该是DIRTY READS(最好更改隔离级别而不是使用NOLOCK HINT).请注意,脏名称,如名称所示,将返回不一致的数据(例如,您的总表单可能不平衡).

  • 不要误会我的意思,这是一个很好的答案,但我不会在不了解他们的应用和设计的情况下绝对说话.例如,如果您的应用是具有"查询"功能的企业应用,该怎么办?猜猜谁在写你的查询?到你的数据库?客户!那里没有足够的索引!! 快照隔离级别?有多少人同时点击您的数据库?因为我们用这个选项谈论资源!! 所以,是的,我们未经洗涤的群众不是DB大师必须使用脏读! (2认同)
  • “‘通常’的 WITH NOLOCK 提示几乎总是错误的答案。” 如果我的问题是:我想做脏的、非阻塞的 SELECT 语句,这些语句当前会导致 20-60 秒的阻塞。那么正确答案是什么? (2认同)

Qua*_*noi 15

来自文档:

Shared (S)锁允许并发事务(SELECT)在悲观并发控制下读取资源.有关更多信息,请参阅Types of Concurrency Control.当shared (S)资源上存在锁定时,没有其他事务可以修改数据.Shared (S)读取操作完成后立即释放资源上的锁,除非将事务隔离级别设置为可重复读取或更高,或者使用锁定提示shared (S)在事务持续期间保留锁定.

A shared lock与另一个共享锁或更新锁兼容,但不与exlusive锁兼容.

这意味着您的SELECT查询将阻止UPDATEINSERT查询,反之亦然.

SELECT查询将放置一个临时共享锁时,它读取来自表值的块,并取出它时,它读完.

对于存在锁定的时间,您将无法对锁定区域中的数据执行任何操作.

两个SELECT查询永远不会相互阻塞(除非它们是SELECT FOR UPDATE)

您可以SNAPSHOT在数据库上启用隔离级别并使用它,但请注意,它不会阻止UPDATE查询锁定SELECT查询(这似乎是您的情况).

但是,它会阻止SELECT查询被锁定UPDATE.

另请注意SQL Server,与Oracle使用锁管理器不同,它会将其锁定在内存中的链表中.

这意味着在重负载下,放置和移除锁定这一事实可能很慢,因为链表本身应该由事务线程锁定.