死锁:插入到文件表中的语句似乎互相阻塞

时间:2018-07-13 12:25:26

标签: c# database-deadlocks filetable

我们无法插入文件表。这是我们当前的星座,我将尝试尽可能详细地解释它:

基本上我们有三个表:

  • T_Document(文档的主要元数据)
  • T_Version(文档的版本化元数据)
  • T_Content(文档的二进制内容FileTable)

我们的WCF服务保存文档并被多人使用。该服务将打开一个事务,并调用保存文档的方法SaveDocument:

//This is the point where the tranaction starts
using (IDBTransaction tran = db.GetTransaction())
{
    try
    {
        m_commandFassade.SaveDocument(document, m_loginName, db, options, lastVersion);
        tran.Commit();
        return document;
    }
    catch
    {
        tran.Rollback();
        throw;
    }
}

SaveDocument方法如下:

public void SaveDocument(E2TDocument document, string login, IDBConnection db, DocumentUploadOptions options, int lastVersion)
{
    document.GuardNotNull();
    options.GuardNotNull();

    if (lastVersion == -1)
    {
        //inserting new T_Document
        SaveDocument(document, db);
    }
    else
    {
        //updating the existing T_Document
        UpdateDocument(document, db); //document already exists, updating it
    }

    Guid contentID = Guid.NewGuid();
    //inserting the content
    SaveDocumentContent(document, contentID, db); 
    //inserting the new / initial version
    SaveDocumentVersion(document, contentID, db); 
}

基本上,您看到的所有方法都是插入或更新这三个表。插入内容查询看起来像这样会造成一些麻烦:

 INSERT INTO T_Content
       (stream_id
       ,file_stream
       ,name)
 VALUES
       (#ContentID
       ,#Content
       ,#Title) 

和方法(请将此作为伪代码):

    private void SaveDocumentContent(E2TDocument e2TDokument, Guid contentID, IDBConnection db)
    {
        using (m_log.CreateScope<MethodScope>(GlobalDefinitions.TracePriorityForData))
        {
            Command cmd = CommandFactory.CreateCommand("InsertContents");
            cmd.SetParameter("ContentID", contentID);
            cmd.SetParameter("Content", e2TDokument.Content);
            string title = string.Concat(e2TDokument.Titel.RemoveIllegalPathCharacters(), GlobalDefinitions.UNTERSTRICH,
                contentID).TrimToMaxLength(MaxLength_T_Contents_Col_Name, SuffixLength_T_Contents_Col_Name);
            cmd.SetParameter("Title", title);
            db.Execute(cmd);
        }
    }

我没有死锁分析经验,但是死锁图显示了将内容插入文件表时,它似乎被另一个进程同时写入同一表的死锁情况。

Deadlock (另一边显示相同的语句,我的应用程序日志确认两次并发尝试保存文档)

同一死锁一天出现30次。我已经将交易减少到最低程度,删除了所有不必要的选择,但是我没有运气来解决这个问题。

我最好奇的是如何可能在文件表的插入中死锁。是否有我不知道的正在执行的内部事情。我在该表的探查器跟踪中看到了一些奇怪的语句,这些代码在代码的任何地方都没有使用,例如:

set @pathlocator = convert(hierachyid, @path_locator__bin)

以及类似的东西

if exists (
      select 1
             from [LGOL_Content01].[dbo].[T_Contents]
            where parent_path_locator = @path_locator
        )

如果您需要更多详细信息,请告诉我。任何进行操作的技巧都很棒。

编辑1:\

下面您将找到T_Content插入的执行计划:

insert_exec_plan

1 个答案:

答案 0 :(得分:0)

因此,经过数小时的时间和与Microsoft的研究和咨询,死锁实际上是与文件表/ sql服务器相关的错误,该错误将由Microsoft修复。