flysun027

有思想的博客

导航

SQL SERVER 内存优化表踩坑记

Posted on 2022-02-14 16:18  flysun027  阅读(614)  评论(0编辑  收藏  举报

背景

因为生产应用需要刷新大量的状态数据到数据库中用于客户端的显示,于是新建了一张状态表,表内行数固定,状态更新到列内。刚开始运行时还行,更新都很及时,查询速度也不慢。于是就这样使用了有一个月的时间。直到生产反应交互变慢,有时会出现响应超时的情况。

于是想到SQL SERVER 有内存优化表功能,根据内存优化表设置方法设置好内存优化表之后,系统运行效率缺失有提升,数据更新时间缩短到原来的三分之一了。本以为万事大吉,啤酒炸鸡。

故障现象

  1. 一段时间之后数据库无法连接。
  2. 从 MS 查看数据库被置为恢复状态,并且一直处于恢复中。
  3. SQL SERVER 日志中出现。An XTP checkpoint operation encountered an error。(事后检查日志时发现的)随着时间的延续,出现越来越频繁。

紧急恢复办法

因为是生产系统必须尽快恢复,刚开始完全没有思路,只能硬着头皮上了。

此时数据库处于恢复状态,任何附加分离操作都无法进行。总结出了下面的操作步骤来恢复数据库。

  1. 首先准备好一个正常状态的数据库备份,恢复然后分离备用。
  2. 手动停止 SQL SERVER 服务。
  3. 找到备用数据库的 FILESTREAM 文件所在路径,把 filestream.hdr 覆盖到当前故障的数据库中。
  4. 启动 SQL SERVER 服务,并且立即把数据库设置为紧急模式。这里需要多试几次,不一定每次都成功,时机很重要。
  5. 修改 FILESTREAM 文件 自增为“无限制”。分离数据库。
  6. 重启服务器。再附加数据库就可以看到数据库恢复正常了。

原因调查

根据日志查找到下面是一些关于内存优化表的解释:
The Memory-Optimized table automatic checkpoint will be triggered when the database transaction log file becomes bigger than 1.5 GB since the last checkpoint, including the transaction log records for both the Memory-Optimized and disk-based tables. The Memory-Optimized tables checkpoint occurs periodically in order to advance the active part of the transaction log, allowing the tables to be recovered to the last successful checkpoint and applying the last active portion of the transaction log to complete the recovery process.
当数据库事务日志文件自上一个检查点(包括内存优化表和基于磁盘的表的事务日志记录)以来大于1.5 GB时,将触发内存优化表自动检查点。内存优化表检查点定期出现,以推进事务日志的活动部分,允许将表恢复到最后一个成功的检查点,并应用事务日志的最后一个活动部分来完成恢复过程。
There is a special case in SQL Server 2016 in which the checkpoint characteristics for Memory-Optimized tables differs, called the Large Checkpoint, that is enabled on large machines with 16 or more logical processors, 128GB or greater memory or the ones that is capable of greater than 200MB/sec I/O measured for the IO subsystem of that database. The automatic large checkpoint is triggered only when 12GB of the transaction log file is filled up since the last checkpoint. The purpose of the large checkpoints is to ensure that the checkpoint process would not be continually executing and would scale efficiently.
SQL Server 2016中存在一种特殊情况,即内存优化表的检查点特征不同,称为大型检查点,它在具有16个或更多逻辑处理器、128GB或更大内存的大型计算机上启用,或者在该数据库的IO子系统上测得的I/O大于200MB/秒的大型计算机上启用。仅当自上一个检查点以来事务日志文件的12GB空间已满时,才会触发自动大检查点。大型检查点的目的是确保检查点流程不会持续执行,并且可以有效扩展。

英文原文:https://www.sqlshack.com/sql-server-2016-memory-optimized-tables-checkpoint-operation/

中文翻译:https://blog.csdn.net/culuo4781/article/details/107626408

此外还发现了一个补丁 KB3206584,是解决Sql Server 2016 中使用的内存优化表中时,检查点文件过度增长。这个补丁和当前问题没有关系,补丁是解决错误在普通计算机上默认开启大检查点的设置失误。

 

网站找到的类似问题

https://social.msdn.microsoft.com/Forums/en-US/f9743bce-1968-42a7-bb9b-250a50f9fd67/inmemory-oltp-quotan-xtp-checkpoint-operation-encountered-an-errorquot-no-idea-why

 

关于当前问题非常有用的一篇文章,下面的博客中还有很多关于 sql server 的内容非常值得推荐:

其主要内容是说 绝对不能限制 MEMORY_OPTIMIZED_DATA 文件组的文件大小,必须让他自由扩展。

http://nedotter.com/archive/2018/07/dangerous-moves-setting-max-size-for-in-memory-oltp-containers/

 

总结

  1.     这种建立状态表更新状态的办法并不是特别好,一是更新频繁数据库响应不及时,二是数据库本质还是用来保存数据,像这样刷新会产生大量的更新日志,导致数据库日志文件暴增。
  2.     如果需要用到 MEMORY_OPTIMIZED_DATA 文件组,绝对不能限制 MEMORY_OPTIMIZED_DATA 文件组的文件大小,必须让他自由扩展。