Тупик между двумя вставками в одной таблице - PullRequest
1 голос
/ 07 марта 2020

Мы только начали устранять тупики, возникающие в нашей системе. Мы проследили большую часть этого, за исключением наименее частого случая: тупик в той же таблице между 2 транзакциями INSERT.

Что может быть причиной тупиков? Информация у нас есть:

  • Это случалось нечасто: 3 случая за последний месяц; мы не можем принудительно вызвать взаимоблокировку в нашей среде разработки.
  • Таблица M_DocumentsOrder содержит 60 тыс. строк
  • Вместо «keylock» (что было обычным в наших других случаях взаимоблокировки), показывает xml » pagelock "вместо
  • Клиент использует EntityFramework для соединения с базой данных и проверки кода кажется простым .Add () затем .SaveChanges () что-то вроде:

    using (MyTransaction context = new MyTransaction())
    {
            ...set data
            context.DocumentsOfOrder.Add(document);
            context.SaveChanges();
    }
    

Вот тупик_ xml:

<deadlock>
  <victim-list>
    <victimProcess id="process27221b688c8" />
  </victim-list>
  <process-list>
    <process id="process27221b688c8" taskpriority="0" logused="2880" waitresource="PAGE: 11:1:6488424 " waittime="1935" ownerId="909010590" transactionname="user_transaction" lasttranstarted="2020-02-27T04:29:40.627" XDES="0x272e9308428" lockMode="U" schedulerid="5"
      kpid="12772" status="suspended" spid="226" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2020-02-27T04:29:40.633" lastbatchcompleted="2020-02-27T04:29:40.633" lastattention="1900-01-01T00:00:00.633" clientapp="EntityFramework" hostname="HOSTNAME"
      hostpid="17832" loginname="myuser" isolationlevel="read committed (2)" xactid="909010590" currentdb="11" currentdbname="MyDatabase" lockTimeout="4294967295" clientoption1="671219744" clientoption2="128056">
      <executionStack>
        <frame procname="d4aaa79f-2ccf-4ea7-a07b-944a4c5cf03d.dbo.tr_M_DocumentsOfOrder_U" queryhash="0xc7b676ceb02e8dc7" queryplanhash="0xc7b676ceb02e8dc7" line="8" stmtstart="394" stmtend="712" sqlhandle="0x03000b00bb81a769bb1a3500e6a9000000000000000000000000000000000000000000000000000000000000">
        UPDATE [M_DocumentsOfOrder] SET [MODIFIED]=GETUTCDATE() FROM Inserted WHERE [M_DocumentsOfOrder].ID = M_DocumentsOfOrder.I </frame>
        <frame procname="d4aaa79f-2ccf-4ea7-a07b-944a4c5cf03d.dbo.tr_M_DocumentsOfOrder_I" queryhash="0x7de7ba0aa490af07" queryplanhash="0x85bac9a23b352e1e" line="7" stmtstart="392" stmtend="720" sqlhandle="0x03000b00825db368ba1a3500e6a9000000000000000000000000000000000000000000000000000000000000">
        UPDATE [M_DocumentsOfOrder] SET CREATED=GETUTCDATE() ,MODIFIED=GETUTCDATE() FROM Inserted Where [M_DocumentsOfOrder].ID = Inserted.I </frame>
        <frame procname="unknown" queryhash="0x69216ae0d9369f18" queryplanhash="0x25afc3efc8bd6515" line="1" stmtstart="42" stmtend="342" sqlhandle="0x02000000e89c2d220cda0bca1e051913383a04bc14b1959e0000000000000000000000000000000000000000"> unknown </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"> unknown </frame>
      </executionStack>
      <inputbuf> (@0 bigint,@1 bigint)INSERT [dbo].[M_DocumentsOfOrder]([Document_ID], [Order_ID], [CREATED], [MODIFIED]) VALUES (@0, @1, NULL, NULL) SELECT [ID] FROM [dbo].[M_DocumentsOfOrder] WHERE @@ROWCOUNT &gt; 0 AND [ID] = scope_identity() </inputbuf>
    </process>
    <process id="process277b78904e8" taskpriority="0" logused="8305172" waitresource="PAGE: 11:1:8384387 " waittime="1121" ownerId="909010544" transactionname="user_transaction" lasttranstarted="2020-02-27T04:29:40.527" XDES="0x274dbf6c428" lockMode="U" schedulerid="2"
      kpid="20852" status="suspended" spid="133" sbid="2" ecid="0" priority="0" trancount="2" lastbatchstarted="2020-02-27T04:29:40.533" lastbatchcompleted="2020-02-27T04:29:40.533" lastattention="1900-01-01T00:00:00.533" clientapp="EntityFramework" hostname="HOSTNAME2"
      hostpid="16164" loginname="myuser" isolationlevel="read committed (2)" xactid="909010544" currentdb="11" currentdbname="MyDatabase" lockTimeout="4294967295" clientoption1="671219744" clientoption2="128056">
      <executionStack>
        <frame procname="d4aaa79f-2ccf-4ea7-a07b-944a4c5cf03d.dbo.tr_M_DocumentsOfOrder_U" queryhash="0xc7b676ceb02e8dc7" queryplanhash="0xc7b676ceb02e8dc7" line="8" stmtstart="394" stmtend="712" sqlhandle="0x03000b00bb81a769bb1a3500e6a9000000000000000000000000000000000000000000000000000000000000">
        UPDATE [M_DocumentsOfOrder] SET [MODIFIED]=GETUTCDATE() FROM Inserted WHERE [M_DocumentsOfOrder].ID = M_DocumentsOfOrder.I </frame>
        <frame procname="d4aaa79f-2ccf-4ea7-a07b-944a4c5cf03d.dbo.tr_M_DocumentsOfOrder_I" queryhash="0x7de7ba0aa490af07" queryplanhash="0x85bac9a23b352e1e" line="7" stmtstart="392" stmtend="720" sqlhandle="0x03000b00825db368ba1a3500e6a9000000000000000000000000000000000000000000000000000000000000">
        UPDATE [M_DocumentsOfOrder] SET CREATED=GETUTCDATE() ,MODIFIED=GETUTCDATE() FROM Inserted Where [M_DocumentsOfOrder].ID = Inserted.I </frame>
        <frame procname="unknown" queryhash="0x69216ae0d9369f18" queryplanhash="0x25afc3efc8bd6515" line="1" stmtstart="42" stmtend="342" sqlhandle="0x02000000e89c2d220cda0bca1e051913383a04bc14b1959e0000000000000000000000000000000000000000"> unknown </frame>
        <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"> unknown </frame>
      </executionStack>
      <inputbuf> (@0 bigint,@1 bigint)INSERT [dbo].[M_DocumentsOfOrder]([Document_ID], [Order_ID], [CREATED], [MODIFIED]) VALUES (@0, @1, NULL, NULL) SELECT [ID] FROM [dbo].[M_DocumentsOfOrder] WHERE @@ROWCOUNT &gt; 0 AND [ID] = scope_identity() </inputbuf>
    </process>
  </process-list>
  <resource-list>
    <pagelock fileid="1" pageid="6488424" dbid="11" subresource="FULL" objectname="d4aaa79f-2ccf-4ea7-a07b-944a4c5cf03d.dbo.M_DocumentsOfOrder" id="lock270620df700" mode="U" associatedObjectId="72059477776334848">
      <owner-list>
        <owner id="process277b78904e8" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process27221b688c8" mode="U" requestType="wait" />
      </waiter-list>
    </pagelock>
    <pagelock fileid="1" pageid="8384387" dbid="11" subresource="FULL" objectname="d4aaa79f-2ccf-4ea7-a07b-944a4c5cf03d.dbo.M_DocumentsOfOrder" id="lock274fde20700" mode="IX" associatedObjectId="72059477776334848">
      <owner-list>
        <owner id="process27221b688c8" mode="IX" />
      </owner-list>
      <waiter-list>
        <waiter id="process277b78904e8" mode="U" requestType="convert" />
      </waiter-list>
    </pagelock>
  </resource-list>
</deadlock>

Вот определение таблицы:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[M_DocumentsOfOrder](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [Document_ID] [bigint] NOT NULL,
    [Order_ID] [bigint] NOT NULL,
    [CREATED] [datetime] NULL,
    [MODIFIED] [datetime] NULL,
 CONSTRAINT [PK_M_DocumentsOfOrder] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[M_DocumentsOfOrder]  WITH CHECK ADD  CONSTRAINT [FK_M_DocumentsOfOrder_Order] FOREIGN KEY([Order_ID])
REFERENCES [dbo].[Order] ([ID])
GO

ALTER TABLE [dbo].[M_DocumentsOfOrder] CHECK CONSTRAINT [FK_M_DocumentsOfOrder_Order]
GO

ALTER TABLE [dbo].[M_DocumentsOfOrder]  WITH CHECK ADD  CONSTRAINT [FK_M_DocumentsOfOrder_Document] FOREIGN KEY([Document_ID])
REFERENCES [dbo].[Documents] ([ID])
GO

ALTER TABLE [dbo].[M_DocumentsOfOrder] CHECK CONSTRAINT [FK_M_DocumentsOfOrder_Document]
GO

CREATE NONCLUSTERED INDEX [nci_wi_M_DocumentsOfOrder_2D7DBB9CD2F5855142A5836868D3A952] ON [dbo].[M_DocumentsOfOrder]
(
    [Order_ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]
GO


CREATE TRIGGER [dbo].[tr_M_DocumentsOfOrder_I] ON [dbo].[M_DocumentsOfOrder] FOR INSERT AS 
BEGIN 
    IF CONTEXT_INFO() =  cast('disabled' as varbinary(128))
        RETURN;

    UPDATE [M_DocumentsOfOrder] 
        SET CREATED=GETUTCDATE()
        ,MODIFIED=GETUTCDATE()
         FROM Inserted Where [M_DocumentsOfOrder].ID = Inserted.ID
END
GO

ALTER TABLE [dbo].[M_DocumentsOfOrder] ENABLE TRIGGER [tr_M_DocumentsOfOrder_I]
GO

CREATE TRIGGER [dbo].[tr_M_DocumentsOfOrder_U] ON [dbo].[M_DocumentsOfOrder] AFTER UPDATE 
AS
BEGIN
    IF CONTEXT_INFO() =  cast('disabled' as varbinary(128))
    RETURN;

    UPDATE [M_DocumentsOfOrder] SET [MODIFIED]=GETUTCDATE()
    FROM Inserted WHERE [M_DocumentsOfOrder].ID = M_DocumentsOfOrder.ID
END
GO

ALTER TABLE [dbo].[M_DocumentsOfOrder] ENABLE TRIGGER [tr_M_DocumentsOfOrder_U]
GO
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...