墨西哥工厂机房失火,异常断电后开启报表服务器,发现一个数据库OTS状态变为SUSPECT,不能查询,不能查看属性,不能备份。
Windows 2003sp2+SQL Server 2005sp2
1.尝试ONLINE数据库,失败。
Database 'OTS' cannot be opened - it has been marked SUSPECT by recover Explanation
查看对应的数据文件和日志文件,存在.
2.运行checkdb ‘OTS’,提示Database 'OTS' cannot be opened.
3.关闭SQL SERVER,拷出MDF,LDF文件.
*遇到数据库有问题时,最好不要用SQL SERVER的备份,因为全备份会截断事务日志,可能造成数据库无法恢复.也不要做detach和delete动作,这样可能MDF檔再也附加不上去,数据库彻底没用了.事实上,此时也无法进行这些动作。
4.检查磁盘空间是否足够,MEM是否正常.
如果磁盘不再有可用空间,无法完成restore过程,数据库也会被置为suspect状态.
5.开启SQL SERVER,用sa账号登录。
USEmaster
GO
sp_configure'allowupdates',1
GO
RECONFIGUREWITHOVERRIDE
GO
执行sp_resetstatus'OTS',关闭ots数据库的置疑标志。完成后信息如下:
Database'OTS'statusreset!
WARNING:YoumustrebootSQLServerpriortoaccessingthisdatabase!
sp_configure'allowupdates',0
GO
RECONFIGUREWITHOVERRIDE
GO
6.重启SQL SERVER,故障依旧。
7.尝试将OTS数据库改名后新建一同名数据库,失败,不能rename.
8.删除掉OTS数据库,尝试用备份出来的MDF和LDF档新建一个同名数据库。
*不到万不得已,千万不要做删除的动作。事实证明,OTS数据库删除后,数据文件和日志文件再也不能附加上去,故障不能重现。
9.将MDF和LDF文件拷到其他磁盘,再附加,报同样错误.
10.使用sp_attach_single_db只附加MDF檔,仍然报错.
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0x5b206e03; actual: 0x2acd7ef5). It occurred during a read of page (1:79842) in database ID 7 at offset 0x00000026fc4000 in file 'D:\Data\OTS.mdf'.Additional messages in the SQL Server error log or system event log may provide more detail. This is a severe error condition that threatens database integrity and must be corrected immediately. Complete a full database consistency check (DBCC CHECKDB). This error can be caused by many factors; for more information, see SQL Server Books Online.
11.关闭数据库,对磁盘进行扫描.同时修复坏磁盘错误.这个过程持续了相当长时间.完成后,再次开启SQL SERVER,故障依旧.
12.用CREATE DATABASE DBName ON ( FILENAME = N'DBFile' ) FOR ATTACH_REBUILD_LOG附加数据库时出现提示:The log cannot be rebuilt because the database was not cleanly shut down.
13.此时已经没有OTS库可以拿来做恢复了,只好在网上寻找恢复工具.找到一个Recovery for SQL Server,可以从MDF和LDF中将大部分结构和数据恢复出来,但是有部分数据对象有问题,特别是存储过程有一些乱码.
14.新建同名的数据库OTS(数据库文件名也跟以前一样),停止数据库服务,用COPY出来的.mdf文件覆盖新数据库的同名文件,启动数据库服务。
运行alter database OTS set emergency,将数据库设置为emergency mode
运行下面的命令恢复数据库:
use master
exec sp_dboption 'OTS', N'single', N'true' --将目标数据库置为单用户状态
dbcc checkdb('OTS')
数据库CHECK发现大量GAM,SGAM分配错误,和类似以下信息:
Msg 8935, Level 16, State 1, Line 1
Table error: Object ID 862626116, index ID 1, partition ID 72057594055360512, alloc unit ID 72057594063814656 (type In-row data). The previous link (1:66955) on page (1:1183) does not match the previous page (1:200244) that the parent (1:69276), slot 23 expects for this page.
Msg 8935, Level 16, State 1, Line 1
Table error: Object ID 862626116, index ID 1, partition ID 72057594055360512, alloc unit ID 72057594063814656 (type In-row data). The previous link (1:41230) on page (1:1757) does not match the previous page (1:91286) that the parent (1:57623), slot 6
通过系统表查看Object ID 862626116的TABLE,发现PK字段有重复值。
因为此表数据是从其他DB抄过来的,所以数据丢失也没有关系,所以执行下面的语句。
dbcc checkdb('OTS',REPAIR_ALLOW_DATA_LOSS)
提示上面提到的TABLE PK字段有重复值,而GAM,SGAM分配错误已经被repair
dbcc checkdb('OTS',REPAIR_REBUILD)
仍然提示上面提到的TABLE PK字段有重复值。我们暂时不管它,将目标数据库置为多用户状态
exec sp_dboption 'OTS', N'single', N'false'
此时数据库已经可用,再来看那个有问题的TABLE,constraint已经没有了,只剩下PK和index,我们将PK取消掉,查找出有重复值的行,删除掉,再建上PK。
再次运行checkdb 'OTS',已经没有错误。
最后做一次数据库的完整备份。
总结:
1.出现问题时不要惊慌,惊慌的后果往往是不理性的思考甚至不思考就做出一些不可逆的动作。
2.没有把握时,不要轻易做分离数据库、删除数据库、重启数据库服务器动作。
3.在数据库可以打开的时候,使用CheckDB,等待它运行完成并报告所有错误,再根据这些错误来制定修复策略,虽然这个过程会比较长。
4.CheckDB并不能解决一切问题,所有数据只能靠完整的备份来恢复。所以,备份重于一切。如果实在没有办法,也可以借助一些工具,通过读取MDF,LDF档,生成脚本的方法来恢复结构和数据。
5.不管修复动作能不能成功,都要注意查找产生问题的原因,防止再次出现类似问题。