【问题标题】:Do SQL server prioritize select and update statements?SQL Server 优先选择和更新语句吗?
【发布时间】:2015-07-23 03:10:10
【问题描述】:

假设 SQL 服务器同时从不同的线程和连接接收到同一张表的 select 和 update 语句

他们中的任何一个被优先考虑吗?

我知道如果表已被锁定以进行更新,则选择语句会延迟到更新完成(默认情况下更新语句会锁定表我不正确?)。如果由于更新导致表锁持续很长时间,select语句被取消,等待错误过多

那么当两者同时收到时会发生什么?

【问题讨论】:

  • 但是您尝试两条语句不会同时开始执行,其中一条将是第一个(即使是纳秒)
  • 死锁检测。要撤消的资源最少的命令将成为死锁牺牲品。这始终是一个选择命令。
  • UPDATE 锁定它正在更新的 - 而不是整个表! (当然,除非您一次更新超过 5000 行 - 那么它可能会升级为表级锁)
  • @lrb 这是否意味着 SQL 服务器开始执行这两个查询,当看到死锁时它会取消选择语句对吗?
  • @marc_s ty 了解更多详情

标签: sql-server sql-server-2014


【解决方案1】:

SELECT 语句将在它正在读取的任何行上放置一个共享锁 (S) - 根据隔离级别,该锁将被持有不同的时间。在默认的READ COMMITTED 隔离级别中,只有在实际读取行时才会持有锁——一旦读取,锁就会立即释放。

shared 锁与其他共享锁兼容 - 因此任意数量的SELECT 语句可以同时读取相同的行。

UPDATE 语句将在要更新的行上放置 update (U) 锁,以读取现有值。然后,在完成之后,在实际更新的值被写回之前,锁被转换为一个独占(X)锁,用于写入数据。这些锁被持有直到它们正在执行的事务被提交(或回滚)。

更新锁与另一个更新锁不兼容,也不与排他锁兼容。但是它与共享锁兼容 - 因此,如果 UPDATE 语句当前仅读取现有值,则另一个事务可能会使用带有共享锁的 SELECT 语句读取相同的值。

独占锁与任何东西都不兼容 - 当X 锁在其上时,您甚至无法再读取该行。

因此,如果您有两个语句进入并尝试访问同一行,那么:

  • 如果 SELECT 先出现,它将在行上放置 S 锁,读取它,然后通常会再次释放该锁
  • 同时UPDATE语句可以在行上放置U锁并读取已有值;在释放S 锁之前,无法将锁“提升”到X - 如果没有发生这种情况,UPDATE 语句将等待,并最终超时,如果S 锁是从未发布

  • 如果UPDATE锁先出现,它将在行上放置U锁以读取现有值

  • 同时,另一个事务可能会在行上放置S 锁以读取它
  • 再说一遍:UPDATE 语句只有在 S 锁消失后才能前进到 X 级别以写回新值 - 否则它将超时

  • 如果UPDATE 锁先出现,它将在行上放置U 锁以读取现有值,并且已经在行上放置X 锁以实际执行更新

  • 那么此时,甚至没有其他事务可以读取该行 - 它们将不得不等待(或者超时,如果它们需要很长时间才能获得服务)

阅读SQL Server Transaction Locking and Row Versioning Guide 以更深入地了解该主题和更多详细信息

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2012-09-10
    相关资源
    最近更新 更多