使用EMERGENCY模式去访问一个RECOVERY PENDING状态或者SUSPECT状态的数据库

来源:互联网 发布:绝对值编码器plc编程 编辑:程序博客网 时间:2024/05/22 04:50

        目前在搜索引擎中搜索到的最常见的blog,是关于修复一个质疑的或者未恢复的数据库。解决这些问题的最好方式是使用你的备份,拥有一个备份策略,可以让你花最少的时间去恢复,并且没有数据丢失。因为某种原因,你没有备份,怎么办?那么,取决于数据库里的什么损坏了且损坏何时被发现的。

        当数据库损坏时,数据库处于3种状态:

      1.ONLINE

              1.如果数据库的一个数据文件损坏且在一个query中或者一些其他的操作中,这个损坏正好碰上,数据库将保持online且可以访问。

      2.RECOVERY PENDING

              1.如果SQL SERVER知道recovery要在数据库中运行某些东东从一开始就阻止,数据库将处于这种状态。 这不同于SUSPECT,因为没说会失败---只是没开始。

              2.一个例子当数据库没有正常的关闭(比如至少有一个未提交的活动事务时,数据库关了)且日志文件被删  

      3.SUSPECT 

              1.如果事务日志损坏,它将阻止恢复或者事务完全回滚,此时,数据库将处于这种状态。

              2.一些例子:

                    *  当数据库没有正常关闭时,恢复努力去读损坏的数据页或者遇到一个损坏的日志记录。

                    *  一个通常的事务回滚,努力去读损坏的数据页或者遇到一个损坏的日志记录。

       你可以在sys.databases目录视图里查看一个数据库的状态:

            SELECT  [state_desc]  FROM  [sys].[databases]  WHERE  [name]  =  N'数据库名';
            GO

       或者使用DATABASEPROPERTYEX函数:

              SELECT  DATABASEPROPERTYEX (N'数据库名', N'STATUS');
              GO

       请注意:当数据库是RECOVERY PENDING状态时,DATABASEPROPERTYEX返回SUSPECT,我将在下面演示。

       因此数据库所处的状态决定你能做什么,如果你没有备份。最容易的情况是当数据库还处于ONLINE状态。在这种情况下,你可能运行repair消除损坏,最有可能的是一些数据丢失,然后采取步骤阻止损坏再次发生。如果repair不能修复所有的错误,在没有备份的情况下,你唯一的选择是提取尽可能多的数据到一个新的数据库里。

       另外2种数据库状态是更困难的,使得人们去寻找帮助。在这种情况下,数据库根本不能访问,因为恢复没有运行或者完成,因此数据库处于不一致的状态。它可能是逻辑上的不一致(比如一个事务修改数据没有恢复)或者更糟糕它可能是结构上的不一致(比如一个系统事务修改索引关系没有恢复)。无论哪种方式,SQL Server想阻止你进入数据库,因为它不知道数据库的数据和结构处于什么状态。但是如果你没有备份,你需要进入数据库,不论事物处于什么样的状态。

       你可以使用EMERGENCY模式。在SQL Server 2005中,sysadmin角色中的成员可以使数据库处于EMERGENCY状态中:

         ALTER  DATABASE  [数据库名]  SET  EMERGENCY; 
         GO

       一旦处于EMERGENCY状态,仅仅只有sysadmin角色中的成员可以访问数据库。数据库只读,什么都不能写入事务日志。

      看看下面的例子:

          CREATE  DATABASE  [emergencydemo]; 
          GO 
          USE  [emergencydemo]; 
          GO

          CREATE  TABLE  [salaries]  ( 
                         [FirstName]     CHAR (20), 
                         [LastName]     CHAR (20), 
                         [Salary]             INT); 
          GO  

          INSERT  INTO  [salaries]  VALUES  ('John', 'Williamson', 10000); 
          INSERT  INTO  [salaries]  VALUES ('Stephen', 'Brown', 12000);  
          INSERT  INTO  [salaries]  VALUES ('Jack', 'Bauer', 10000);
          GO

       我将开始一个显示的用户事务,更新表中的一行:

          BEGIN  TRANSACTION; 
          GO

          UPDATE  [salaries]  SET  [Salary]  =  0  WHERE  LastName  =  'Brown'; 
          GO

        现在我将强制持有更新行的数据页写入磁盘:

          CHECKPOINT; 
          GO

       因此我们有了一个活动的,未提交的事务,就是更改了表,表的更改写入了磁盘。如果此时断电了,故障恢复将运行,事务将回滚。我将通过关闭SQL Server来模拟这个。在另外一个连接里:

          SHUTDOWN  WITH  NOWAIT; 
          GO

          使用登录名 rickcom\cjadcom 的 NOWAIT request 已将服务器关闭。
             SQL Server 正在终止此进程。

       我也将通过删除日志文件模拟损坏事务日志。

       现在我再次启动SQL Server,我们可以在错误日志里看到下面的内容:

       12/26/2013 14:59:06 spid19s        Starting up database 'emergencydemo'.
       12/26/2013 14:59:07 spid19s        错误: 17207,严重性: 16,状态: 1。
       12/26/2013 14:59:07 spid19s        FileMgr::StartLogFiles: Operating system error 2(系统找不到指定的文件。)  occurred while creating or opening file 'D:\……\emergencydemo_log.LDF'. Diagnose and correct the operating system error, and retry the operation。
       12/26/2013 14:59:07 spid19s        文件激活失败。物理文件名称'D:\……\emergencydemo_log.LDF'可能不正确。
       12/26/2013 14:59:07 spid19s        无法重新生成日志。原因是数据库关闭时存在打开的事务/用户

          数据库没有干净的关闭,事务日志不可用,因此恢复不能运行。最后的消息让人感兴趣--在SQL Server 2005中,有个特性,如果你附加或者打开一个数据库,没有事务日志文件,数据库是干净关闭的,SQL Server将自动产生一个新的日志文件。然而在我们这种情况下不能发生。

      如果我尽力进入数据库会发生什么。

        USE [emergencydemo]; 
        GO

       消息 945,级别 14,状态 2,第 1 行
         由于文件不可访问,或者内存或磁盘空间不足,所以无法打开数据库 'emergencydemo'。有关详细信息,请参阅SQL Server 错误日志。

       那么数据库处于什么状态?

         SELECT DATABASEPROPERTYEX (N'emergencydemo', N'STATUS'); 
         GO

       返回SUSPECT。但是使用sys.databases表

         SELECT [state_desc] FROM [sys].[databases] WHERE [name] = N'emergencydemo'; 
         GO

       返回RECOVERY PENDING。这是我前面预料的,恢复甚至没有机会开始。

       现在我将数据库设为EMERGENCY模式,我可以进去看看里面的东东处于什么状态:

         ALTER DATABASE [emergencydemo] SET EMERGENCY;  

         GO

       当一个数据库被设为EMERGENCY模式后,你在错误日志里看到:

         12/26/2013 16:07:52 spid53     Setting database option EMERGENCY to ON for database emergencydemo.

         12/26/2013 16:07:52 spid53     Starting up database 'emergencydemo'.

         12/26/2013 16:07:52 spid53     The database 'emergencydemo' is marked EMERGENCY_MODE and is in a state that does not allow recovery to be run.

      我们再次试用数据库吧:

        USE [emergencydemo]; 
        GO 

      这次好了。数据是什么状态?

        SELECT  *  FROM  [salaries]; 
        GO

    FirstName                LastName                    Salary  

----------------------      ------------------------      --------------------

             John                              Williamson                           10000

           Stephen                              Brown                                  0

              Jack                                Bauer                                10000

     不一致,就像我预料的。

 

翻译自:http://www.sqlskills.com/blogs/paul/search-engine-qa-4-using-emergency-mode-to-access-a-recovery-pending-or-suspect-database/

不对的地方请指正,谢谢!!

        

 


      

         

         

 


 

             

 

 

 

                 

 

 

                              

0 0
原创粉丝点击