Sql server 有没有跨多个线程使用SqlBulkCopy的安全方法

Sql server 有没有跨多个线程使用SqlBulkCopy的安全方法,sql-server,thread-safety,sqlbulkcopy,Sql Server,Thread Safety,Sqlbulkcopy,我们在批处理作业上引入了SqlBulkCopy,该批处理作业跨多个线程执行,但现在会出现间歇性死锁。我们没有使用表锁选项。正在插入的表具有聚集索引 每个线程都插入一个唯一的PortfolioSnapshotId(带有一批AssetID) 在这种情况下,有什么方法可以安全地使用SqlBulkCopy吗 XML格式如下: <event name="xml_deadlock_report" package="sqlserver" timestamp="2017-12-06T02:38:31.38

我们在批处理作业上引入了SqlBulkCopy,该批处理作业跨多个线程执行,但现在会出现间歇性死锁。我们没有使用表锁选项。正在插入的表具有聚集索引

每个线程都插入一个唯一的PortfolioSnapshotId(带有一批AssetID)

在这种情况下,有什么方法可以安全地使用SqlBulkCopy吗

XML格式如下:

<event name="xml_deadlock_report" package="sqlserver" timestamp="2017-12-06T02:38:31.382Z">
  <data name="xml_report">
    <type name="xml" package="package0" />
    <value>
      <deadlock>
        <victim-list>
          <victimProcess id="process248e1c96108" />
        </victim-list>
        <process-list>
          <process id="process248e1c96108" taskpriority="0" logused="63904" waitresource="PAGE: 14:1:289932632 " waittime="4523" ownerId="2409980792" transactionname="user_transaction" lasttranstarted="2017-12-06T02:38:26.657" XDES="0x2453d39ce58" lockMode="IX" schedulerid="14" kpid="24604" status="suspended" spid="151" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-12-06T02:38:26.657" lastbatchcompleted="2017-12-06T02:38:26.657" lastattention="2017-12-06T02:38:23.760" clientapp="XXXX" hostname="XXXX" hostpid="137000" loginname="XXXX" isolationlevel="read committed (2)" xactid="2409980792" currentdb="14" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
            <executionStack>
              <frame procname="adhoc" line="1" stmtend="1206" sqlhandle="0x020000000f2bea1e535f1cbf04ef8318984df8965399be020000000000000000000000000000000000000000">
unknown    </frame>
            </executionStack>
            <inputbuf>
insert bulk TableName ([AssetId] NVarChar(255) COLLATE Latin1_General_CI_AS, [ParentAssetId] NVarChar(255) COLLATE Latin1_General_CI_AS, [PortfolioSnapshotId] UniqueIdentifier, [Quantity] Decimal(28,8), [CompressedProperties] VarBinary(max)) with (CHECK_CONSTRAINTS)   </inputbuf>
          </process>
          <process id="process248e1c8cca8" taskpriority="0" logused="67244" waitresource="PAGE: 14:1:289933280 " waittime="4523" ownerId="2409980337" transactionname="user_transaction" lasttranstarted="2017-12-06T02:38:26.220" XDES="0x25e82396e58" lockMode="IX" schedulerid="2" kpid="33292" status="suspended" spid="158" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-12-06T02:38:26.220" lastbatchcompleted="2017-12-06T02:38:26.220" lastattention="2017-12-06T02:38:24.507" clientapp="XXXX" hostname="XXXX" hostpid="137000" loginname="XXXX" isolationlevel="read committed (2)" xactid="2409980337" currentdb="14" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
            <executionStack>
              <frame procname="adhoc" line="1" stmtend="1206" sqlhandle="0x020000000f2bea1e535f1cbf04ef8318984df8965399be020000000000000000000000000000000000000000">
unknown    </frame>
            </executionStack>
            <inputbuf>
insert bulk TableName ([AssetId] NVarChar(255) COLLATE Latin1_General_CI_AS, [ParentAssetId] NVarChar(255) COLLATE Latin1_General_CI_AS, [PortfolioSnapshotId] UniqueIdentifier, [Quantity] Decimal(28,8), [CompressedProperties] VarBinary(max)) with (CHECK_CONSTRAINTS)   </inputbuf>
          </process>
        </process-list>
        <resource-list>
          <pagelock fileid="1" pageid="289932632" dbid="14" subresource="FULL" objectname="XXXX.dbo.TableName" id="lock247f3004d00" mode="X" associatedObjectId="72057594048872448">
            <owner-list>
              <owner id="process248e1c8cca8" mode="X" />
            </owner-list>
            <waiter-list>
              <waiter id="process248e1c96108" mode="IX" requestType="wait" />
            </waiter-list>
          </pagelock>
          <pagelock fileid="1" pageid="289933280" dbid="14" subresource="FULL" objectname="XXXX.dbo.TableName" id="lock247f4f97c80" mode="X" associatedObjectId="72057594045661184">
            <owner-list>
              <owner id="process248e1c96108" mode="X" />
            </owner-list>
            <waiter-list>
              <waiter id="process248e1c8cca8" mode="IX" requestType="wait" />
            </waiter-list>
          </pagelock>
        </resource-list>
      </deadlock>
    </value>
  </data>
</event>

出现死锁是因为存在NC索引(同一对象名的两个不同对象Id上的页面锁IX->X)。考虑到聚集索引位于同一个键上,并且更具选择性,我不认为使用NC索引的原因。我将删除该NC索引。

由于存在NC索引(同一对象名的两个不同对象Id上的页面锁IX->X),因此会发生死锁。考虑到聚集索引位于同一个键上,并且更具选择性,我不认为使用NC索引的原因。我将删除该NC索引。

添加死锁信息(XML,不是它的图片),以及所有相关的表结构,包括每个索引。@RemusRusanu done:)添加死锁信息(XML,不是它的图片),以及所有相关的表结构,包括所有索引。@RemusRusanu done:)NC索引之所以存在,是因为它排除了CompressedProperties列,而CompressedProperties列在其他方面非常大,因此在对这些列进行筛选时需要扫描的数据更少。我们已经考虑将这些数据提取到一个单独的表中。不确定这里是否还有其他选择?我不完全清楚为什么索引本身会导致死锁?你能澄清一下吗?非常感谢!使用NC索引是因为它不包括CompressedProperties列,否则该列非常大,因此在对这些列进行筛选时要扫描的数据较少。我们已经考虑将这些数据提取到一个单独的表中。不确定这里是否还有其他选择?我不完全清楚为什么索引本身会导致死锁?你能澄清一下吗?非常感谢!使用
CREATE TABLE [dbo].[TableName](
  [AssetId] [nvarchar](255) NOT NULL,
  [ParentAssetId] [nvarchar](255) NULL,
  [PortfolioSnapshotId] [uniqueidentifier] NOT NULL,
  [Quantity] [decimal](28, 8) NULL,
  [CompressedProperties] [varbinary](max) NULL
 CONSTRAINT [PK_TableName] PRIMARY KEY CLUSTERED 
(
  [PortfolioSnapshotId] ASC,
  [AssetId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[TableName]  WITH CHECK ADD  CONSTRAINT [FK_TableName_PortfolioSnapshot] FOREIGN KEY([PortfolioSnapshotId])
REFERENCES [dbo].[PortfolioStore_PortfolioSnapshot] ([Id])

CREATE NONCLUSTERED INDEX [IX_TableName_PortfolioSnapshotId] ON [dbo].[TableName]
(
  [PortfolioSnapshotId] ASC
)
INCLUDE (   [AssetId],
  [ParentAssetId],
  [Quantity],
  [Price]) 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