备份数据库的时候设置 BufferCount 选项不正确导致 out of memory 的情况
备份数据库的时候设置 BufferCount 选项不正确导致 out of memory 的情况
今天群里面的东辉兄跟我说备份生产数据库的时候报错

环境:
32位的SQLSERVER2008
机器有16G内存
数据库大小差不多60G
数据库已经打开了AWE功能
因为是生产库,暂时不能升级到64位SQL2008,那么还有没有其他办法可以解决这个问题呢??
上网搜索了一下就找到了这篇文章:
Incorrect BufferCount data transfer option can lead to OOM condition
译文:
今天介绍两个DBA在做数据库备份的时候一般都不会去指定的备份参数。一般备份数据库大家会用下面的方法:
1、使用SSMS或者TSQL脚本来备份数据库
2、使用第三方的备份软件,这些第三方软件利用 SQLVDI.DLL暴露出来的编程接口或者使用快照备份
当你写好备份命令并发送到服务器端的时候,你可以在你的备份命令里添加如下两个参数:
MAXTRANSFERSIZE
BUFFERCOUNT
联机丛书对于这两个参数的解释是:
http://technet.microsoft.com/zh-cn/library/ms186865(SQL.105).aspx
数据传输选项
BUFFERCOUNT = { buffercount | @buffercount_variable }
指定用于备份操作的 I/O 缓冲区总数。可以指定任何正整数;但是,较大的缓冲区数可能导致由于 Sqlservr.exe 进程中的虚拟地址空间(VAS)不足而发生“内存不足”错误。
缓冲区使用的总空间由下面的公式确定:buffercount * maxtransfersize。
注意
有关使用 BUFFERCOUNT 选项的重要信息,请参阅不正确的 BufferCount 数据传输选项可以导致 OOM 情况博客。
MAXTRANSFERSIZE = { maxtransfersize | @maxtransfersize_variable }
指定要在 SQL Server 和备份介质之间使用的最大传输单元(字节)。
可能的值是 65536 字节 (64 KB) 的倍数,最多可到 4194304 字节 (4 MB)。
根据你是否提供这两个参数值,SQLSERVER会指定用于备份的连续的缓冲区大小。
这是对于32位系统中大量的连续的内存分配的 non-Buffer pool区域的虚拟地址空间是至关重要的。这会令备份失败(言下之意,备份使用的是non buffer pool)。
当使用SQLVDI,重要的是在VDI配置已经完成之后,我们不能改变MAXTRANSFERSIZE 。大量的连续的内存分配决定于备份设备的数量和数据库文件存放的磁盘的数量
当你进行备份或者还原数据库的时候可以通过跟踪标志3213来查看你的备份/还原 配置参数。
具体可以参考我这篇文章:《SQLSERVER数据库备份操作和还原操作做了什么》
我会给你们演示指定不正确的BUFFERCOUNT 参数或者不指定这个参数出现的致命错误
Trace Flag 3213
我使用下面的SQL命令来备份SQLSERVER数据库
backup database dbBackup to disk = 'C:\dbBackup1.bak', disk = 'C:\dbBackup2.bak', disk = 'C:\dbBackup3.bak', disk = 'C:\dbBackup4.bak', disk = 'C:\dbBackup5.bak', disk = 'C:\dbBackup6.bak' with stats = 1, format, buffercount = 10, maxtransfersize = 4194304
我特意指定了buffercount参数的值为10 和maxtransfersize为4MB
跟踪标志3213的输出显示了下面的信息
最后使用了 40MB buffer 空间去完成备份
Backup/Restore buffer configuration parameters Memory limit: 3954MB Buffer count: 10 Max transfer size: 4096 KB Min MaxTransfer size: 64 KB Total buffer space: 40 MB
上面的内容在SQLSERVER联机丛书上已经提到过。
我们现在需要知道buffer count不指定的情况下会发生什么。如果我们不指定buffer count,那么buffer count 会比之前指定的时候大
Backup/Restore buffer configuration parameters Memory limit: 3954MB Buffer count: 26 Max transfer size: 4096 KB Min MaxTransfer size: 64 KB Total buffer space: 104 MB
如果你看到上面的输出会发现不指定的情况下buffer space已经飙升到104MB,这是因为buffer count已经增长到26
默认的数据库备份的Buffer Count的计算
SQL Server 2005 或以上
(NumberofBackupDevices * GetSuggestedIoDepth) + NumberofBackupDevices + (2*DatabaseDeviceCount)
SQL Server 2000
(NumberofBackupDevices * GetSuggestedIoDepth) + NumberofBackupDevices + (DatabaseDeviceCount)
注意:如果使用的是磁盘,那么备份时候GetSuggestedIoDepth的默认值是3
上面的公式运算完毕之后会返回一个返回值给SQLSERVER,根据备份介质的不同,例如磁盘、tape磁带 、VDI返回不同的值
根据上面的公式,第一个例子里面我的备份设备是6,磁盘数是1,因此: 在我的例子里buffer count是[(6*3) + 6 + (2*1)]=26
我将上面的SQL运行在64位SQLSERVER实例上。当我把上面的SQL运行在32位SQLSERVER实例上,
这将占近三分之一的可用的 non-Buffer Pool内存 SQL Server(MemToLeave)区域。
当我使用下面的SQL,从原来的6个备份设备增加到12个,SQLSERVER就会报错
backup database dbBackup
to disk = 'C:\dbBackup1.bak',
disk = 'C:\dbBackup2.bak',
disk = 'C:\dbBackup3.bak',
disk = 'C:\dbBackup4.bak',
disk = 'C:\dbBackup5.bak',
disk = 'C:\dbBackup6.bak'
disk = 'C:\dbBackup7.bak'
disk = 'C:\dbBackup8.bak'
disk = 'C:\dbBackup9.bak'
disk = 'C:\dbBackup10.bak'
disk = 'C:\dbBackup11.bak'
disk = 'C:\dbBackup12.bak'
with stats = 1, format, buffercount = 10, maxtransfersize = 4194304
报错信息
Msg 3013, Level 16, State 1, Line 1
BACKUP DATABASE is terminating abnormally.
Msg 701, Level 17, State 17, Line 1
There is insufficient system memory to run this query.
Backup/Restore buffer configuration parameters
Backup/Restore buffer configuration parameters Memory limit: 4029MB Buffer count: 50 Max transfer size: 4096 KB Min MaxTransfer size: 64 KB Total buffer space: 200 MB
我的32位SQLSERVER 的最大的可用连续块在NON BUFFER POOL (MemToLeave)里面只有157MB,因此, 就会报OOM(out of memory)错误
大多数第三方备份软件会使用一个 Max Transfer Size值但是不会指定Buffer Count 的大小。如果你在做备份的时候,遇到OOM错误,你应该下意识的检查一下
Total Buffer Space的使用量在你备份的时候。
在这种情况下,你应该减少备份设备的数目或者减少buffer count通过指定buffer count的值在书写备份命令的时候
下面的表格指出了默认的buffer count值对于不同的备份/还原操作

如果你在数据库完整备份到磁盘的时候想大概估计 Buffer memory的用量,下面的SQL脚本能够计算出来
DECLARE @MaxTransferSize FLOAT ,
@BufferCount BIGINT ,
@DBName VARCHAR(255) ,
@BackupDevices BIGINT -- Default value is zero. Value to be provided in MB.
SET @MaxTransferSize = 0 -- Default value is zero
SET @BufferCount = 0 -- Provide the name of the database to be backed up
SET @DBName = 'dbBackup' -- Number of disk devices that you are writing the backup to
SET @BackupDevices = 1 DECLARE @DatabaseDeviceCount INT SELECT @DatabaseDeviceCount = COUNT(DISTINCT ( SUBSTRING(physical_name, 1,
CHARINDEX(physical_name,
':') + 1) ))
FROM sys.master_files
WHERE database_id = DB_ID(@DBName)
AND type_desc <> 'LOG' IF @BufferCount = 0
SET @BufferCount = ( @BackupDevices * 3 ) + @BackupDevices + ( 2
* @DatabaseDeviceCount ) IF @MaxTransferSize = 0
SET @MaxTransferSize = 1 SELECT 'Total buffer space (MB): '
+ CAST (( @Buffercount * @MaxTransferSize ) AS VARCHAR(10))
至于更详细的参数可以参考我这篇文章:《SQLSERVER数据库备份操作和还原操作做了什么》



实验
我在电脑上安装了一个SQL2005 express版本 32位
使用下面的SQL语句进行备份就会报OOM错误
BACKUP DATABASE [test] TO DISK ='E:\test1FULLBACKUP.BAK' ,
disk = 'E:\test2FULLBACKUP.bak',
disk = 'E:\test3FULLBACKUP.bak',
disk = 'E:\test4FULLBACKUP.bak',
disk = 'E:\test5FULLBACKUP.bak',
disk = 'E:\test6FULLBACKUP.bak'
WITH BUFFERCOUNT=999999999,FORMAT
消息 3013,级别 16,状态 1,第 1 行
BACKUP DATABASE 正在异常终止。
消息 701,级别 17,状态 123,第 1 行
没有足够的系统内存来运行此查询。
但是指定 BUFFERCOUNT=1就不会
BACKUP DATABASE [test] TO DISK ='E:\test1FULLBACKUP.BAK'
WITH BUFFERCOUNT=1

东辉兄的情况
下午的时候我叫他指定 BUFFERCOUNT=1 试试
结果没有报OOM错误
使用了17分钟备份完差不多60G的数据库
虽然指定 BUFFERCOUNT=1 备份速度会慢一点,但是non buffer pool的内存占用不会那么多
感谢东辉兄提供这么鲜明的例子o(∩_∩)o
如有不对的地方,欢迎大家拍砖o(∩_∩)o
备份数据库的时候设置 BufferCount 选项不正确导致 out of memory 的情况的更多相关文章
- C#DataGrid列值出现E形式的小数,将DataGrid表格上的数据保存至数据库表时会因格式转换不正确导致报错
问题描述:在DataGridView中调整金额一列,当输入小数0.000001后会显示1E-6,此时进行保存操作时报错,提示无法将string类型转换成Decimal 原因分析:由于列调整金额为1E- ...
- MySQL 备份数据库
一.数据备份 1.备份一个数据库 mysqldump基本语法: mysqldump -u username -p dbname table1 table2 ...-> BackupName.sq ...
- SQL SERVER备份数据库文件(使用SSMS)
微软的SQL SERVER是市面占有率比较大的数据库,在平时的使用与维护中,备份数据是一件十分重要的! 备份操作,用微软自带的ssms(SQL Server Management Studio)工具即 ...
- SQL server2012怎么备份数据库(设置自动备份)
1.打开SQL server配置管理器,设置sql server服务里的SQL server代理服务为自动并启动 2.启动Master Data Services Configuration Mana ...
- crontab的相关设置&linux定时备份数据库
对于才了解crontab的人来说,应该按照以下的步骤来设置crontab 1.首先要检查是否装了crontab http://blog.sina.com.cn/s/blog_4881040d01011 ...
- SQL SERVER 2012设置自动备份数据库
为了防止数据丢失,这里给大家介绍SQL SERVER2012数据自动备份的方法: 一.打开SQL SERVER 2012,如图所示: 服务器类型:数据库引擎: 服务器名称:127.0.0.1(本地), ...
- SQLSERVER 设置自动备份数据库
1. SQLSERVER 简单的设置 计划任务 进行 备份数据库的操作. 首先需要打开 一些设置 执行 命令如下: sp_configure ; GO RECONFIGURE; GO sp_confi ...
- Linux(CentOS7)设置自动备份数据库到阿里云OSS
环境:阿里云服务器CentOS7.4 + MySQL5.6 基本思路: 1.编写shell脚本,备份数据库到指定目录下 2.编写Python脚本,把文件上传到OSS 3.把shell脚本和Python ...
- mysql load data infile的使用 和 SELECT into outfile备份数据库数据
LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE t ...
随机推荐
- 去除DEDECMS后台预览文章URL地址多余的数字信息
在使用织梦模板时发现这样一个问题:在后台预览文章的时候,出现的文章网址尽管是静态URL,但是会在网址的尾部出现问号并跟随一个时间戳,在复制URL时就显得很不方便.那么如何解决这一问题呢? 经过查找资料 ...
- “REST”——Representational State Transfer(表述性状态转移)
Representational State Transfer http://www.infoq.com/cn/articles/understanding-restful-style/#anch10 ...
- VC++ 将IP字符串转为 DWORD值
CString strIP="192.168.1.184"; DWORD dwAddress= ntohl( inet_addr(strIP)); m_IPAddr.SetAddr ...
- linq 延迟执行带来的困扰
有这样一个案例: var filteredResult = from f in orgFileList select f; ; i < WorkStatusFilters.ListWorkSta ...
- [转载] 2. JebAPI 之 jeb.api.dex
本文转载自: https://www.zybuluo.com/oro-oro/note/142842 1. jeb.api.dex.Dex 这个类代表正在被JEB处理的DEX文件. 要想更好的了解这个 ...
- Delphi 字符数组存入文件
TDMSRequestBuffer=object Head:TDMSHead; Data:array[0..2047] of char; DataSize:Integer; p ...
- 读取assets文件夹下图片(ods_interview)
今天看了一道题,现在总结一下里面使用到的知识点: 1.assets文件的访问: 原文出处:http://blog.csdn.net/fengyuzhengfan/article/details/383 ...
- 四则运算(Android)版
实验题目: 将小学四则运算整合成网页版或者是Android版.实现有无余数,减法有无负数.... 设计思路: 由于学到的基础知识不足,只能设计简单的加减乘除,界面设计简单,代码量少,只是达到了入门级的 ...
- PHP魔法方法的使用
1.__get / __set 当类没有要存取的属性时,就调用这两个函数 $obj = new IMooc\Object();$obj->title = "hello";ec ...
- Visual Studio 必备神器
会使用工具是人类文明的一大进步,今天敏捷大行其道,好的工具可以大大的提高生产力,这里说的工具都是VS平台上的扩展工具,一些机械的部分可以交给工具去处理,自己多关注其他部分.下面分享下我觉得不错的工具, ...