浅谈SQL Server中的事务日志(五)----日志在高可用和灾难恢复中的作用

本篇文章是系列文章中的第五篇,是对前一个日志系列的补充篇。如果您对日志的基本概念还没有一个比较系统的了解,可以参看本系列之前的文章:

浅谈SQL Server中的事务日志(一)----事务日志的物理和逻辑构架

浅谈SQL Server中的事务日志(二)----事务日志在修改数据时的角色

浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色

浅谈SQL Server中的事务日志(四)----在完整恢复模式下日志的角色

 

简介

    日志的作用是保证持久性和数据一致性,通过日志可以实现数据的Undo与Redo,因此通过日志,SQL Server不仅仅可以实现灾难恢复,还可以通过日志的Redo来实现高可用性。本篇文章主要讲述日志在SQL Server中提供的几种高可用性中的作用以及在灾难恢复中的角色。

 

日志损坏

    日志可能会由于IO子系统的故障而损坏,当出现日志损坏时,如果您对日志的原来略有了解,并能在日志损坏的情况下尽量挽救数据,那么感觉一定是非常好的:-),下面我们来了解几种日志损坏的情况下的恢复情况。

 

1.数据库正常关闭,日志损坏。

    当数据库正常关闭时,日志损坏就不是那么重要了,因为此时数据库中所有提交的事务对应的脏数据都已经CheckPoint到物理磁盘,因此不存在数据不一致的问题。因此,如果MDF和NDF文件完好,直接指定 FOR ATTACH_REBUILD_LOG参数后附加即可,如图1所示。

浅谈SQL Server中的事务日志(五)----日志在高可用和灾难恢复中的作用_第1张图片

图1.如果数据库正常关闭,直接附加即可

 

    但值得注意的是,使用该方式附加数据库会自动重建日志文件,日志文件大小为0.5MB,也就是2个VLF,自动增长为10%,因此您需要手动再来设置一下日志的大小,避免出现太多VLF的情况。

 

2.数据库非正常关闭,日志损坏

    在讲述这种情况之前,我们首先来看数据库所能处在的几种状态,一个完整的模型如图2所示。

    浅谈SQL Server中的事务日志(五)----日志在高可用和灾难恢复中的作用_第2张图片

    图2.数据库所能处在的状态关系

   

    上面的几种状态的具体转换关系超出了本文的讨论范围,但是这里我会强调两种和日志损坏关系很大的状态:RECOVERY_PENDING和SUSPECT状态。

    假如出现了数据库没有正常关闭,也就是还有数据没有CheckPoint到磁盘,如果数据库要启动就必须经历Recovery过程,如果日志损坏,则无法进行该Recovery过程,就会造成数据不一致的问题。

    此时,数据库可能处于下面两种状态之一:

  • RECOVERY_PENDING:需要运行crash recovery,但该过程由于资源等待无法开始,比如说日志完全损坏
  • SUSPECT:crash recovery已经开始,但无法完成

 

    因此处理该类情况要基于您所在的业务环境是否允许数据损失,可以选择从备份中恢复数据,或是将数据库状态改为EMERGENCY。EMERGENCY模式意味着数据库跳过crash recovery阶段,此时虽然可以访问数据库,但是会存在数据事务不一致的问题,如果仅仅是某些数据页不一致还好,但如果是对表结构修改的事务存在,那就可能存在数据库架构不一致的问题。如果您没有合适的备份集,那只能通过该方式来恢复数据。将数据库设置为EMERGENCY模式非常简单,如代码清单1所示。

ALTER DATABASE AdventureWorks2012 SET EMERGENCY

代码清单1.将数据库设置为紧急模式

 

    与该模式有关的一个选项是REPAIR_ALLOW_DATA_LOSS,该选项依然会执行crash recovery过程,但会跳过受损的日子,从而尽可能的修复数据一致性问题,该选项会创建一个新的日志文件,最后使得数据库处于ONLINE状态,使用该选项的一个简单例子如代码清单2所示。

ALTER DATABASE AdventureWorks2012 SET SINGLE_USER
 
DBCC CHECKDB(AdventureWorks2012,REPAIR_ALLOW_DATA_LOSS)

代码清单2.使用REPAIR_ALLOW_DATA_LOSS选项

 

    值得注意的是,作为DBA永远是要有“备”无患,上面这些操作是在您准备工作不充分的情况下才要去考虑的。

 

3.数据库处于在线状态,日志损坏

    在这种情况下,如果SQL Server在运行时需要使用的日志损坏(比如说回滚时),则SQL Server会将数据库下线,并转为SUSPECT模式。

    同样如果没有备份的话,只能考虑使用EMERGENCY模式。

    还有一种方式是,将数据库的恢复模式改为简单,然后手动发起一个CheckPoint来截断日志,最后再将数据库改回完整恢复模式。但这种方式会破坏日志链。但可能会将被损坏的日志清除掉。

 

 

日志在高可用性中的作用

 

镜像与AlwaysOn

    这两种高可用性技术都是基于日志来维护一个数据库的副本。通过将日志实时的传送到副本,在副本上来不断的进行REDO操作,就可以保证主体和副本数据库之间的实时同步。

    对于镜像来说,可以同步或异步将日志传送的1个副本。

    而对于AlwaysOn可用性组来说,就可以将日志最多同步到2个副本+异步到2个副本(据说SQL Server 2014已经将该特性翻倍,也就是最多可以4个同步副本和最多4个异步副本,但目前还没有发布,所以只是小道消息)。

    所谓的同步概念就是主副本只有将传送的日志发送到辅助副本之后,由辅助副本返回ACK信息后,才能够在本地提交,因此可能会造成明显的延迟并影响性能。这里还值得注意的是,主副本不是等待事务在辅助副本提交之后才能提交,而是只是需要收到辅助副本返回的收到日志的ACK信息即可。

    无论对于上面两种高可用特性,无论是哪一种,都需要考虑监控发送队列和REDO队列。发送队列过长意味着当故障转移时,可能丢失大量数据,同时还会阻止日志截断。REDO队列过长意味着当故障转移时,RECOVERY截断将会消耗更多的时间,从而使得故障转移消耗的宕机时间延长。这两种队列的监控都可以使用性能监视器进行,如图3所示。

浅谈SQL Server中的事务日志(五)----日志在高可用和灾难恢复中的作用_第3张图片

图3.监控队列的计数器

 

事务日志传送

    相比其他高可用性功能来说,事务日志传送功能比较简单。本质上就是一个不断备份、传送、还原日志的过程。使用事务日志传送对于测试日志是否有效来说非常合适。

    事务日志传送还有一点值得注意的地方就是,当有批量操作的时候,考虑使用大容量事务日志模式,从而避免大量的日志通过网络传输。

    事务日志对于维护一个数据库冗余的副本来说是最简单的方式,虽然不能保证数据实时,但对于特定业务场景还是非常有意义的。

 

事务复制

    与前几种高可用性特性不同的是,事务日志无法直接传送事务日志。因为发布端和订阅端数据库的结构可以完全不一样,订阅端可以仅仅订阅一个或多个表,表中的一部分列,或是一部分数据子集。由于发布端和订阅端的表结构和数据不一致,因此无法直接将发布端的日志传送到订阅端。

    因此事务复制的原理是Log Reader Agent定期读取发布端的日志,汇总日志对发布内容的更改,从而将这些更改变为逻辑操作,从而使得订阅端可以Replay这些操作来打到数据同步的目的。

    这里值得注意的是,如果Log Reader Agent还没有扫描最新的修改,事务复制可能造成发布端的日志无法截断。

 

 

小结

    本篇文章作为对前面四篇文章的补充,讲述了日志在灾难恢复和高可用性中的原理和作用。这些原理对于设计一个好的备份计划、高可用性计划来说,是必不可少的。

你可能感兴趣的:(数据库)