백업 파일 확인

  • 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

 

 

 

요약: 애초에 인코딩은 꼭 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

1. 데이터타입: geography

2. 저장: 

INSERT INTO [테이블명] ([geography컬럼명]) values (geography::Point([위도], [경도], 4326));
-- 4326은 우리가 흔히 사용하는 좌표 CRS임

3. 문자열로 변환 조회
단, 이 경우 "POINT ([경도] [위도])" 형태로 반환되므로, 각각 decimal type의 컬럼으로 저장하는 편이 나았음 (다른 방법이 있을 수 있음)

SELECT convert(nvarchar(50), [geography컬럼명]) as [별칭] FROM [테이블명];
-- POINT ([경도] [위도])

4. 특정 위치를 기준으로 반경 5km 조회하기 - geography 타입을 사용한 이유

-- STDistance는 차이를 미터로 반환함

-- 1. 변수선언이 가능한 경우
DECLARE @Origin GEOGRAPHY
SET @Origin = GEOGRAPHY::Point([위도], [경도])
SELECT * FROM [테이블명] WHERE @Origin.STDistance([geography컬럼명]) <= (5 * 1000);

-- 2. DB에서 바로 조회할 경우.
SELECT * FROM [테이블명] WHERE (SELECT [geography컬럼명] FROM [테이블명] WHERE [관리키컬럼명]=[관리키]).STDistance([geography컬럼명]) <= (5 * 1000);

 

influx cli를 통해서 백업가능하다.

백업 공식문서 https://docs.influxdata.com/influxdb/v2/admin/backup-restore/backup/

influx backup [저장경로] -t [관리자초기토큰]

근데 골때리는게 저 관리자초기토큰이다.

아래의 명령어로 일반적인 관리자토큰으로 기존 토큰 목록을 조회할 수 있는데 influxdb UI와 달리 실제 token 값도 조회가 가능하다.

influx auth list -t [관리자토큰]

여기서 [read:/authorizations write:/authorizations read:/buckets write:/buckets read:/dashboards write:/dashboards read:/orgs write:/orgs read:/sources write:/sources read:/tasks write:/tasks read:/telegrafs write:/telegrafs read:/users write:/users read:/variables write:/variables read:/scrapers write:/scrapers read:/secrets write:/secrets read:/labels write:/labels read:/views write:/views read:/documents write:/documents read:/notificationRules write:/notificationRules read:/notificationEndpoints write:/notificationEndpoints read:/checks write:/checks read:/dbrp write:/dbrp read:/notebooks write:/notebooks read:/annotations write:/annotations read:/remotes write:/remotes read:/replications write:/replications] 이런 권한을 가진 토큰이 바로 저 관리자초기토큰인데 나의 경우에는 이게 없었다.

없는 경우 복원기능으로 복원해야 백업이 가능하다.(는 걸 뒤지고 뒤져서 포럼 어딘가의 답변에서 겨우 찾았다. 공식문서끼리 링크 좀 걸어줬으면 좋겠다.)

관리자초기토큰 복원 공식문서 https://docs.influxdata.com/influxdb/v2/reference/cli/influxd/recovery/auth/create-operator/

influxd recovery auth create-operator --bolt-path [bolt파일경로]
influxd recovery auth create-operator --org [organization이름] --username [관리자아이디] --bolt-path [bolt파일경로]

이 방식으로 관리자초기토큰을 복원하는데 성공했다. 이름은 [관리자아이디]'s Recovery Token
사실 간밤에 복원했을때는 recovery token 뭐 이런거랑 이거랑 2개였는데 오늘 출근하니까 한개는 없어지고 이거만 남았다ㅋㅋㅋ

bolt파일경로는 config.toml 파일에서 확인할 수 있다. config.toml 파일은 centos기준 /etc/influxdb/ 에 있다.

추후에 또 이 문제로 헤맬 수 있을 듯 하여 문서로 남겨놓는다.

 

'DB' 카테고리의 다른 글

postgreSQL 한글정렬 문제  (2) 2025.07.03

1. dump파일을 저장할 곳을 생성해서 이동

2. 백업: mysqldump -u root -p DB명 > 파일명.sql

3. 복원: mysql -u root -p DB명 < 파일명.sql

3-1. 복원은 mysql 커맨드 상태에서 use DB명하고, source 파일명.sql 로 해도 가능함

다른 스키마도 다른 설정을 바꿔줄 필요없이 복원이 가능함

// 1. MySQL 정지
systemctl stop mysqld

// 2. MySQL 환경변수를 변경해서 비밀번호없이 root 로그인할 수 있도록 변경
systemctl set-environment MYSQLD_OPTS="--skip-grant-tables"

// 3. MySQL 재시작
systemctl start mysqld

// 4. MySQL 접속. 현재 비번 입력없이 접속이 가능하므로 그냥 엔터침
mysql -u root -p

// 5. root 비밀번호을 null 초기화 후 일단 MySQL 접속해제
UPDATE mysql.user SET authentication_string = null where user = 'root';
FLUSH PRIVILEGES;
quit

// 6. MySQL 재접속. 현재 비번은 null이므로 엔터치고 접속하면 됨
mysql -u root -p

// 7. root 비밀번호 재설정 후 MySQL 접속해제
alter user 'root'@'localhost' identified with caching_sha2_password by '새비밀번호';
FLUSH PRIVILEGES;
quit

// 8. MySQL 정지 후 환경변수 제거 후 다시 재시작
systemctl stop mysqld
systemctl unset-environment MYSQLD_OPTS
systemctl start mysqld

 

'DB > MySQL' 카테고리의 다른 글

DB Dump 및 복원  (0) 2022.06.22
SELECT 와 UPDATE 동시에 하기  (0) 2021.06.17
datetime 컬럼을 분단위로 group by 하기  (1) 2020.09.29
5.7 DB 파일로 복원  (0) 2020.06.04
외부 접근 허용  (0) 2019.10.28

UPDATE [테이블A],[Select 질의] B SET [테이블A].필드 = B.필드 WHERE [테이블A].id = B.id

출처: https://shakddoo.tistory.com/entry/Mysql-Select결과를-Update-문에-반영하기 [겨울팥죽 여름빙수]

'DB > MySQL' 카테고리의 다른 글

DB Dump 및 복원  (0) 2022.06.22
CentOS7, MySQL8 에서 root 계정 비밀번호를 분실한 경우  (0) 2022.06.22
datetime 컬럼을 분단위로 group by 하기  (1) 2020.09.29
5.7 DB 파일로 복원  (0) 2020.06.04
외부 접근 허용  (0) 2019.10.28

GROUP BY DATE(컬럼명), HOUR(컬럼명), FLOOR(MINUTE(컬럼명)/1)

'DB > MySQL' 카테고리의 다른 글

CentOS7, MySQL8 에서 root 계정 비밀번호를 분실한 경우  (0) 2022.06.22
SELECT 와 UPDATE 동시에 하기  (0) 2021.06.17
5.7 DB 파일로 복원  (0) 2020.06.04
외부 접근 허용  (0) 2019.10.28
SELECT UPDATE  (0) 2011.06.30

0. MySQL 실행 중지

설치경로\bin\mysqld\mysqladmin -u root -p shutdown

 

1.

기본 경로: C:\ProgramData\MySQL\MySQL Server 5.7\Data\

기존 DB 스키마 폴더와 ibdata1 파일을 덮어 씌우기

 

2. MySQL 재시작

 

'DB > MySQL' 카테고리의 다른 글

SELECT 와 UPDATE 동시에 하기  (0) 2021.06.17
datetime 컬럼을 분단위로 group by 하기  (1) 2020.09.29
외부 접근 허용  (0) 2019.10.28
SELECT UPDATE  (0) 2011.06.30
Create table select, Insert select  (0) 2011.06.17

1. 방화벽

인바운드규칙 / 연결허용 / tcp 3306

 

2. DB의 권한

-- 새 유저 생성할거면 이 구문부터
CREATE USER 계정이름@'%' IDENTIFIED BY '비밀번호';

-- 기존유저 혹은 새유저에 권한 부여
GRANT ALL PRIVILEGES ON 데이터베이스이름.* TO 계정이름@'%';
FLUSH PRIVILEGES;

 

여기까지 해서 해결되었지만 안된다면 이 분 글을 더 참고하면 됨

출처: https://blog.jiktong.kr/2221

'DB > MySQL' 카테고리의 다른 글

datetime 컬럼을 분단위로 group by 하기  (1) 2020.09.29
5.7 DB 파일로 복원  (0) 2020.06.04
SELECT UPDATE  (0) 2011.06.30
Create table select, Insert select  (0) 2011.06.17
스키마내 테이블 수  (0) 2011.06.17

+ Recent posts