首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Server全文填充死锁

Server全文填充死锁
EN

Database Administration用户
提问于 2019-09-16 14:13:50
回答 1查看 2K关注 0票数 4

我已经在表(这里的细节)中的非持久化计算列上创建了一个全文索引。

然而,每隔几天,人口就会陷入僵局并停止活动。具体地说:

描述:在全文填充过程中发生致命错误,导致填充被取消.总体类型是: AUTO;数据库名为XYZ (id: 7);目录名为UsersCatalog (id: 8);表名用户(id: 863342140)。修正在全文爬行日志中记录的错误。然后,恢复人口。这方面的基本Transact-SQL语法是:对table_name简历填充进行修改全文索引。

僵局报告如下:

代码语言:javascript
复制
<deadlock>
 <victim-list>
  <victimProcess id="process28fdc561088" />
 </victim-list>
 <process-list>
  <process id="process28fdc561088" taskpriority="20" logused="0" waitresource="PAGE: 7:1:6079614 " waittime="1171" ownerId="2020759813" transactionname="IFTSAutoNested" 
           lasttranstarted="2019-09-16T00:16:49.027" XDES="0x28f61f40408" lockMode="S" schedulerid="8" kpid="8000" status="background" spid="35" sbid="0" ecid="0" priority="0" trancount="3">
   <executionStack>
    <frame procname="adhoc" line="1" stmtstart="60" stmtend="814" sqlhandle="0x020000008bfb2728b1fbd70b14e785d0a8727ca1f478b5690000000000000000000000000000000000000000">
unknown    </frame>
   </executionStack>
   <inputbuf>
   </inputbuf>
  </process>
  <process id="process2966e0368c8" taskpriority="20" logused="20752" waitresource="PAGE: 7:1:6079661 " waittime="1171" ownerId="2020759849" transactionname="IFTSEndOfBatch" 
           lasttranstarted="2019-09-16T00:16:49.047" XDES="0x29230f2e408" lockMode="IX" schedulerid="4" kpid="12296" status="background" spid="33" sbid="0" ecid="0" priority="0" trancount="0">
   <executionStack />
   <inputbuf>
   </inputbuf>
  </process>
 </process-list>
 <resource-list>
  <pagelock fileid="1" pageid="6079614" dbid="7" subresource="FULL" objectname="XYZ.sys.fulltext_index_docidstatus_863342140" id="lock2897baa0d00" mode="IX" associatedObjectId="72057606237061120">
   <owner-list>
    <owner id="process2966e0368c8" mode="IX" />
   </owner-list>
   <waiter-list>
    <waiter id="process28fdc561088" mode="S" requestType="wait" />
   </waiter-list>
  </pagelock>
  <pagelock fileid="1" pageid="6079661" dbid="7" subresource="FULL" objectname="XYZ.sys.fulltext_index_docidstatus_863342140" id="lock294a6477a00" mode="SIU" associatedObjectId="72057606237061120">
   <owner-list>
    <owner id="process28fdc561088" mode="S" />
   </owner-list>
   <waiter-list>
    <waiter id="process2966e0368c8" mode="IX" requestType="convert" />
   </waiter-list>
  </pagelock>
 </resource-list>
</deadlock>

在其他情况下,它是使用一个批量进程将数据从一个表复制到那个表的死锁。就像这样:

代码语言:javascript
复制
-- Select a batch
UPDATE  TOP (@BatchSize)
        [import].[TempTable]
SET     BatchStatusFlag = 1
OUTPUT  inserted.Id, inserted.ServerId  INTO @UpdatedIds (SourceId, TargetId)
WHERE   BatchStatusFlag = 0

-- Move/update info for that batch
UPDATE  u
SET     ...
FROM    dbo.Users u
INNER JOIN [import].[TempTable] s ON s.Id = u.Id
INNER JOIN @UpdatedIds ids ON ids.Id = u.Id

在这种情况下,第二个更新(更新dbo.Users的更新)是使用全文服务死锁的更新。

2个问题:

  • 为什么它是死锁/我如何避免它?
  • 当发生这种情况时,它是否重新尝试并重新索引这些更改?(即使延迟时间较长)

Server版本: Microsoft 2016 (RTM) (KB4019088) - 13.0.1742.0 (X64) 2017年7月5日23:41:17版权(c)微软公司标准版(64位)在Windows 2016数据中心6.3 (构建14393:) (Hypervisor)

EN

回答 1

Database Administration用户

回答已采纳

发布于 2019-09-16 17:24:36

让我们先回答问题2。正如您在第一条错误消息中所看到的,它告诉您发出一个:

ALTER FULLTEXT INDEX ON <table_name> RESUME POPULATION

如果重新索引自动启动,则不需要重新索引。

现在,关于第一个问题,让我们来研究一下。

全文索引生成需要确保在重建索引时不更新非持久化计算列中使用的字段的文本。否则,索引将被破坏。这可能是通过在构建持久化数据时对数据保持共享页锁,然后在更新索引时对数据保持独占锁来实现的。

另一方面,批量复制进程试图添加行,这将更新表中的页。由于进程是原子的(例如,将确保在释放隐式事务之前正确插入所有数据),该进程将检查要插入(可能是伪随机序列)数据的正确页,然后锁定页面以插入该数据,并在所有数据到位之前保持锁。这可能导致您正在经历的死锁。

对于大容量更新过程,在更新时,将执行联接,使用共享锁标识要更新的行,然后采取排他锁(行或页(视情况而定))来执行更新。同样,如果与FT索引重建检查的页面序列相比,行/页序列是伪随机的,则可以锁定一些页面以满足重建的需要,而另一些页面则可以通过更新所需的重建来锁定。

这怎么能修好呢?这是一个更困难的问题。如果在索引构建中(通过持久化字段)计算非持久化数据的开销(通过持久化字段),则不太可能发生这种情况,但这将扩大数据的使用范围。您还可以实现其他进程检查的某种形式的标志,在开始重建之前打开它,在重建完成后关闭它,这将等待这些进程直到重建完成。

也许还有其他可能的解决方案,但这些都是我此刻所能想到的。

票数 3
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/248874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档