use*_*567 1 sql-server sql-server-2014
我们有一张桌子,
CREATE TABLE [dbo].[MyTable](
[MasterKey] [uniqueidentifier] NOT NULL,
[DetailKey] [varchar](100) NULL,
[JSON] [nvarchar](max) NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [ix_MyTable_details] ON [dbo].[MyTable]
(
[MasterKey] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
我们有以下查询导致太多死锁/块。
IF EXISTS(SELECT 1 from [MyTable](nolock) where [MasterKey]= @MasterKey AND [DetailKey] = @DetailKey)
BEGIN
UPDATE [MyTable]
SET [JSON] = @JSON
WHERE [MasterKey]= @MasterKey AND [DetailKey] = @DetailKey
END
ELSE
BEGIN
INSERT INTO [MyTable]
([MasterKey]
,[DetailKey]
,[JSON])
VALUES
(@MasterKey
,@DetailKey
,@JSON)
END
Run Code Online (Sandbox Code Playgroud)
请注意,不同的用户同时使用 MasterKey 密钥,但在窥视时间我们看到应用程序变得无响应。当我们看到日志时,我们发现了很多块/死锁。我们还可以在此表中看到 Sch-S 锁。
添加 MasterKey 和 DetailKey 作为主键可以解决这个问题还是我们能做什么?
请注意,有时 JSON 大小很大,因为它包含 base64 格式的图像。
通常,您应该始终更改此方法:
IF EXISTS ( /* scan the table with a where clause */ )
UPDATE ( /* scan the table AGAIN with a where clause */ )
ELSE
INSERT
Run Code Online (Sandbox Code Playgroud)
对此:
UPDATE ( /* scan the table JUST ONCE with a where clause */ )
IF @@ROWCOUNT = 0
INSERT
Run Code Online (Sandbox Code Playgroud)
忘记你曾经学过第一种方法。这就像去杂货店检查他们是否有鸡蛋,然后回家拿钱包,然后再回到杂货店买鸡蛋。
此外,是的,聚集索引在许多情况下都可以提供帮助。是MasterKey
真正的关键(例如是不是唯一的)?或者是MasterKey
+DetailKey
候选键的组合?在后一种情况下,以两列作为键列的索引(是否聚集)将有助于减少查询在找到具有该MasterKey
值的行(这会延长阻塞并可能导致死锁取决于其他因素)。
实际用例。首先,更改索引:
DROP INDEX [ix_MyTable_details] ON [dbo].[MyTable];
CREATE UNIQUE CLUSTERED INDEX cix_MyTable_details
ON dbo.MyTable(MasterKey, DetailKey);
Run Code Online (Sandbox Code Playgroud)
然后将查询更改为:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE dbo.[MyTable]
SET [JSON] = @JSON
WHERE MasterKey = @MasterKey AND DetailKey = @DetailKey;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.[MyTable]
([MasterKey]
,[DetailKey]
,[JSON])
VALUES
(@MasterKey
,@DetailKey
,@JSON);
END
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
80 次 |
最近记录: |