데이터베이스 백업과 복원 작업은 데이터베이스 속성인 복구 모델 설정에 영향을 받으며 복구 모델이란 데이터 베이스의 트랜잭션 로그를 관리하는 방법의 유형이다.

 

복구 모델은 단순(Simple), 전체(Full), 대량 로그(Bulk Logged) 3가지가 있다.

 

※ 데이터베이스 복구 모델 확인 스크립트

SELECT Name,
      (SELECT DATABASEPROPERTYEX(name,'RECOVERY') AS RecoverModel
  FROM master..sysdatabases 
 ORDER BY Name

 

(1) 단순 (Simple)

체크포인트가 발생할 때마다 트랜잭션 로그가 비워지는 모델.

트랜잭션이 보관 되지 않으므로 트랜잭션 로그백업을 지원하지 않으며, 복원 시 전체 또는 차등 백업한 시점까지만 복원 할 수 있고 원하는 특정 시점이나 페이지 복원은 불가능 하다. 

이에 트랜잭션 로그의 저장소 공간은 작지만 마지막 전체, 차등백업 이후 데이터는 손실 될 수 있다.

테스트 환경 또는 데이터 베이스 용량이 적을때 많이 사용한다.

단순 복구 모델 사용 시 데이터 손실을 방지하기 위해서 주기적인 전체 또는 차등 백업을 권장.

 

(2) 대량로그 복구 모델(Bulk Logged)

BCP, Bulk INSERT, SELECT INTO , CREATE INDEX, DBDCC DBREINDEX , DROP INDEX 등 대량의 변경 작업을 처리하는 대량(Bulk) 명령을 수행 할 때, 발생하는 모든 트랜잭션 로그를 기록하지 않고 최소한의 로깅을 제공하여 전체 복구 모델에 비해 빠른 성능을 가지고 있다.

 

(3) 전체 복구 모델(Full)

대량 작업, 인덱스 생성 정보까지 모든 트랜잭션을 기록하는 모델이다.

SQL SEVER에서 지원하는 모든 백업 유형을 사용할 수 있다. 특정 시점 복원이나 데이터 손실을 방지 할 수 있으나 그만큼 용량과 비용이 많이 발생된다.

 

13번에서 DMV를 소개했지만 다시 한번 공부해보고자 정리!

 

DMV를 활용해서 직접 확인하는 경우도 있지만

보통은 스크립트로 저장해서 필요할때마다 확인하는 경우가 많은 것 같다.(나의 경우..)

DMV 개수도 많고 외워두면 편하긴 하지만 필요할때마다 일일히 짜기도 귀찮기도해서

몇가지 자주쓰는 스크립트로 DMV를 활용할 수 있도록 만들어 두는 것이 좋을 것 같다.

(사실 노트북에 있는데 귀찮아서 찾아보고 공부!!)

출처는 구글링을 통해 여기저기서 가져오고 필요한것과 필요없는것을 수정하는 방식으로...

 

(1) CPU 소모량이 많은 Stored Procedure 찾기

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT db_name(C.dbid) AS DBName 
       ,object_schema_name(C.objectid,dbid) AS SchemaName 
       ,object_name(C.objectid,dbid) AS StoredProcedure 
       ,sum(B.execution_count) AS Execution_count 
       ,sum(B.total_worker_time) AS total_cpu_time 
       ,sum(B.total_worker_time) / (sum(B.execution_count) * 1.0) AS avg_cpu_time 
FROM sys.dm_exec_cached_plans AS A
JOIN sys.dm_exec_query_stats  AS B on A.plan_handle=B.plan_handle
CROSS APPLY sys.dm_exec_sql_text(A.plan_handle)  AS C
WHERE db_name(C.dbid) is not null and A.objtype='proc'
GROUP BY db_name(C.dbid), object_schema_name(objectid,C.dbid), object_name(objectid,C.dbid)
ORDER BY sum(B.total_worker_time) DESC
 
cs

 

 

(2) 비용이 드는 쿼리 찾기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT TOP 20   
       SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,  
       (( CASE qs.statement_end_offset  
          WHEN -1 THEN DATALENGTH(qt.TEXT)  
          ELSE qs.statement_end_offset 
          END - qs.statement_start_offset)/2)+1) AS 수행쿼리,  
        qs.execution_count              AS 쿼리계획이_마지막컴파일후_실행횟수,  
        qs.total_logical_reads          AS 쿼리계획이_컴파일후_실행될때_수행한_총논리적읽기수,  
        qs.last_logical_reads           AS 마지막_수행한_논리적읽기수,  
        qs.total_logical_writes         AS 쿼리계획이_컴파일후_실행될때_수행한_총논리적쓰기수,   
        qs.last_logical_writes          AS 마지막_수행한_논리적쓰기수,  
        qs.total_worker_time            AS [쿼리계획이_컴파일후_실행될때_사용된_총CPU시간(마이크로초)],   
        qs.last_worker_time             AS [마지막_실행될때_사용된_CPU시간(마이크로초)],  
        qs.total_elapsed_time/1000000     AS [실행완료하는데 소요된 총 경과시간(마이크로초)_초로변환],  
        qs.last_elapsed_time/1000000     AS [최근 실행완료하는데 소요된 경과시간(마이크로초)_초로변환],  
        qs.last_execution_time AS 해당쿼리가_마지막으로_실행된_시간 
  FROM       sys.dm_exec_query_stats AS qs 
  CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt  
  CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qp  
  ORDER BY    qs.last_worker_time DESC    
 
cs

 

 

(3) 쿼리계획에 대한 요약 성능 확인

읽기, 쓰기, 총 행, 완료 시간, 계획 해시, 메모리 부여 정보, 스레드, 열 저장소 통계, 유출 및 병렬 처리 정도와 같은 단일 계획에 연결된 통계

 

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT TOP 5 
      query_stats.query_hash AS "Query Hash",  
      SUM(query_stats.total_worker_time) / SUM(query_stats.execution_count) AS "Avg CPU Time",  
      MIN(query_stats.statement_text) AS "Statement Text"   
FROM (SELECT QS.*,   
            SUBSTRING(ST.text, (QS.statement_start_offset/2+ 1,  
            ((CASE statement_end_offset
              WHEN -1 THEN DATALENGTH(ST.text)  
              ELSE QS.statement_end_offset END  - QS.statement_start_offset)/2+ 1) AS statement_text  
FROM sys.dm_exec_query_stats AS QS   
CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle) as ST) as query_stats 
GROUP BY query_stats.query_hash   
ORDER BY 2 DESC;  
cs

 

더 만들어보기.....~!!

'SQL Server 운영' 카테고리의 다른 글

[MSSQL] 22. 복구모델의 이해  (0) 2021.05.12
[MSSQL] 20. RAID 구성  (0) 2021.02.09
[MSSQL] 19. JOIN의 종류와 특징  (0) 2021.02.05
[MSSQL] 18. Index 정리  (0) 2021.02.04
[MSSQL] 17. 백업종류 및 백업 스크립트  (0) 2021.02.01

20 RAID 구성

RAID : Redundant Array of Inexpensive/Independent Disk
RAID 란?

저장장치 여러 개를 묶어 고용량·고성능 저장 장치 한 개와 같은 효과를 얻기 위해 개발된 기법이다.
RAID의 주 사용 목적은 크게 무정지 구현(안정성)과 고성능 구현으로 구분된다.

 

RAID의 장점은

1) 운용 가용성, 데이터 안정성 증대

2) 디스크 용량 증설의 용이성

3) 디스크 I/O 성능 향상


RAID 종류

 

(1) RAID 0 : Simple Striping / 단순 데이터 스트라이핑

아래 그림과 같이 DataBlock 0~ 15가있으면 디스크에 순서대로 나누어 뿌리는 방법이다.

속도가 빠르지만 DISK가 하나라도 잘못되면 모든 디스크가 날라가게 된다.

속도 최우선, 안정성 최하 라고 할 수 있으며 거의 쓰지 않는다.

 

 

 

(2) RAID 1 : Simple Mirroring

RAID 1은 단순 미러링이라고 해서 최소 2개이상의 디스크에 데이터를 나눠서 뿌리는 방법이다.

최소 2개 디스크가 필요하고 같은 데이터를 저장하기에 한개의 디스크가 고장나도 복구가 가능한 것이 장점입니다.

안정성 GOOD!

 

 


(3) RAID 3 

RAID 3은 하나의 볼륨에만 패리티 저장.

장점 : 적은 볼륨 사용.(디스크 절약)

단점 : 동일 위치 동시 장해시 복구 불능.


 


(4) RAID 4 

RAID3과 동일하지만 RAID3은 Byte단위이고, RAID4는 Block 단위로 저장.

패리티 코드를 동일한 디스크에 저장하기 때문에,

패리티 디스크의 사용량이 높아 해당 디스크의 수명이 줄어든다고 합니다.

거의 쓰지 않고 RAID 5로 대체 됨.
 

 

 

(5) RAID 5

RAID 5는 Block단위로 스트리핑하고 패리티 1개를 디스크에 저장하는 방식이다.

1개의 디스크 에러 시 복구 가능 (2개 이상의 디스크 에러 시 복구 불가능) 

RAID 0에서 성능, 용량을 조금 줄이는 대신 안정성을 높인 RAID Level


 

 

 

(6) RAID 10 / 1+0

 

 

RAID 1+0 은 RAID 1로 이루어진 DISK들을 다시 RAID 0으로 묶는 것이다.
RAID 01보다 더 많이 사용한다.

그 이유는 RAID 0+1에서는 하나의 디스크가 장애가 생기면, RAID 0 으로 묶인 디스크 set 전체가 복구되어야 한다. RAID 10 에서는 하나의 디스크에 에러가 나도 mirroring 을 통해 그 디스크만 복구가 가능하다.
 

 

(7) RAID 01 / 0+1 

 

 

반대로RAID 01은 RAID 0의 묶음을 RAID 1로 다시 묶는 것이다.

19. JOIN의 종류와 특징

SQL Server에는 3가지 종류의 JOIN이 있다.

Nested Loop Join, Merge Join, Hash Join

 

(1) Nested Loop Join NL조인

NL조인은 주로 작은 입력을 인덱스를 사용해 조인 할 때 효과적이다.

메모리를 사용하지 않고 OLTP처럼 한번에 처리하는 단위가 작고 정렬이 적은 환경에 적합하다.

동작하는 방식은 말 그대로 중첩 반복문 형식이다.

외측 테이블, 내측 테이블이 존재하고 외측 참조 테이블의 입력에서 행을 한개씩 가져와서 내측 테이블을 반복해서 탐색하는 조인이다.

외측(선행) 테이블이 기준이 되므로 외측 테이블의 데이터가 작으면 작을수록 성능이 좋다.

 

1. 선행 테이블에서 조건을 만족하는 첫 번째 행을 찾음

2. 선행 테이블의 조인 키를 가지고 후행 테이블에 조인 키가 존재하는지 찾음

3. 후행 테이블의 인덱스에 선행 테이블의 조인 키가 존재하는지 확인

4. 인덱스에서 추출한 레코드 식별자를 이용하여 후행 테이블을 액세스. 만족시 해당 행을 추출버퍼에 넣음

5 ~ 11 번은 앞의 작업을 반복합니다.

 

 

(2) Merge Join, Sort Merge Join

두 Join 입력이 작지 않지만 Join 열을 (인덱스로부터 미리) 정렬된 상태로 가져올 수 있는 경우 가장 빠른 방법이다.

조인할 양쪽 입력 조인 조건을 기준으로 정렬을 한 후에 앞에서부터 순차 비교를 하면서 조인한다.

테이블을 읽는 작업은 정렬을 할 때 1번만 발생하기 때문에 부하가 없고, 정렬된 입력을 사용해 순차 비교를 하기 때문에 인덱스를 사용할 때 발생되는 추가 비용도 발생하지 않는다. 

하지만 머지 조인은 정렬하기 위한 메모리가 필요하므로 메모리가 부족하면 성능저하가 발생한다.

1. 선행 테이블에서 주어진 조건을 만족하는 행을 찾음

2. 선행 테이블의 조인 키를 기준으로 정렬 작업을 수행

1 ~ 2번 작업을 선행 테이블의 조건을 만족하는 모든 행에 대해 반복 수행

3. 후행 테이블에서 주어진 조건을 만족하는 행을 찾음

4. 후행 테이블의 조인 키를 기준으로 정렬 작업을 수행

3 ~ 4번 작업을 후행 테이블의 조건을 만족하는 모든 행에 대해 반복 수행

5. 정렬된 결과를 이용하여 조인을 수행하며 조인에 성공하면 추출버퍼에 넣음

 

 

(3) Hash Join

해시 조인은 인덱스를 사용할 수 없는 환경에서 결과를 정렬할 필요가 없을 때 효율적이다.

Join 입력의 크기가 크고 정렬되지 않았으며 인덱싱되지 않은 입력을 효율적

1. 선행 테이블에서 주어진 조건을 만족하는 행을 찾음

2. 선행 테이블의 조인 키를 기준으로 해쉬 함수를 적용하여 해쉬 테이블을 생성. 조인 컬럼과 SELECT 절에서 필요로 하는 컬럼도 함께 저장됨

1 ~ 2 번 작업을 선행테이블의 조건을 만족하는 모든 행에 대해 반복 수행

3. 후행 테이블에서 주어진 조건을 만족하는 행을 찾음

4. 후행 테이블의 조인 키를 기준으로 해쉬 함수를 적용하여 해당 버킷을 찾음

5. 조인에 성공하면 추출버퍼에 넣음

3 ~5 번 작업을 후행 테이블의 조건을 만족하는 모든 행에 대해서 반복 수행

 

18. Index 정리

 

(1) SQL Server 인덱스 B-Tree

SQL Server의 인덱스는 기본적으로 B-Tree(정확히는 B+Tree) 구조를 가진다.

최상위 레벨 Root Level , 최하위 레벨 Leaf Level, 중간 레벨 NonLeaf Level 각 레벨 페이지들은 더블 링크드 리스트로 연결 된다.

 

 

 

(2) 힙, 클러스터드 인덱스, 비클러스터드 인덱스

 

- 힙 : 테이블에 클러스터드 인덱스가 없으면 힙이다.  데이터는 추가된 순서대로 쌓이게 된다.

 

- 클러스터드 인덱스 : 데이터가 클러스터드 인덱스의 키로 정렬이 된다. 테이블 자체가 B-Tree 인덱스 구조를 이룬다.

                             테이블은 하나의 순서로만 정렬 가능하므로 클러스터드 인덱스는 한개만 가능하다.

 

- 비클러스터드 인덱스 : 테이블 구조가 변경 되는 것이 아니고, 테이블과 별개로 인덱스 키로만 구성된 별도의 B-Tree 인덱스 영역이 새로 생긴다. 

SQL Server 2005 까지는 349개, 2008 부터는 999개 까지 가능하다.

비클러스터드 인덱스는 생성된 테이블의 구조에 따라 아래와 같이 조금 차이가 있다.

 

* 힙 테이블에서 비클러스터 인덱스 생성한 경우

=> 인덱스 페이지는 데이타의 위치를 가르키는 RID 값을 가지고 있고 이 RID 값으로 힙 영역에서 인덱스 레벨이 아닌 컬럼을 검색한다.

이것이 바로 RID Lookup이다.

 

* 클러스터드 인덱스가 있는 테이블에서 비클러스터드 인덱스를 생성한 경우

=> RID가 아닌 클러스터드 인덱스의 키가 기록된다. 그래서 이 넌클러스터드 인덱스로 데이터를 찾을 경우에는 넌클러스터드 인덱스의 리프레벨에서 클러스터드 인덱스의 키를 확인한 후 이 키를 이용해서 데이터를 찾는 "Key Lookup"이 발생합니다.

 

* Lookup

Lookup은 인덱스 페이지의 주소값을 이용한 랜덤 액세스 방식으로 실제 I/O 비용이 많이 발생하므로 주의하여 작성해야함.

 

 

(3) Index Scan과 Index Seek

 

- Index Scan

An index scan is where SQL server reads the whole of the index looking for matches - the time this takes is proportional to the size of the index.

 

인덱스 Scan은 맞는 인덱스를 찾기 위해 전체 인덱스를 읽는 것. 소요 시간은 인덱스 크기에 비례한다.

테이블 전체 또는 인덱스의 리프 레벨을 모두 읽는다는 것. 

 

- Index Seek

An index seek is where SQL server uses the b-tree structure of the index to seek directly to matching records  - time taken is only proportional to the number of matching records.

 

인덱스 Seek는 B-Tree 구조에 맞는 인덱스를 바로 찾는 것. 소요시간은 일치하는 레코드의 수.

인덱스 트리를 타고 단 하나의 값을 찍어 검색하는 방식. 인덱스를 탄다. 루트->중간->리프로 Seek 

 

  • In general an index seek is preferable to an index scan (when the number of matching records is proprtionally much lower than the total number of records), as the time taken to perform an index seek is constant regardless of the toal number of records in your table.
  • Note however that in certain situations an index scan can be faster than an index seek (sometimes significantly faster) - usually when the table is very small, or when a large percentage of the records match the predicate.

(4) 인클루드 인덱스, 필터드 인덱스, 커버드 인덱스

 

- 인클루드 인덱스

인클루드 인덱스는 비클러스터드 인덱스 생성 시 인덱스 키가 아닌 컬럼도 리프 레벨에 같이 추가하는 것이다.

SQL Server 2005부터 가능하며 INCLUDE 절로 생성.

장점은 키가아닌 컬럼도 인덱스 수준에서 검색이 가능하므로 Lookup을 하지 않아 쿼리 성능이 향상되며, 리프 레벨에만 구성하므로 인덱스 크기에는 영향이 미미하다.

 

- 필터드 인덱스

SQL Server 2008부터 가능하며 특정 집합, 어떤 조건에 대해서만 인덱스를 생성한다.

인덱스 생성 시 where 조건을 주어서 특정 조건을 가진 인덱스이다.

장점은 인덱스 사이즈가 줄어들고 쿼리성능 향상, 인덱스 관리 비용이 줄어든다.

 

 

 - 커버드 인덱스

커버드 인덱스는 쿼리에 사용된 모든 컬럼이 인덱스로 구성되었을때 그 인덱스를 커버드 인덱스라고 한다.

 

17. 백업종류 및 스크립트

 

(1) 전체 백업(FULL) 

전체 백업은 선택된 데이터베이스 안에 있는 모든 데이터 페이지와 복구에 필요한 트랜잭션 로그 일부를 포함.

용량이 크면 클수록 전체백업 소요 시간이 길어지므로 차등 백업과 트랜잭션 로그 백업을 같이 병행 하는게 좋다.

 

WITH INIT  :  INIT일 경우 파일 이름 과 동일한 백업 세트가 존재하면 미디어 헤더만 보존하고 백업 세트는 덮어쓴다. 

기본값은 NOINIT이며 기존 백업세트를 보존하면서 새로운 백업 미디어 세트를 동일한 파일에 추가한다.

1
2
BACKUP DATABASE OriDataBase TO DISK = 'C:\bak\OriDataBase.bak'
WITH INIT, NAME = 'OriDataBase_bak_210201'
cs

 

(2) 차등 백업(Differential)

매번 전체 백업을 받으면 I/O비용과 디스크 공간에 비효율 적이므로 차등 백업을 실행.

전체 백업 이후 변경된 데이터 익스텐트에 대해서만 백업을 실행한다.

여러번 차등 백업을 했더라도 처음의 전체 백업과 가장 최근의 차등 백업을 하면 차등 백업이 생성된 시점까지 복원이 가능하다.

 

WITH DIFFERENTIAL : 차등 백업을 한다는 옵션

STATS = 지정한 숫자별로 진행률을 볼 수 있다.

1
2
BACKUP DATABASE OriDataBase TO DISK = 'C:\bak\OriDataBase_Diff.bak'
WITH DIFFERENTIAL, STATS = 10, INIT, NAME = 'OriDataBase_Diff_210201'
cs

 

 

(3) 트랜잭션 로그 백업

데이터베이스의 데이터 페이지가 아니라 데이터의 변경 기록이 남아있는 트랜잭션(INSERT, UPDATE, DELETE 등)을 백업한다. 전체 백업이 실행 되어 있어야하고 복구 모델이 전체(FULL) 또는 대량로그(BULK LOGGED)어야만 가능하다.

 

1
BACKUP LOG OriDataBase TO DISK = 'C:\bak\OriDataBase_LOG.TRN'
cs

 

 

 (4) 파일, 파일그룹 백업

대용량 데이터베이스가 장애로 인해 전체 데이터베이스 복원을 해야한다면 소요시간이 길어지므로 파일 그룹이 나눠져있다면 파일그룹별로 백업을 하면 좀 더 빠르게 복원이 가능하다. 복원 시 PRIMARY 파일 그룹을 가장 먼저 복원하고 그 다음 파일 그룹을 순차적으로 복원 가능.

 

FILEGROUP = 옵션 지정으로 특정 FILEGROUP만 백업

1
BACKUP DATABASE OriDataBase FILEGROUP = 'PRIMARY' TO DISK = 'C:\SQL\OriDataBase_FILEGROUP.bak'
cs

 

 

(5) 부분 백업

전체 백업과 유사하지만 모든 파일 그룹을 백업하지 않고 PRIMARY 파일 그룹과 읽기/쓰기가 모두 가능한 파일그룹을 백업한다. 

 

READ_WRITE_FILEGROUPS = 옵션으로 읽기와 쓰기 모두 가능한 파일그룹을 백업. 

1
BACKUP DATABASE OriDataBase READ_WRITE_FILEGROUPS TO DISK = 'C:\SQL\OriDataBase_RW.bak'
cs

 

(6) 차등 부분 백업

차등 백업과 부분백업의 특징을 가짐. 

 

1
2
BACKUP DATABASE OriDataBase READ_WRITE_FILEGROUPS TO DISK = 'C:\SQL\OriDataBase_RW_Diff.bak 
WITH DIFFERENTAIL
cs

 

(7) 복사 전용 백업

SQL SERVER 2005이후 지원. 백업을 수행해도 백업체인에 영향이 없어서 기존 차등 백업이나 트랜잭션 로그 백업에 영향이 없다. 테스트 목적으로 다른 곳으로 옮길 때 유용

 

1
2
BACKUP DATABASE OriDataBase TO DISK = 'C:\SQL\OriDataBase_Copy.bak'
WITH COPY_ONLY
cs

 

'SQL Server 운영' 카테고리의 다른 글

[MSSQL] 19. JOIN의 종류와 특징  (0) 2021.02.05
[MSSQL] 18. Index 정리  (0) 2021.02.04
[MSSQL] 16. 가상로그파일 VLF  (0) 2021.01.27
[MSSQL] 15. 로그 전달 Log Shipping  (0) 2021.01.24
[MSSQL] 14. Replication - 복제  (0) 2021.01.23

16.  가상로그파일 VLF

SQL Server에서 로그파일(LDF)은 데이터 파일처럼 익스텐트로 구성되지 않고

가상 로그 파일(Virtual Log File 이하 VLF)로 구성되어 있습니다.  

VLF는 로그 파일의 크기에 따라 가변적으로 변하며 SQL Server에 의해 정해 집니다.

VLF의 최소 단위는 256K이며 트랜잭션 로그가 가장 작은 512K일 때 두 개의 VLF가 생성 됩니다.  

 

 

If the log files grow to a large size in many small increments, they will have many virtual log files. This can slow down database startup and also log backup and restore operations.

 

로그파일이 큰사이즈로 많이 작은 증가? 이면 가상 로그 파일이 많이 생성됩니다. 이로 인해 데이터베이스 시작뿐 아니라 로그 백업 및 복원 작업이 느려질 수 있습니다. 반대로 로그 파일이 적거나 하나의 증분인 큰 크기로 설정된 경우 적은 수의 매우 큰 가상 로그 파일이 포함됩니다.  

 

출처 : 

docs.microsoft.com/ko-kr/sql/relational-databases/sql-server-transaction-log-architecture-and-management-guide?view=sql-server-2017#physical_arch

 

 

아래 이미지 같이 가상로그파일이 4개인 경우 , 뒤에 2개를 쓰고 있었다고 가정.

그 다음 로그파일 시작은 Virtual Log1이 된다. 

순환식 으로 쓰여진다라는 말.

 

(위 이미지와 같은 VLF 설명)

출처 : http://www.sqler.com/bSQLQA/597442
 

LDF는 순환구조 형태로 되어있습니다.

아래 나오는 네모를 VLF라고 생각하시면 됩니다.

 

□: 트랜잭션 로그 백업이 되었거나 혹은 아직 사용되지 않은 것(DBCC LOGINFO 에서 Status 가 0인 값)

■: 현재 사용중이거 혹은 이미 사용했으나 트랜잭션 로그 백업이 되지 않은 것(DBCC LOGINFO 에서 Status 가 2인 값)

 

기본

 

DML이 많이 발생하면... 이렇게 로그가 많이 사용이 되겠지요~!

 

여기서 트랜잭션 로그 백업을 수행하면.. 아래처럼 현재 사용중인 VLF는 제외하고.. 백업이 됩니다.

 

하지만... 대량의 IO가 유발되고... 트랜잭션 로그 백업 시점에도 트랜잭션이 진행중이라면.. 아래 처럼 될 수도 있습니다 ^^

이 내용은 하단에 링크 참고하세요~

 

 

다시 원래대로 돌아와서..

DML이 발생하면서..  끝까지 다 쓰게 되면.. 순환해서 앞에서 부터 다시 이용하게 됩니다.

 

이런 식입니다.

 

이러다... 만약 전부 다 쓰게 되면.. 아래 처럼되겠죠~!

 

이 상태에선..더이상 공간이 없기 때문에.. 추가 사이즈를 할당하게 됩니다.

이런 식이 되겠죠. 추가되는 공간은.. 비율 혹은 MB로 설정하도록 되어있습니다.

 

이러다보면... LDF 사이즈가 계속 증가가 되고... VLF 갯수역시 늘어나게 됩니다.

LDF 사이즈를 늘어나지 않게 하려면..반드시 트랜잭션 로그 백업을 수행해야 합니다.

 

이렇게 증가할때마다 VLF 갯수가 늘어나게 되고... 몇천개씩 되는 문제가 발생하게 됩니다.


 

15. 로그 전달 - Log Shipping

- 주 서버 인스턴스의 주 데이터베이스 에서 별도의 보조 서버 인스턴스에 있는 하나 이상의 보조 데이터베이스로 트랜잭션 로그 백업을 자동으로 보내는 작업.

- 자동 장애 조치가 없다.

- 에이전트로 이루어 지므로 실시간 동기화는 불가능.

- 모니터 서버라는 선택적인 세 번째 서버 인스턴스는 백업 및 복원 작업의 기록과 상태를 기록하고 예약된 대로 작업이 실행되지 않으면 선택적으로 경고를 발생시킨다.

 

(1) 조건 및 권한

  - 주 데이터베이스는 복구 모델이 전체 또는 대량 로그 복구 모델이어야 한다. / Full or Bulk Logged

  - 공유를 만들어 트랜잭션 로그 백업을 보조 서버에서 사용할 수 있도록 설정해야 함.

 

(2) 순서

  1. 주 서버 인스턴스에서 트랜잭션 로그를 백업합니다.

  2. 보조 서버 인스턴스에 트랜잭션 로그 파일을 복사합니다.

  3. 보조 서버 인스턴스에 로그 백업을 복원합니다.

 

14. Replication - 복제

복제는 한 데이터베이스에서 다른 데이터베이스로 데이터와 데이터베이스 개체복사 및 배포한 다음 데이터베이스 간에 동기화를 수행하여 일관성을 유지하는 일련의 기술

 

(1) 스냅샷 복제 - 많은 양의 데이터가 변경되지만 자주 변경되지는 않을 때 가장 적합. 단독으로 사용할 수 있지만 게시에서 지정한 모든 개체 및 데이터의 복사본을 만드는 스냅샷 프로세스는 일반적으로 트랜잭션 및 병합 게시에 대한 초기 데이터 및 데이터베이스 개체 집합을 제공하는 데에도 사용

 

(2) 트랜잭션 복제  - 스냅샷 복제로 데이터 동기화 이후, 데이터 변경과 스키마 변경을 로그 판독기 에이전트가 수집하여 배포 DB에 기록하면 구독자에게 반영. 실시간 동기화가 된다. 일반적으로 확장성 및 가용성 향상, 데이터 웨어하우징 및 보고, 여러 사이트의 데이터 통합, 다른 유형의 데이터 통합, 일괄 처리 작업 오프로드 등을 포함하여 높은 처리량이 필요한 서버 간 시나리오에서 사용.


(3) 병합 복제  - 게시자와 구독자의 데이터 변경과 스키마 변경내용을 트리거로 추적해서 변경 추적 테이블에 기록하고, 그 내용을 병합해서 게시자와 구독자에 반영. 관리가 다소 복잡. 주로 데이터 충돌 가능성이 있는 모바일 애플리케이션이나 분산 서버 애플리케이션에 사용됩니다. 일반적인 시나리오에는 모바일 사용자와 데이터 교환, 소비자 POS(Point of Sale) 애플리케이션, 여러 사이트의 데이터 통합 등이 있음.

 

(4) 피어 투 피어 복제 - 노드(Node)라고 하는 여러 SQL Server 인스턴스로 DB 복제본을 유지 관리. 확장성과 고가용성 이점. 모든 데이터를 복제. 거의 실시간으로 일관되게 전파.

 

 

 

13. DMV - 동적관리뷰 

동적 관리 뷰 및 함수는 서버 인스턴스 상태 모니터링, 문제 진단 및 성능 튜닝에 사용할 수 있는 서버 상태 정보를 반환합니다.

 

동적 관리 뷰 또는 함수를 쿼리하려면 개체에 대한 SELECT 권한과 VIEW SERVER STATE 또는 VIEW DATABASE STATE 권한이 필요합니다. 

 

- 동적관리뷰 개수는? : 아래 쿼리를 활용하여 확인해보니 총 273개입니다.

SELECT N'SYS.' + NAME AS NAME, TYPE_DESC 
  FROM SYS.SYSTEM_OBJECTS 
 WHERE NAME LIKE N'DM[_]%' 
 ORDER BY NAME
 

 

 

모두를 알기는 불가능하니, 자주 쓰는 DMV에 대해서 알아보겠습니다.

 

(1) sys.dm_exec_query_stats - 캐시된 쿼리 계획에 대한 집계 성능 통계

ex - 평균 CPU 시간별로 상위 5개의 쿼리 찾기

SELECT TOP 5 query_stats.query_hash AS "Query Hash",   
    		 SUM(query_stats.total_worker_time) / SUM(query_stats.execution_count) AS "Avg CPU Time",  
             MIN(query_stats.statement_text) AS "Statement Text"  
  FROM  (SELECT QS.*,  SUBSTRING(ST.text, (QS.statement_start_offset/2) + 1,  
		((CASE statement_end_offset WHEN -1 THEN DATALENGTH(ST.text)  
         	 ELSE QS.statement_end_offset END   
                    - QS.statement_start_offset)/2) + 1) AS statement_text  
     	   FROM sys.dm_exec_query_stats AS QS  
     	  CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle) as ST) as query_stats  
 GROUP BY query_stats.query_hash  
 ORDER BY 2 DESC;  

 

(2) sys.dm_exec_sql_text(sql_handle)  - 지정 된 sql_handle 에 의해 식별 되는 SQL 일괄 처리의 텍스트를 반환

- text 컬럼에 SQL 쿼리 실행 텍스트가 나옴.

 SELECT B.text,* 
  FROM sys.dm_exec_query_stats AS A
  CROSS APPLY sys.dm_exec_sql_text(A.sql_handle) AS B  
 ORDER BY A.creation_time DESC

 

(3) sys.dm_exec_procedure_stats - 저장 프로시저에 대한 집계 성능 통계

- 평균 경과 시간으로 식별된 상위 10개의 저장 프로시저 찾기 예제

SELECT TOP 10 d.object_id, d.database_id, OBJECT_NAME(object_id, database_id) 'proc name',   
       d.cached_time, d.last_execution_time, d.total_elapsed_time,  
       d.total_elapsed_time/d.execution_count AS [avg_elapsed_time],  
       d.last_elapsed_time, d.execution_count  
  FROM sys.dm_exec_procedure_stats AS d  
 ORDER BY [total_worker_time] DESC;  

 

(4) sys.dm_exec_requests실행 되는 각 요청에 대한 정보를 반환

(5) sys.dm_exec_query_plan - 계획 핸들로 지정한 일괄 처리에 대한 XML 형식의 실행 계획을 반환

 

+ Recent posts