SQL Server 死锁和数据页

标签 sql sql-server

  1. 如果表中的一行(没有主键)在对该行进行某些修改(更新查询)时被锁定,我假设首先在表上获取意向锁,然后在排他之​​前获取页在行上获取锁。

    现在假设其他一些线程希望同时对同一表中的一些其他行进行修改(更新查询),然后 SQL Server 抛出以下错误:

    Msg 1205, Level 13, State 45, Line 1
    Transaction (Process ID 65) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

    这个错误可能是同一个表的 other 行在第一个查询的同一数据页中锁定的数据中的原因吗?

  2. 我知道数据页还会选择我们不要求的其他数据。那么如果我们在一个表中有一个主键,那么数据页仍然会选择额外的数据还是只选择具有主键的那一行?

最佳答案

  1. might be the reason that the other row of the same table was amongst the data locked in the same data page of the first query?

没有。如果两个查询使用相同的粒度(例如行),那么它们将在高层(表(分区)、页面)获得兼容的意向锁,在低层(行)获得不同的锁。即使他们使用不兼容的粒度,也不会发生死锁。可能会发生阻塞,但不会出现死锁。

I know data page also selects additional data that we do not request for. So if we have a primary key in a table, then will Data Page still select additional data or only that row with the primary key?

这根本没有任何意义。您将逻辑(主键)与物理(数据页)混合在一起,数据页还选择了我们不要求的其他数据,这对我来说简直是不可能解析的。我只能推测你想说的是以下内容:

In a table organized as a heap (no clustered index) all scans have to inspect every row to test a predicate. This will result in lock conflicts.

当并发更新发生在堆(没有聚簇索引的表)上时,如果没有要考虑的非聚簇索引,则更新不会死锁。所有更新将以相同的顺序(堆物理分配顺序)扫描表,并且将以相同的顺序获取所有锁。更新可以阻塞,但不能死锁。

当并发更新发生在堆或组织为聚集索引的表上时,但存在非聚集索引,那么每次更新都可以使用一个(或多个)非聚集索引来定位更新的候选行。不使用相同谓词(即不同的 WHERE 子句)的更新可以以不同的顺序使用不同的 NC 索引。这些可能会死锁,因为获取锁的顺序会有所不同。

当并发更新发生在组织为聚集索引的表上时,可能会发生死锁,因为应用程序可以按照导致死锁的顺序显式请求更新(Tran 1 更新键 A,然后更新键 B,而 Tran 2 更新 key B,然后更新 A)。

发生死锁的方式有很多,但这些是 UPDATE 与 UPDATE 死锁发生的基本方式。

如果您想要有关死锁的答案,任何死锁,在 SQL Server 中 always start by capturing the deadlock graph .没有死锁信息,一切都是猜测。

附言。请不要将聚集组织表称为“主键”。主键是一个逻辑概念。

关于SQL Server 死锁和数据页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24767314/

相关文章:

c# - 更新数据库上的插入值不正确 - MVC

c# - SqlParameter 值还是 SqlValue?

mysql - SQL如何获取数据而不将其包含在group by中

sql - 枚举器的 SQL Select 优化

sql - 通过查询获取组中每条记录的MAX值

sql-server - 同时触发的 SSRS 报告订阅是否同时运行?

sql-server - SSIS 2008 - 获取变量中的当前日期

sql-server - MS SQL 2012 插入触发器 : Insert all rows from a table

mysql - 在多个 SQL 语句中使用 Count() 并使用 join 连接它们

c++ - SQL 字符串错误?没有这样的专栏