今天的主题是关于SQL数据库日志截断的相关问题。针对的数据库是Microsoft SQLServer 2005
笔者的项目中涉及到了大量的数据库操作,其中一部分应用是使用WebService进行分布式批量数据导入的模块。由于中间有许多数据必须使用事务保证数据的一致性,由于比如销售数据等大数据量事务处理会带来日志暴涨的问题(当然,导入设计可以进行优化,这个主题不再本话题下),今天查了一下日志,已经超过了25G了,这显然会影响性能。于是就想到将数据库日志截断,数据截断一般使用:
- DUMP TRANSACTION [需要截断的数据库名称] WITH NO_LOG
这里笔者在做的时候很久以前曾经遇到比较白痴的问题,就是执行后发现日志大小没有变,就感觉没有执行成功。其实不是,需要再执行以下数据库收缩,这时候日志文件就会回复到初始大小,默认就是1MB。收缩数据库的语句是:
- DBCC SHRINKDATABASE ([需要收缩的数据库名称],TRUNCATEONLY)
但是这样还不行,考虑日志是恢复和保证数据一致性重要信息,那么万一数据库碰到问题就麻烦了,所以应当立即备份。
考虑以上操作,觉得可以写一个通用的脚本,把这几个步骤放到一起来,保证备份到固定位置。于是就编写如下脚本。
- -----------------------------------------------
- --Author:ETZRP
- --Date:2009-01-07
- --Useage:Remove Log and Backup DB
- -----------------------------------------------
- --截断日志
- DUMP TRANSACTION [要操作的数据库] WITH NO_LOG
- --收缩数据库
- DBCC SHRINKDATABASE ([要操作的数据库],TRUNCATEONLY)
- --备份数据库
- go
- USE master
- declare @Version varchar(20)
- declare @DateAppend varchar(20)
- declare @BasePath varchar(200)
- declare @BakPath varchar(200)
- --设定备份的基本目录
- set @BasePath='D:/SQL_Data'
- --设定版本,每个版本的备份放在不同的地方
- set @Version='V1.0.5'
- --生成形如20090107这样的时间串
- set @DateAppend=ltrim(str(year(getdate())))
- if(month(getdate())<10)
- set @DateAppend=@DateAppend+'0'
- set @DateAppend=@DateAppend+ltrim(str(month(getdate())))
- if(day(getdate())<10)
- set @DateAppend=@DateAppend+'0'
- set @DateAppend=@DateAppend+ltrim(str(day(getdate())))
- --设定备份的完整路径,奇怪的是,如果直接使用下面=后面的表达式会出错。所以新建一个变量
- set @BakPath=@BasePath+'/'+ @Version +'/Db.Bak.'+@DateAppend
- USE master
- --创建备份设备,如果存在则无需建立
- if not exists(select * from sysdevices where name='DB_Bak')
- begin
- EXEC sp_addumpdevice 'disk','DB_Bak',@BakPath
- end
- --备份数据库
- BACKUP DATABASE [要操作的数据库] TO DB_Bak
- --备份日志
- BACKUP LOG [要操作的数据库] TO DB_Bak
这样这一切都可以自动完成了,当然可以发散一下将其改造成为存储过程,或者根据需要做成一个调度。
需要注意的是,笔者在实践的时候的心得是使用脚本创建的还原的时候需要使用强制还原,因为日志都没了。
参考资料:
http://topic.csdn.net/t/20031229/15/2614346.html
http://topic.csdn.net/t/20030517/09/1795833.html