当我更新/插入单行时应该锁定整个表吗?

Mid*_*one 26 sql-server locking

我有两个长时间运行的查询,它们都在事务上并访问同一个表但在这些表中完全分开的行.这些查询还会根据这些查询执行一些更新和插入.

似乎当它们同时运行时会遇到某种类型的锁定,并且当它更新其中一行时,它阻止了任务完成并锁定.我正在对正在读取的行使用独占行锁,并且在进程上显示的锁是lck_m_ix锁.

两个问题:

  1. 当我更新/插入单行时是否会锁定整个表?
  2. 可以做些什么来解决这类问题?

onu*_*ade 22

通常没有,但它取决于(最常用于SQL Server的答案!)

SQL Server必须以某种方式锁定事务中涉及的数据.在执行修改时,它必须锁定表本身中的数据以及任何受影响索引的数据.为了提高并发性,服务器可能决定使用几种锁定"粒度",以允许多个进程运行:行锁,页锁和表锁是常见的(还有更多).哪种锁定程序在起作用取决于服务器如何决定执行给定的更新.使事情变得复杂的是,还存在诸如shared,exclusive和intent exclusive之类的锁的分类,其控制是否可以读取和/或修改锁定的对象.

根据我的经验,SQL Server主要使用页锁来更改表的一小部分,如果表的大部分(来自统计数据)受更新或影响,则过去某个阈值将自动升级为表锁.删除.我们的想法是,锁定表(一个锁)比获取和管理数千个单独的行或页锁以进行大更新更快.

要查看特定情况下发生的情况,您需要查看查询逻辑,并在运行时查看sys.dm_tran_locks,sys.dm_os_waiting_tasks或其他DMV中的锁定/阻塞条件.您可能希望了解每个流程中的哪个步骤确切地被锁定,以发现为什么阻止另一个流程.


Rem*_*anu 20

简短版本:

  1. 没有
  2. 修复你的代码.

长版:

LCK_M_IX是一个意图锁,意味着该操作将在下级元素上放置一个X锁.例如.更新表中的行时,操作表在锁定X正在更新/插入/删除的行之前对表执行IX锁定.意图锁是处理层次结构的常用策略,例如表/页/行,因为锁管理器无法理解请求锁定的资源的物理结构(即,它不能知道页P1上的X锁与不兼容由于R1包含在P1中,因此在行R1上进行S锁定.有关更多详细信息,请参阅锁定模式.

您在意图锁上看到争用这一事实意味着您正在尝试获取高级对象锁,例如表锁.您需要分析被阻止请求的源代码(请求锁定与LCK_M_IX不兼容的源代码)并删除对象级别锁定请求的原因.这意味着什么将取决于你的源代码,我不知道你在那里做什么.我的猜测是你使用了错误的锁定提示.

更通用的方法是依靠SNAPSHOT ISOLATION.但是,这很可能无法解决您所看到的问题,因为快照隔离只能使行级争用问题受益,而不是请求表锁定的应用程序.


Aar*_*and 11

使用交易的常见目的:尽可能保持简短和甜蜜.我从问题中的措辞中得知你正在开展交易,然后做各种各样的事情,其中​​一些需要很长时间.然后期望多个用户能够同时运行相同的代码.遗憾的是,如果您在该组代码的开头执行插入,那么在提交或回滚之前执行其他40项操作,则该插入可能会阻止其他所有人运行相同类型的插入,从而实际上将您的操作从免费为所有人.

找出每个查询正在做什么,以及您是否获得了您不希望的锁定升级.只是因为你对查询说WITH(ROWLOCK)并不意味着SQL Server将能够遵守...如果你触及多个索引,索引视图,持久计算列等等,那么你的行锁有多种原因可能没有任何水.您可能在事务中稍后会花费比您想象的更长的时间,也许您没有意识到事务中涉及的所有对象(不仅仅是当前正在运行的语句)的锁定可以保留交易的持续时间.