当SQL SERVER数据库状态为质疑(SUSPECT)状态时,我们可以用以下方法来处理: DBCC报错

1. 修改数据库为紧急模式:ALTER DATABASE DBName SET EMERGENCY .

2. 检查数据库的完整性:DBCC  CHECKDB(‘DBName’)

3. 检查没有错误则恢复数据库为正常模式:ALTER DATABASE  DBName SET ONLINE;

4  如检查数据库有错误则修改数据库为单用户模式,依情况选择以下命令行进行修复数据;

DBCC CHECKDB('DBName',  REPAIR_FAST);

DBCC CHECKDB('DBName',  REPAIR_REBUILD);

DBCC CHECKDB('DBName',  REPAIR_ALLOW_DATA_LOSS);

修复完成后将数据库改为正常模式,重启SQL服务或重启服务器。

   ALTER DATABASE DBName SET EMERGENCY       /* 修改数据库为紧急模式*/
ALTER DATABASE DBName SET SINGLE_USER /* 修改数据库为单用户模式*/
ALTER DATABASE DBName SET MULTI_USER /* 修改数据库为多用户模式*/
ALTER DATABASE DBName SET ONLINE /* 数据库从紧急&单用户&多用户模式恢复为正常模式*/ DBCC CHECKDB('DBName') /* 检查数据库完整性*/
DBCC CHECKDB('DBName', REPAIR_FAST) /* 快速修复数据库*/
DBCC CHECKDB('DBName', REPAIR_REBUILD) /* 重建索引并修复*/
DBCC CHECKDB('DBName', REPAIR_ALLOW_DATA_LOSS) /*如果必要允许丢失数据修复,数据库修复需在单用户模式下进行

数据库质疑修复总结 For SQL Server 2000/2005/2008/2008R2

 转自:https://blogs.msdn.microsoft.com/apgcdsd/2013/06/26/for-sql-server-2000200520082008r2/
 

本文的步骤基于以下条件:

1.     SQL Server可以启动。

2.     数据库没有做有效的备份。

3.     当前用户有Sysadmin权限。

数据库质疑的原因会有多种多样,不同的suspect采用的步骤也会有所不同,以下的步骤不能适用所有的情况,但包括了一些基本的步骤。 数据库suspect是指数据库内部处于不一致的状态,很有可能会有数据丢失。 我们推荐您从“好的数据库备份”恢复。 我们这里所指的“好的数据库备份”是指:

1.  在做数据库备份之前,您检查过DBCC CHECKDB没有错误。

2.  备份之后的数据库没有更改,或者更改可以忽略。

  在做任何修复操作之前,请务必备份.mdf/.ndf以及.ldf文件。

2   SQL Server 2000修复步骤

  如果没有“好的数据库备份”,我们不能保证没有数据丢失。 以下是恢复suspect数据库 (SQL Server 2000)的一般方法,供您参考。 同时在操作下列步骤之前,您可以备份质疑数据库的MDF、NDF、LDF文件,以便以下步骤恢复失败时能够回滚到原来的状态。

1.  在查询分析器中,运行如下命令将数据库置于紧急模式。

  

Sp_configure 'allow update', 1

Go

Reconfigure with override

Go

Begin Tran

Update master..sysdatabases set status = 32768 where name ='<DatabaseName>’

Commit Tran

--此处<DatabaseName>需要替代成您出问题的数据库名字。

--以下同

Go

Select * from sysdatabases

--检查数据库状态是否已经变成 32768

Go

2. 重启SQL Server服务。

3.  如果第二步中重启服务,数据库再次进入suspect模式,请设置数据库紧急模式,使用BCP方式导出数据。

否则在查询分析器中,重新连接到SQL Server,运行如下命令重建日志。

特别注意: dbcc rebuild_log是内部命令,请您阅读附件中的DBCC Rebuild Run Command.doc。 只有当您同意了附件中的内容,才可以运行此命令。

dbcc rebuild_log('<DatabaseName>’,'<The file name and the path of the log file>')

--此处<The file name and the path of the log file>是新的日志文件的物理文件的绝对地址。

go

如果rebuild_log失败,请运行如下命令,

Use <DatabaseName>

Go

如果数据库在emergency 方式能够进入紧急模式,直接使用BCP方式导出数据,没有其他方式来恢复数据库。

如果不能进入,则没有其他方式恢复数据库

如果数据库在Rebuild_log之后恢复正常,进入第四步。

4.  关掉查询分析器,再次打开查询分析器,运行如下语句,查询出问题的数据库的DBID

Select * from master.dbo.sysdatabases

5.  再运行如下命令,检查是否有人在使用当前出问题的数据库,如果有的话,请将他们退出。

  Select * from master.dbo.sysprocesses

6.  然后运行如下命令,将数据库置于单用户使用模式。如果设置不生效,可以尝试使用企业管理器->数据库属性-> 选项来直接设置.

exec sp_dboption N'<DatabaseName>', N'single', N'true'

7.  在查询分析器中,运行如下命令,检查数据库是否有损坏。

  dbcc checkdb(‘<DatabaseName>')

8.  如果您运行上述命令发现数据库有错误。 此时我们需要根据错误来处理。 接下去有两个方向。

方向一:

使用Repair_Allow_Data_Loss选项修复数据库。

优点: 可能可以恢复尽量多的数据

缺点:

a)  不一定能够将全部错误修复,还有可能越修越多。同时,需要大量时间,需要经过多次执行修复命令.十几次,甚至数十次.修复时间不能预估.

b)  就算我们将所有错误修复,我们也不能保证数据在应用程序逻辑这一层次上的数据正确性,您需要找您的应用程序提供商来检查数据在程序逻辑层次是否正确。

dbcc checkdb ('<DB_name>', REPAIR_ALLOW_DATA_LOSS) go

--此命令可能需要运行多次,才能完全修复。

方向二:

通过BCP,DTS,select into等方式将好的表,或者表中好的数据导出来。建议使用BCP的方法,这样可以最大限度的回复数据.BCP会停在出错的纪录上,但是前面的数据就能成功导出.使用DTS或Select into的话, 我们很难判断最大限度能导出的记录数.

优点:导出来的数据保证在应用程序逻辑这一层次的正确性

缺点:不会修复数据库中存在的错误,丢失的数据量会比较大,取决于第7步的运行结果。

9.  数据库完全恢复正常之后,将数据库置于正常状态,并将单用户模式改成多用户模式。(16或者0)

begin tran

  update sysdatabases set status = 8 where name = 'db_name'

commit tran

sp_configure 'allow', 0

reconfigure with override

exec sp_dboption N'<DatabaseName>', N'single', N'false'

另外,在上述步骤之前或者之中,可能会有数据库在企业管理器中看不到,并且无法attach的状况。 通常可以建同名数据库(注意:物理文件名也要一致),停止SQL Server,覆盖文件,重启SQLServer的方式来解决。

3   SQL Server 2005/2008/2008R2修复步骤

方法一

  


use master
alter database <DatabaseName>set emergency  --设置为紧急模式

alter database <DatabaseName>set single_user with rollback immediate  --设置为单用户模式

use <DatabaseName>  --切换到故障数据库

dbcc checkdb  --检查故障数据库

use master  --切换到master

alter database <DatabaseName>Rebuild Log on  --重建日志文件

(name=<DatabaseName>_log,filename='c:\sql\logs\<DatabaseName>_log.LDF')

select * from sys.databases  --验证是否重建成功

dbcc checkdb('<DatabaseName>', repair_allow_data_loss)  --允许丢失数据修复

sp_dboption '<DatabaseName>','single user','false'

方法二

alter database <DatabaseName> set emergency

go

alter database <DatabaseName> set single_user with rollback immediate

go

use master

go

alter database <DatabaseName> Rebuild Log on

(name=<DatabaseName>_log,filename='c:\sql\logs\<DatabaseName>_log.LDF')

go

use <DatabaseName>

go

dbcc checkdb

go

--此时checkdb有错误才需要做步骤d)

d) 此时数据库应处于emergency状态,创建一个新数据库,通过bcp/bulk insert/DTS/SSIS方式将数据导出到新的数据库.

请注意,这种情况下索引,存储过程,视图等,都需要手工导出来。

4             导数据总结

1. 创建一个空的数据库。

2. 使用脚本禁用所有外键约束。

Use <NewDatabase>

GO

DECLARE @disable BIT

set @disable= 1

DECLARE

    @sql VARCHAR(500),

    @tableName VARCHAR(128),

    @foreignKeyName VARCHAR(128)

-- A list of all of the Foreign Keys and the table names

DECLARE foreignKeyCursor CURSOR

    FOR

SELECT

        ref.constraint_name AS FK_Name,

        fk.table_name AS FK_Table

      FROM

        INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS ref

        INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON ref.constraint_name =fk.constraint_name

      ORDER BY

        fk.table_name,

        ref.constraint_name

OPEN foreignKeyCursor

FETCH NEXT FROM foreignKeyCursor INTO @foreignKeyName, @tableName

WHILE ( @@FETCH_STATUS = 0 )

    BEGIN

     IF @disable = 1

        SET @sql = 'ALTER TABLE [' + @tableName + '] NOCHECK CONSTRAINT [' + @foreignKeyName +']'

     ELSE

        SET @sql = 'ALTER TABLE [' + @tableName + '] CHECK CONSTRAINT [' + @foreignKeyName + ']'

        PRINT 'Executing Statement - ' + @sql

     EXECUTE(@sql)

        FETCH NEXT FROM foreignKeyCursor INTO @foreignKeyName, @tableName

    END

CLOSE foreignKeyCursor

DEALLOCATE foreignKeyCursor

    Go

3. 使用脚本禁用所有触发器。

DECLARE    @disable BIT

set @disable= 1

 DECLARE

        @sql VARCHAR(500),

        @tableName VARCHAR(128),

        @tableSchema VARCHAR(128)

-- List of all tables

    DECLARE triggerCursor CURSOR

        FOR

SELECT

        t.TABLE_NAME AS TableName,

        t.TABLE_SCHEMA AS TableSchema

      FROM

        INFORMATION_SCHEMA.TABLES t

      ORDER BY

        t.TABLE_NAME,

        t.TABLE_SCHEMA

    OPEN triggerCursor

    FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema

    WHILE ( @@FETCH_STATUS = 0 )

        BEGIN

            IF @disable = 1

                SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] DISABLE TRIGGER ALL'

            ELSE

                SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] ENABLE TRIGGER ALL'

            PRINT 'Executing Statement - ' + @sql

            EXECUTE ( @sql )

            FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema

        END

    CLOSE triggerCursor

    DEALLOCATE triggerCursor

4.     生成脚本并执行启用Identity_Insert。

select 'SET IDENTITY_INSERT dbo.['+ name +'] on 

go'

from dbo.sysobjects

where type='U'

5.     自动生成脚本导入数据到新的数据库中。(对于存在计算列或者Identity字段的表需要手动修改语句)

select 'insert into NewDB.dbo.'+ name +' select * from '+ name

from dbo.sysobjects

where type='U'

6.     使用脚本启用所有外键约束,触发器,禁用Identity_Insert。

启用外键:

DECLARE  @disable BIT

set @disable= 0

DECLARE

    @sql VARCHAR(500),

    @tableName VARCHAR(128),

    @foreignKeyName VARCHAR(128)

-- A list of all of the Foreign Keys and the table names

DECLARE foreignKeyCursor CURSOR

    FOR

  SELECT

        ref.constraint_name AS FK_Name,

        fk.table_name AS FK_Table

      FROM

        INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS ref

        INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk ON ref.constraint_name =fk.constraint_name

      ORDER BY

        fk.table_name,

        ref.constraint_name

OPEN foreignKeyCursor

FETCH NEXT FROM foreignKeyCursor INTO @foreignKeyName, @tableName

WHILE ( @@FETCH_STATUS = 0 )

    BEGIN

      IF @disable = 1

         SET @sql = 'ALTER TABLE [' + @tableName + '] NOCHECK CONSTRAINT [' + @foreignKeyName +']'

      ELSE

         SET @sql = 'ALTER TABLE [' + @tableName + '] CHECK CONSTRAINT [' + @foreignKeyName + ']'

        PRINT 'Executing Statement - ' + @sql

      EXECUTE(@sql)

        FETCH NEXT FROM foreignKeyCursor INTO @foreignKeyName, @tableName

    END

CLOSE foreignKeyCursor

DEALLOCATE foreignKeyCursor

     Go

启用触发器:

DECLARE  @disable BIT

set @disable= 0

 DECLARE

        @sql VARCHAR(500),

        @tableName VARCHAR(128),

        @tableSchema VARCHAR(128)

    -- List of all tables

    DECLARE triggerCursor CURSOR

        FOR

    SELECT

        t.TABLE_NAME AS TableName,

        t.TABLE_SCHEMA AS TableSchema

      FROM

        INFORMATION_SCHEMA.TABLES t

      ORDER BY

        t.TABLE_NAME,

        t.TABLE_SCHEMA

    OPEN triggerCursor

    FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema

    WHILE ( @@FETCH_STATUS = 0 )

        BEGIN

            IF @disable = 1

                SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] DISABLE TRIGGER ALL'

            ELSE

                SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] ENABLE TRIGGER ALL'

            PRINT 'Executing Statement - ' + @sql

            EXECUTE ( @sql )

            FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema

        END

    CLOSE triggerCursor

DEALLOCATE triggerCursor

禁用Identity_Insert:

select 'SET IDENTITY_INSERT dbo.['+ name +'] off 

go'

from dbo.sysobjects

where type='U'

5       附录

我们可以看到,数据库恢复是一个非常复杂也是非常不可靠的方式,这就要求我们事先做好数据库的备份。以下是我们对数据库备份的一些基本策略,供您参考。

1.对所有的数据库来说,备份策略取决于数据库被修改的频繁程度,以及数据库的重要程度。一般来说,系统数据库不像用户数据库那样会经常的修改。重要的系统数据库有:

  Master

  Master 数据库存储了SQL Server 系统一级的信息,是最重要的数据库。它还包括所有的登陆帐号和所有的系统配置信息。同时它还存储了SQL Server还包含哪些数据库(包括用户数据库),这些数据库存在哪个地方等等信息。

  MSDB

  MSDB 数据库包含了所有作业的的内容和调度信息等等。

  我们建议您每一个星期备份一次系统数据库。同时当您手动更改过系统数据库时,应该立即手动备份一次。比如添加了一个用户,新建了一个数据库,更改了一个作业等等。

2.对所有的用户数据库,如果它是一个重要的数据库,除了用完全的恢复模式外,还需要调度备份您的数据库:

  A)完全备份每周一次

  B)差异备份每天或者每半天一次

  C)日志备份每小时或者半小时一次

注意:

  A)所有的这些都可以用数据库维护计划来完成(Maintenance Plan),同时它也可以自动删除旧的文件,比如说4周之前的,以避免磁盘空间不够的问题。

  B)我们不建议备份到网络磁盘上。以我们的经验,直接备份到网络磁盘会有些问题。

  C)上述备份时间周期仅供参考,您需要根据实际情况制定计划。

数据库被置疑主要是因为数据库data文件或者日志文件损坏. Data文件就是MDF、NDF文件,日志就是事务日志, 通常是LDF文件.

文件损坏的原因有:

(1) 一个最常见的原因是磁盘问题. 如果数据库文件因为磁盘原因而binary受到损坏,那么SQL Server 往往不能从文件正常读取数据,这个时候很容易导致数据库置疑. 对于这种情况, 你往往可以从机器的系统日志中发现磁盘相关的错误. 在SQL Server 的错误日志中也常常可以看到823错误:

错误 823 严重级别 24 消息正文

在文件 ''%4!'' 的偏移量 %3! 处的 %2! 过程中,检测到 I/O 错误 %1!。

注意损坏可以是静态的损坏, 比如磁盘某磁道的问题而导致文件的某部分不能被正常读取等. 也可以是动态的.比方说由于硬件问题,文件在SQL Server 的读写过程中损坏.

(2) 如果SQL Server还在运行而机器突然断电或热启动,那么数据库文件就有损坏的可能.

(3) 一些病毒也可以导致文件损坏

(4) 人为的因素. 比方说日志文件被误删等.

6             引用

Disabling Constraints and Triggers (Quite useful)

http://msdn.microsoft.com/en-us/magazine/cc163442.aspx

联机丛书的管理SQL Server -> 备份和还原数据库这一章节

关于SQL Server 备份和恢复的文章

http://www.microsoft.com/technet/prodtechnol/sql/2000/maintain/sqlbackuprest.mspx

SQL Server 的高可用性

http://support.microsoft.com/?id=822400

How to move SQL Server databases to a new location by using Detach and Attach functions in SQL Server

http://support.microsoft.com/kb/224071

数据库质疑修复(SUSPECT)总结,DBCC报错的更多相关文章

  1. 连接远程MySQL数据库项目启动时,不报错但是卡住不继续启动的,

    连接远程MySQL数据库项目启动时,不报错但是卡住不继续启动的, 2018-03-12 17:08:52.532DEBUG[localhost-startStop-1]o.s.beans.factor ...

  2. dotnetcore ef 调用多个数据库时用户命令执行操作报错

    dotnetcore ef 调用多个数据库时用户命令执行操作报错 1.多个DbContext 时报错: 报错: More than one DbContext was found. Specify w ...

  3. Oracle数据库误删文件导致rman备份报错RMAN-06169解决办法

    Oracle数据库误删文件导致rman备份报错RMAN-06169解决办法 可能是误删文件导致在使用rman备份时候出现以下提示 RMAN-06169: could not read file hea ...

  4. vue-electron 使用sqlite3数据库,执行npm run build 报错 .NET Framework 2.0 SDK,Microsoft Visual Studio 2005[C:\temp\wechat\node_modules\sqlite3\build\binding.sln]

    问题描述 vue-electron 使用sqlite3数据库,执行npm run build 报错如下: .NET Framework 2.0 SDK,Microsoft Visual Studio ...

  5. ORACLE数据导入导出后新数据库中某些表添加操作报错[ORA-12899]

    由于项目需要,我在搭建了新的开发环境后,需要将之前环境中的ORACLE数据库导出,再导入到新的开发环境下.当导出导入完成后,使用数据库进行添加操作时 发现针对很多表的添加操作报错,具体报错原因描述为: ...

  6. MySQL数据库储存bit类型的值报错

    当我们储存bit类型的值时,不能直接写入数字 上图中的画圈部分就是bit类型,若是直接填入"1"或"0"等等就会报错,如下: 这时候,我们要看bit(M)的M值 ...

  7. Mycat分布式数据库架构解决方案--配置defaultAccount属性报错解决方案

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 该文章 ...

  8. flask从数据库反向导入Model以及出现报错No module named sqlacodegen.main

    使用flask的朋友肯定了解了flask_sqlalchemy,不了解的小伙伴也可以查看博文:Flask 操作Mysql数据库 - flask-sqlalchemy扩展 上面博文中讲解了如何将flas ...

  9. IDEA(2018)连接MySQL数据库失败的解决方法(报错08001)

     解决方法: 将url改成: jdbc:mysql://localhost:3306/studentmanage?useSSL=true&serverTimezone=Hongkong& ...

随机推荐

  1. C# Soap调WebService

    public class WebServiceHelper { /// <summary> /// Soap协议Post方法 /// </summary> /// <pa ...

  2. mysql 主库有数据通过锁库做主从

    master@localhost[(none)]> grant replication slave on *.* to 'repl'@'192.168.1.177' identified by ...

  3. 实时竞价(RTB) 介绍(基础篇)

    前言: 说到"实时竞价"大家一定都不陌生,那么为何如今实时竞价发展这么迅猛,当然这个主要得益于总体移动互联网环境的成熟,以及中国本地移动广告市场出现爆发式增长.那么到底什么是实时竞 ...

  4. Python学习之格式符

    %s    字符串 (采用str()的显示) %r    字符串 (采用repr()的显示) %c    单个字符 %b    二进制整数 %d    十进制整数 %i    十进制整数 %o    ...

  5. jquery特效 商品SKU属性规格选择实时联动

    转载,原文链接 功能:各种属性的值选中后,SKU填写表格进行变动,对属性.属性值的数量自适应,编辑时不因去掉勾选导致原有值不显示 所有代码均属原创,现在共享,如果有更好的实现方式,希望互相交流 最终实 ...

  6. 【转载】java连接MYSQL

    原文出自 http://qq163230530.blog.163.com/blog/static/4289250620081186262719/ 这篇文章主要以MySQL为例讲下Java如何连接到数据 ...

  7. php基本语法之逻辑运算符

    百度经验 | 百度知道 | 百度首页 | 登录 | 注册 新闻 网页 贴吧 知道 经验 音乐 图片 视频 地图 百科 文库 帮助 首页 分类 杂志 任务 签到 回享计划 商城 知道 百度经验 > ...

  8. 图谱论(Spectral Graph Theory)基础

    拉普拉斯矩阵(Laplacian matrix),也称为导纳矩阵(Admittance matrix)或者基尔霍夫矩阵(Kirchohoff matrix) 归一化的拉普拉斯矩阵定义为 例子: 拉普拉 ...

  9. 如何给Eclipse添加一个JDK或JRE

    第一:  第二:  第三:  第四: 

  10. 浅谈IM软件怎样建立安全socket连接、登录

    ----------------------------------------------------欢迎查看IM软件业务知识<专栏>-------------------------- ...