# 데이터베이스 설계와 정규화

데이터를 효율적으로 저장하기 위해 데이터베이스를 잘 설계하는 것이 중요하다. 데이터베이스 설계에서 가장 중요한 개념 중 하나는 **정규화(Normalization)**이다. 정규화는 데이터 중복을 줄이고 데이터의 일관성을 유지하도록 테이블을 분리하는 과정이다.

정규화의 단계

  1. 1차 정규화(1NF): 모든 열이 원자 값(더 이상 나눌 수 없는 값)만 가지도록 한다.
    • 예: 하나의 셀에 여러 값(전화번호 여러 개)을 넣지 않는다.
  2. 2차 정규화(2NF): 기본 키에 대해 부분 종속성이 없는 상태를 만든다. 기본 키의 일부분에만 종속된 컬럼이 없어야 한다.
  3. 3차 정규화(3NF): 기본 키에 대해 이행적 종속성이 없는 상태로 만든다. 기본 키가 아닌 열이 다른 비기본 키 열에 종속되지 않도록 한다.

예를 들어, 고객 정보와 주문 정보를 한 테이블에 넣지 않고, 고객 테이블과 주문 테이블을 분리하는 것이 정규화의 예다.


# 고급 SQL 쿼리

JOIN

테이블 간 관계를 이용해 데이터를 조회할 때 사용하는 것이 JOIN이다. JOIN에는 여러 종류가 있다.

1. INNER JOIN: 두 테이블에 모두 존재하는 값만 반환한다.

SELECT Customers.Name, Orders.OrderDate
FROM Customers
INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID;
 

2. LEFT JOIN: 왼쪽 테이블의 모든 행과, 오른쪽 테이블에 매칭되는 행을 반환한다. 매칭되지 않는 오른쪽 행은 NULL로 표시한다.

SELECT Customers.Name, Orders.OrderDate
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID;

3. RIGHT JOIN: 오른쪽 테이블의 모든 행과, 매칭되는 왼쪽 테이블의 행을 반환한다.

4. CROSS JOIN: 두 테이블의 모든 가능한 조합을 반환한다. (경우에 따라 조심해서 사용해야 한다.)

# 서브쿼리(Subquery)

서브쿼리는 쿼리 안에 포함된 또 다른 쿼리다. 주로 조건에 따라 데이터를 필터링할 때 사용한다.

SELECT Name 
FROM Customers 
WHERE CustomerID IN (
    SELECT CustomerID FROM Orders WHERE OrderDate > '2024-01-01'
);

# GROUP BY와 HAVING

GROUP BY는 특정 열의 값으로 데이터를 그룹화하고, HAVING은 그룹화된 데이터에 조건을 적용한다.

SELECT CustomerID, COUNT(OrderID) AS TotalOrders
FROM Orders
GROUP BY CustomerID
HAVING TotalOrders > 5;

# 인덱스(Index)와 성능 최적화

1. 인덱스(Index)의 개념

인덱스는 테이블의 특정 열에 대해 검색 성능을 향상시키는 자료 구조다. 인덱스를 추가하면 조회 속도가 빨라지지만, 삽입·수정·삭제 작업은 느려질 수 있다.

CREATE INDEX idx_customer_name ON Customers (Name);
  • PRIMARY KEY: 기본 키는 자동으로 인덱스가 생성된다.
  • UNIQUE INDEX: 중복이 허용되지 않는 인덱스다.
  • FULLTEXT INDEX: 텍스트 검색에 사용되는 인덱스다. (MyISAM 또는 InnoDB에서 지원)

2. 실행 계획(EXPLAIN)

EXPLAIN 명령어를 사용해 쿼리의 실행 계획을 확인하고, 인덱스 사용 여부나 병목 지점을 파악할 수 있다.

EXPLAIN SELECT * FROM Customers WHERE Name = 'John Doe';

# 트랜잭션(Transaction)과 격리 수준

1. 트랜잭션(Transaction)

트랜잭션은 데이터베이스에서 일련의 작업을 하나의 단위로 묶어 처리하는 것이다. 모든 작업이 성공적으로 완료되거나(Commit), 실패 시 모두 취소(rollback)된다.

START TRANSACTION;
INSERT INTO Orders (CustomerID, OrderDate) VALUES (1, '2024-10-10');
UPDATE Customers SET Balance = Balance - 100 WHERE CustomerID = 1;
COMMIT;

2. 격리 수준(Isolation Levels)

MySQL에서는 동시에 여러 트랜잭션이 실행될 때 데이터 일관성을 유지하기 위해 격리 수준을 설정한다. 격리 수준은 다음과 같다:

  1. READ UNCOMMITTED: 다른 트랜잭션의 커밋되지 않은 변경 사항도 읽을 수 있다.
  2. READ COMMITTED: 커밋된 데이터만 읽을 수 있다.
  3. REPEATABLE READ: 하나의 트랜잭션 내에서 같은 쿼리를 여러 번 실행해도 결과가 동일하다.
  4. SERIALIZABLE: 가장 엄격한 수준으로, 모든 트랜잭션을 순차적으로 실행한다.
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

# 사용자 권한 관리와 보안

MySQL에서는 각 사용자가 특정 작업을 수행할 수 있는 권한을 부여하거나 제한할 수 있다.

1. 사용자 생성 및 권한 부여

CREATE USER 'user1'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT ON CustomerDB.* TO 'user1'@'localhost';
  • GRANT: 특정 권한을 부여한다.
  • REVOKE: 부여된 권한을 회수한다.

2. 사용자 권한 확인

SHOW GRANTS FOR 'user1'@'localhost';​

# 복제(Replication)와 고가용성

복제는 하나의 MySQL 서버(마스터)의 데이터를 다른 서버(슬레이브)로 동기화하는 기능이다. 이는 백업, 데이터 가용성, 읽기 성능 향상에 유용하다.

1. 마스터 서버 설정

[mysqld]
server-id=1
log-bin=mysql-bin

2. 슬레이브 서버 설정

[mysqld]
server-id=2
replicate-do-db=CustomerDB

3. 슬레이브 시작

CHANGE MASTER TO MASTER_HOST='master_host', MASTER_USER='replication_user', MASTER_PASSWORD='password';
START SLAVE;

# 성능 튜닝과 모니터링

1. 쿼리 캐시(Query Cache)

쿼리 결과를 캐시에 저장하여 동일한 쿼리의 성능을 높인다. 하지만 MySQL 최신 버전에서는 쿼리 캐시가 더 이상 지원되지 않는다.

2. MySQL 프로파일링

MySQL 프로파일링 도구를 사용해 쿼리 성능을 분석할 수 있다.

SET profiling = 1;
SELECT * FROM Customers WHERE Name = 'John Doe';
SHOW PROFILES;

3. 오류 로그 및 모니터링 도구

MySQL 로그 파일을 확인하여 문제를 진단하고, MySQL Workbench와 같은 모니터링 도구를 사용해 서버 상태를 실시간으로 관찰한다.


8. 백업과 복원

1. 백업

정기적으로 데이터를 백업하여 데이터 손실을 방지한다.

mysqldump -u root -p CustomerDB > backup.sql

2. 복원

백업한 데이터를 복원할 때는 다음 명령어를 사용한다.

mysql -u root -p CustomerDB < backup.sql

'데이터베이스 > Mysql' 카테고리의 다른 글

MySQL 정리  (2) 2024.10.12
Mysql 덤프(dump) - 리스토어(restore)  (1) 2024.09.12

MySQL은 관계형 데이터베이스 관리 시스템(RDBMS)으로, 데이터를 효율적으로 저장하고 관리하며, 테이블 형태로 데이터를 정리해준다. 각 테이블은 행과 열로 구성되어 있는데, 스프레드시트와 비슷하지만 훨씬 큰 데이터와 복잡한 쿼리를 처리할 수 있게 설계되었다.

# MySQL의 기본 개념

  1. 데이터베이스란? 데이터베이스는 단순히 데이터를 모아둔 것이다. 예를 들어, 고객 정보를 추적하는 애플리케이션이 있다고 하면, 고객 정보, 주문 내역, 제품 정보 등이 저장되어야 한다. 이 모든 정보가 저장되는 곳이 바로 데이터베이스다.
  2. 테이블 MySQL에서 테이블은 데이터를 구조화된 형태로 저장하는 공간이다. 테이블은 다음과 같이 구성된다:
    • 열(Columns): 어떤 종류의 데이터를 저장할지 정의한다. 예를 들어, 고객을 위한 테이블에는 CustomerID, Name, Email, PhoneNumber 같은 열이 있을 수 있다.
    • 행(Rows): 각 행은 테이블에 있는 하나의 데이터 항목을 나타낸다. 예를 들어, 한 행에는 한 명의 고객 정보가 저장된다:
      • 1, Park Guen, Park@example.com, 555-1234.
      • 2, Sung Jun, Sung@example.com, 999-4321.
  3. SQL (Structured Query Language) SQL은 MySQL 데이터베이스와 상호작용하기 위해 사용되는 언어이다. 이를 통해 테이블을 생성하고, 데이터를 삽입하며, 데이터를 조회하고, 수정 및 삭제하는 등의 작업을 할 수 있다. 대표적인 SQL 명령어는 다음과 같다:
    • CREATE – 새 테이블을 생성한다.
    • INSERT – 테이블에 데이터를 삽입한다.
    • SELECT – 테이블에서 데이터를 조회한다.
    • UPDATE – 테이블의 데이터를 수정한다.
    • DELETE – 테이블에서 데이터를 삭제한다.

# MySQL 설정

1. MySQL 설치 사용하는 운영체제(Windows, macOS, Linux)에 따라 MySQL 설치 방법이 조금 다를 수 있다. 일반적으로 MySQL 웹사이트에서 설치 프로그램을 다운로드하고, 안내에 따라 설치를 진행하면 된다.

설치가 완료되면, root 사용자 계정을 설정할 필요가 있다. root 계정은 MySQL 서버의 관리자 계정으로, 모든 데이터베이스와 테이블에 대한 전체 제어 권한을 가진다.

2. MySQL 서버 시작 MySQL은 서비스로 실행되며, 이 서비스를 시작해야 데이터베이스에 연결하고 쿼리를 실행할 수 있다. macOS나 Linux에서는 다음과 같은 명령어로 MySQL 서비스를 시작할 수 있다:Windows에서는 서비스가 자동으로 시작될 수도 있으며, 서비스 관리자에서 수동으로 시작할 수도 있다.

sudo service mysql start
 

3. MySQL 접속 설치가 완료되면, MySQL에 접속하기 위해 다음과 같은 도구를 사용할 수 있다:

  • MySQL Workbench: 쿼리를 실행하고 데이터베이스를 관리할 수 있는 그래픽 도구다.
  • 명령줄 인터페이스(CLI): 터미널이나 명령 프롬프트에서 직접 명령어를 입력하여 MySQL에 접속할 수 있다.

명령줄을 통해 MySQL에 접속하려면 다음 명령어를 사용한다:여기서 -u root는 root 사용자로 로그인하겠다는 의미이며, -p는 비밀번호 입력을 요청하는 옵션이다.

mysql -u root -p

 

 

# 데이터베이스 및 테이블 생성

1. 데이터베이스 생성 MySQL에서 데이터베이스는 간단한 SQL 명령어로 생성할 수 있다. 예를 들어, 고객 관리 시스템을 위한 데이터베이스를 생성하려면 다음과 같이 한다:이 명령어는 CustomerDB라는 이름의 빈 데이터베이스를 생성한다.

CREATE DATABASE CustomerDB;
 

2. 테이블 생성 데이터베이스가 준비되면, 데이터를 저장할 테이블을 생성한다. 예를 들어, Customers라는 테이블을 생성하는 SQL 명령어는 다음과 같다:

CREATE TABLE Customers (
    CustomerID INT AUTO_INCREMENT PRIMARY KEY,
    Name VARCHAR(100),
    Email VARCHAR(100),
    PhoneNumber VARCHAR(15)
);
  • CustomerID는 각 고객을 위한 고유 식별자다. 자동으로 증가하며, PRIMARY KEY는 각 행을 고유하게 식별할 수 있음을 의미한다.
  • **VARCHAR(100)**은 최대 100글자의 문자열을 저장할 수 있도록 한다.
  • **PhoneNumber VARCHAR(15)**는 최대 15글자의 고객 전화번호를 저장한다.

# 테이블에 데이터 삽입

테이블이 생성되면, 데이터를 삽입할 수 있다. 다음은 Customers 테이블에 새로운 고객 정보를 추가하는 예다:

INSERT INTO Customers (Name, Email, PhoneNumber)
VALUES ('Park Guen', 'Park@example.com', '555-1234');

이 명령어는 Name, Email, PhoneNumber 열에 해당하는 값을 가진 새로운 행을 테이블에 추가한다.

# 데이터 조회 (SELECT 쿼리)

테이블에서 데이터를 조회하려면 SELECT 명령어를 사용한다. 예를 들어, Customers 테이블에서 모든 데이터를 가져오려면 다음과 같이 한다:

SELECT * FROM Customers;

여기서 *는 "모든 열"을 선택한다는 의미다. 특정 열만 조회하고 싶다면 다음과 같이 지정할 수 있다:

SELECT Name, Email FROM Customers;

이 명령어는 Name과 Email 열의 데이터만 출력한다.

# 데이터 수정

기존 데이터를 수정하려면 UPDATE 명령어를 사용한다. 예를 들어, 고객의 전화번호를 변경하려면 다음과 같이 한다:

UPDATE Customers
SET PhoneNumber = '555-5678'
WHERE CustomerID = 1;

이 명령어는 CustomerID가 1인 고객의 전화번호를 수정한다.

# 데이터 삭제

데이터를 삭제하려면 DELETE 명령어를 사용한다. 예를 들어, CustomerID가 1인 고객을 삭제하려면 다음과 같이 한다:

DELETE FROM Customers WHERE CustomerID = 1;

이 명령어는 해당 행을 Customers 테이블에서 삭제한다.

# 기본 유지보수 및 도구

1. 데이터 백업 데이터 손실을 방지하기 위해 정기적으로 데이터베이스를 백업하는 것이 중요하다. mysqldump 유틸리티를 사용하여 데이터베이스 백업을 생성할 수 있다:

mysqldump -u root -p CustomerDB > backup.sql

이 명령어는 CustomerDB 데이터베이스의 내용을 backup.sql 파일로 저장한다.

 

2. 백업 복원 백업한 데이터를 복원하려면 mysql 명령어를 사용한다:이 명령어는 backup.sql 파일의 데이터를 CustomerDB에 복원한다.

mysql -u root -p CustomerDB < backup.sql

3. 에러 로그 및 문제 해결 MySQL이 시작되지 않거나 오류를 발생시키는 경우가 있을 수 있다. MySQL은 일반적으로 설치 디렉토리에 로그 파일을 기록한다. macOS나 Linux에서는 /var/log/mysql/에서 이러한 로그를 찾을 수 있다. 문제가 발생하면 이 로그 파일을 확인해보는 것이 좋다.

# 초보자들이 자주 저지르는 실수

1. 데이터베이스 선택을 잊지 않기 테이블에서 작업하기 전에 항상 올바른 데이터베이스를 선택해야 한다. 이를 위해 다음 명령어를 사용한다:

USE CustomerDB;

2. 기본 키와 다른 키 혼동 데이터를 고유하게 식별하기 위해 항상 테이블에 기본 키를 정의해야 한다. 기본 키가 없으면 데이터를 관리하는 데 어려움이 발생할 수 있다.

3. NULL 값 무시 테이블의 열은 NULL 값을 허용할지 여부를 설정할 수 있다. NULL은 값이 없음을 의미한다. 데이터베이스 설계 시, 각 열이 NULL 값을 허용할지 신중하게 결정해야 한다.

# 요약

  • MySQL은 관계형 데이터베이스에서 데이터를 저장하고 관리하는 데 사용된다.
  • 데이터는 테이블에 행과 열로 구성된다.
  • SQL 명령어를 사용하여 데이터베이스를 생성하고, 데이터를 삽입하고, 조회하고, 수정 및 삭제한다.
  • 데이터를 정기적으로 백업하고, 로그 파일을 통해 문제를 모니터링한다.

'데이터베이스 > Mysql' 카테고리의 다른 글

Mysql 심화 정리  (0) 2024.10.14
Mysql 덤프(dump) - 리스토어(restore)  (1) 2024.09.12

1. 덤프(restore)

# 덤프 명령어

mysqldump -h <RDS_ENDPOINT> -P <PORT> -u <USERNAME> -p <DATABASE_NAME> > dump01.sql
 
  • <RDS_ENDPOINT>: RDS 인스턴스의 엔드포인트 주소.
  • <PORT>: MySQL 서버 포트 (기본값 3306).
  • <USERNAME>: 데이터베이스 사용자 이름.
  • <DATABASE_NAME>: 덤프할 데이터베이스의 이름.
  • dump01.sql: 생성될 덤프 파일의 이름.
  • 생성되는 경로 : 현재 경로

# 덤프시 생기는 에러

경고 메세지 (넘버링은 편의상 사용):

1. "Warning: 
A partial dump from a server that has GTIDs will by default include 
the GTIDs of all transactions, even those that changed suppressed parts of 
the database."
2. "If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a 
complete dump, pass --all-databases --triggers --routines --events.
Warning: 
A dump from a server that has GTIDs enabled will by default include 
the GTIDs of all transactions, even those that were executed during its extraction 
and might not be represented in the dumped data. This might result in an 
inconsistent data dump. In order to ensure a consistent backup of the database, 
pass --single-transaction or --lock-all-tables or --master-data."

 

이 경고 메시지는 MySQL 데이터베이스를 덤프할 때 GTID (Global Transaction Identifier)와 관련된 사항과 데이터의 일관성을 보장하기 위한 설정에 대한 경고이다. 

1.  GTID 관련 경고

  • 해석: GTID가 활성화된 서버에서 덤프를 생성하면 기본적으로 모든 트랜잭션의 GTID가 포함된다. 이 GTID는 덤프 파일에서 제외된 데이터베이스의 일부를 변경한 트랜잭션의 GTID도 포함될 수 있다.
  • 해결 방법: GTID를 덤프에서 제외하려면 --set-gtid-purged=OFF 옵션을 사용해야 한다. 
mysqldump -h <RDS_ENDPOINT> -P <PORT> -u <USERNAME> -p --set-gtid-purged=OFF <DATABASE_NAME> > dumpfile01.sql

2.  일관성 있는 백업 경고

  • 해석: 전체 데이터베이스의 덤프를 만들려면 --all-databases, --triggers, --routines, --events 옵션을 추가하여 덤프를 생성해야 한다.
 
mysqldump -h <RDS_ENDPOINT> -P <PORT> -u <USERNAME> -p --all-databases --triggers --routines --events > dumpfile01.sql
  • 일관성 보장: 데이터베이스의 일관성을 보장하려면 --single-transaction 또는 --lock-all-tables 또는 --master-data 옵션을 추가할 수 있다.
  • --single-transaction: InnoDB 테이블을 사용하는 경우, 트랜잭션을 시작하고 전체 덤프를 한 트랜잭션 내에서 실행한다. (데이터베이스의 일관성을 유지 가능)
mysqldump -h <RDS_ENDPOINT> -P <PORT> -u <USERNAME> -p --single-transaction <DATABASE_NAME> > dumpfile01.sql

 

 
 
  • --lock-all-tables: 모든 테이블을 잠그고 덤프를 생성한다. 이 옵션은 MyISAM 테이블을 사용할 때 유용하다.
mysqldump -h <RDS_ENDPOINT> -P <PORT> -u <USERNAME> -p --lock-all-tables <DATABASE_NAME> > dumpfile01.sql
 
  • --master-data: 복제 정보를 포함하여 덤프를 생성한다. 주로 복제 설정을 위한 덤프에서 사용된다.
mysqldump -h <RDS_ENDPOINT> -P <PORT> -u <USERNAME> -p --master-data <DATABASE_NAME> > dumpfile01.sql

* 에러 해결 요약

  • GTID 제외: --set-gtid-purged=OFF 옵션을 사용하여 GTID를 덤프에서 제외한다.
  • 전체 덤프: --all-databases, --triggers, --routines, --events 옵션을 추가하여 전체 데이터베이스 덤프를 만든다.
  • 데이터 일관성: --single-transaction, --lock-all-tables, --master-data 중 하나를 사용하여 데이터의 일관성을 보장한다.

 

2.  복원(restore)

# 복원시 주의사항

1. 데이터베이스 존재 여부: 복원시킬 데이터베이스가 존재해야 한다. 만약 데이터베이스가 없다면, 먼저 생성해야 한다. 데이터베이스를 생성하려면 다음 명령어를 사용할 수 있다

mysql -h localhost -u <USERNAME> -p -e "CREATE DATABASE data01;"
2. 권한 문제: 사용자가 데이터베이스에 대한 적절한 권한을 가지고 있는지 확인이 필요하다.

# 복원 명령어

 
mysql -h localhost -u <USERNAME> -p <database명> < <dump 파일명>
# 예시
mysql -h localhost -u root -p data01 < dumpfile.sql​
  • localhost: 데이터베이스가 로컬호스트에 위치할 경우 사용.
  • root: 데이터베이스 사용자 이름.
  • data01: 복원할 데이터베이스 이름.
  • dumpfile.sql: 덤프 파일의 이름.

복원 과정을 시작하면 비밀번호를 입력하라는 프롬프트가 표시된다. 비밀번호를 입력한 후 덤프 파일의 내용이 test04 데이터베이스에 복원된다.

 

'데이터베이스 > Mysql' 카테고리의 다른 글

Mysql 심화 정리  (0) 2024.10.14
MySQL 정리  (2) 2024.10.12

+ Recent posts