백업과 복구
복구 모델을 선택하고 특정 시점으로 되돌립니다.
실습용 데이터베이스를 따로 만듭니다
이 단원은 데이터베이스를 실제로 지웠다가 되돌립니다.
MssqlLab 을 복원해 버리면 앞 단원의 실습 상태가
사라지므로 작은 것을 따로 만들어 사용합니다.
CREATE DATABASE MssqlLabBak; ALTER DATABASE MssqlLabBak SET RECOVERY FULL; GO USE MssqlLabBak; GO CREATE TABLE dbo.T_LOG ( num int IDENTITY PRIMARY KEY, memo nvarchar(100), reg_date datetime2(0) NOT NULL DEFAULT SYSDATETIME() ); INSERT INTO dbo.T_LOG (memo) VALUES (N'첫 번째'), (N'두 번째'), (N'세 번째');
백업 파일을 둘 폴더도 하나 만들어 두십시오. 아래에서는
C:\mssql-lab-backup\ 을 사용한 것으로 적습니다.
SQL Server 서비스 계정이 쓸 수 있는 폴더여야 합니다.
복구 모델이 나머지를 정합니다
어디까지 되돌릴 수 있는가는 복구 모델이 정합니다. 백업 계획을 세우기 전에 이것부터 정해야 합니다.
| 모델 | 로그 | 로그 백업 | 되돌릴 수 있는 지점 |
|---|---|---|---|
| SIMPLE | 커밋되면 재사용됩니다 | 할 수 없습니다 | 마지막 백업 시점까지 |
| FULL | 로그 백업 전까지 쌓입니다 | 해야 합니다 | 원하는 시각까지 |
| BULK_LOGGED | 대량 작업만 줄여 기록합니다 | 해야 합니다 | 대량 작업 구간은 시점 지정 불가 |
ALTER DATABASE MssqlLabBak SET RECOVERY SIMPLE; GO BACKUP LOG MssqlLabBak TO DISK = 'C:\mssql-lab-backup\x.trn';
SIMPLE 은 편해 보이지만 "마지막 백업 이후는 전부 잃는다" 는 뜻입니다. 하루 한 번 백업한다면 최대 하루치입니다. 그것이 괜찮은 자료인지 업무 쪽과 먼저 정하십시오. 사고가 난 다음에 정할 수는 없습니다.
백업 세 가지
-- 전체 — 그 시점의 데이터베이스 전부입니다. BACKUP DATABASE MssqlLabBak TO DISK = 'C:\mssql-lab-backup\Lab_full.bak' WITH INIT, NAME = N'전체'; -- 차등 — 마지막 전체 백업 뒤에 바뀐 것만입니다. BACKUP DATABASE MssqlLabBak TO DISK = 'C:\mssql-lab-backup\Lab_diff.bak' WITH INIT, DIFFERENTIAL, NAME = N'차등'; -- 로그 — 마지막 로그 백업 뒤의 기록입니다. BACKUP LOG MssqlLabBak TO DISK = 'C:\mssql-lab-backup\Lab_log1.trn' WITH INIT, NAME = N'로그1';
| 종류 | 크기 | 담는 것 |
|---|---|---|
| 전체 | 3.27 MB | 그 시점 전부 |
| 차등 | 1.27 MB | 전체 백업 뒤 바뀐 것 |
| 로그 | 0.07 MB | 마지막 로그 백업 뒤의 기록 |
| 옵션 | 뜻 |
|---|---|
| INIT | 그 파일의 기존 백업을 지우고 새로 씁니다 |
| NOINIT | 뒤에 덧붙입니다(기본값) |
| CHECKSUM | 읽으면서 검사합니다. 붙이는 편이 낫습니다 |
| COPY_ONLY | 백업 순서를 건드리지 않습니다 |
| COMPRESSION | 압축합니다. 에디션에 따라 막힙니다 |
COPY_ONLY 는 "지금 한 벌 떠 두고 싶다"
는 자리에 씁니다. 개발 서버로 옮기려고 백업을 뜰 때 그냥 뜨면
차등 백업의 기준점이 그리로 옮겨 가 정규 백업 순서가
흐트러집니다. COPY_ONLY 를 붙이면 그런 일이
없습니다.
파일 안을 들여다봅니다
-- 무엇이 들어 있습니까 RESTORE HEADERONLY FROM DISK = 'C:\mssql-lab-backup\Lab_full.bak'; -- 어떤 파일들로 이루어져 있습니까 RESTORE FILELISTONLY FROM DISK = 'C:\mssql-lab-backup\Lab_full.bak'; -- 이 파일이 성한가 RESTORE VERIFYONLY FROM DISK = 'C:\mssql-lab-backup\Lab_full.bak';
| BackupName | 종류 | DatabaseName | RecoveryModel | 마친 시각 |
|---|---|---|---|---|
| 전체 | Database | MssqlLabBak | FULL | 2026-09-03 20:27:04 |
| LogicalName | PhysicalName | Type |
|---|---|---|
| MssqlLabBak | C:\…\MssqlLabBak.mdf | D |
| MssqlLabBak_log | C:\…\MssqlLabBak_log.ldf | L |
지운 것을 되돌립니다
실제로 사고를 내고 사고 직전으로 되돌려 봅니다. 지금까지 만들어 둔 것은 전체 백업(3행) · 로그1(5행) · 차등(6행)입니다.
USE MssqlLabBak; GO SELECT COUNT(*) FROM dbo.T_LOG; SELECT CONVERT(varchar(23), SYSDATETIME(), 121) AS 사고직전시각; GO -- 사고가 납니다. WHERE 를 빠뜨렸다고 합시다. DELETE FROM dbo.T_LOG; SELECT COUNT(*) FROM dbo.T_LOG;
| 값 | |
|---|---|
| 사고 전 행수 | 6 |
| 사고 직전 시각 | 2026-09-03 20:27:04.573 |
| 사고 뒤 | 0 |
가장 먼저 할 일은 지금 로그를 백업하는 것입니다. 사고 이후의 기록까지 떠 두어야 그 안의 어느 시점으로든 갈 수 있습니다. 이것을 하지 않으면 마지막 백업 이후가 통째로 사라집니다.
USE master; GO BACKUP LOG MssqlLabBak TO DISK = 'C:\mssql-lab-backup\Lab_log2.trn' WITH INIT, NAME = N'로그2 — 사고 뒤';
세 단계로 되돌립니다
USE master; GO ALTER DATABASE MssqlLabBak SET SINGLE_USER WITH ROLLBACK IMMEDIATE; GO -- 1. 전체 백업을 올립니다. 아직 열지 않습니다. RESTORE DATABASE MssqlLabBak FROM DISK = 'C:\mssql-lab-backup\Lab_full.bak' WITH NORECOVERY, REPLACE; GO -- 2. 차등을 얹습니다. 전체 백업 뒤의 변화가 한 번에 따라옵니다. RESTORE DATABASE MssqlLabBak FROM DISK = 'C:\mssql-lab-backup\Lab_diff.bak' WITH NORECOVERY; GO -- 3. 로그를 그 시각까지만 적용하고 엽니다. RESTORE LOG MssqlLabBak FROM DISK = 'C:\mssql-lab-backup\Lab_log2.trn' WITH RECOVERY, STOPAT = '2026-09-03 20:27:04.573'; GO ALTER DATABASE MssqlLabBak SET MULTI_USER;
| name | 상태 |
|---|---|
| MssqlLabBak | RESTORING |
| num | memo |
|---|---|
| 1 | 첫 번째 |
| 2 | 두 번째 |
| 3 | 세 번째 |
| 4 | 네 번째 |
| 5 | 다섯 번째 |
| 6 | 여섯 번째 |
| 옵션 | 뜻 |
|---|---|
| NORECOVERY | 더 얹을 것이 있습니다. 데이터베이스를 열지 않습니다 |
| RECOVERY | 이것이 마지막입니다. 열어서 사용할 수 있게 합니다 |
| REPLACE | 같은 이름이 이미 있어도 덮어씁니다 |
| STOPAT | 그 시각까지만 적용합니다 |
| MOVE | 파일 경로를 바꿉니다. 다른 서버로 옮길 때 씁니다 |
마지막 하나만 RECOVERY 입니다.
중간에 실수로 RECOVERY 를 붙이면 그 뒤를 더 얹지
못하고 처음부터 다시 해야 합니다.
운영 중인 것을 덮어쓰지 말고 다른 이름으로 복원하십시오.
RESTORE DATABASE 복구용 … WITH MOVE … 로 옆에
올린 뒤 필요한 행만 옮겨 오는 것이 안전합니다. 사고 이후에
들어온 정상 자료까지 날리는 일이 없습니다.
얼마나 자주 뜹니까
두 가지를 먼저 정합니다. 기술이 아니라 업무 쪽과 정할 일입니다.
| 정할 것 | 묻는 방법 | 정해지면 |
|---|---|---|
| 얼마나 잃어도 됩니까 | "몇 분치까지 다시 입력할 수 있습니까" | 로그 백업 주기가 정해집니다 |
| 얼마나 빨리 살려야 합니까 | "몇 시간까지 멈춰도 됩니까" | 전체·차등 주기가 정해집니다 |
15분치를 잃어도 된다면 로그 백업을 15분마다 뜨면 됩니다. 복원 시간을 줄이려면 차등을 중간에 끼웁니다 — 전체 하나에 로그 96개를 얹는 것보다 전체 · 차등 · 로그 몇 개가 훨씬 빠릅니다.
-- 흔한 계획입니다. -- 일요일 새벽 전체 -- 그 밖의 새벽 차등 -- 15분마다 로그 -- 마지막 백업이 언제였는지 늘 확인할 수 있게 해 두십시오. SELECT d.name AS DB, d.recovery_model_desc AS 복구모델, MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END) AS 마지막전체, MAX(CASE WHEN b.type = 'I' THEN b.backup_finish_date END) AS 마지막차등, MAX(CASE WHEN b.type = 'L' THEN b.backup_finish_date END) AS 마지막로그 FROM sys.databases d LEFT JOIN msdb.dbo.backupset b ON b.database_name = d.name WHERE d.database_id > 4 GROUP BY d.name, d.recovery_model_desc;
| DB | 복구모델 | 마지막전체 | 마지막로그 |
|---|---|---|---|
| MssqlLabBak | FULL | 2026-09-03 20:27:04 | 2026-09-03 20:27:06 |
| MssqlLab | SIMPLE | NULL | NULL |
FULL 로 바꿔 두고 로그 백업을 뜨지 않는 것이 가장 흔한
사고입니다. 로그가 지워지지 않아 계속 커지다가
디스크를 다 채우고 데이터베이스가 멈춥니다.
log_reuse_wait_desc 가
LOG_BACKUP 이면 그 상태입니다(5.7).
직접 해보기
백업이 제때 돌고 있는지 한눈에 보는 문장을 만들어 보세요. 며칠째 백업이 없거나, FULL 인데 로그 백업이 없는 것을 찾아야 합니다.
운영 중인 데이터베이스에서 Board.COMMENTS
의 어제치 1,000행을 실수로 지웠습니다. 그 뒤로도 글과 댓글이 계속
들어오고 있습니다. 어떻게 되살리겠습니까.
실습에서 만든 것을 지웁니다.
ALTER DATABASE MssqlLabBak SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE MssqlLabBak;
백업 파일을 둔 폴더도 함께 정리하십시오.
- 복구 모델이 나머지를 정합니다. SIMPLE 이면 로그 백업 자체가 막히고(4208) 시점 복원도 못 합니다. 마지막 백업 이후는 전부 잃습니다.
- 백업은 셋입니다 — 전체(그 시점 전부) · 차등(전체 백업 뒤 바뀐 것) · 로그(마지막 로그 백업 뒤의 기록).
- 같은 데이터베이스에서 3.27MB · 1.27MB · 0.07MB 였습니다. 차등은 전체 백업이 오래될수록 커집니다.
- 개발용으로 한 벌 뜰 때는
COPY_ONLY를 붙이십시오. 차등의 기준점이 옮겨 가지 않습니다. - 사고가 나면 가장 먼저 지금 로그를 백업합니다. 그것이 있어야 사고 직전으로 갈 수 있습니다.
- 복원은 전체 → 차등 → 로그 순이고, 마지막 하나만
RECOVERY입니다. 중간에 붙이면 처음부터 다시 해야 합니다. STOPAT으로 그 시각까지만 적용합니다. 6행이 0행이 되었다가 6행으로 돌아왔습니다.- 운영을 덮어쓰지 말고 다른 이름으로 복원해 필요한 행만 옮기십시오. 사고 뒤에 들어온 정상 자료를 지키는 방법입니다.
- FULL 로 바꿔 두고 로그 백업을 뜨지 않는 것이 가장 흔한 사고입니다. 로그가 디스크를 채우고 데이터베이스가 멈춥니다.
msdb.dbo.backupset으로 마지막 백업이 언제였는지 늘 볼 수 있게 해 두십시오. 복원은 평소에 한 번 해 봐야 합니다.