简体   繁体   English

SQL Server,插入一行锁定整个表

[英]SQL Server, insert one row locks whole table

We have an issue with some deadlock and I posted this question . 我们遇到了一些死锁的问题,我发布了这个问题

With some help and a lot of searching myself I believe I figured out what is going on. 通过一些帮助和大量搜索自己,我相信我弄清楚发生了什么。 In order to solve the deadlocks without controlling lock escalation I need to understand why sql server locks the whole table on inserting one row. 为了在不控制锁升级的情况下解决死锁,我需要理解为什么sql server在插入一行时锁定整个表。

Here is my insert statement (with renamed variables): 这是我的insert语句(带有重命名的变量):

DECLARE 
    @Type1 INT = 11,
    @Type2 INT = NULL,
    @Value1 VARCHAR(20) = '0',
    @Value2 VARCHAR(20) = '0',
    @Value3 VARCHAR(20) = '0',
    @Value4 VARCHAR(20) = '0',
    @Date1 DATETIME = '2011-11-25',
    @Date2 DATETIME = '2011-11-25',
    @Value5 NVARCHAR(50) = '',
    @Value6 NVARCHAR(50) = '',
    @Type3 INT = NULL,
    @Value7 VARCHAR(20) = '4',
    @Type4 INT = 4,
    @Type5 INT = 15153,
    @Type6 INT = 3,
    @Type7 INT = 31,
    @Type8 INT = 5976,
    @Type9 INT = 5044,
    @Guid1 UNIQUEIDENTIFIER = 'a8293471-3hb4-442b-844f-44t92f17n67s',
    @Value8 VARCHAR(200) = '02jfgg55savolhffr1mkjf45',
    @value10 INT = 1,
    @Option2 BIT = 0,
    @Value9 VARCHAR(20) = null,
    @Option1 BIT = 0

insert into dbo.OurTable
(
    Type1
    ,Type2
    ,Value1
    ,Value2
    ,Value3
    ,Value4
    ,Date1
    ,Date2
    ,Value5
    ,Value6
    ,Type3
    ,Value7
    ,Type4
    ,Type5
    ,Type6
    ,Type7
    ,Type8
    ,Type9
    ,value10
    ,Col1
    ,Col2
    ,Col3
    ,Col4
    ,Value8
    ,Option2
    ,Value9
)
values
(
    CASE
        WHEN [dbo].[GetType](@Type1, null) = 6 AND @Option1 = 1 AND [dbo].[GetType](@Type4, 0) <> 1
        THEN 7
        ELSE [dbo].[GetType](@Type1, null)
    END
    ,[dbo].[GetType](@Type2, null)
    ,case when @Value1 = 'null' then null else CAST(@Value1 as numeric(18, 6)) end
    ,case when @Value2 = 'null' then null else CAST(@Value2 as numeric(18, 6)) end
    ,case when @Value3 = 'null' then null else CAST(@Value3 as numeric(18, 6)) end
    ,case when @Value4 = 'null' then null else CAST(@Value4 as numeric(18, 6)) end
    ,[dbo].[GetDate](@Date1, null)
    ,[dbo].[GetDate](@Date2, null)
    ,@Value5
    ,@Value6
    ,[dbo].[GetType](@Type3, null)
    ,case when @Value7 = 'null' then null else CAST(@Value7 as numeric(18, 6)) end
    ,[dbo].[GetType](@Type4, null)
    ,@Type6
    ,case when LOWER(@Type7) = 'null' then null else @Type7 end
    ,@Type5
    ,@Type9
    ,@Type8
    ,@value10
    ,GETDATE()
    ,GETDATE()
    ,[dbo].[GetGuid](@Guid1)
    ,[dbo].[GetGuid](@Guid1)
    ,@Value8
    ,@Option2
    ,case when @Value9 = 'null' then null else CAST(@Value9 as int) end
)

If I run this statement in a transaction and then query sys.dm_tran_locks before committing I get 10233 rows belonging to that session. 如果我在事务中运行此语句,然后在提交之前查询sys.dm_tran_locks,那么我将获得属于该会话的10233行。

SELECT *
FROM sys.dm_tran_locks l
WHERE l.resource_type <> 'DATABASE' AND l.request_session_id = 65

65 is the session id of my current window when testing. 65是测试时当前窗口的会话ID。

Also if I look at table locking (which is the cause of my deadlock) I can see that it puts a X lock on the table OurTable. 另外,如果我查看表锁定(这是我的死锁的原因),我可以看到它在表OurTable上放了一个X锁。

resource_type   resource_associated_entity_id   Name    resource_lock_partition request_mode    request_type    request_status
OBJECT  290100074   OurTable    0   X   LOCK    GRANT
OBJECT  290100074   OurTable    1   X   LOCK    GRANT
OBJECT  290100074   OurTable    2   X   LOCK    GRANT
OBJECT  290100074   OurTable    3   X   LOCK    GRANT
OBJECT  290100074   OurTable    4   X   LOCK    GRANT
OBJECT  290100074   OurTable    5   X   LOCK    GRANT
OBJECT  290100074   OurTable    6   X   LOCK    GRANT
OBJECT  290100074   OurTable    7   X   LOCK    GRANT
OBJECT  290100074   OurTable    8   X   LOCK    GRANT
OBJECT  290100074   OurTable    9   X   LOCK    GRANT
OBJECT  290100074   OurTable    10  X   LOCK    GRANT
OBJECT  290100074   OurTable    11  X   LOCK    GRANT
OBJECT  290100074   OurTable    12  X   LOCK    GRANT
OBJECT  290100074   OurTable    13  X   LOCK    GRANT
OBJECT  290100074   OurTable    14  X   LOCK    GRANT
OBJECT  290100074   OurTable    15  X   LOCK    GRANT

I don't know if this is done due to lock escalation or if it requests an exclusive lock on the table from start. 我不知道是否由于锁升级或者从开始请求表上的独占锁来完成此操作。 Anyhow this causes me trouble with deadlocks. 无论如何这会导致我遇到麻烦。

The reason there are 16 lock rows on a single table is because of lock partitioning. 单个表上有16个锁定行的原因是锁定分区。

My question is, why doesn't it request an intent exclusive lock (IX) on the table? 我的问题是,为什么不在桌面上请求一个意图独占锁(IX)? Instead it requests an exclusive lock. 相反,它要求独占锁。 How do I prevent this? 我该如何防止这种情况? I get no tuning tips in the tuning advisor, I have already tried that. 我在调优顾问中没有任何调整技巧,我已经尝试过了。

EDIT There is a insert trigger on OurTable which updates a field on OurTable3. 编辑 OurTable上有一个插入触发器,用于更新OurTable3上的字段。 It looks like this: 它看起来像这样:

UPDATE OurTable3 SET Date1 = NULL
    FROM OurTable3 as E 
        JOIN OurTable2 as C on E.Id = C.FKId
        JOIN OurTable as ETC on ETC.FKId = C.Id
            AND (ETC.Date2 IS NULL OR CAST(ETC.Date2 AS DATE) > E.Date1) 
            AND ETC.Type1 = 1

As you can see it doesn't update OurTable but query OurTable in order to update the correct row in OurTable3. 正如您所看到的,它不会更新OurTable,而是查询OurTable以更新OurTable3中的正确行。

I found the answer. 我找到了答案。 A little blunder from a developer in our team (I always blame everybody else :-). 我们团队中的开发人员犯了一个小错误(我总是责怪其他人:-)。 I probably should have known the answer already because again, Martin Smith pointed out in the other question that I should check ALLOW_ROW_LOCKS and ALLOW_PAGE_LOCKS. 我可能应该已经知道了答案,因为Martin Smith在另一个问题中指出我应该检查ALLOW_ROW_LOCKS和ALLOW_PAGE_LOCKS。 But at that time we thought that partitionid related to an index id and I only checked that index. 但那时我们认为partitionid与索引id相关,我只检查了那个索引。

What I did was creating a new table with the same data. 我所做的是创建一个具有相同数据的新表。 The effect was gone and I only had the correct IX lock on the new table. 效果消失了,我只在新表上有正确的IX锁。 Then I created every index and tested between every creation until I suddenly had the effect again. 然后我创建了每个索引并在每个创建之间进行测试,直到我突然再次产生效果。

I found this index on OurTable: 我在OurTable上找到了这个索引:

CREATE NONCLUSTERED INDEX [IX_OurTable] ON [dbo].[OurTable] 
(
    [Col1] ASC,
    [Col2] ASC,
    [Col3] ASC,
    [Col4] ASC,
    [Col5] ASC
)
INCLUDE ( [Col6],
[Col7],
[Col8],
[Col9]) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = OFF, ALLOW_PAGE_LOCKS  = OFF, FILLFACTOR = 90) ON [PRIMARY]
GO

With ALLOW_ROW_LOCKS = OFF and ALLOW_PAGE_LOCKS = OFF it's obvious we would have this effect on the insert and also the selects. 使用ALLOW_ROW_LOCKS = OFF和ALLOW_PAGE_LOCKS = OFF时,很明显我们会对插入和选择产生这种影响。

Thank you for your comments and many thanks to Martin who really helped me to solve these deadlock problems. 感谢您的评论,非常感谢Martin真正帮助我解决这些死锁问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在SQL Server上插入/更新表锁 - Insert/Update Table Locks on SQL Server SQL Server VARBINARY INSERT锁定表超过30分钟 - SQL Server VARBINARY INSERT Locks Table for 30+ Minutes SQL Server触发器锁定表 - SQL Server trigger locks table SQL Server:如果在一个表中插入一行,我如何编写触发器以在不同的表中插入同一行? - SQL Server: If a row is inserted in one table, how do I write a trigger to insert that same row in a different table? SQL-SERVER 程序如何在一个表中插入行,然后将行插入到另一个表中作为外键链接到另一个表 - SQL-SERVER Procedure How do i insert row one table then insert row into another table link to another table as foreign key 如何在SQL Server 2012中将数据从另一个表的多个表行插入一个表行? - How to insert data into one table row from multiple table rows in another table in SQL Server 2012? SQL Server事务:插入会导致锁定? - SQL Server transactions: insert causes locks? SQL Server在表中间插入行的方法 - SQL Server way to insert row in middle of the table SQL Server 2008 - 批量将整个文本文件插入到一个字段中 - SQL Server 2008 - Bulk Insert a whole text file into one field 在Microsoft SQL Server Management Studio中插入整个表 - Insert whole table in Microsoft SQL Server Management Studio
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM