트랜잭션로그 파일이 손상된 데이터베이스 복원 하기

 

  • Version : SQL Server 2005, 2008, 2008R2, 2012, 2014

 

SQL Server에서 데이터베이스를 연결할 때 sp_attach_db명령을 사용한다. 하나 이상의 로그파일이있는 경우 여러 로그파일을 다시 작성하려면 CREATE DATABASE … FOR ATTACH_REBUILD_LOG를 사용한다. 아래 스크립트는 AdventureWorks2012의 파일을 현재 데이터베이스 연결한다.

EXEC sp_attach_db @dbname = N'AdventureWorks2012',

@filename1 =

N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Data\AdventureWorks2012_Data.mdf',

@filename2 =

N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Data\AdventureWorks2012_log.ldf';

 

트랜잭션 로그 파일이 없는 경우에는 SP_ATTACH_SINGLE_FILE_DB 명령을 사용한다.

 

MDF만으로 복원작업을 진행 하였을 때 SQL Server 엔진이 트랜잭션로그 누락과 함께 연결실패를 반환하는 경우의 복원 방법에 대해서 알아보자. 실습을 위해 TestDB 데이터베이스를 생성하고 TestTable을 생성 한다.

USE [master]

GO

 

CREATE DATABASE [TestDB]

CONTAINMENT = NONE

ON PRIMARY

( NAME = N'TestDB_file1',

            FILENAME = N'C:\SQL_Data\TestDB_1.mdf',

            SIZE = 128MB ,

            MAXSIZE = UNLIMITED,

            FILEGROWTH = 64MB)

LOG ON

( NAME = N'TestDB_log_file1',

             FILENAME = N'C:\SQL_Data\TestDB_1.ldf',

             SIZE = 8MB,

             MAXSIZE = 2048GB,

             FILEGROWTH = 8MB)

GO

ALTER DATABASE TestDB SET RECOVERY FULL

GO

 

USE TestDB

GO

 

SELECT * INTO TestTable

FROM sys.objects

 

 

트랜잭션이 실행되는 동안 데이터베이스를 셧다운 할 수 있는 시간을 충분히 만들기 위해 다음 스크립트를 실행 한다.

USE TestDB;

GO

 

INSERT INTO dbo.TestTable

SELECT a.*

FROM TestTable a

CROSS JOIN sys.objects b

CROSS JOIN sys.objects c

CROSS JOIN sys.objects d

 

 

다른 SSMS를 실행하여 다음의 스크립트를 실행하여 SQL Server를 중지 한다.

SHUTDOWN WITH NOWAIT

 

 

 

SQL Server가 중지되면 기존에 실행되던 TestTable 인서트 작업은 취소 된다.

 

 

SQL Server 서비스가 중지 되었을 때 TestDB의 트랜잭션 로그를 삭제 한다. 그리고 SQL Server 서비스를 시작한다. 다음과 같은 복구 보류(Recovery Pending)을 확인 할 수 있다.

 

 

이 시점에서 우리는 일치하지 않는 데이터베이스 파일이 있음을 확인 할 수 있다. 먼저 데이터베이스를 삭제하여 시스템 카탈로그를 정리할 수 있다. 우리는 데이터베이스를 복사 또는 이름을 변경하기 위해 데이터베이스를 오프라인 한다.

USE master

GO

 

ALTER DATABASE TestDB SET OFFLINE

GO

 

그리고 데이터베이스를 삭제하여 시스템 카탈로그의 메타데이터를 정리 한다.

USE master

GO

 

DROP DATABASE TestDB

GO

 

 

현재 트랜잭션로그 파일이 없으므로 sp_attach_single_file_db를 사용하여 데이터베이스를 연결한다. 하지만 다음과 같은 에러를 확인 할 수 있다.

USE master

GO

 

EXEC sys.sp_attach_single_file_db @dbname = 'TestDB',

@physname = N'C:\SQL_Data\TestDB_1.mdf'

GO

 

파일 활성화 오류입니다. 물리적 파일 이름 "C:\SQL_Data\TestDB_1.ldf"이(가) 잘못된 것 같습니다.

데이터베이스를 종료할 때 열려 있는 트랜잭션/사용자가 있거나, 데이터베이스에 검사점이 없거나, 데이터베이스가 읽기 전용이므로 로그를 다시 작성할 수 없습니다. 이 오류는 트랜잭션 로그 파일을 수동으로 삭제했거나 하드웨어 또는 외부 오류로 인해 손상된 경우 발생할 수 있습니다.

메시지 1813, 수준 16, 상태 2, 줄 1

새 데이터베이스 'TestDB'을(를) 열 수 없습니다. CREATE DATABASE가 중단됩니다.

 

 

 

CREATE DATABASE..FOR ATTACH를 시도하였지만 다음과 같은 동일한 오류를 확인 할 수 있다.

USE [master]

GO

CREATE DATABASE [TestDB] ON

( FILENAME = N'C:\SQL_Data\TestDB_1.mdf' )

FOR ATTACH_REBUILD_LOG

GO

 

파일 활성화 오류입니다. 물리적 파일 이름 "C:\SQL_Data\TestDB_1.ldf"이(가) 잘못된 것 같습니다.

데이터베이스를 종료할 때 열려 있는 트랜잭션/사용자가 있거나, 데이터베이스에 검사점이 없거나, 데이터베이스가 읽기 전용이므로 로그를 다시 작성할 수 없습니다. 이 오류는 트랜잭션 로그 파일을 수동으로 삭제했거나 하드웨어 또는 외부 오류로 인해 손상된 경우 발생할 수 있습니다.

메시지 1813, 수준 16, 상태 2, 줄 1

새 데이터베이스 'TestDB'을(를) 열 수 없습니다. CREATE DATABASE가 중단됩니다.

 

 

 

다른 방법으로 우선 복구할 더미 데이터베이스를 생성하고 새로 생성된 데이터베이스에 강제로 MDF와 LDF를 연결하여 데이터베이스를 복원한다. 우선 TestDB_Repair이라는 데이터베이스를 생성한다.

USE [master]

GO

 

CREATE DATABASE [TestDB_Repair]

CONTAINMENT = NONE

ON PRIMARY

( NAME = N'TestDB_Repair_file1',

            FILENAME = N'C:\SQL_Data\TestDB_Repair_1.mdf',

            SIZE = 8MB ,

            MAXSIZE = UNLIMITED,

            FILEGROWTH = 64MB)

LOG ON

( NAME = N'TestDB_Repair_log_file1',

             FILENAME = N'C:\SQL_Data\TestDB_Repair_1.ldf',

             SIZE = 8MB,

             MAXSIZE = 2048GB,

             FILEGROWTH = 32MB)

GO

 

그리고 TestDB_Repair 데이터베이스를 오프라인 한다.

USE master

GO

 

ALTER DATABASE [TestDB_Repair] SET OFFLINE WITH ROLLBACK IMMEDIATE

GO

 

분리된 TestDB_Repair 데이터베이스에 기존의 TestDB의 데이터베이스 MDF를 연결하고 LDF는 TestDB_Repair로 연결한다.

USE master

GO

 

ALTER DATABASE [TestDB_Repair] MODIFY FILE(NAME='TestDB_Repair_file1', FILENAME= 'C:\SQL_Data\TestDB_1.mdf')

ALTER DATABASE [TestDB_Repair] MODIFY FILE(NAME='TestDB_Repair_log_file1', FILENAME= 'C:\SQL_Data\TestDB_Repair_1.ldf')

GO

 

데이터베이스를 온라인 하면 다음과 같은 에러를 확인 할 수 있다.

USE master

GO

 

ALTER DATABASE [TestDB_Repair] SET ONLINE

GO

 

메시지 5173, 수준 16, 상태 1, 줄 2

하나 이상의 파일이 데이터베이스의 주 파일과 일치하지 않습니다. 데이터베이스를 연결하려면 올바른 파일 이름으로 작업을 다시 시도하십시오. 이 데이터베이스가 기존 데이터베이스인 경우에는 파일이 손상되었을 수 있으므로 백업에서 파일을 복원해야 합니다.

로그 파일 'C:\SQL_Data\TestDB_Repair_1.ldf'이(가) 주 파일과 일치하지 않습니다. 이 파일이 다른 데이터베이스에서 작성되었거나 로그가 이전에 다시 작성되었을 수 있습니다.

메시지 5181, 수준 16, 상태 5, 줄 2

데이터베이스 "TestDB_Repair"을(를) 다시 시작할 수 없습니다. 이전 상태로 돌아갑니다.

메시지 5069, 수준 16, 상태 1, 줄 2

ALTER DATABASE 문이 실패했습니다.

 

 

 

데이터베이스를 복원하기 위해 TestDB_Repair 데이터베이스를 비상 모드 및 단일 사용자 모드로 변경한다. DBCC CHECKDB REPAIR_ALLOW_DATA_LOSS 옵션을 실행하여 손실된 데이터는 삭제하고 데이터베이스 복원 작업을 진행 한다. 이때 TRACEON(3604)를 실행하여 모든 로그를 출력하여 확인 할 수 있도록 한다. 실행한다. DBCC CHECKDB REPAIR_ALLOW_DATA_LOSS 작업이 완료 되었으면 다중 사용자 모드로 만들어서 서비스를 사용한다.

USE master

GO

 

DBCC TRACEON(3604)

GO

 

ALTER DATABASE TestDB_Repair SET EMERGENCY

GO

 

ALTER DATABASE TestDB_Repair SET SINGLE_USER

GO

 

DBCC CHECKDB('TestDB_Repair', REPAIR_ALLOW_DATA_LOSS) WITH ALL_ERRORMSGS

GO

 

ALTER DATABASE TestDB_Repair SET MULTI_USER

GO

 

 

 

이렇게 해서 트랜잭션 로그가 손상된 데이터베이스에서 일부 데이터 손실을 감안하고(커밋 되지않은 데이터) 복구하는 방법에 대해서 알아 보았다. 하지만 모든 상황에서 복구가 가능한 것은 아니다. 다음의 경우에는 복구 실패한 사례도 있다.

 

 



강성욱 / jevida@naver.com
Microsoft SQL Server MVP
Blog : http://sqlmvp.kr
Facebook : http://facebook.com/sqlmvp

No. Subject Author Date Views
Notice SQL강좌: 챗GPT와 함께 배우는 SQL Server 무료 강좌 목차와 소개 (2023년 9월 업데이트) 코난(김대우) 2023.08.18 36168
Notice Python 무료 강좌 - 기초, 중급, 머신러닝(2023년 6월 업데이트) 코난(김대우) 2021.01.01 18653
» 트랜잭션로그 파일이 손상된 데이터베이스 복원 하기 jevida(강성욱) 2017.01.11 4720
2013 트랜잭션 로그 백업을 읽고 트랜잭션 발생 시간 및 사용자 찾기 jevida(강성욱) 2017.01.11 3375
2012 RESOURCE_GOVERNOR_IDLE과 쿼리 성능 jevida(강성욱) 2017.01.11 2086
2011 TDE 암호화된 데이터베이스 복원 jevida(강성욱) 2017.01.11 2560
2010 재해복구를 위한 SQL Server 역할 가져오기 jevida(강성욱) 2017.01.11 2347
2009 비관리자 계정에 Profiler 실행 권한 부여하기 jevida(강성욱) 2017.01.11 3344
2008 SQL Server Agent 공유 일정 생성하기 jevida(강성욱) 2017.01.11 2226
2007 인덱스 리빌드는 통계를 업데이트 할까? jevida(강성욱) 2017.01.11 2565
2006 인덱스 유지관리 작업과 SQL Server 쿼리 성능 jevida(강성욱) 2017.01.11 3465
2005 네트워크 드라이브에 데이터베이스 복원하기 jevida(강성욱) 2017.01.11 4336
2004 확장 저장 프로시저를 활용한 논리디스크 용량 확인 jevida(강성욱) 2017.01.11 2548
2003 날짜 참조 테이블 만들기 jevida(강성욱) 2017.01.11 3268
2002 인덱스 상세 정보 확인 jevida(강성욱) 2017.01.11 3845
2001 DTC Transacntion 오버헤드 jevida(강성욱) 2017.01.11 1340
2000 대용량 로드를 위한 BULK INSERT 옵션 jevida(강성욱) 2017.01.11 5607
1999 SQL Server 2014 Diagnostic Information Queries jevida(강성욱) 2017.01.11 1667
1998 SQL Server 2012 Contained Database jevida(강성욱) 2017.01.11 1085
1997 SQL Server 2008R2 Diagnostic Information Queries jevida(강성욱) 2017.01.11 1469
1996 SQL Server 2005 Diagnostic Information Queries jevida(강성욱) 2017.01.11 1406
1995 601 Error, Could not continue scan with NOLOCK due to SQL Server data Movement jevida(강성욱) 2017.01.11 4191





XE Login