作者: 朱赛凡
在系统掉电或者因为服务器故障直接按电源按钮时,经常会出现即使物理磁盘没有任何故障,而数据库系统或者文件系统损坏情形。数据是最宝贵的资源,为此对此方面问题进行研究。
系统突然掉电导致数据丢失主要原因是由于各个层面的数据缓存导致:突然掉电导致缓存中的数据丢失,从而使得数据库文件和文件系统数据不一致,导致数据丢失。此种错误可认为属于逻辑错,区别因为物理磁盘坏道等情况导致的物理错误。
1. Linux系统
在Linux操作系统中写入磁盘的数据首先被缓存到Linux操作系统的页面缓存中(Page cache)。可以利用“cat/proc/meminfo”命令来查看Page Cache的信息。
Linux操作系统利用pdflush进程来讲写入页面缓存的 “脏数据”写入磁盘。用户可以执行”Sync”命令强制将缓存中“脏数据”写入磁盘,而应用程序可以通过调用”fsync”强制将对应文件写入磁盘。不过Sync函数表示将文件在OS cache中的数据排入写队列,并不能真正确保写入磁盘,因此不可靠。
Linux操作系统中,应用程序可以在打开文件时设置”O_SYNC”标记,让系统将数据同步写入到磁盘,即只有确实将数据写入磁盘后才返回。如果设置“O_DIRECT”标记则文件读和写都绕过操作系统缓存,很多数据库系统(例如ORACLE)认为自己的缓存管理机制更优,为避免多重缓存(操作系统层面和应用层面)会使用”O_DIRECT”。设置”O_DIRECT”后会影响顺序读写性能,而不会对随机读写性能产生太大影响。
除”O_SYNC”标记外,还有“O_DSYNC”、”O_RSYNC”。”O_SYNC”比”O_DSYNC” 更加严格,前者要求文件数据和属性都必须写入磁盘,而后者只要求文件数据。O_RSYNC表示文件读取时,该文件的OScache必须已经全部flush到磁盘了。相对应除”fsync”外,还有”fdatasync”,后者只把文件数据写入磁盘。
2. Windows系统
Windows操作系统可以调用CreateFile时,利用“FILE_FLAG_WRITE_THROUGH”标记来指示操作系统直接将数据写入磁盘。例如SQL Server数据在打开其数据和日志文件时都会使用该标记。
Windows系统可以在设备管理器中对具体的磁盘来是否启用缓存。“启用磁盘上写入缓存”指是否启用磁盘板载上的缓存,“启用高级性能”根据网上所查资料表示是操作系统层的缓存。
目前硬盘(SATA、ATA、SCSI和 IDE)的控制器中一般会带有一定大小的板载缓存。
掉电后硬盘驱动器缓存只能依赖电容器完成扇区写入操作,无法保证将缓存中所有数据写入磁介质上。RAID卡或者磁盘阵列柜除非有后备电源保护,否则在掉电后就会丢失缓存中的数据。
在数据可靠性要求非常高场合,需要关闭磁盘或者RAID控制器写缓存。对于直接插硬盘的服务器,Linux操作系统中可以通过执行“hdparam –w0 磁盘设备”关闭对应磁盘写缓存(SATA磁盘需要sdparm工具来关闭写缓存),Windows系统可以在设备管理器禁用”启用磁盘上的写入缓存”关闭磁盘写缓存。
通过设置RAID卡写策略:”write-back”或“write-throug”,前者表示先写缓存,后者表示直接写磁盘。同时一般可以通过RAID卡来设置与该RAID卡相连磁盘的写缓存功能。例如目前使用RAID卡就可以配置是否关闭与该卡相连磁盘的写缓存(设置DISK CACHE : nochange、enable、disable)。根据网上所查资料,很多RAID卡控制器会默认关闭所连磁盘写缓存,详细情况要咨询硬件厂商。
目前关系数据库系统基本采用日志技术来保证事务ACID特性,D表示持久性。持久性意味在数据库实例crash情况下(例如掉电)必须保证事务数据的安全。
例如在ORALCE中当在oracle中执行数据修改操作时,先将数据库操作日志记录到redologbuffer中,但如果用户执行commit,则必须将redolog buffer中更改写入到redolog 文件中。
采用日志机制主要优势是实例崩溃后,实例重新启动时通过redolog重放机制能自动、快速恢复。
数据库日志机制发挥作用前提是数据库发出将redolog写入到redolog文件命令后,低层要确保确实是写入了磁盘。例如将数据库安装在磁盘阵列柜上,如果RAID采用write-back,或者操作系统本身提供fsync命令是个伪实现,那么就有可能导致日志损坏,从而无法进行恢复。
为此在微软公司的网站上发布了” 每个数据库管理员都应了解的在 SQL Server 中使用磁盘驱动器缓存的说明”,建议为确保Sqlserver数据库安全,应该禁用磁盘缓存。
开源MySQL数据库系统提供支持事务和不支持事务的两种存储引擎。MyISAM不支持事务,InnoDB支持事务。对MyISAM存储引擎,当数据库掉电时很容易导致表文件不一致,此时只能通过特定的修复工具对受损的文件进行全局扫描,来试图修复其中逻辑错误,这种过程一般非常长。而对InnoDB则能快速恢复,但前提是OS层必须真正实现Fsync。InnoDB缺点是,如果对每个修改操作都执行commit,则插入性能很差。
文件系统也类似,例如Ext2文件系统没有采用日志机制,因此突然掉电后修复时间非常长,为此Ext3文件系统加入日志机制来加快恢复速度。但是Ext3默认只会将元数据记录日志。Windows NTFS文件系统也是日志文件系统,但是根据以往经验,对TB级别恢复速度也很慢。