每次事务日志已满时,数据库进入恢复模式

Die*_*roz 7 sql-server sql-server-2012 transaction-log recovery-model

我面临的情况有点难以解决。我需要帮助来了解正在发生的事情。

TL;DR:每次 SQL Server 中的事务日志已满时,它都需要关闭数据库以进入恢复模式并回滚有问题的事务吗?这总是由设计完成还是仅在发生不好的事情时才会发生?


场景:

我们大量使用的生产数据库之一,它运行多个 ETL 作业和长时间运行的表批处理,进入恢复模式并在一段时间内无法访问。这周发生了 3 次(这个服务器已经运行了大约 2 年,我们过去没有注意到这个问题)。

查看错误日志很清楚发生了什么:事务日志已满,数据库需要回滚事务,回滚失败,数据库关闭,并以恢复模式启动。

DBA 认为这是 SQL Server 的正常行为。也就是说,按照他的说法,每次事务日志满了,一个事务需要回滚,数据库就会因为日志空间不足而进入恢复模式。回滚后(根据他的说法只能在恢复模式下完成),数据库将再次可用。

我找不到此信息的参考。所以我强烈反对。如果有人让我相信我错了,我将不胜感激。

我的观点:

据我所知,DBMS 是用来管理/运行查询的。如果空间不足,查询将失败。就这么简单。我不是在谈论其他任何东西的性能,而只是在谈论可用性。

接受 DBMS在设计上需要关闭自身以回滚任何事务对我来说是没有意义的。根据我的理解,我是否正在运行大量查询或查询设计是否不当都无关紧要。错误的查询应该会失败,而生活仍在继续。不是吗?

我的猜测是其他原因导致它失败,我需要跟踪正在发生的事情。

我的理解是错误的还是这真的是 SQL Server 的设计方式?假设我没有错,我还能做些什么来追踪这个问题的来源?


一些附加信息

  • select @@version:Microsoft SQL Server 2012 (SP1) - 11.0.3156.0 (X64) 2015 年 5 月 4 日 18:48:09 版权所有 (c) Windows NT 6.2(内部版本 9200:)微软公司标准版(64 位)
  • 此数据库处于简单恢复模式。
  • 同一个实例中还有其他数据库。它们没有出现相同的问题,但它们也没有被大量使用。
  • 只有事务日志已满,磁盘未满。磁盘有足够的空间,但数据库的日志大小有限。
  • 我们监控这台服务器,CPU 负载正常,内存使用正常,磁盘使用 RAID-5,控制器没有崩溃或读取失败。资源使用有一些高峰,但并不少见。
  • 我知道可以改进查询以有效地使用日志。我也知道我可以增加事务日志空间。但这真的不是我的重点。
  • 最近聘请了一位 DBA 来管理这个数据库。所以最近更改了几个配置,用于调整目的。他让我知道所有的变化(比如禁用自动收缩、增加自动增长大小等)。我没有发现任何可能损害数据库的内容。

日志转储(按发生顺序,删除重复项)

[02:58:37am ~ 04:47:42pm, 12 times]错误:845。严重性:17。状态:1。等待页面的缓冲区锁存类型 3 时发生超时 (1:8728760)。数据库 ID 7. FlushCache:在 77540 毫秒内清理了 10460 个缓冲区,其中 6709 次写入(避免了 864 个新的脏缓冲区),数据库 7:0 平均吞吐量:1.05 MB/秒。I/O 饱和度:107。上下文切换 391 上一个未完成的目标:4800。avgWriteLatency 0 FlushCache:清理 95448 个 buf,在 85820 毫秒内进行了 37560 次写入(避免了 60465 个新的脏 buf),db 7:09 平均吞吐量:8 MB。I/O 饱和度:17026。上下文切换 20713 最后一个未完成的目标:446。avgWriteLatency 3。

[02:58:37am ~ 04:47:42pm, 13 times]等待缓冲区锁存器时发生超时 - 类型 3。bp 000000109B9E69C0。第 1 页:73430228。状态 0x10b。数据库 ID:7. 分配单元 ID:72057594304790528. 任务 0x00000008BC0850C8:1. 等待时间 300 秒。标志 0x100000001a。拥有任务 0x0000000827B38188。没有继续等待。

[02:58:37am ~ 04:47:42pm, 12 times]错误:5901。严重性:16。状态:1。属于数据库“XXXXXXXXXX”的一个或多个恢复单元未能生成检查点。这通常是由于缺乏系统资源(如磁盘或内存)或在某些情况下由于数据库损坏造成的。检查错误日志中以前的条目以获取有关此故障的更多详细信息。

[05:14:29pm ~ 05:14:53pm, 9 times] 错误:9002。严重性:17。状态:4。由于“ACTIVE_TRANSACTION”,数据库“XXXXXXXXXX”的事务日志已满。

[05:14:53pm, once]错误:3314。严重性:21。状态:3。由于例程“XdesRMReadWrite::RollbackToLsn”中的错误 3314,数据库 XXXXXXXXXX 已关闭。在与数据库的所有连接都中止后,将尝试重新启动非快照数据库。

[05:14:53pm ~ 05:14:53pm, 16 times]错误:3314。严重性:21。状态:3。在撤销数据库“XXXXXXXXXX”中记录的操作期间,日志记录 ID (8064074:20971:110) 发生错误。通常,特定故障之前在 Windows 事件日志服务中记录为错误。从备份还原数据库或文件或修复数据库。

[05:14:53pm ~ 05:14:53pm, 9 times]错误:9001。严重性:21。状态:5。数据库“XXXXXXXXXX”的日志不可用。检查事件日志以获取相关错误消息。解决所有错误并重新启动数据库。

[05:14:58, once] 正在启动数据库“XXXXXXXXXX”。

[05:15:02, once]数据库 'XXXXXXXXXX' (7) 的恢复已完成 0%(剩余大约 2931 秒)。第 1 阶段(共 3 个)。这只是一条信息性消息。无需用户操作。

...

[05:51:01pm, once]6 个事务在数据库 'XXXXXXXXXX' (7:0) 中回滚。这只是一条信息性消息。无需用户操作。

[05:51:01pm, once]恢复正在数据库 'XXXXXXXXXX' (7) 中写入检查点。这只是一条信息性消息。无需用户操作。

[05:56:47pm, once]数据库 XXXXXXXXXX(数据库 ID 7)的恢复在 2505 秒内完成(分析 1774 毫秒重做 406623 毫秒撤消 1749182 毫秒。)这只是一条信息性消息。无需用户操作。

我在错误日志或事件查看器中没有发现其他相关的日志条目。事件查看器中发生的最接近的错误是:

[04:56:45pm ~ 05:27:24pm, 13 times]特定于应用程序的权限设置不会向具有 CLSID {FDC3723D-1588-4BA3-92D4-42C430735D7D} 和 APPID {83B33982-693D-4824-B42E-7196AE61BB05} 的 COM 服务器应用程序授予本地激活权限。 Personal.user SID (S-1-5-21-000000000-000000000-0000000000-00000) 来自地址 LocalHost (Using LRPC) 在应用程序容器中运行的 Unavailable SID (Unavailable)。可以使用组件服务管理工具修改此安全权限。

此错误发生在数据库开始恢复过程前约 18 分钟,并且有时在恢复开始期间重复发生。和DBA用户有点关系,但我真的不知道是什么(我还没有时间问DBA)。

Sql*_*ide 3

首先,很少有家政规则。

  • 您(或您的 DBA)应该根据您的恢复模型来管理事务日志空间。
  • 不要让事务日志变满并影响数据库/应用程序的可用性。

以下两个链接可以帮助您更好地管理事务日志文件。

当事务日志文件已满且无法进一步增长时,您遇到的情况不是正常行为。

当事务日志已满时,SQL Server 数据库引擎将发出 9002 错误。当数据库联机或恢复时,日志可能会填满。如果数据库处于联机状态时日志已满,则数据库仍保持联机状态,但只能读取而不能更新。如果恢复期间日志已满,数据库引擎会将数据库标记为“RESOURCE PENDING”。无论哪种情况,都需要用户操作以使日志空间可用。

对完整事务日志的适当响应部分取决于导致日志填满的条件。要发现在给定情况下阻止日志截断的原因,请使用 sys.database 目录视图的 log_reuse_wait 和 log_reuse_wait_desc 列。

您看到的是事务回滚失败。有关更多详细信息,请阅读这篇文章。

根据 Paul Randal 的博客文章,您遇到了一个错误,该错误已在 SQL 2012 SP4 中修复。

有关错误 3314 的更多详细信息:

参考: