数据库置疑修复评析.docx
《数据库置疑修复评析.docx》由会员分享,可在线阅读,更多相关《数据库置疑修复评析.docx(13页珍藏版)》请在冰豆网上搜索。
数据库置疑修复评析
数据库置疑修复[评析]
数据库置疑修复
数据库置疑的解决方法:
(1):
如果是严重的置疑,就这样解决停止SQL服务,备份你的置疑的数据库的数据文件(直接将MDF,LDF文件拷贝出去就可以).
然后启动SQL服务,再删除置疑的数据库
然后按下面的步骤处理:
1.新建一个同名的数据库
2.再停掉sqlserver(注意不要分离数据库)
3.用原数据库的数据文件覆盖掉这个新建的数据库
4.再重启sqlserver
5.此时打开企业管理器时会出现置疑,先不管,在SQL查询分析器中执行下面的语句(注意修改其中的数据库名)
6.完成后(刷新数据库)一般就可以访问数据库中的数据了,这时,数据库本身一般还有问题,解决办法是,利用数据库的脚本创建一个新的数据库,并将数据导进去就行了.
USEMASTER
GO
SP_CONFIGURE'ALLOWUPDATES',1RECONFIGUREWITHOVERRIDE
GO
UPDATESYSDATABASESSETSTATUS=32768WHERENAME='置疑的数据
库名'
Go
sp_dboption'置疑的数据库名','singleuser','true'
Go
DBCCCHECKDB('置疑的数据库名')
Go
updatesysdatabasessetstatus=28wherename='置疑的数据库
名'
Go
sp_configure'allowupdates',0reconfigurewithoverride
Go
sp_dboption'置疑的数据库名','singleuser','false'
Go
------------------------------------------------------------------------------------------------------------------------
(2)
重置置疑状态
如果SQLServer因为磁盘驱动器不再有可用空间,而不能完成数据库的恢复,那么Microsoft?
SQLServer?
2000会返回错误1105并且将sysdatabases中的status列设为置疑。
按下面的步骤解决这个问题:
执行sp_resetstatus。
用ALTERDATABASE向数据库添加一个数据文件或日志文件。
停止并重新启动SQLServer。
用新的数据文件或日志文件所提供的额外空间,SQLServer应该能完成数据库的恢复。
释放磁盘空间并且重新运行恢复操作。
sp_resetstatus关闭数据库的置疑标志,但是原封不动地保持数据库的其它选项。
注意只有在您的主要支持提供者指导下或有疑难解答建议的做法时,才可以使用sp_resetstatus。
否则,可能会损坏数据库。
由于该过程修改了系统表,系统管理员必须在创建这个过程前,启用系统表更新。
要启用更新,使用下面的过程:
USEmaster
GO
sp_configure'allowupdates',1GO
RECONFIGUREWITHOVERRIDEGO
过程创建后,立即禁用系统表更新:
sp_configure'allowupdates',0GO
RECONFIGUREWITHOVERRIDEGO
只有系统管理员才能执行sp_resetstatus。
执行该过程后,立即关闭SQLServer。
语法为:
sp_resetstatusdatabase_name
下面的例子将关闭PRODUCTION数据库的置疑标志。
sp_resetstatusPRODUCTION
下面是结果集:
Database'PRODUCTION'statusreset!
WARNING:
YoumustrebootSQLServerpriortoaccessingthis
database!
sp_resetstatus存储过程代码
下面是sp_resetstatus存储过程的代码:
IFEXISTS(SELECT*fromsysobjectswherename='sp_resetstatus')
DROPPROCEDUREsp_resetstatus
GO
CREATEPROCsp_resetstatus@dbnamevarchar(30)AS
DECLARE@msgvarchar(80)
IF@@trancount>0
BEGIN
PRINT'Can''trunsp_resetstatusfromwithinatransaction.'
RETURN
(1)
END
IFsuser_id()!
=1
BEGIN
SELECT@msg='YoumustbetheSystemAdministrator
(SA)'
SELECT@msg=@msg+'toexecutethisprocedure.'
RETURN
(1)
END
IF(SELECTCOUNT(*)FROMmaster..sysdatabases
WHEREname=@dbname)!
=1
BEGIN
SELECT@msg='Database'+@dbname+'doesnotexist!
'
PRINT@msg
RETURN
(1)
END
IF(SELECTCOUNT(*)FROMmaster..sysdatabases
WHEREname=@dbnameANDstatus&256=256)!
=1
BEGIN
PRINT'sp_resetstatuscanonlyberunonsuspectdatabases.'
RETURN
(1)
END
BEGINTRAN
UPDATEmaster..sysdatabasesSETstatus=status^256
WHEREname=@dbname
IF@@error!
=0OR@@rowcount!
=1
ROLLBACKTRAN
ELSE
BEGIN
COMMITTRAN
SELECT@msg='Database'+@dbname+'statusreset!
'
PRINT@msg
PRINT''
PRINT'WARNING:
YoumustrebootSQLServerpriorto'
PRINT'accessingthisdatabase!
'
PRINT''
END
GO
-----------------------------------------------------------
---------------------------------
(3)
在MSSQLSERVER中一直有这样的问题,SQLSERVER的状态"置疑",我们先来分析一下SQLSERVER数据库"置疑"的原因:
1.错误的删除日志;
2.硬件(HD)损坏,造成日志和数据文件写错误;
3.硬盘的空间不够,比如日志文件过大;
解决办法:
这是最简单的办法是有数据库的全备份,然后恢复即可.
步骤:
1.删除原始的数据库:
USEMASTER
GO
DROPDATABASEDB_SUEPECT
2.建立同名的数据库:
USEmaster
GO
CREATEDATABASEDB_SUSPECT
ON
(NAME=DBNAME_DAT,
FILENAME='C:
',
SIZE=10,
FILEGROWTH=5)
LOGON
(NAME='DBNAME_LOG',
FILENAME='g:
',
SIZE=5MB,
FILEGROWTH=5MB)
GO
3.恢复数据库:
RESTOREDATABASEDB_SUSPECT
FROMDBNAME_BACKUP.DAT
4.数据库完整性检测:
DBCCCHECKDB('DB_SUSPECT')
5.重新启动MSSQLSERVER服务.
如果没有全备份,那就要用一些特殊的方法:
1.设置数据库为紧急模式
UseMaster
GO
sp_configure'allowupdates',1
reconfigurewithoverride
GO
UPDATEsysdatabasesSETstatus=32768wherename=
'DB_SUSPECT'
GO
2.停掉SQLServer服务:
NETSTOPMSSQLSERVER
3.把原始数据库的数据文件DBNAME_DAT.MDF,DBNAME_LOG.LDF移走:
4.启动SQLServer服务:
NETSTARTMSSQLSERVER
5.重新建立一个同名的数据库DB_SUSPECT;
USEmaster
GO
CREATEDATABASEDB_SUSPECT
ON
(NAME=DBNAME_DAT,
FILENAME='C:
',
SIZE=10,
FILEGROWTH=5)
LOGON
(NAME='DBNAME_LOG',
FILENAME='g:
',
SIZE=5MB,
FILEGROWTH=5MB)
GO
6.设置数据库运行在单用户的模式:
USEMASTER
GO
ALTERDATABASEDB_SUSPECTSETSINGLE_USER
GO
7.停掉SQL服务:
NETSTOPMSSQLSERVER
8.把原来的数据文件再覆盖回来:
9.启动SQLServer服务:
NETSTARTMSSQLSERVER
10.重新设置SQLSERVER的状态:
USEMASTER
GO
EXECsp_resetstatus"DB_SUSPECT"
11.数据库完整性检测:
DBCCCHECKDB('DB_SUSPECT')
12.恢复数据库为多用户模式:
USEMASTER
GO
ALTERDATABASEDB_SUSPECTSETMULTI_USER
GO
13.恢复SQLSERVER原始的配置:
USEMATER
GO
UPDATEsysdatabasesSETstatus=4194320wherename=
'DB_SUSPECT'
GO
14.配置SQLSERVER不允许更新系统表:
USEMASTER
GO
sp_configure'allowupdates',0
reconfigurewithoverride
GO
15.重新启动MSSQLSERVER服务:
最好重新启动操作系统
16.备份数据库:
可以通过SQLSERVER企业管理器或T-SQL.需要备份MASTER和DB_SUSPECT
对该贴的补充:
1.如果不需要恢复到指定的时间点,你可以将数据库的恢复模式配置为简单,这样
UPDATE,DELETE,SELECT就不会记录日志,日志就不会增加的很大:
ALTERDATABASEDB_NAMESETRECOVERYSIMPLE
2.如果你的恢复模式是全部,你一定要配置日志字段收缩:
sp_dboption'databasename','trunc.logonchkpt.',true
sp_dboption'databasename','autoshrink',true
3.通过每日备份将日志收缩:
BACKUPDATABASEDATABASE_NAMETOBACKUP_DEVICES
BACKUPLOGDATABASE_NAMETOLOG_DEVICES
OR
BACKUPLOGDATABASE_NAMEwithtruncate_only
**检查日志的容量:
DBCCSQLPERF(LOGSPACE)这时日志并没有收缩!
4.每天在备份数据库完成之后,重新启动MSSQLSERVERSERVICE.
USEDATABASE_NAME
go
DBCCSHRINKFILE(2,truncateonly)
**检查日志的容量:
DBCCSQLPERF(LOGSPACE)这时日志已经收缩!
5.手动快速收缩日志:
/*runbelowscript,youwillshrinkyoudatabaselogfiles
immediately,inmyexperience,youneedtorunthe
scriptfor3or
4minutesbeforestoppingitmanually*/usedatabasename
dbccshrinkfile(2,notruncate)
dbccshrinkfile(2,truncateonly)
createtablet1(char1char(4000))go
declare@iint
select@i=0
while(1=1)
begin
while(@i<100)
begin
INSERTINTOT1VALUES('A')
SELECT@I=@I+1
END
TRUNCATEtableT1
BACKUPLOGyoudatabasenamewithtruncate_only
end
go
-----------------------------------------------------------
-------
(4)
任何数据库系统都无法避免崩溃的状况,即使你使用了Clustered,双机热备„„仍然无法完全根除系统中的单点故障,何况对于大部分用户来说,无法承受这样昂贵的硬件投资。
所以,在系统崩溃的时候,
如何恢复原有的宝贵数据就成为一个极其重要的问题了。
在恢复的时候,最理想的情况就是你的数据文件和日志文件都完好无损了,这样只需要sp_attach_db,把数据文件附加到新的数据库上即可,或者在停机的时候把所有数据文件(一定要有master等)都copy到原有路径下也行,不过一般不推荐这样的做法,sp_attach_db比较好,虽然麻烦许多。
但是呢,一般数据库崩溃的时候系统是未必能有时间把未完成的事务和脏页等写入磁盘的,这样的情况sp_attach_db就会失败。
那么,寄期望于DBA制定了一个良好的灾难恢复计划吧。
按照你的恢复计划,还原最新的完全备份,增量备份或者事务日志备份,然后如果你的活动事务日志还能读得出来的话,恭喜你~你可以还原到崩溃前的状态。
一般的单位都是没有专职的DBA的,如果没有可用的备份,更可能是最近一次备份的时间过于久远而导致不可接受的数据损失,而且你的活动事务日志也处于不可用的状态,那就是最麻烦的情况了。
不幸的很的是,一般数据库崩溃都是由于存储子系统引起的,而这样的情况是几乎不可能有可用的日志用于恢复的。
那么就只好试一下这些方案了。
当然,是要求至少你的数据文件是存在的,要是数据文件、日志文件和备份都没有了的话,别找我,你可以到楼顶上去唱“神啊,救救我吧”。
首先,你可以试一下sp_attach_single_file_db,试着恢复一下你的数据文件,虽然能恢复的可能性不大,不过假如这个数据库刚好执行了一个checkpoint的话,还是有可能成功的。
如果你没有好到有摸彩票的手气,最重要的数据库没有像你期盼的那样attach上去,不要气馁,还是有别的方案的。
我们可以试着重新建立一个log,先把数据库设置为emergencymode,sysdatabases的status为32768就表示数据库处于此状态。
不过系统表是不能随便改的,设置一下先UseMaster
Go
sp_configure'allowupdates',1
reconfigurewithoverride
Go
然后
updatesysdatabasessetstatus=32768wherename=''
现在,祈求满天神佛的保佑吧,重新建立一个log文件。
成功的机会还是相当大的,系统一般都会认可你新建立的日志。
如果没有报告什么错误,现在就可以松一口气了。
虽然数据是恢复了,可是别以为事情就算完成了,正在进行的事务肯定是丢失了,原来的数据也可能受到一些损坏。
先把SQLServer重新启动一下,然后检查你的数据库吧。
先设置成单用户模式,然后做dbcc
sp_dboption'','singleuser','true'DBCCCHECKDB('')
如果没有什么大问题就可以把数据库状态改回去了,记得别忘了把系统表的修改选项关掉。
updatesysdatabasessetstatus=28wherename=''--当然你
的数据库状态可能不是这个,自己改为合适的值吧。
也可以用sp_resetstatus
go
sp_configure'allowupdates',0
reconfigurewithoverride
Go
checkdb的时候可能报告有一些错误,这些错误的数据你可能就只好丢弃了。
checkdb有几种修复选项,自己看着用吧,不过最后你可能还是得用REPAIR_ALLOW_DATA_LOSS,完成所有修复。
chekcdb并不能完成所有的修复,我们需要更进一步的修复,用DBCCCHECKTABLE对每一个表做检查吧。
表的列表可以用sysobjects里面得到,把OBJECTPROPERTY是IsTable的全部找出来检查一下吧,这样能够基本上解决问题了,如果还报告错误,试着把数据selectinto到另一张表检查一下。
这些都做完了之后,把所有索引、视图、存储过程、触发器等重新建立一下。
DBCCDBREINDEX也许可以帮你一些忙。