diff --git "a/08\354\236\245/8\354\236\245_\354\241\260\354\210\230\354\247\204.md" "b/08\354\236\245/8\354\236\245_\354\241\260\354\210\230\354\247\204.md" new file mode 100644 index 0000000..4271d19 --- /dev/null +++ "b/08\354\236\245/8\354\236\245_\354\241\260\354\210\230\354\247\204.md" @@ -0,0 +1,117 @@ +# 8장. 테이블 설계의 기초 - 테이블의 개념과 정규형 + +테이블은 공통 요소들의 집합이며, 함수이다.(X를 입력하면 Y를 출력하는 대응표) + +### 테이블 설계의 기초 + +관계형 데이터베이스에서 데이터는 테이블에 저장된다. 대규모의 복잡한 데이터를 모순없이 장기적으로 관리하기 위해 테이블 설계가 중요하다. + +테이블은 `어떤 공통 속성을 가진 집합(개념)` 이며, 표의 형식을 가진다. + +→ 테이블 명은 반드시 복수형이나 집합명사로 표현해야 한다. + +시스템에서 하드웨어어와 관련있는가로 구분지어, +아키텍처 설계 = 물리 설계 +테이블 설계 = 논리 설계 + +### 테이블 설계 규칙 + +1. 사물과 사물의 집합은 계층이 다르다 + + 예시) 완두콩 테이블, 토마토 테이블, 옥수수 테이블 X → 채소 테이블 + + 예시) 토마토 테이블(O) → 토마토A, 토마토B, 토마C.. + +2. 가장 상위의 개념 집합으로 정리한다 + + : 문맥에 따라 규정하는 집합이 달라질 수 있다 + + 예시) 회원 테이블(O), 일반 회원 & 프리미엄 회원 테이블(O), 남성 회원 & 여성 회원 테이블(O).. + + → 가장 상위의 회원을 테이블로 만들고, 일반&프리미엄 회원, 성별은 열로 구별한다 + + → 이렇게 했을 때, 애플리케이션의 유연성이 높아진다 + +3. 열이란 개체의 속성이다 + + RDB를 자바에 맵핑하면 테이블은 클래스, 행은 인스턴스, 열은 속성에 해당 + +4. 현실 세계에 같은 사람은 2명 있지 않다 + + → 한 개의 테이블의 내용에는 중복 행이 있다면 실제 두 데이터의 구분이 지 않는다 → 허용하지 않는다 + +5. 기본키 할당은 관리의 기본 + + → 데이터를 고유하게 식별할 수 있는 기본키를 반드시 할당하라(ex. 회원 ID, 건강보험증 번호 등) + +6. 기본키는 중복되면 안된다 +7. 기본키의 값이 바뀌면 왜 곤란한가 + - 변경 후 값의 유일성을 보증할 수 없다 + - 과거 데이터와의 결합(매칭)이 어렵다 +8. 기본키 열로 Null 불가 + +### 정규형 + +정규형 = 제대로 된 형태 = 데이터의 갱신이 발생한 경우에도 부정합이 발생하기 어려운 테이블의 형태 + +제1-5정규형이 있지만 실무에서는 정합성을 유지하기 위해 주로 `제2,3정규형`을 이해하는 것이 중요! + +**함수 종속성(Functional Dependency)** + +테이블은 Y = F(X)의 관계를 맺는 입력값과 출력값의 대응표이다 + +→ 기본키 열(X)와 일반키 열(Y) 사이에 성립하는 함수적인 유일성을 함수 종속성. 중괄호로 표현. + +`{사원 ID} → {이름, 나이}` + +**제1정규형(1NF)** + +테이블 셀에 복합적인 값(배열, 복수의 값)을 포함하지 않는다 + += 스칼라 값(단일값, 더 이상 나눠지지 않는 값) 이외의 값을 포함하지 않는다 + +- 복합키를 허용하면 기본키가 행의 값(일반키의 열)을 고유하게 특정할 수 없기 때문 + +**제2정규형(2NF)** + +부분 함수 종속성(기본키를 구성하는 열의 일부에만 함수 종속이 존재하는 것)을 가지지 않는다 + +→ 기본키: {주문번호 + 상품코드} But {상품코드} → {상품명} + +⇒ 집합을 더 명확하게 분리시킨다 + +![Untitled](https://lxxjn0-dev.netlify.app/static/8a27ce35b98f16356d07f35214c5d397/7d769/regular-3.png) + +- 제2정규화가 되지 않으면, + - 테이블의 부분 정보를 알지 못하면 데이터를 등록하기 어렵다 + - 부분 함수 종속에 해당하는 부분이 중복되며, 일부가 잘못 등록될 수 있다 = 데이터 부정합 = 갱신 이상 + +**제3정규형(3NF)** + +추이함수 종속(기본키 이외의 키 간에 발생하는 함수 종속)을 가지지 않는다 + +⇒ 추이 함수 종속이 생기는 부분을 테이블 분리(집합을 명확히 분리) + +![Untitled](https://img1.daumcdn.net/thumb/R800x0/?scode=mtistory2&fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9974AB4E5BD9AB0A1E) + +- 제3정규화가 되지 않으면, 아직 관계가 생기지 않은 데이터를 등록(ex. 기계공학과)할 방법이 없다 + +### ER 다이어그램 + +테이블의 수가 많아지면 테이블 간의 관계성을 파악하기 어렵다. 이런 테이블 간의 관련선을 한눈에 알 수 있게 그래픽으로 표현하는 기술이 ER 다이어그램 + +![Untitled](https://blog.kakaocdn.net/dn/4AmaB/btqEP3qzzcU/TLPnBeceKcKJ2g7Ylib5Dk/img.png) + +- 엔티티는 사각형으로 표현 + - 엔티티 윗 부분은 기본키 + - 엔티티 아래 기타 열 표기 + - FK는 외래키 +- 외래키에 의한 엔티티간의 관계(릴레이션십)은 기호로 표현 + - 점선: 참조하는 엔티티는 참조되는 엔티티(부모 개체)의 존재여부와 관계없이 존재할 수 있음 + - 직선: 참조하는 엔티티는 참조되는 엔티티(부모 개체)가 존재해야 존재할 수 있음 + + → 부모 개체의 키가 주식별자인 경우 + + - O: 0 + - -: 1 + - 새다리 모양: 2이상(복수) \ No newline at end of file diff --git "a/08\354\236\245/empty.txt" "b/08\354\236\245/empty.txt" deleted file mode 100644 index e69de29..0000000 diff --git "a/09\354\236\245/9\354\236\245_\354\241\260\354\210\230\354\247\204.md" "b/09\354\236\245/9\354\236\245_\354\241\260\354\210\230\354\247\204.md" new file mode 100644 index 0000000..941763a --- /dev/null +++ "b/09\354\236\245/9\354\236\245_\354\241\260\354\210\230\354\247\204.md" @@ -0,0 +1,93 @@ +# 9장. 백업과 복구 - 장애에 대비하는 구조 + +### 지속성과 성능이 양립하는 구조 + +트랜잭션의 ACID성질 중 Durability에 의해 한 번 반영(commit)된 동작은 영속화된다. 정상적인 동작 시 뿐만아니라 데이터베이스 서버나 OS의 비정상적인 종료 등 시스템 장애에서도 유지된다. 보존되는 데이터는 대부분 하드디스크에 저장된는데, 동기화 쓰기를 하면 성능에 부정적이기 때문에 로그 선행 쓰기(WAL 로그), 데이터베이스 버퍼 구조를 이용해 데이터베이스 파일에 동기화한다. + +**로그 선행 쓰기 - WAL(write ahead log)** + +변경에 대한 로그 레코드를 이용해서 동기화한다 + +MySQL에서는 InnoDB 로그라고 부른다 + +- 디스크에 연속해서 쓰기 때문에 무작위로 쓰는 것보다 성능이 좋다 +- 디스크에 쓰는 용량과 횟수를 줄일 수 있다 +- 데이터베이스 버퍼를 이용해 데이터베이스의 데이터 파일로의 변경을 효율성 높게 수행한다 + +**데이터베이스 버퍼** + +WAL에 변경을 작성하기 때문에 트랜잭션 커밋마다 동기화 할 필요가 없다. 하지만 계속해서 비동기적인 쓰기를 하면 로그와 데이터 파일 간 일관성을 유지하기 어렵다 + +→ 데이터 파일로의 입력을 데이터베이스 버퍼 경유로 일원화해서 단순화 + +→ 효율적으로 데이터의 일관성 유지 가능 + +**MySQL 갱신 흐름** + +1. 갱신 대상 데이터를 포함한 페이지가 버퍼 풀에 있는지 확인하고 없다면 파일에서 읽어들인다 +2. 버퍼 풀의 해당 페이지에서 갱신을 수행한다 +3. 2의 갱신 내용이 커밋과 함께 로그에 기록된다. 버퍼 풀에 갱신되었지만, 아직 데이터 파일에 써지지 않은 페이지는 버퍼풀 내에서 더티 페이지로 다룬다 +4. 데이터 페이지는 나중에 적당한 타이(체크 포인트)밍에 정리되어 데이터 파일로 써진다 +5. 4의 체크포인트 이전 로그 파일은 불필요해진다. 갱신과 더불어 1부터 순서가 반복된다 + +**크래시 발생시 각 구조의 상태** + +- WAL: 마지막으로 커밋된 트랜잭션의 갱신 정보를 가진다 +- 데이터베이스 버퍼: 크래시로 내용이 소실된다 +- 데이터베이스 파일: 최종 체크포인트까지 갱신 정보를 가진다 + +크래시(예를 들어 MySQL 서버의 비정상적 종료)시, 체크포인트 이후의 WAL로그를 데이터베이스 파일에 반영 + +⇒ 롤 포워드 + +### 백업과 복구 + +DBMS의 복구 구조가 존재하지만 논리적 파괴(DDL 문에 따른 테이블 파기)나 물리적 파손(디스크 장치 고장)에는 대응이 불가능하다. 따라서 주기적으로 백업하고 그를 이용해 복원이나 복구하는 것이 좋다. + +**PIRT?** + +Point-in-time Recovery: 백업 이후의 임의의 시점으로 복원하는 것 + +실행된 갱신을 기록한 로그를 보존해서 복원한 데이터베이스에 순차 반영해서 복원할 수 있다 + +**바이너리 로그** + +MySQL에서 PIRT를 위해 사용하는 로그(InnoDB 포함 모든 MySQL) + +InnoDB 로그는 크래시 복구에만 이용(InnoDB 전용) + +**백업의 관점** + +1. 핫 백업(온라인 백업) vs 콜드 백업(오프라인 백업) + + 백업 시 데이터베이스의 상태에 따라 구분 → 백업 도중 DB 접근이 가능한지 안한지 + + - 핫 백업: 트랜잭션 구조 or 특수 로그 지정 or OS나 하드웨어의 스냅샷을 사용하기도! +2. 논리 백업 vs 물리 백업 + - 논리 백업: SQL기반 텍스트 백업(장애가 발생한 이유를 알 수 있다, 이식성 우수, 파일이 큼) + - 물리 백업: 데이터 영역을 그대로 덤프하는 이미지로 바이너리 형식으로 기록(가볍고 빠름, 호환 어렵) +3. 풀 백업 vs 부분 백업 + - 풀 백업: 전체 백업(단순, 시간이 오래 걸림, 용량이 많이 필요) + ![Untitled](https://t1.daumcdn.net/cfile/tistory/992364475CCED7DA2E) + - 부분 백업: 풀 백업 후 이후 갱신된 데이터를 백업(빠르고 용량이 작음, 복원 절차가 복잡) + - 증분 백업 + + ![Untitled](https://t1.daumcdn.net/cfile/tistory/99565D4C5CCED8191A) + - 차등 백업 + + ![Untitled](https://t1.daumcdn.net/cfile/tistory/993ED7425CCED8621F) + + **롤 포워드 리커버리** + + 현재 데이터 베이스 = 풀 백업한 데이터 + 풀 백업 후 얻은 모든 증분 백업(바이너리 로그) + + +### 데이터 베이스 관리 시 주의점 + +- 백업 파일은 데이터베이스와 다른 디스크 장치로 나눠 보관할 것 +- 가능하면 물리적으로 분리하는 것도 좋음 +- 데이터베이스 장애는 자연 현상. 언제나 일어날 수 있음을 기억하고 대책을 세우고 비율을 줄이기 위해 노력해야함 + + → 백업과 복구에 걸리는 시간, 부하 측정해 운영하기 + +- 백업을 필요로 하는 시스템의 상황에 맞게 백업 방식을 선정할 것 \ No newline at end of file diff --git "a/09\354\236\245/empty.txt" "b/09\354\236\245/empty.txt" deleted file mode 100644 index e69de29..0000000