解决简单恢复模式下产生的日志增加

简介程序员

  最近测试服务器进行数据归档,其间程序员发现一个问题,空间不足,我查看缘由发现日志文件暴涨。而后将数据库改成简单恢复模式,可是依然存在这个问题。通过查询资料发现了日志文件在简单模式下依然增长的缘由。sql

Simple概念数据库

  Simple恢复模式也叫作”Checkpoint with truncate log“,其实这个名字更形象,在Simple模式下,SQL Server会在每次checkpoint或backup以后自动截断log,也就是丢弃全部的闲置日志记录,仅保留用于实例启动时自动发生的instance recovery所需的少许log,这样作的好处是log文件很是小,不须要DBA去维护、备份log,但坏处也是显而易见的,就是一旦数据库出现异常,须要恢复时,最多只能恢复到上一次的备份,没法恢复到最近可用状态,由于log丢失了。缓存

Checkpoint服务器

  CheckPoint和lazyWriter同样,都会将缓冲区内脏数据写入到磁盘,同时在简单恢复模式下截断日志;lazyWriter缓存不足的时候会触发执行,这里咱们暂且不作讨论。性能

针对CheckPoint我请教了Careyson之后总结出如下几个触发其执行的缘由:测试

  1. 一些Internal CheckPoint时,好比说关闭数据库实例等。
  2. 数据库完整备份或差别备份(日志备份不会触发checkpoint)。
  3. 数据库恢复模式为简单恢复模式下当日志文件使用超过70%时。
  4. CheckPoint执行的时间间隔阈值被足够多的日志记录超过。
  5. 手动执行CheckPoint。

场景描述:this

  Simple模式主要用于非critical的业务,好比开发库和测试库,那么此次因为测试环境的磁盘紧张咱们也都采用了简单模式。可是数据归档发生时依然产生了大量的日志,而且增长了磁盘占用,这又是什么缘由那?由于咱们在归档处理中使用了大量的insert和delete以及update操做,这样话,短期内产生了大量的日志,这个时候日志迅速增长;又由于在SQL Server中,CheckPoint是一个完整的过程,这个过程的耗时取决于脏数据的大小。一旦在很短期内,日志的CheckPoint没完成的时候日志增长超过了日志的规定上限。则将产生更多的日志。spa

  如上所述,产生这个问题的缘由就是:CheckPoint时间间隔阈值被足够多的日志记录超过,触发CheckPoint才写入磁盘。日志

  下面这个实例来自于:

      http://sqlblog.com/blogs/linchi_shea/archive/2009/04/12/a-race-condition-in-the-simple-recovery-mode-why-is-my-log-autogrowing.aspx

    让咱们用一个脚原本实际的阐明这种行为。首先在一个测试数据库中运行一下脚本建立一个测试表并填充一些数据。

  测试数据库设置:

  1.设置为简单的恢复模式。

  2.日志的大小为100M。

  3.日志文件的自动增加被禁用(由于观察日志空间被用完的错误比检查自动增加要容易)。

复制代码
--建立表并初始化数据
create table test(i int, c char(1000))
go
declare @i int 
set @i = 1
while @i < 10000     --插入9999条测试数据
begin          
  insert test values(@i'abc')          
  set @i = @i + 1      
end
复制代码

   运行如下脚本,观察资源竞争:

复制代码
set nocount on go
declare @change_size int
set @change_size = 100 -- 根据须要来调整这个值
declare @i int
set @i = 1
while @i < 100      
begin           
if @i % 2 = 0             
   update test set c = replicate('a'@change_size)            
else               
  update test set c = replicate('b'@change_size)                       
select @i = @i + 1       
end
复制代码

 反复根据修改@change_size来看结果,当我将@change_size改成120甚至更大时,获得了9002的错误信息,很是准确的告诉我数据库的事务日志已满。

经过上面这个引用的例子,很好地再现了问题的产生机制,那么咱们怎么处理这个状况那?

解决

  方案1:

  强制执行CheckPoint。可是执行后有个很很差的影响,严重影响了存储过程的执行时间。由此可知这样作很消耗性能啊。

  方案2:

  缩短CheckPoint时间间隔阈值。

 默认值是0,意味着由SQL Server来管理这个回复间隔。   

 也能够SQL语句实现这个功能:

  方案3:

  增大日志文件大小。

总结:

  日志文件是一个双刃剑,WAL机制很好的保证了数据的一致性和维护性。可是也产生了额外的性能和维护的成本的上升。须要咱们根据实际状况去处理这些不一样的情景。须要注意的是在TempDB中是不会产生日志的,除非手动执行。除此以外,并不是全部的时间间隔后都会产生日志,由于当数据不多的时候有可能不触发Checkpoint执行。

相关文章
相关标签/搜索