死锁:插入一个文件表语句似乎互相阻塞
Deadlock: Insert into a filetable statements appears to block one another
我们无法插入文件table。这是我们现在的星座,我尽量详细的解释一下:
基本上我们有三个table:
- 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);
}
基本上您看到的所有方法都是插入或更新这三个 table。插入内容查询,看起来像这样制造一些麻烦:
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);
}
}
我没有死锁分析的经验,但是死锁图告诉我,当将内容插入到文件中时table,它似乎被另一个进程也写入同一个 [=62] =] 同时.
(另一面显示相同的语句,我的应用程序日志确认两次并发尝试保存文档)
同样的死锁一天出现30次。我已经将交易缩减到最低限度,删除了所有不必要的选择,但我没有运气解决这个问题。
我最好奇的是它如何可能在插入文件时发生死锁table。是否有我不知道的内部正在执行的事情。我在 table 的探查器跟踪中看到了一些奇怪的语句,我们没有在代码中的任何地方使用它们,例如:
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 插入的执行计划:
所以,经过数小时的研究和咨询微软,死锁实际上是一个与文件表/sql服务器相关的错误,微软将修复它。
我们无法插入文件table。这是我们现在的星座,我尽量详细的解释一下:
基本上我们有三个table:
- 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);
}
基本上您看到的所有方法都是插入或更新这三个 table。插入内容查询,看起来像这样制造一些麻烦:
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);
}
}
我没有死锁分析的经验,但是死锁图告诉我,当将内容插入到文件中时table,它似乎被另一个进程也写入同一个 [=62] =] 同时.
同样的死锁一天出现30次。我已经将交易缩减到最低限度,删除了所有不必要的选择,但我没有运气解决这个问题。
我最好奇的是它如何可能在插入文件时发生死锁table。是否有我不知道的内部正在执行的事情。我在 table 的探查器跟踪中看到了一些奇怪的语句,我们没有在代码中的任何地方使用它们,例如:
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 插入的执行计划:
所以,经过数小时的研究和咨询微软,死锁实际上是一个与文件表/sql服务器相关的错误,微软将修复它。