我有两个长时间运行的查询,它们都在事务上并访问同一个表,但这些表中的行完全独立。这些查询还根据这些查询执行一些更新和插入。
看来,当这些并发运行时,它们会遇到某种类型的锁,并且会阻止任务完成并在更新其中一行时锁定。我在正在读取的行上使用独占行锁,并且进程上显示的锁是 lck_m_ix 锁。
两个问题:
- 当我更新/插入一行时,它会锁定整个表吗?
- 可以采取哪些措施来解决此类问题?
最佳答案
通常不会,但这取决于(SQL Server 最常用的答案!)
SQL Server 必须以某种方式锁定事务中涉及的数据。当您执行修改时,它必须锁定表本身中的数据以及任何受影响的索引中的数据。为了提高并发性,服务器可能决定使用几种锁定“粒度”,以允许多个进程运行:行锁、页锁和表锁很常见(还有更多)。锁定的范围取决于服务器决定如何执行给定的更新。让事情变得复杂的是,还有共享锁、独占锁和意向独占锁等分类,它们控制锁定的对象是否可以读取和/或修改。
根据我的经验,SQL Server 主要使用页锁来更改表的一小部分,并且如果表的较大部分(根据统计数据)似乎受到影响,超过某个阈值将自动升级为表锁更新或删除。这个想法是,锁定一个表(一个锁)比获取和管理数千个单独的行或页锁以进行大更新更快。
要了解特定情况下发生的情况,您需要查看查询逻辑,并在运行时检查 sys.dm_tran_locks、sys.dm_os_waiting_tasks 或其他 DMV 中的锁定/阻塞条件。您可能希望发现每个进程中的哪一步到底锁定了什么,以发现为什么一个进程会阻塞另一个进程。
关于sql-server - 当我更新/插入一行时,它是否应该锁定整个表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2248011/