【问题标题】:Is there any way that I could get the table from one running SP and give it to another SP in SQL Server?有什么方法可以从一个正在运行的 SP 获取表并将其提供给 SQL Server 中的另一个 SP?
【发布时间】:2016-04-12 11:31:58
【问题描述】:

我是 SQL DBA 角色的新手。我有一个可能每天运行多次的存储过程 (SP1)。它在 table1 上运行昂贵的SELECT,可能需要 15 分钟才能完成。我有另一个存储过程 (SP2),它在 table1 上运行 SELECT,可能需要 1 秒才能完成。

SP1 运行后,SP2 必须等到 SP1 完成!有什么方法可以让我获得运行 SP2 所需的资源(如从 table1 中选择)并在 SP2 完成后将其返回给 SP1?

我不想使用SELECT WITH (NOLOCK),因为其他查询可能会尝试编辑 table1。

【问题讨论】:

  • 嗯。你知道答案,但你不想使用它。
  • 好吧,我想知道是否有更清洁的方法。
  • 所以澄清一下,SP1 采用排他表锁,这样 SP2 在 SP1 完成之前无法从表中读取?你说的“把它还给SP1”是什么意思?回馈什么?
  • 是的。将表交还给 SP1 以继续其 SELECT。
  • 我们在旧的遗留数据库中遇到了类似的问题。每个人都在试图弄乱索引,RECOMPILE,甚至是NOLOCK,但最终 SP 被重写并且运行速度快了大约 8 倍......如果你不放弃太多,你可能会发布 SP1 的代码加上结构信息(尤其是索引)。也许有更好的螺丝来调整......

标签: sql sql-server sql-server-2014


【解决方案1】:

您的问题的简单答案是“否”。似乎您在 SP1 中有一个运行时间很长的查询,该查询在 Table1 中获取共享锁,因此 SP2 中的任何 UPDATEINSERT 都必须等到 SP1 完成才能获取必要的排他锁(您没有t 提到了事务/隔离级别,所以我假设是 SELECT 本身需要时间而不是任何后续处理 - 尽管您已经说过 SP1 可能会执行一些 UPDATEs 或 INSERTs 它自己)。据我所知,您希望 SP1 在其 SELECT 中释放其锁定,以便 SP2 可以执行其 UPDATEs,然后,一旦 SP2 释放其锁定,则允许 SP1 继续其 SELECT。恐怕这违背了 SQL 的锁定逻辑,实际上也违背了 ACID 原则。如果它按照您的意愿工作,那么为了确保结果一致,SP1 必须在每次 SP2(或其他进程)执行UPDATE 时重新启动其SELECT,这会对数据库性能造成灾难性后果。

听起来您需要考虑重组您的存储过程/应用程序。让 SP 定期运行需要 15 分钟并可能锁定表,这听起来像是一个主要瓶颈。它不能被分解 - 也许将 SP2 的一些逻辑合并到其中一个部分中?还有,为什么要这么久?是否没有可以应用索引来减少 SELECT 花费的时间并避免您似乎遭受的那种表/范围锁?

【讨论】:

    【解决方案2】:

    你看过READ_COMMITTED_SNAPSHOT吗?

    您肯定需要先在非生产环境中对其进行测试,但希望它可以替代NOLOCK

    但是,Books Online 说:

    快照隔离的最终效果是事务可以看到所有数据,因为它在事务开始时就已经存在,而无需在基础表上执行或放置任何锁。这可以在存在争用的情况下提高性能。

    这里有一个警告,它可能对您的 TempDB 有害,但如果您有足够的空间,它可能会对您有所帮助。

    我肯定会首先阅读它,也许会查看其他一些answers

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-16
      • 2017-05-08
      • 1970-01-01
      相关资源
      最近更新 更多