데이터 베이스가 갖춰야 할 기본 기능
- 데이터의 검색과 갱신
- 데이터베이스는 주소록에서 시작
- 데이터의 조회 및 등록, 수정, 삭제가 가능해야 함
- 데이터 포멧 및 처리 성능에 대한 고려가 필요
-
동시성 제어 (= 배타 제어)
- 데이터베이스는 동시에 복수의 사용자로부터 검색 및 갱신 처리를 받음
- 갱신의 무결성이 중요 (갱신 상황에 대한 제어가 필요)
- 만일 두 명의 사용자가 같은 파일에 접근해 수정하려 한다면 다음 동작 중 하나가 시나리오가 될 것
- 한 사람이 파일을 열고 있을 때, 다른 사람은 열 수 없음
- 한 사람이 파일을 열고 있을 때, 다른 사람은 읽기 전용(ReadOnly)으로만 파일을 열 수 있음
- 어떤 사람도 문제없이 파일을 열 수 있고, 나중에 수행된 쪽의 갱신이 반영
- 이를 더티 쓰기(Dirty Write)라고 하며, 선착순으로 갱신을 반영하는 상황
- 데이터 무결성 관점에서 지양
-
장애 대응
- 데이터베이스는 장애에 강해야 한다.
- 데이터 보호와 장애 대책에 최대한으로 예민해져야 함
- 데이터 소실은 큰 사회문제와 손해배상청구 유발
- 데이터 소실 문제에 대한 대책
- 데이터 다중화: 데이터를 복수의 장소에 분산해서 유지 (예방책)
- 백업: 데이터 소실이 발생했을 때 데이터를 복원하는 방법 (사후대책)
-
보안
- 데이터베이스에 보존된 데이터를 어떻게 숨길 것인가
- 데이터베이스는 사용자가 서버를 의식하지 못하도록 설계되고 있음
데이터베이스의 종류
- 계층형 데이터베이스
- 데이터를 계층구조로 관리 (조직도, 전체 구조도)
- 최초의 현대적 데이터베이스
-
관계형 데이터베이스
- 2차원 표 형식으로 데이터를 관리 (현재 가장 주류)
- 프로그래밍 언어를 사용하지 않아도 데이터를 조작 가능 (SQL)
- SQL이란 관계형 데이터베이스가 데이터를 조작하기 위해 준비한 언어
- 객체지향 데이터베이스 & XML 데이터베이스
- 객체와 XML 형식으로 데이터를 관리 (비주류)
-
NoSQL 데이터베이스
- Not only SQL (SQL뿐만 아니라 다른 것이 더 있다)
- 관계형 데이터베이스의 기능 일부를 버리고 성능(처리속도)을 높임
- 대량의 데이터를 고속으로 처리해야 하는 웹서비스와 잘 맞음
데이터베이스의 구성
DBMS와 데이터베이스
- Database
- 데이터 저장소를 뜻하는 추상화된 개념
- DBMS(Database Management System)
- 데이터베이스의 기능을 제공하는 소프트웨어
- 데이터베이스 추상화를 구현한 제품
- MySQL, PostgreSQL, Oracle…
시스템과 데이터베이스
- 시스템은 여러가지 소프트웨어를 조합해 만들어야 하며, 이 작업을 SI(System Integration)라고 함
- 사용되는 소프트웨어는 크게 3가지로 구분하며 계층성을 띔
- 애플리케이션
- 비즈니스 로직을 자동화한 소프트웨어
- 사용자는 애플리케이션을 매개로 데이터베이스에 접근
- 미들웨어
- 중간 소프트웨어
- DBMS가 해당하는 위치
- 운영체제
- 시스템을 동작하게 하기 위한 토대가 되는 기능을 제공하는 소프트웨어
- 애플리케이션
- 적합한 조합은 예산, 제품 기능, 엔지니어 리소스를 고려해 선택
-
제품의 비즈니스적 관점도 고려 필요
- 현시점에서 최고라고 생각해 선택한 조합이 수년 후에는 불가능해지는 곳이 IT 세계
- HP-UX + Oracle 조합은 두 기업의 친밀한 관계로 지속되었으나, 추후 서로 소송으로 얽힘
데이터베이스와 비용
- 시스템 혹은 서비스를 새로 만드는 목적은 돈벌이
- 관공서나 지방공공단체는 직접적인 이익추구를 하지 않지만, 사회 전체의 이익을 높이기 위해 시스템을 사용
- 비용감각이 있는 엔지니어가 되어야 함
- 시스템 전체 비용 내역
- 초기비용
- 서비스 이용시 최초로 지급하는 비용
- 하드웨어 구매비용, 엔지니어 급여…
- 운영비용
- 서비스 이용 기간에 지속적으로 지급하는 비용
- 유지보수 비용 (장애 대응, 프로그램 수정)
- 초기비용
-
데이터베이스 관점의 비용
-
초기비용
-
소프트웨어 라이센스 요금 (사용허가료)
- 시스템 규모가 클수록 라이센스료가 증가 (CPU, 사용자 수는 규모의 척도)
- 종류
-
프로세서 라이센스(Processor License)
- 하드웨어(DB 서버) CPU 성능에 따라 가격 결정
- 어느 정도 규모를 가진 상용 시스템에서 채택
- 사용자 라이센스(User License)
- 사용자 수에 따라 가격 결정
- 사용자 수 파악이 쉬운 소규모 환경에서 채택
-
프로세서 라이센스(Processor License)
- 에디션과 옵션
- 종류
- 스탠다드 에디션
- 중소규모 시스템용
-
엔터프라이즈 에디션
- 대규모 시스템용
- 신뢰성, 성능, 보안 등의 추가 기능 지원 제공
- 익스프레스 에디션
- 시험판
- 평범한 기능 및 동작 확인용
- 스탠다드 에디션
- 종류
-
소프트웨어 라이센스 요금 (사용허가료)
-
운영비용
-
기술지원 비용
- 버그에 대한 기술적 Q&A, 긴급 수정 프로그램 배포 등의 지원
- 데이터베이스는 복잡한 로직으로 구현되어 있으므로, 해당 데이터베이스 개발자의 도움 필요
- 기술 지원 없는 소프트웨어 사용은 생명줄 없이 등산하는 것
- 너무 오래된 버전의 제품은 기술지원을 받을 수 있는 기간이 짧음
-
EOSL(End of Service LIfe)
- 제품이 배포되고 오랜 시간이 지나 기술 지원이 종료되는 시점
- EOSL 가까우면 서비스 채택을 지양하거나 새로운 서비스로 마이그레이션해야 함
- 반대로 최신 버전은 버그의 집합체로 안정성과 신뢰성에 결함이 있는 경우가 많음
-
기술지원 비용
-
초기비용
- 현실적인 데이터베이스 비용 선택지
-
벤더 제품의 데이터베이스
- 초기비용 있음 + 운영비용 있음
- 고기능이 더 많음
- 반영구적 거주 가능
-
오픈소스 데이터베이스
- 초기비용 없음 + 운영비용 있음
- 기술지원료만 유상 혹은 구독 요금제
- 초기비용 없이 간단히 시작할 수 있어 의사결정 비용이 낮음
-
벤더 제품의 데이터베이스
- 초기비용이 낮으면 전체비용이 높은 경우가 많으니 전체 비용을 확실히 계산 후 냉정한 판단 필요
구독 요금 (Subscription)
- 무기한 사용의 라이센스 형태와 달리 기한을 정한 사용 허가
- 운영비용만 존재
- 기술 지원이 포함
데이터베이스와 아키텍처 구성
아키텍처 역사
- 아키텍처
- 시스템을 만들기 위한 물리 레벨의 조합
- 시스템의 목적과 기능을 표현 (아키텍처를 보고 그 시스템의 용도와 목적을 추측할 수 있음)
- 폭넓은 지식이 필요 (데이터베이스, 서버, OS, 미들웨어, 저장소, 로드밸런서, 방화벽…)
- 초반 아키텍처 설계가 프로젝트의 비용과 성패를 결정
- 역사
- Stand-alone (1980)
- 데이터베이스가 동작하는 머신(DB서버)이 네트워크 없이 독립적으로 동작
- 물리적으로 서버 앞에 앉아서 사용해야함
- 클라이언트/서버 (1990~2000)
- 네트워크를 통해 데이터베이스 서버 1대에 복수 사용자의 단말이 접속하는 구성
- 보안상 이유로 주로 기업이나 조직 내 닫힌 네트워크(LAN)에 이용
- 네이티브 애플리케이션을 사용해 비즈니스 로직이 클라이언트에 존재
-
Web 3계층 (2000~)
- Web Server, WAS, DB 서버로 이루어진 구성
- 클라이언트(브라우저)와 DB 서버 사이에 웹 서버와 웹 애플리케이션 서버를 둠
- 네트워크를 이용해도 애플리케이션 계층과 DB 계층의 보안성을 높일 수 있음
- 클라이언트의 비즈니스로직을 애플리케이션 계층으로 옮겨서 애플리케이션 관리 비용을 낮춤
- Stand-alone (1980)
다중화 관련 용어
-
다중화(=고가용성)
- 서비스 정지를 막기 위해 서버를 여러개 두어 1대가 고장나도 나머지가 동작하도록 구성하는 설계
-
클러스터링(Clustering)
- 동일한 기능의 컴포넌트를 병렬화하는 것
- 클러스터링으로 가용성을 높인다 = 여유도(Redundancy)를 확보한다 = 다중화
- 가용성
- 사용자 입장에서 시스템을 어느정도 사용할 수 있는지
- 신뢰성
- 컴포넌트(하드웨어, 소프트웨어)가 고장나는 빈도나 고장 기간을 나타내는 개념
- 가용성을 높이는 2가지 전략
- 심장전략: 시스템 내 각 컴포넌트의 신뢰성을 높이기
-
신장전략: 컴포넌트를 병렬화하기 (물량작전)
- 신뢰성이 낮은 컴포넌트를 사용하더라도 다중화(클러스터링)한다면 시스템 전체 가용성 상승
- 가동률(=가용률)
- 시스템이 무고장으로 동작할 확률
- 100% - 장애 발생률(서버)
- 100%는 원리적으로 불가능 (비용을 들여도 달성 불가능)
- 서버가 늘어날수록 가동률이 증가하나 증가 폭은 크게 적어짐
- 시스템 세계에서는 가용률 99%도 낮은 수치 (= 1년 중 3일 15시간 36분 서비스 다운)
- 유지보수 등의 계획정지를 포함하지 않는 경우 실제 가용률이란 표현을 사용하는 경우도 존재
- 단일 장애점(SPFO, Single Point of Failure)
- 다중화되어 있지 않아서 전체 서비스의 계속성에 영향을 주는 컴포넌트
- 단일 장애점의 신뢰성이 시스템 전체의 가용성을 결정
- 단일 장애점을 없애기 위해 대부분 이중화 노력
DB 서버의 다중화
- DB 서버는 데이터를 보존하는 영속 계층이기 때문에, 오랫동안 클러스터링이 어려운 컴포넌트로 인식
- 웹서버, WAS는 데이터를 일시적으로 처리하므로 다중화가 간편
- 데이터는 항상 갱신되므로 DB 서버 다중화는 데이터 정합성이 중요
- DB 서버 아키텍처 = DB 서버 + 저장소
- 대량의 데이터를 영구적으로 보존해야하고 그에 따른 성능도 요구됨
- DB 아키텍처 패턴
-
클러스터링(Clustering)
-
Shared Disk (기본 다중화)
- DB 서버 다중화 + 1개 저장소
- 저장소가 1개라 데이터 정합성은 신경 쓸 필요 없음
- 종류 (DB 서버 동시 동작 여부에 따라)
-
Active-Active
- 컴포넌트를 동시에 가동
- Oracle RAC, DB2 pureScale 말고는 없음
- 장점
- 시스템 다운 시간이 짧음 (한 대가 다운되어도 남은 서버가 계속 처리)
- 좋은 처리 성능 (DB 서버 대수가 증가하면 동시 가동 CPU 및 메모리도 증가)
- 단점
- 저장소가 병목지점이므로 생각만큼 성능 향상이 없는 경우도 존재
- 저장소가 파괴될 경우 데이터 유실
-
Active-Standby
- 컴포넌트 중 실제 가동하는 것은 Active, 남은 것은 대기(Standby)
- Standby 상태 DB 서버는 Active DB 서버에 장애가 날 때만 사용
- Heartbeat: Standby DB 서버는 일정 간격으로 Active DB에 이상 없는지 체크 (수 초~수십 초)
- 신호가 끊기면 장애 발생으로 판단하고 Standby DB 서버 종작
- 전환시간만큼의 시스템 다운 발생 (수십초~수분)
- 종류
- Cold-Standby
- 평소에는 Standby DB 작동 X, Active DB가 다운된 시점에 작동
- Hot-Standby
- 평소에도 Standby DB 작동
- 전환시간이 더 짧지만, 라이센스료가 더 비쌈
- 사치스러운 구성이지만, 그럼에도 Active-Active보다 저렴
- Cold-Standby
-
Active-Active
-
가용성과 성능이 좋은 순서(= 라이센스 가격순)
- Active-Active
- Active-Standby(Hot-Standby)
- Active-Standby(Cold-Standby)
-
Shared Nothing (성능 추구를 위한 다중화)
- 네트워크 이외의 자원을 모두 분리하는 방식
- 서버, 저장소, 데이터를 한 세트 단위로 해서 여러 세트로 분리
- 구글이 개발한 구조를 Sharding이라고도 부름 (구글이 극적인 방식으로 유효성 증명)
- 장점
- 구조가 간단하고 저장소 병목 방지
- 서버와 저장소 세트를 늘리면 병렬처리 때문에 선형적으로 성능(처리율)이 향상
- 단점
-
각각의 DB 서버가 동일한 1개 데이터에 엑세스할 수 없음
- 시 단위 DB 서버 + 저장소 세트
- 고양시 데이터는 고양시 데이터를 가진 DB 서버만 엑세스 가능
- 경기도 인구 계산할 때는 각 시별 세트로부터 데이터를 집계 정리하는 서버 필요
- DB 서버 다운 대책으로 커버링(Covering) 구성 필요
- 한 DB 서버가 다운되면 다른 DB 서버가 이어받아 계속 처리
-
각각의 DB 서버가 동일한 1개 데이터에 엑세스할 수 없음
- 네트워크 이외의 자원을 모두 분리하는 방식
-
Shared Disk (기본 다중화)
-
리플리케이션 (Replication)
- DB 서버와 저장소 세트를 복수로 준비하는 구성
- 종류
- 마스터 슬레이브 (주로 사용)
- 멀티 마스터 (복잡해서 흔치 않음)
-
성능과 갱신주기 사이에 트레이드 오프 고려 필요
- Active 세트(마스터)와 Standby 세트(슬레이브)가 나뉘어 있음
- 주기적으로 Standby측 저장소를 최신 데이터로 동기화해야 함 (데이터 정합성 유지)
- 장점
-
원격지 리플리케이션 덕분에 가용성이 매우 높음
- DB 서버와 저장소가 모두 사용 불능이어도 다른 1세트가 살아있다면 서비스 지속
- 자연재해로 서울 데이터센터가 파괴돼도 부산 데이터 센터가 무사하면 계속 처리 가능
-
피라미드형 리플리케이션 구성을 하면 부하 분산도 가능
- 오래된 데이터를 사용해도 되는 기능은 손자나 증손자 세트에 분산
-
원격지 리플리케이션 덕분에 가용성이 매우 높음
-
클러스터링(Clustering)
커넥션과 세션
- 커넥션 (Connection)
- 로그인 후 사용자와 데이터베이스가 연결된 상태
- 커넥션이 유지되는 한 사용자는 데이터베이스와 무언가를 주고 받을 수 있음
- 데이터베이스는 동시에 여러 개의 커넥션 유지 가능 (=동시에 복수의 사용자 연결 병행처리)
- 전화 이미지와 유사
- 전화번호 입력 - 전화 걸기 - 상대방이 전화를 받음
- 사용자 정보 입력 - 로그인 실행 - 커넥션 연결 완료
- 세션 (Session)
- 커넥션의 시작과 종료 사이에서 교환의 시작과 종료까지의 단위
- 커넥션과 매우 유사하지만 실제로 커넥션 확립 후 세션 생성
- 기본적으로 커넥션과 세션은 1:1 대응
- 커넥션이 성립되면 동시에 암묵적으로 세션도 시작, 세션을 끊으면 커넥션도 끊어지는 경우가 대다수
관계형 데이터베이스의 계층
- 데이터베이스 내부의 테이블은 몇 개의 그룹으로 나뉘어 관리 (디렉토리와 유사)
-
4 계층 트리구조 (ANSI 표준 SQL)
- 1계층: 인스턴스 (Instance)
- 물리적 개념으로 DBMS 동작 단위
- 프로세스, 서버라 부름
- 멀티 인스턴스가 가능하지만, 거의 사용하지 않음
- 2계층: 데이터베이스 (Database)
- 3계층: 스키마 (Schema)
- 데이터베이스의 디렉토리에 해당하는 것
- 사용자가 스키마를 자유롭게 만들어 용도별 분류 혹은 권한 관리 등을 할 수 있음
- 4계층: 오브젝트 (Object)
- 테이블(Table), 인덱스 (Index), 저장 프로시저 (Stored Procedure) 등을 총칭
- 1계층: 인스턴스 (Instance)
- 실제 RDBMS의 계층 분류
-
3계층 RDBMS: MySQL, Oracle
- MySQL은 데이터베이스와 스키마를 동일한 것으로 간주
- Oracle은 인스턴스 아래에 데이터베이스를 한 개만 만들 수 있다는 독자적 제약 (실질적 3계층)
- 4계층 RDBMS: PostgreSQL, SQL Server, DB2
-
3계층 RDBMS: MySQL, Oracle
트랜잭션과 동시성 제어
-
트랜잭션 (Transaction)
- DB의 상태를 변경시키기 위해 복수의 SQL 쿼리를 한 작업 단위로 묶은 것
- 데이터를 파일에 저장하지 않고 데이터베이스를 이용하는 이유 중 하나
- 특성 (ACID)
-
Atomic(원자성)
- 트랜잭션 내 작업들이 전부 성공하거나 전부 실패하는 것을 보증
- 전부 성공하면 COMMIT, 하나라도 실패하면 ROLLBACK
-
Consistency(일관성)
- 허용된 방식으로만 데이터를 변경할 수 있도록 보증
- 트랜잭션은 데이터 변경 시 무결성 제약을 지킴 (유니크 제약 등)
-
Isolation(격리성, 고립성)
- 트랜잭션을 복수 사용자가 동시에 실행해도 각각의 처리가 모순없이 실행되는 것을 보증
- 모순 없음: 복수의 트랜잭션이 순서대로 실행되는 경우와 같은 결과를 얻을 수 있는 상태
- = Serializable (직렬화 가능)
- 다만 격리성은 동시성 관련 성능 이슈로 인해 트랜잭션 격리 수준을 선택 가능
- Serializable은 격리성을 온전히 반영하지만 성능면에서 실용적이지 않음
-
Durability(지속성)
- 트랜잭션이 커밋되면 영구적이 되어 그 결과를 잃지 않는 것
-
시스템 장애도 견딜 수 있음(데이터베이스나 OS의 비정상적 종료)
- 트랜잭션을 하드 디스크에 로그로도 기록하므로, 성공한 트랜잭션들은 복구
-
Atomic(원자성)
-
잠금 (Lock)
- 갱신시 락을 걸어서 후속처리를 블록하는 방법
- 갱신 중일 때 조회는 블록하지 않음
- 조회는 락을 얻지 않음
- 결과적으로 트랜잭션 수행 동안 하나의 로우를 동시에 수정하는 것은 안됨
- 잠금단위: 테이블 전체, 블록, 행
- 락 획득 경우
- 한 트랜잭션이 갱신을 시도하면 락을 얻음 (
INSERT
,UPDATE
,DELETE
) -
SELECT ~ FOR UPDATE
로 조회하면, 조회 시점부터 해당 트랜잭션이 끝날 때까지 락을 얻음- 애플리케이션에서 금액 조회 후 해당 금액 관련 계산시 필요
- 한 트랜잭션이 갱신을 시도하면 락을 얻음 (
-
락 타임아웃
- 갱신과 갱신이 부딪히는 경우 나중에 온 트랜잭션이 잠금 대기상태가 됨
- 설정한 락 타임아웃 대기시간을 넘어가면 다음 중 하나의 롤백 진행
- 오류가 발생한 쿼리만 롤백 (MySQL 기본 설정)
- 트랜잭션 롤백을 원할 때는 타임아웃 후 명시적 ROLLBACK 실행
- 트랜잭션 전체 롤백
-
innodb_rollback_on_timeout
설정
-
- 오류가 발생한 쿼리만 롤백 (MySQL 기본 설정)
-
교착 상태 (Dead Lock)
- 트랜잭션끼리 각자가 점유하고 있는 락을 교차해 얻으려고 하여, 상황이 바뀌지 않는 상태
- DBMS는 교착상태를 자동으로 검출해 상태를 보고
- 일반적인 데이터베이스에서 발생할 가능성이 있고 모든 것을 없앨 수는 없음
- 애플리케이션에서 트랜잭션을 항상 재실행할 수 있는 구조로 만들어야 함
- 대책
- 트랜잭션을 작은 단위로 자주 커밋
- 항상 각각의 테이블 액세스 순서 정하기
- 이유 없는
SELECT ~ FOR UPDATE
피하기 - 잠금 범위를 줄이기 (행 단위), 다만 동시성이 많은 경우 테이블 단위가 유리할 때도 있음
- 갱신시 락을 걸어서 후속처리를 블록하는 방법
-
트랜잭션 격리 수준 (Transaction Isolation level, ANSI 표준)
- 실용적인 성능을 위해 Serializable로 부터 격리 수준을 완화해 자신이 아닌 다른 트랜잭션의 영향받는 것을 허용하는 4가지 단계
- 조회하는 사람 관점에서 생각하기
- 종류
-
Read Uncommitted (가장 완화)
- 다른 트랜잭션이 커밋하지 않은 데이터까지 조회
- 이상현상: Dirty Read, NonRepeatable Read, Phantom Read
- 갱신시 데이터 정합성 문제가 발생할 수 있어서 유의 (Dirty Read)
-
Read Committed - 일반적으로 가장 많이 사용
- 커밋 완료된 데이터만 조회 (최신 쿼리 실행 시점 커밋 데이터 읽음)
- 이상현상: NonRepeatable Read, Phantom Read
-
Repeatable Read
- 커밋 완료된 데이터만 조회하며, 하나의 트랜잭션에서 반복해 행을 조회하더라도 똑같은 행을 보장
- 이상현상: Phantom Read
-
Serializable (가장 엄격)
- 커밋 완료된 데이터만 조회하며, 트랜잭션을 순차적으로 진행시킴
- 이상현상이 없으나 성능이 낮음
-
Read Uncommitted (가장 완화)
-
이상현상
- 격리 수준을 완화하면 직렬화 가능에서 발생하지 않았던 현상 발생
-
Dirty Read
- 다른 트랜잭션이 아직 커밋하지 않은 데이터까지 읽음
- 사용자 A가 값을 변경하고 아직 커밋을 안해도 사용자 B가 변경 값을 읽음
-
NonRepeatable Read
- 한 트랜잭션 내에서 같은 행을 다시 조회할 때 값이 다름
- 행에 초점
- 사용자 A가 값을 읽고 사용자 B가 해당 값을 변경했을 때, 사용자 A가 다시 조회하면 최초 값이 아닌 변경된 값을 읽음
-
Phantom Read
- 한 트랜잭션 내에서두 번이상 범위 조회(count, 범위 검색 등)를 할 때, 데이터가 나타나거나 사라짐
- 전체 데이터에 초점
- 사용자 A가 범위 검색을 해 3행을 얻었는데 사용자 B가 범위 검색 조건에 해당하는 데이터 행을 하나 추가하고 커밋하면, 사용자 A가 범위 검색을 재실행했을 때 4행을 얻음
MySQL 테이블 종류
MyISAM형 테이블: 트랜잭션 사용이 불가능한 단순한 구조
InnoDB형 테이블: 트랜잭션 사용 가능 (MVCC 구조, multi versioning concurrency control)
MVCC에 따른 MySQL의 특성 (Multi Versioning Concurrency Control)
- 갱신중이라도 읽기는 블록되지 않음 (읽기와 읽기도 서로 블록하지 않음)
- 갱신 시 락을 얻음 (락은 기본적으로 행 단위로 얻으며 트랜잭션 종료시까지 유지)
- 갱신과 갱신 상황에서 나중에 온 트랜잭션의락 획득 시도를 블록 (락 타임아웃만큼 대기)
- 갱신 시 갱신 전 데이터를 UNDO 로그로 롤백 세그먼트 영역에 유지 (트랜잭션 롤백, 격리수준 대응 용)
Read Uncommitted
사용이 드문 이유과거에는 MVCC가 주류가 아니어서, 시점에 따라 읽기가 블록되는 경우가 있었다. 해당 시기에는 값의 부정확함을 담보하더라도 읽기를 블록하지 않고 싶어
Read Uncommitted
를 편리하게 사용했었는데, 현재는 MVCC가 읽기를 블록하지 않아서 필요성이 크게 줄었다. DBMS 차원에서 지원하지 않는 경우도 있다. (PostgreSQL, Firebird)
오토커밋(AutoCommit)
- 명시적 트랜잭션 개시:
BEGIN TRANSACTION
,START TRANSACTION
,SET TRANSACTION
- 트랜잭션 개시가 명시적으로 지정되지 않았을 때, 오토커밋 모드에 여부에 따라 다음과 같이 트랜잭션을 구별
- 오토커밋 모드
- 하나의 SQL 문이 하나의 트랜잭션 (쿼리 실행 직후 자동 커밋)
- 보통 DBMS의 기본 설정(디폴트)
-
수동커밋 (오토커밋 모드 비활성)
-
COMMIT
혹은ROLLBACK
실행할 때까지가 하나의 트랜잭션 - 트랜잭션 기능을 제대로 수행하기 위한 조건
- 수동커밋을 설정하는 것을 트랜잭션을 시작한다고 표현
-
- 설정한 오토커밋 옵션은 해당 세션 내에서 계속 유지 (중간에 변경 가능)
- 오토커밋 모드
- DDL은 실행시 자동으로 암묵적 커밋이 발생
DDL, DML, DCL
- SQL 명령은 DDL, DML, DCL로 구분되며, SQL문 대부분은 DML이다.
- 데이터 정의 언어 (DDL, Data Definition Language)
- 스키마 혹은 테이블 등의 데이터를 저장하는 그릇을 작성하거나 제거
-
CREATE
,DROP
,ALTER
- 데이터 조작 언어 (DML, Data Manipulation Language)
- 테이블의 행의 검색 및 변경에 사용
-
SELECT
,INSERT
,UPDATE
,DELETE
- 데이터 제어 언어 (DCL, Data Control Language)
- 데이터베이스에서 실행한 변경을 확정하거나 취소하는 데 사용
-
COMMIT
,ROLLBACK
테이블 설계의 기초
- 관계형 데이터베이스가 표준이 된 이유는 데이터 정합성을 높이기 위한 설계 노하우가 매우 발달했기 때문
- 테이블은 집합이자 함수다!
- 테이블의 개념
- 테이블 명은 반드시 복수형이나 집합명사로 표현해야 함 (=공통 속성을 가진 것의 집합)
- 테이블은 현실세계를 반영
- 집합과 사물의 계층을 지켜야 함
- 가장 상위의 개념집합으로 정리해야 함
- 중복 행을 허용하지 않음 (기본키의 중요성)
- 등록 후 변경이 전혀 없는 과거 이력 데이터 같은 경우는 기본키 관리가 엄격하지 않아도 됨
- 거래, 병력, 급여 명세 등
- 다만, 기본적으로 기본키는 자연키보다 대리키(surrogate key)를 권장 (자연키는 변화함)
- 테이블은 클래스와 비슷하지만 메소드를 가지지 않아서 액션이 없고 데이터 조작만 받는 수동적인 존재
-
함수 종속성
-
테이블은 함수다 (=함수 종속성)
- 함수는 입력 값과 출력 값의 대응표
- 테이블은 기본키를 특정하면 어떤 레코드의 열 값 전체가 고유하게 특정됨
- 제2정규형과 제3정규형은 함수 종속성을 정리해 가는 과정
-
테이블은 함수다 (=함수 종속성)
-
정규화
- 기본적인 테이블 정의 이론
- 설계 감각이 없는 사람이라도 어느정도 기계적으로 정답에 도달할 수 있도록 고안된 절차
- 테이블 설계는 90%(제1,2,3정규형 충족) + 10%(성능을 고려한 반정규화)
- 정규형을 지키지 않으면 갱신이상이 발생할 수 있음
- 갱신이상: 갱신 시 데이터부정합
- 종류
- 제1정규형(1NF)
- 스칼라 값만 존재하는 테이블 (테이블 셀에 배열 같은 복합적인 값을 포함하지 않음)
- 관계형 데이터베이스 테이블은 전부 제1정규형을 자동으로 만족 (기술적으로 위반 불가능)
- 제2정규형(2NF)
- 부분함수 종속성이 없는 테이블
- 기본키가 1개 열이라면, 자동으로 제2정규형 만족
- 부분함수 종속성
- 기본키가 복합키일 때, 기본키를 구성하는 열의 일부에만 함수 종속성이 있는 것
- 부분함수 종속성이 있는 테이블
- 열: [“고객기업 ID”, “주문번호”, “주문접수일”, “고객기업명”, “고객기업 규모”]
- 기본키가 {“고객기업 ID”, “주문번호”}일 때
- 테이블에 “고객기업명”, “고객기업 규모” 열은 “고객기업 ID”만으로 특정됨
- 두 열에 대해서 “주문번호”는 쓸데없는 정보
- 부분함수 종속이 존재하면, 해당 키와 종속하는 열만 다른 테이블로 만들어 외부로 꺼내야 함
- 불만족시 갱신이상
- 고객기업 정보를 어느정도 알지 못하면 주문을 등록할 수 없음
- 고객기업 규모를 모르면 값을 넣기 어려움 (NULL, 더미값 등록은 권장 X)
- 같은 고객기업 행이 복수 행 존재 (잘못 등록될 위험)
- 제3정규형(3NF)
- 추이함수 종속이 없는 테이블
- 추이함수 종속
- 기본키 이외의 키 간에 발생하는 함수 종속
- 추이함수 종속이 있는 테이블
- 열: [“고객기업 ID”, “고객기업명”, “고객기업 규모”, “업계코드”, “업계명”]
- {업계코드} -> {업계명}의 함수 종속이 존재
- 추이함수 종속이 존재하면, 마찬가지로 테이블을 나누어 외부로 꺼내야 함
- 불만족시 갱신이상
- 기업 단위의 집합을 반영하는 테이블
- 업계 데이터만 추가하고 싶을 때, 기업과 실제 거래하지 않으면 새 레코드 추가 불가능
- 제1정규형(1NF)
ER 다이어그램 (Entity-Relationship Diagram)
- 테이블 간의 관계를 그래픽으로 이해하기 쉽게 도와주는 기술
- 정규화로 인해 테이블이 많아지면, 시각적 표기가 중요해짐
- IE(Information Engineering) 표기법이 널리 쓰임)
백업과 복구
- 데이터베이스는 크래시(비정상적 시스템 장애)가 일어날 때, 해당 시점까지 최신 커밋된 상태를 복구
- 지속성(Durability)을 지키며 성능을 높이기 위해 데이터베이스는 다음 구조를 가짐
- DBMS의 데이터 보존 기억장치는 하드디스크 (느림)
-
로그 선행 쓰기 (WAL, Write Ahead Log)
- 우선 로그로 변경 내용을 기술하고 로그 레코드를 써서 하드디스크와 동기화 (MySQL InnoDB 로그)
- 디스크에 쓰는 횟수를 줄일 수 있어 성능이 좋음
- 크래시가 일어나면 메모리(버퍼) 상 데이터는 잃지만, WAL과 체크포인트를 참고해 복구 (=롤포워드)
- 지속성(Durability)을 지키며 성능을 높이기 위해 데이터베이스는 다음 구조를 가짐
- 백업
- 크래시 복원도 논리적 파괴(DDL 테이블 파기)나 물리적 파손(디스크 장치 고장)은 대응 불가능
- 정상 동작할 때 주기적으로 백업 중요
- PITR (Point-in-time Recovery)
- 백업 이후 시점 실행된 갱신을 기록한 로그(archive)를 보존해서 복원한 DB에 순차 반영
- 백업으로 복원은 단순히 백업 시점으로 되돌리는 것이라 이후 수행한 갱신 반영 위해 필요
- WAL로 쓰인 로그를 아카이브 지정해 PITR 용으로 보존할 수 있음
- 3가지 관점에 따른 백업 형태
- 데이터베이스 가동 여부
-
핫 백업 (=온라인 백업)
- 데이터베이스를 가동한채로 백업
- 데이터베이스 기능으로 백업 (
mysqldump
)
-
콜드 백업 (=오프라인 백업)
- 데이터베이스를 정지한 상태에서 백업
- OS 기능으로 백업 (데이터 디렉토리의 모든 파일을 전부 복사)
-
핫 백업 (=온라인 백업)
- 백업 데이터 형식 구분
-
논리 백업
- SQL 기반의 텍스트 형식으로 백업 데이터 기록
- 오픈 소스 DBMS 위주
-
물리 백업
- 데이터 영역을 그대로 덤프 (바이너리 형식)
- 벤더 DBMS 위주
-
논리 백업
- 백업 데이터 양
-
풀 백업
- 전체 데이터를 매일 백업
-
부분 백업
- 우선 풀 백업한 후, 갱신된 데이터 따로 백업
- 차등(Differential) 백업
- 풀 백업에서 차등만 백업
- 최초 풀 백업과 최후의 차등 백업으로 복원
- 증분(Incremental) 백업
- 전일로부터 증분만 백업
- 최초 풀 백업과 모든 증분으로 복원
-
풀 백업
- 데이터베이스 가동 여부
- 백업 파일들은 떨어진 곳에 각각 보관하는 것이 중요
- 데이터 베이스와 백업 데이터를 다른 디스크 장치로 나눠 보관
- 장치를 지리적으로 떨어진 장소에 두면, 자연 재해로부터 데이터 보호도 가능
- 데이터베이스 장애는 일정 비율로 항상 일어나므로, 이를 고려해 대책을 세우고 비율을 줄이는 노력 필요
성능과 데이터베이스
- 성능 측정의 2가지 지표
-
처리시간 (Processing Time) = 응답시간 (Response Time)
- 어떤 특정 처리의 시작부터 종료까지 걸린 시간
-
처리율 (Throughput)
- 특정 처리를 단위 시간에 몇 건 처리 가능한가
- 50 TPS (트랜잭션을 초당 50건 처리), 50 PV/S (웹페이지를 초당 50회 열람)
- 시스템의 자원 용량을 결정하는 요인
- 처리율(동시 실행된 처리)에 비례해 필요한 자원 양 증가
- 시스템 자원 중 하나에서 병목 지점이 생기면, 한계점을 넘어 시스템 성능이 급격히 떨어짐
- 사이징(Sizing), 캐퍼시티 플랜(Capacity Plan)
- 한계점을 고려해 미리 자원을 확보해야 함
-
처리시간 (Processing Time) = 응답시간 (Response Time)
- 데이터베이스는 병목 되기 쉬운 포인트
- 취급하는 데이터 양이 가장 많음
-
스케일 아웃으로 해결이 어려움
- 데이터베이스 병목지점은 CPU, 메모리가 아닌 하드디스크
- 스케일 아웃은 Shared Nothing 정도만 해당
- 스케일 업을 통한 해결은 인메모리 데이터베이스로 실현
-
튜닝
-
애플리케이션을 효율화해 같은 양의 자원이라도 성능을 향상하게 하는 기술
- = 어떻게 하면 SQL을 빠르게 할 수 있을까
- 데이터베이스는 성능 향상 제약 상황으로 인해 전통적으로 튜닝 기술이 발달
- 인덱스로 해결할 수 있는지 검사하는 것이 제1 선택
-
애플리케이션을 효율화해 같은 양의 자원이라도 성능을 향상하게 하는 기술
- 데이터베이스의 SQL 처리 과정
-
파스 (Parse)
- SQL 문이 문법적으로 잘못된 부분이 없는지 검사
- 파서(Parser)가 담당
-
실행계획 (Execution Plan)
- SQL 문에 필요한 데이터를 어떤 경로로 접근할지 계획
-
옵티마이저(Optimizer)가 담당
- 수많은 경로 중 가장 효율적인 경로를 선택 (풀 스캔, 레인지 스캔 판단 등…)
-
통계정보(Statistics)
- 옵티마이저가 실행계획을 세울 때 입력값으로 사용하는 정보
- 테이블 데이터를 샘플링 추출해 계산한 것으로 정확한 정보는 아니지만 속도적 이점을 줌
- 테이블 행열수, 각 열의 길이 및 데이터형, 테이블 크기, 기본키 및 NOT NULL 정보, 열 값의 분산 및 편향 등
- DBMS가 자동으로 수집 (대체로 대량의 데이터가 변경될 때)
- 올바른 통계정보 수집이 중요
- 결과 정보 갱신 설정이 ON이 되게 해야함 (혹시 안되어 있다면 낡은 통계 정보 쓰게됨)
- 정기 갱신 형태에서 급격히 데이터 양이 변화하면, 실행계획이 비효율적일 수 있음
- 실행계획 평가
- 데이터 액세스
-
파스 (Parse)
-
테이블 액세스 방법
- 실행 계획의
type
열 - 종류
- 풀 스캔 (
All
)- 테이블에 포함된 레코드를 처음부터 끝까지 전부 읽어 들이는 방법
-
레인지 스캔 (
range
,ref
…)- 인덱스를 사용해 테이블의 일부 레코드에만 액세스하는 방법
- 풀 스캔 (
- 실행 계획의
-
인덱스 (Index)
- 책의 목차, 색인
- 구조 (B-tree)
- 핵심: 데이터를 반드시 정렬된 형태로 유지
-
균형 트리 구조 (Balanced-tree)
- 루트부터 리프까지의 거리가 일정한 트리구조
- 트리 중에서도 성능이 안정화
- 성능적이점
-
어떤 값에 대해서도 같은 시간에 결과를 얻음 (균일성)
- 이진 탐색
- 일반적으로 B-tree의 계층은 3~4 정도로 조절됨
- 어떤 값을 찾아도 2~4회 노드 액세스로 탐색 완료
- 데이터 양이 증가할 수록 성능 개선 효과 우수 (Log N)
- 1GB, 100만행도 소~중규모 데이터
- 인덱스의 큰 개선 효과는 더 큰 데이터에서 나옴
-
내부적으로 정렬을 사용하는 SQL의 정렬을 생략해 고속화
- GROUP BY, 집계 함수, 집합 연산 (UNION, INTERSECT, EXCEPT)…
- 키로 지정된 열에 인덱스가 존재하면, 이미 정렬된 데이터를 바탕으로 정렬 생략
- DB마다 차이는 있음
-
어떤 값에 대해서도 같은 시간에 결과를 얻음 (균일성)
-
갱신 빈도가 높은 테이블은 정기적으로 인덱스 재구성으로 트리의 균형을 되찾아야 함
- 갱신이 반복되면 트리의 균형이 깨져가고, 인덱스 성능도 악화됨
- 어느정도 자동으로 균형 회복 기능 있지만, 수동 재구성도 필요
- 무분별한 인덱스 생성의 역효과
-
인덱스 갱신의 오버헤드로 성능 감소
- 통상 1행 레코드의 인덱스 갱신은 매우 빠름
- 몇천 몇만 몇억행 갱신이 모이면 인덱스 갱신 시간을 얕볼 수 없음
- 의도한 것과 다른 인덱스 사용되기도 함
-
인덱스 갱신의 오버헤드로 성능 감소
- 인덱스 생성 기준
-
크기가 큰 테이블만 만들기
- 크기가 작은 테이블은 풀 스캔과 레인지 스캔의 차이가 없음
-
기본키 제약, 유일성 제약이 부여된 열에는 불필요
- 암묵적으로 이미 인덱스가 작성되어 있음
- 값의 중복 체크를 위한 데이터 정렬에 인덱스를 사용하면 편리하기 때문
-
Cardinality가 높은 열에 만들기
- Cardinality: 값의 분산도
- 카디널리티가 높아야 인덱스 혜택을 받을 수 있음
- 예시
- 운전면허증 번호 »> 넘을 수 없는 벽 »> 한국 시도 행정구역 > 성별
-
크기가 큰 테이블만 만들기