为 BACKUP 命令设置 BUFFERCOUNT、BLOCKSIZE 和 MAXTRANSFERSIZE

Sol*_*zky 37 sql-server backup best-practices maintenance

我找了实际指导的设定值BUFFERCOUNTBLOCKSIZE以及MAXTRANSFERSIZE该的BACKUP命令。我做了一些研究(见下文),我做了一些测试,我完全意识到任何真正有价值的答案都会以“好吧,这取决于……”开头。我对我所做的测试以及我发现的任何资源中显示的测试(见下文)的担忧是,测试是在真空中完成的,很可能是在没有其他负载的系统上完成的。

我很好奇关于这三个基于长期经验的选项的正确指导/最佳实践:数周或数月内的许多数据点。而且我不是在寻找特定值,因为这主要是可用硬件的功能,但我想知道:

  • 各种硬件/负载因素如何影响应该做什么。
  • 是否存在不应覆盖这些值中的任何一个的情况?
  • 是否存在覆盖任何不明显的陷阱?使用了太多内存和/或磁盘 I/O?恢复操作复杂吗?
  • 如果我有一台运行多个 SQL Server 实例的服务器(一个默认实例和两个命名实例),并且如果我同时运行所有 3 个实例的备份,这是否会影响我设置这些值的方式,而不是确保集体(BUFFERCOUNT* MAXTRANSFERSIZE) 不超过可用 RAM?可能的 I/O 争用?
  • 在同一台服务器上拥有三个实例并再次同时运行所有三个实例的备份的相同场景中,在每个实例中同时运行多个数据库的备份如何影响这些值的设置?这意味着,如果三个实例中的每一个都有 100 个数据库,则每个实例同时运行 2 或 3 个备份,这样就有 6 到 9 个备份同时运行。(在这种情况下,我有许多中小型数据库,而不是一些大型数据库。)

到目前为止我收集到的:

  • BLOCKSIZE

    • 支持的大小为 512、1024、2048、4096、8192、16384、32768 和 65536 (64 KB) 字节。[1]
    • 磁带设备的默认值为 65536,否则为 512 [1]
    • 如果您要进行备份并计划从 CD-ROM 复制和恢复,请指定 BLOCKSIZE=2048 [1]
    • 写入单个磁盘时,默认512就可以了;如果使用RAID阵列或SAN,则必须测试以查看默认或65536是否更好。[13(第 18 页)]
    • 如果手动设置,该值需要 >= 用于创建数据文件的块大小,否则您将收到以下错误:

      消息 3272,级别 16,状态 0,第 3 行
      “C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Backup\BackupTest.bak”设备的硬件扇区大小为 4096,但块大小参数指定不兼容的覆盖值 512。使用兼容的块大小重新发出语句。

  • BUFFERCOUNT

    • 默认[2], [8] :

      SQL Server 2005 及更高版本:
      (NumberofBackupDevices * [mystery_multiplier]) + NumberofBackupDevices + (2 * NumberofVolumesInvolved)

    • [mystery_multiplier]:关于这个值有一些不一致。我已经看到它以 3 种形式表达:

      • 3 [2]
      • GetSuggestedIoDepth [8]
      • GetSuggestedIoDepth + 1 [8]


      显示乘数的测试3是在 SQL Server 2005 SP2 [9] 上完成的

      我在 SQL Server 2008 R2 和 2012 上的测试以及关于 SQL Server 2014 [8]的用户评论显示乘数为4. 意思是,给定报告的值GetSuggestedIoDepth(直接在下面),要么:

      • GetSuggestedIoDepth现在4, 或
      • 乘数现在是 GetSuggestedIoDepth + 1
    • GetSuggestedIoDepth3磁盘设备的回报[9]
    • 没有硬设置最大值,但考虑到所需的内存 = ( BUFFERCOUNT* MAXTRANSFERSIZE),实际的最大值似乎是: BUFFERCOUNT <= (available_memory / MAXTRANSFERSIZE)
  • MAXTRANSFERSIZE
    • 可能的值是 65536 字节 (64 KB) 的倍数,最大可达 4194304 字节 (4 MB)。[1]
    • 默认值:如果设备处于读取模式(恢复)或者这是桌面版或速成版,则使用 64K,否则使用 1 MB。[9]
  • 一般/杂项:
    • 可以使用的最大大小是(缓冲池到物理内存/16)。从GlobalMemoryStatusEx (ullTotalPhys) API 调用返回。[9]
    • Trace Flag3213在执行备份/恢复操作时输出备份/恢复配置参数,并将3605输出转储到ERRORLOG文件:DBCC TRACEON (3213, 3605, -1);
    • 您可以使用DISK = N'NUL:'(与/dev/nullUNIX 中的DOS / Windows 等效)来更轻松地测试某些指标(但由于跳过了写入 I/O,因此无法很好地了解总处理时间)

资源

  1. T-SQL BACKUP命令的MSDN 页面
  2. KB904804:在 SQL Server 2000 中备份数据库时遇到性能下降
  3. 提高 SQL Server 备份性能的选项
  4. 备份还原
  5. 优化 SQL Server 备份和还原
  6. 优化备份性能
  7. 如何使用压缩和固态磁盘提高 S​​QL 数据库完整备份速度
  8. 不正确的 BufferCount 数据传输选项可能导致 OOM 条件
  9. 工作原理:SQL Server 备份和还原如何选择传输大小
  10. 工作原理:SQL Server 备份缓冲区交换(VDI 焦点)
  11. SQL 备份调优大型数据库
  12. 用于备份缓冲区的 SQL Server 内存
  13. 案例研究:通过网络快速可靠地备份和恢复 VLDB(.docx 文件)
  14. 建议使用多少个备份设备来提高备份性能?

我测试了:

--DBCC TRACEON (3213, 3605, -1);

BACKUP DATABASE [Test] TO
      DISK =  'NUL:'
     --,DISK = 'NUL:'
     -- DISK =  'BackupTest1.bak'
     -- ,DISK =  'BackupTest2.bak'
WITH
    STATS = 5,
    FORMAT,
    CHECKSUM,
    NO_COMPRESSION,
    COPY_ONLY
    --,BUFFERCOUNT = 40
    --,MAXTRANSFERSIZE = 4194304--2097152,
    --,BLOCKSIZE = 16384 

--DBCC TRACEOFF (3213, 3605, -1);
Run Code Online (Sandbox Code Playgroud)

更新

似乎有时我忘记添加一些我在回答问题时总是要求其他人提供的信息;-)。我确实在上面提供了一些关于我目前情况的信息,但我可以提供更多细节:

我正在为提供 24/7/365.25 SaaS 应用程序的客户工作。因此,用户在任何时候都有可能在线,但实际上,用户都在美国(目前)并且倾向于主要工作“标准”时间:太平洋时间上午 7 点(即东部时间上午 10 点)到太平洋时间下午 7 点(即东部时间晚上 10 点),但每周 7 天,而不仅仅是周一至周五,尽管周末的负载要轻一些。

它们的设置使得每个客户端都有自己的数据库。这是一个利基行业,因此没有数万(或更多)潜在客户。客户端数据库的数量因实例而异,最大的实例拥有 206 个客户端。最大的数据库大约是。8 GB,但只有大约 30 个 DB 超过 1 GB。因此,我并不是专门试图最大限度地提高 VLDB 的性能。

当我开始使用这个客户端时,他们的备份总是完整的,每天一次,并且没有日志备份。他们还将 MAXTRANSFERSIZE 设置为 4 MB,将 BUFFERCOUNT 设置为 50。我将该设置替换为Ola Hallengren数据库备份脚本的略微定制版本。稍微定制的部分是它从一个多线程工具(我编写并希望很快开始销售)运行,该工具在连接到每个实例时动态发现数据库,并允许每个实例进行节流(因此我目前正在运行三个实例同时运行,但每个实例的数据库按顺序排列,因为我不确定同时运行它们的后果)。

现在的设置是每周一天做一次完整备份,其他几天做一次差异备份;每 10 分钟进行一次 LOG 备份。我在此处查询的 3 个选项使用默认值。但是,知道它们是如何设置的,我想确保我没有撤消优化(仅仅因为旧系统中存在一些重大缺陷并不意味着一切是错误的)。目前,对于 206 个数据库,FULL 备份大约需要 62 分钟(每周一次),其余天的 DIFF 备份需要 7 到 20 分钟(FULL 后的第一天为 7 分钟,前一天为 20 分钟)。下一个 FULL)。这就是按顺序运行它们(单线程)。LOG 备份过程(所有 3 个实例上的所有数据库)总共需要 50 到 90 秒的时间(同样是每 10 分钟)。

我意识到我可以为每个 DB 运行多个文件,但是 a) 我不确定多线程和小到中等大小的 DB 会有多好,b) 我不想使恢复过程复杂化(首选处理单个文件的原因有多种)。

我也意识到我可以启用压缩(我的测试查询有意禁用了它),并且我已经向团队推荐了它,但我注意到内置压缩有点糟糕。旧过程的一部分是将每个文件压缩成 RAR,我做了自己的测试,发现是的,RAR 版本至少比本地压缩版本小 50%。我确实尝试先使用本机压缩来加快速度,然后使用 RAR 文件,但是这些文件虽然比仅本机压缩的文件小,但仍然比仅 RAR 压缩版本大一点,并且有足够的差异来证明不使用本机压缩。压缩备份的过程是异步的,每 X 分钟运行一次。如果它发现一个.bak.trn文件,它会压缩它。这样,备份过程不会因压缩每个文件所需的时间而减慢。

Han*_*non 14

您已经解决了问题中的大量项目。谢谢你这么认真!

只是我注意到的几件事:

  • 各种硬件/负载因素如何影响应该做什么。

您是否正在运行 24x7 实例?全天候负载是多少?我注意到您禁用了备份压缩;这是为了测试而设计的,还是出于某种原因在您将其投入生产时将其关闭?如果您有大量的硬件余量 (CPU/RAM),并且在最短的时间内完成备份至关重要,那么您应该考虑到该目标,针对您拥有的特定硬件调整这些参数。如果您想确保全天候为 OLTP 工作负载提供服务,并且不希望备份对其产生影响,您可能需要反过来调整这些参数。您还没有确定您的设计目标,因为您正在寻求一般指导,但是正如您明智地声明“这取决于™”。

  • 是否存在不应覆盖这些值中的任何一个的情况?

如果您担心不再维护实例后的可支持性,并且不确定您的替代品的能力,您可能希望保留默认设置。除非您有特殊需要调整它们,否则您可能希望保留默认值。正如他们所说,让熟睡的狗撒谎。

  • 是否存在覆盖任何不明显的陷阱?使用了太多内存和/或磁盘 I/O?恢复操作复杂吗?

正如您参考的文档明确指出的那样,过多地提高这些参数肯定会对正常运行时间产生负面影响。与所有基于生产的事物一样,您需要在部署之前对其进行彻底测试,除非绝对必要,否则不要理会设置。

  • 如果我有一台运行多个 SQL Server 实例的服务器(一个默认实例和两个命名实例),并且如果我同时运行所有 3 个实例的备份,这是否会影响我设置这些值的方式,而不是确保集体(BUFFERCOUNT * MAXTRANSFERSIZE) 不超过可用 RAM?可能的 I/O 争用?

您需要确保为不可预见的情况留出足够的 RAM。我当然会担心使用超过 60% 或 70% 的可用内存进行备份操作,除非我 100% 确定在备份窗口期间不会发生任何其他事情。

我在SQLServerScience.com 上写了一篇包含一些代码的博客文章,展示了我如何进行备份性能测试


这可能不是我写过的最好的答案,但正如 The Great One™ 曾经说过的那样,“你会 100% 错过你没有拍摄的镜头”

  • 谢谢你的指点,马克斯。+1 :)。我只是在我已经不短的问题中添加了一个 UPDATE 部分,以解决对该问题的一些评论以及您在此处提出的关于为什么我不使用压缩的问题。我相信我也回答了您关于我如何运行备份的问题:-)。 (2认同)