APP下载

浅析SQL数据库修复技术

2016-03-15

网络安全和信息化 2016年7期
关键词:日志备份语句

引言:SQL Server数据库在实际工作中应用的很广泛,在管理SQL Server数据库时,有时可能因为各种原因,会导致数据库出现无法访问等损坏故障。如果之前有数据库备份的话,就很容易恢复数据库的正常运行。但是,如果没有对其进行及时有效的备份,那就只能对其进行修复操作。

数据库可谓是存储数据的大仓库,这对于保证网站和企业内网的安全运行至关重要。数据库损坏是一种物理层面的损坏,即使进行修复,出现数据丢失的情况在所难免。单纯使用修复手段,是无法完美的将数据库恢复如初的。因此,使用正确的数据库备份恢复策略,才可以从根本上数据库的安全。

数据库损坏的原因

我们知道,SQL Server是按照一定的格式将数据存储在文件中的,当SQL Server访问这些数据时,就会将其从物理磁盘中的存储单元读出,并按照固定的格式将其中的数据解析出来,如果在读取磁盘或者解析数据时出现了问题,就会造成数据无法正常读出的情况,这就说明数据库发生了损坏。如果问题出现在日志文件中,就会导致数据库恢复失败。如果问题出现在数据库文件中,虽然可以正常恢复数据,但是在访问其中的数据时,就会出现各种问题。这就涉及到数据库的修复操作,在修复数据库时,有可能造成数据库数据的丢失的问题。使用“DBCC CHECKDB”指令,可以检查数据库中是否存在损坏的情况,对于出现问题的数据库,可以尽力对其进行修复,使其能够重新进行访问。

数据库受损分为各种情况,例如是日志文件损坏的话,需要重建数据库日志文件,这是不得已的办法,可能破坏数据库应用的一致性。如果是数据库文件损坏,又分为多种情形,例如对于非聚集索引页面受损的情况,可以重建非聚集索引,尝试对数据库进行丢失数据的修复。对于聚集索引页面受损的情况,可以采用带有“REPAIR_ALLOW_DATA_LOSS”参数的DBCCCHECKDB命令,对数据库进行修复,但可能出现数据丢失的情况。如果是系统页面或者系统表受损,则只能从备份文件中恢复的方法,对数据库进行修复。实际上,因为SQL Server自身问题导致数据库受损的可能是比较低的,如果一台服务器上的数据库经常发生损坏,就需要对Windows系统自身的运行情况进行检测,特别是对I/O子系统进行检测,来发现磁盘读写缓冲区,数据通道,驱动程序等环节是否存在问题,因为很大比例上的数据库损坏问题都是由于I/O子系统故障所导致。

因此,对I/O子系统进行检测是很有必要的,可以使用SQLIOSim这款小工具,通过模仿SQL Server的行为,以一定的并发负载触发各种SQL Server相关的I/O动作,来验证这些I/O是否被正确执行。如果系统无法通过该工具的测试,就说明存在I/O子系统的相关问题。可以在部署SQL Server服务器之前,利用该工具对系统进行检测,确保I/O子系统不存在问题。随着硬件技术的飞速发展,SQL Server的运行效能不断提高,对I/O层面的压力随之增大,因此,对相关硬件(例如硬盘等)设备进行固件的升级,安装更新的驱动程序等操作,可以提高I/O设备的性能,来更好的应对上述问题。

在SQL Server层面上其实已经添加了残缺页保护,校验和保护等I/O验证功能,可以帮助用户更好更快的捕捉到数据库错误的发生,让用户及时采取修复操作,保证数据库的安全。对应的命令格式为“Alter database 数据库名 page_veryfy{checksum| torn_page_detection |None}”,例 如 执 行“Alter database 数据库名page_veryfy checksum”语句,可以激活校验和保护功能。之后SQL Server根据每个页面的内容计算出一个校验和,并在页面被写入磁盘时将该值保存在页面头部。当从磁盘读出该页面时,会重新计算出一个校验和并与保存在页面头部的值相比较。如果这两个值并不匹配,错误信息824(表示校验和错误)会被报告出来。

解析DBCC CHECKDB命令的功能

使用DBCC CHECKDB指令,可以执行一系列的操作,来检查数据库中所有对象的逻辑和物理的完整性。例如,可以对一些关键的系统表进行检测,这些数据表(即元数据)对普通用户来说是不可见的,其不会占用太多的页面,发生问题的可能性不大。系统表一旦损坏,DBCC CHECKDB恢复操作就会失败,只能使用备份文件进行恢复。之后该指令会检查数据库中所有的页面分配,验证各种内部结构,对数据库中所有表和视图进行检查,检查其是否正确连接索引,索引是否按照正常的方式排列,指针是否一致,页面偏移量是否合理等。

接下来对数据库执行DBCC CHECKALLOC检查,检测数据库中数据表记录元数据的逻辑一致性,检测每个索引视图的内容,检测Service Broker相关对象是否正常等。如果发现数据库存在问题,该指令可以对其进行修复操作。默认情况 下,DBCC CHECKDB指挥验证数据库是否完好,不会主动执行修复数据库操作,当尝试修复数据库时,需要使用相关的修复选项,例如对于“REPAIR_ALLOW_DATA_LOSS”选项来说,会尝试修复报告的所有错误,这样的话,可能会导致数据库丢失一些数据。“REPAIR_FAST”选项主要为了向后兼容,不会执行任何修复操作,无需加以使用,“REPAIR_REBUILD”选项的作用是执行次要的,快速的修复行为,例如修复非聚集索引中的额外键等,以及执行耗时修复来重新生成索引等。这行这样的修复不存在丢失数据的风险。

在执行实际的修复时,必须将目标数据库的用户连接断开,将目标数据库设置为单用户模式,将数据库设置为紧急修复状态。之后再进行具体的修复操作。注意,对数据库执行DBCC CHECKDB检测时,可能花费的时间较长。例如对于没有问题的大小为1TB的数据库文件来说,检测可能需要花费几小时的时间,对于只有几百兆,但是存在一些错误的数据库来说,检测可能会花费十几个小时甚至更长的时间。如果在数据库中设计了分区表机制,实现检测操作就比较简单。对于存储历史数据的分区文件组,可以将文件组类型设置为只读模式,每月定期对其进行DBCCCHECKFILEGROUP操作即可。对于当前的数据,可以在每星期定期单独进行DBCC CHECKFILEGROUP操作。对于没有分区机制的大型数据库来说,运行DBCC CHECKDB操作就比较耗时了。解决的方法是使用另外一台服务器,将正常使用的数据库备份恢复到该机上,在该机上执行DBCC CHECKDB检测即可。之后在备份服务器上使用DBCC CHECKDB指令,对数据库进行检测,如果发现问题,就说明至少在数据库的备份时间点,数据库就已经存在故障了。

数据库修复实例分析

这里就以SQL Server 2014为例,来说明如何修复数据库。例如,当打开目标数据库时,SQL Server弹出“SQL Server检测到基于一致性的逻辑I/O错误不正确”的警告信息,提示在数据库文件特定偏移量位置,对数据库某ID页的执行读取期间有错误发生,并提示这是一个威胁数据库完整性的严重错误,必须立即纠正。在SQL Server Mangment Studio窗口左侧选择目标数据库,在工具栏上点击“新建查询”按钮,输入并执行“dbcc checkdb”命令,在窗口底部的“消息”面板中出现大量的红色的错误信息。因为没有及时创建数据库备份,所以无法完美的恢复数据库。这就要求在允许损失一些数据的情况下,尽可能的修复数据库。在执行修复之前,需要断开用户访问。

输入“DECLARE @temp NVARCHAR(20)”,“DECLARE myCurse CURSOR”,“FOR”,“SELECT spid”,“FROMsys.sysprocesses”,“WHERE dbid=DB_ID('xxxxxx')”,“OPEN myCurse”,“FETCH NEXT FROM myCurse INTO @temp”,“WHERE @@FETCH_STATUS = 0”,“BEGIN”,“EXEC('kill'+@temp)”,“FETCH NEXT FROM myCurse INTO @temp”,“ END”,“CLOSE myCurse”,“DEALLOCATE myCurse”等语句, 其中的“xxxxxx”表示具体的数据库名称。点击工具栏上的“执行”按钮,执行上述语句,其作用是关闭其他用户进程。之后就可以执行数据库的修复操作了,例如输入“USE Master”,“Go”,“DECLARE@Data basename varchar(255)”,“SET @Databasename='xxxxxx'”,“ALTER Database xxxxxx SET SINGLE_USER WITH ROLLBACK IMMEDIATE”,“DBCC Checkd b(@Databasename,REPAIR_ALLOW_DATA_LOSS)”,“DBCC Check(@Databasename,REPAIR_REBUILD)”,“ALTER Database xxxxxx SET MULTI_USER WITH ROLLBACK IMMEDIATE”等语句,其中的“ALTER Database xxxxxx SET SINGLE_USER WITH ROLLBACK IMMEDIATE”语句的作用是将目标数据库设置为单用户状态。

对于SQL Server 2005版本的数据库来说,可以将其替换为“EXEC SP_dboption @ databasename,N’single’,N’true’”语句。最后的“ALTER Database xxxxxx SET MULTI_USER WITH ROLLBACK IMMEDIATE”语句的作用是将目标数据库设置为多用户状态。如果是SQL Server 2005版本,可以替换为“EXEC SP_dboption @databasename,N’single’,N’false’”实 现同样的功能。执行上述语句,执行针对目标数据库的修复操作。当然,在实际操作数据库时,可能会遇到各种错误,例如当对目标数据库执行事务操作时,对数据库某个表的内容进行Update操作,之后执行“CheckPoint”项,立即将修改的内容写入到数据文件中。之后执行了一个延迟操作,然后在同一事务中又执行了一个Update操作,对相同的数据表的内容进行了更改。

当第一个修改完成后,第二个修改操作还没有进行时,SQL Server主进程“sqlservr.exe”突然异常退出,并且因为某些原因,数据库日志文件出现受损的情况,造成重启SQL Server后,无法将前一个修改操作进行回滚,无法保持数据的一致性。这样,当重新连接SQL Server后,在SQL Server Mangment Studio窗口中就会发现目标数据库处于恢复挂起状态。根据系统显示的错误编号为“5105”,严重性为16,状态为1等信息,说明日志文件出现了问题。点击“管理”→“SQL Server日志”项,在其下选择当前日志项目,在日志查看器窗口左侧选择合适的存档编号,在日志中可以发现日志损坏的相关信息。例如无法重新生成日志等,其原因是数据库异常关闭时存在打开的事务/用户,该数据库没有检查点或者该数据库是只读的等。此刻,如果没有数据库备份的话,只能对数据库进行修复操作。

输入并执行“ALTER DATABASE TESTDB10 SET EMERGENCY”语句,将数据库设置为紧急状态,之后执行上述语句,将数据库设置设置为单用户状态,注意将其中的“WHERE dbid= DB_ID('xxxxxx')”修改为合适的数据库名称。之后执行“ALTER DATABASE xxxxxx Rebuild LOG on (name=xxxxxx_log,filename='D:shujukuxxxxxx.LDF')”,“ALTER DATABASE xxxxxx SET MULTI_USER”等语句,对日志文件进行重建处理,并将数据库恢复为多用户状态。对于受损的数据库,系统会显示“SQL Server检测到基于一致性的逻辑I/O错误不正确”的警告信息,根据系统显示的错误编号为824,严重性为24,状态为2的信息。

可以执行“ALTER DATABASE xxxxxx set EMGERGENCY”,“ALTER DATABASE xxxxx set single_user with rollback immediate”,“GO”,“DBCC CHECKD B(xxxxxx,'REPAIR_ALLOW_DATA_LOSS')”,“GO”,“ALTER DATABASE xxxxx set multi_user”等语句,可以对目标数据库文件进行修复。当对目标数据库进行刷新后,可以正常使用该数据库。但是,对同一事务中数据操作会出现不一致的情况,虽然对数据库逻辑上分析不存在问题,但是对数据库的应用存在明显的问题,对于日志的修复可能破坏数据库应用的一致性,是迫不得已的方法。所以更根本上说,建议及时对数据库进行备份并根据需要安全的恢复数据,这样才能保证数据在业务逻辑上的一致性。如果数据库出现损坏的情况,系统会显示“SQL Server检测到基于一致性的逻辑I/O错误不正确”的警告信息,根据系统显示的错误编号为 824,928 严重性为 20,24,状态,1,2的信息。可以执行“use master”,“go”,“SP_CONFIGURE 'ALLOW UPDATES',1”,“go”,“RECONFIGURE WITH OVERRIDE”,“go”,“ALTER DATABASE xxxxxx SET EMERGENCY”,“go”,“ALTER DATABASE xxxxxx set single_user with rollback immediate”,“GO”,“DBCC CHECKD B(xxxxxx,'REPAIR_ALLOW_DATA_LOSS')”,“GO”,“ALTER DATABASE xxxxxx set multi_user”,“go”等语句,对数据库进行修复操作。

猜你喜欢

日志备份语句
“备份”25年:邓清明圆梦
VSAT卫星通信备份技术研究
一名老党员的工作日志
扶贫日志
重点:语句衔接
创建vSphere 备份任务
雅皮的心情日志
游学日志
旧瓶装新酒天宫二号从备份变实验室
如何搞定语句衔接题