백업 파일 확인

  • RESTORE HEADERONLY FROM DISK='C:\Backup\A.bak';
    → 백업된 SQL Server 버전, 날짜, 종류(FULL/DIFF/LOG) 확인
  • RESTORE FILELISTONLY FROM DISK='C:\Backup\A.bak';
    → 데이터/로그 파일 논리명 확인

 

📌 기본 FULL 백업 복원

sqlcmd -S 서버명\인스턴스명 -E -Q " RESTORE DATABASE B FROM DISK = 'C:\Backup\A.bak' WITH MOVE 'A_Data' TO 'C:\Data\B.mdf', MOVE 'A_Log' TO 'C:\Data\B_log.ldf', REPLACE, STATS=10;"
  • -S : 서버명\인스턴스명 (로컬 기본 인스턴스면 -S . 가능)
  • -E : Windows 인증 (SQL 로그인 쓰려면 -U 사용자 -P 비밀번호)
  • MOVE : 논리 파일명을 새 물리 경로로 지정
  • REPLACE : 기존 DB 덮어쓰기
  • STATS=10 : 진행률 10% 단위 출력

📌 DIFF 백업 복원 (FULL 복원 후)

sqlcmd -S 서버명\인스턴스명 -E -Q " RESTORE DATABASE B FROM DISK = 'C:\Backup\A_diff.bak' WITH NORECOVERY, STATS=10;"
  • NORECOVERY : 이후 로그 복원을 위해 DB를 복원 모드로 유지

📌 LOG 백업 복원 (DIFF 후 이어서)

sqlcmd -S 서버명\인스턴스명 -E -Q " RESTORE LOG B FROM DISK = 'C:\Backup\A_log.trn' WITH RECOVERY, STATS=10;"
  • RECOVERY : 마지막 로그 복원 후 DB를 ONLINE으로 전환

📌 복원 후 무결성 검사

sqlcmd -S 서버명\인스턴스명 -E -Q " DBCC CHECKDB ('B') WITH NO_INFOMSGS, ALL_ERRORMSGS;"

📌 자주 쓰는 팁

  • 헤더 확인 : RESTORE HEADERONLY FROM DISK='A.bak'
  • 파일 목록 확인 : RESTORE FILELISTONLY FROM DISK='A.bak'
  • 복원 진행률 확인 : 다른 세션에서
SELECT percent_complete, estimated_completion_time FROM sys.dm_exec_requests WHERE command = 'RESTORE DATABASE';

 

SSMS 에서 잘 안될때는 sqlcmd로 하면 잘 된다.

 

 

 

추가 점검/최적화 (선택)

  • sp_updatestats 실행 → 통계 갱신
  • 인덱스 재구성/재빌드 → 성능 최적화
  • 새 FULL 백업 생성 → 이후 백업 체인 새로 시작

🔧 sp_updatestats 실행

USE DB명;
EXEC sp_updatestats;


🔧 인덱스 재구성 (Reorganize)

  • 특징: 조각난 인덱스를 정리해서 페이지를 압축하고, 구조를 최적화
  • 장점: 빠르고 온라인으로 실행 가능 (대부분의 경우 DB 사용 중에도 가능)
  • 예시:

USE B; ALTER INDEX ALL ON dbo.테이블명 REORGANIZE;

🔧 인덱스 재빌드 (Rebuild)

  • 특징: 인덱스를 완전히 새로 만드는 작업
  • 장점: 조각난 정도가 심할 때 가장 효과적
  • 단점: 시간이 오래 걸리고, 기본적으로 오프라인 작업 (Enterprise Edition은 ONLINE 옵션 가능)
  • 예시:

USE B; ALTER INDEX ALL ON dbo.테이블명 REBUILD WITH (FILLFACTOR = 90, ONLINE = ON);

  • FILLFACTOR : 페이지에 여유 공간을 남겨둬서 이후 삽입 성능 개선
  • ONLINE = ON : Enterprise Edition에서만 지원, 작업 중에도 테이블 사용 가능

🔧 전체 DB 인덱스 최적화

  • 모든 테이블에 대해 인덱스를 재구성/재빌드하려면:

USE B; EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REBUILD';

  • 또는

USE B; EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REORGANIZE';

📌 선택 기준

  • 조각난 정도가 10~30% → REORGANIZE
  • 조각난 정도가 30% 이상 → REBUILD
  • 조각난 정도 확인:
SELECT
    dbschemas.[name] as 'Schema',
    dbtables.[name] as 'Table',
    dbindexes.[name] as 'Index',
    indexstats.avg_fragmentation_in_percent,
    indexstats.page_count
FROM sys.dm_db_index_physical_stats (DB_ID('B'), NULL, NULL, NULL, 'LIMITED') AS indexstats
    INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
    INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
    INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
                                         AND indexstats.index_id = dbindexes.index_id
WHERE indexstats.database_id = DB_ID('B');

 

📌 자동 인덱스 유지보수 스크립트 (Enterprise Edition용)

USE B;
GO

DECLARE @TableName NVARCHAR(128);
DECLARE @IndexName NVARCHAR(128);
DECLARE @SQL NVARCHAR(MAX);

-- 인덱스 조각난 정도 확인 후 자동 처리
DECLARE cur CURSOR FOR
SELECT
    t.name AS TableName,
    i.name AS IndexName,
    ips.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
JOIN sys.tables t ON ips.object_id = t.object_id
WHERE i.type_desc IN ('CLUSTERED', 'NONCLUSTERED')
  AND ips.page_count > 100; -- 작은 인덱스는 제외

OPEN cur;
FETCH NEXT FROM cur INTO @TableName, @IndexName, @SQL;

WHILE @@FETCH_STATUS = 0
BEGIN
    IF @SQL BETWEEN 10 AND 30
        SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REORGANIZE;';
    ELSE IF @SQL > 30
        SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REBUILD WITH (ONLINE = ON);';
    ELSE
        SET @SQL = NULL;

    IF @SQL IS NOT NULL
    BEGIN
        PRINT '실행: ' + @SQL;
        EXEC (@SQL);
    END

    FETCH NEXT FROM cur INTO @TableName, @IndexName, @SQL;
END

CLOSE cur;
DEALLOCATE cur;
GO

📌 설명

  • sys.dm_db_index_physical_stats: 인덱스 조각난 정도 확인
  • 조건:
  • page_count > 100: 너무 작은 인덱스는 제외 (효과 없음)
  • ONLINE 옵션: Enterprise Edition에서만 지원, Standard Edition은 제거해야 함

📌 실행 팁

  • 복원 직후나 주기적인 유지보수 작업에 사용
  • 실행 전 반드시 DB를 사용하지 않는 시간대에 돌리는 게 안전
  • 로그가 많이 쌓일 수 있으니, 필요하면 로그 백업도 고려

📌 자동 인덱스 유지보수 스크립트 (Standard Edition용)

USE B;
GO

DECLARE @TableName NVARCHAR(128);
DECLARE @IndexName NVARCHAR(128);
DECLARE @Frag FLOAT;
DECLARE @SQL NVARCHAR(MAX);

DECLARE cur CURSOR FOR
SELECT
    t.name AS TableName,
    i.name AS IndexName,
    ips.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
JOIN sys.tables t ON ips.object_id = t.object_id
WHERE i.type_desc IN ('CLUSTERED', 'NONCLUSTERED')
  AND ips.page_count > 100; -- 작은 인덱스 제외

OPEN cur;
FETCH NEXT FROM cur INTO @TableName, @IndexName, @Frag;

WHILE @@FETCH_STATUS = 0
BEGIN
    IF @Frag BETWEEN 10 AND 30
        SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REORGANIZE;';
    ELSE IF @Frag > 30
        SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON [' + @TableName + '] REBUILD;';
    ELSE
        SET @SQL = NULL;

    IF @SQL IS NOT NULL
    BEGIN
        PRINT '실행: ' + @SQL;
        EXEC (@SQL);
    END

    FETCH NEXT FROM cur INTO @TableName, @IndexName, @Frag;
END

CLOSE cur;
DEALLOCATE cur;
GO

 

 

 

터미널을 새로 하나 열어서

find /var/opt/gitlab/git-data/repositories -exec chown git:git {} \;

입력하고 컨테이너를 재시작한다.

 

출처: https://gitlab.com/gitlab-org/charts/gitlab/-/issues/5546#note_2017038672

원인은 세션별 동시에 읽어들일 수 있는 파일수가 정해져 있는데 초과할 경우 발생한다.

해결은 mac이나 linux면 그 숫자를 늘려주면 된다고 한다.

문제는 windows

범인은 swc였다.

babel을 활성화하면 해결된다.

느린 게 때론 괜찮을 때도 있다.

1. 현재버전 확인하기

docker image의 버전이 lastest라면 도움말에서 현재 사용중인 버전을 확인할 수 있다.
/help

 

2. 업그레이드 계획 세우기

https://gitlab-com.gitlab.io/support/toolbox/upgrade-path

에서  

현재버전부터 올리고 싶은 버전까지 선택

 

summary 와 18.3.1 사이의 … 을 누르면 단계별로 거쳐야하는 버전이 나온다
이렇게....

    각 버전들의 이미지를 미리미리 받아놓는게 편하다. 

3. 컨테이너 교체
    시놀로지 도커에서 기존 컨테이너를 지우고 2번에서 알려주는 다음버전으로 새 컨테이너를 생성한다.
    폴더 경로는 당연히 기존과 같아야 한다.

4. 컨테이너 생성후 시작한지 대충 3-4분 이후부터는 웹 로그인이 가능하다.

5. 관리자 영역 => 모니터링 => 백그라운드 마이그레이션 메뉴에서 Queued에 있는 것들이 완료로 다 가면 컨테이너 종료.
     /admin/background_migrations

6. 2번에서 그 다음버전 확인하고 3번부터 반복.
    2에서 제공하는 각 버전들의 이미지들을 미리 받아놨다면 완료된 이미지는 지우면서 하면 할만하다.

캡쳐는 15.0.5부터로 되어있지만 14부터 올리고 있었는데 15.0.5까지는 얼마 안 걸리길래 우습게 봤더니 15.4.6으로 올리고 있는데 5번이 오래걸리는 꼴이 버전 1개 올릴때마다 대략 30분 걸린다는 말이 허언이 아닌 것 같다. 나스라서 그런지 40분 이상 걸릴때도 있다.
이러다보니 하루 날잡아서 하기 보다는 점심시간이나 퇴근하기 직전에 하나씩 올리는 것이 낫겠다 싶다.

요약: 애초에 인코딩은 꼭 utf8로 설치하고 데이터베이스 생성시 collate는 "C.utf8"로 하자
백업복원으로 재생성할 수 없다면 일일히 수정해야 한다

ALTER TABLE [테이블명]
ALTER COLUMN [컬럼명]
SET DATA TYPE character varying(10) COLLATE "C.utf8";

테스트링크: https://onecompiler.com/postgresql/43pk5sws4

테스트코드

SHOW lc_collate;

SELECT * FROM pg_collation WHERE collname like 'ko%' or collname like '%utf%';

-- create
CREATE TABLE test_table (
  seq SERIAL PRIMARY KEY,
  cd VARCHAR(10) NOT NULL,
  nm VARCHAR(10)  NOT NULL,
  nm2 VARCHAR(10)  NOT NULL COLLATE "C.utf8"
);

-- insert
INSERT INTO test_table (cd, nm, nm2) VALUES ('BROWN', '브라운', '브라운');
INSERT INTO test_table (cd, nm, nm2) VALUES ('FUBAO', '푸바오', '푸바오');
INSERT INTO test_table (cd, nm, nm2) VALUES ('ETC', 'ETC', 'ETC');
INSERT INTO test_table (cd, nm, nm2) VALUES ('NO', '123', '123');

-- fetch 
SELECT a.* FROM test_table as a ORDER BY nm;
SELECT a.* FROM test_table as a ORDER BY nm2;

 

 

이하는 삽질로 얻은 지식 정리

1. 데이터베이스 스키마의 locale 확인

SHOW lc_collate

- 이것은 변경이 불가능하다. 데이터베이스 스키마를 새로 생성해야한다. 그리고 이것으로 기본 정렬된다.

- SELECT * FROM pg_database 에서는 모든 데이터베이스 스키마의 정보를 확인할 수 있고 UPDATE pg_database  SET  어쩌고 해서 수정할 수도 있으나 정렬 자체는 변하지 않았다.

 

2. 해당 스키마에서 사용할 수 있는 collate 확인

SELECT * FROM pg_collation 

한글 윈도우에서 기본 로케일로 설치한 것(이하 윈도우)은 utf8 관련은 전혀 없으나
docker로 설치한 것(이하 도커)은 collname기준 "C.utf8", "en_US.utf8" 두가지 있었다

=> 결론. 윈도우라도 인코딩 utf8로 설치해놔야 배포서버와의 환경차이로 인한 혼란을 줄일 수 있다.

 

3. 2의 테이블에 없는 것은 추가할 수 있다.

https://postgresql.kr/docs/13/sql-createcollation.html

ex) CREATE COLLATION [collation이름] (provider = icu, locale = 'ko_KR.utf8')

 

4. 데이터베이스의 collate를 바꾸지 않고 쿼리문에서 일시적으로 collate를 적용해서 정렬하는 방법

SELECT * FROM [테이블명] ORDER BY [컬럼명] COLLATE "ko-KR-x-icu"

collate 이름은 반드시 쌍따옴표로 해야 하며, 3의 테이블에서 collname컬럼을 사용해야 한다.
그런데 ko로 시작하는 것들로 정렬해보니 영어보다 한글이 먼저 나온다ㅠㅠ

 

'DB' 카테고리의 다른 글

InfluxDB2 backup  (0) 2024.02.06

+ Recent posts