데이터베이스는 일정한 규칙, 혹은 규약을 통해 구조화되어 저장되는 데이터의 모음이다. 해당 데이터베이스를 제어, 관리하는 통합 시스템을 DBMS라고 하며, 데이터베이스 안에 있는 데이터들은 특정 DBMS마다 정의된 쿼리 언어를 통해 삽입, 삭제, 수정, 조회 등을 수행할 수 있다.
데이터베이스의 종류에는 크게 관계형 DB와 NoSQL DB로 나눌 수 있다. 이 중 대표적인 관계형 DB에는 MySQL, 대표적인 NoSQL 데이터베이스인 MongoDB가 있다.
MySQL DB 구조 : 레코드 - 테이블 - 데이터베이스
MongoDB 구조 : 도큐먼트 - 컬렉션 - 데이터베이스
ERD는 데이터베이스를 구축할 때 가장 기초적인 뼈대 역할을 하며, 릴레이션(테이블) 간의 관계들을 정의한 것이다.
ERD는 시스템의 요구 사항을 기반으로 작성되며 이 ERD를 기반으로 데이터베이스를 구축한다. 데이터베이스를 구축한 이후에도 디버깅 또는 비즈니스 프로세스 재설계가 필요한 경우에도 설계도 역할을 담당하기도 한다. 하지만 ERD는 관계형 구조로 표현할 수 있는 데이터를 구성하는데 유용할 수 있지만 비정형 데이터를 충분히 표현할 수 없다는 단점이 있다.
비정형 데이터란 비구조화 데이터를 말하며, 미리 정의된 데이터 모델이 없거나 미리 정의된 방식으로 정리되지 않은 정보를 말한다.
정규화 과정은 릴레이션(테이블) 간의 잘못된 종속 관계로 인해 데이터베이스 이상 현상이 일어나서 이를 해결하거나, 저장 공간을 효율적으로 사용하기 위해 릴레이션을 여러 개로 분리하는 과정이다.
정규화 과정은 정규형 원칙을 기반으로 정규형을 만들어가는 과정이며, 정규화된 정도는 정규형(NF, Normal Form)으로 표현한다.
정규형 원칙이란?
- 같은 의미를 표현하는 릴레이션이지만 좀 더 좋은 구조로 만들어야하고, 자료의 중복성은 감소해야하고, 독립적인 관계는 별개의 릴레이션으로 표현해야 하며, 각각의 릴레이션은 독립적인 표현이 가능해야 하는 것을 말한다.
릴레이션의 모든 도메인이 더 이상 분해될 수 없는 원자 값으로만 구성되어야한다. 즉, 릴레이션의 속성 중에서 한 개의 속성에 두 개 이상의 값을 가지는 경우가 있어서는 안된다.
제2정규형은 제1정규형을 만족하면서, 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속되면 제2정규형에 속한다. 그러므로, 릴레이션의 속성 중 기본키에 완전히 종속되어있지 않은 속성이 존재한다면 별도의 테이블로 분리해야한다.
제3정규형은 제2정규형을 만족하면서, 기본키가 아닌 모든 속성이 이행적 함수 종속을 만족하지 않는 상태를 말한다. 릴레이션의 기본키가 아닌 속성이 다른 속성을 결정한다면 이를 별도로 분리해야한다.
보이스/코드 정규형은 제3정규형을 조금 더 강화시킨 개념이다. 제3정규화를 만족하는 릴레이션에 대해 모든 결정자가 후보키가 되도록 테이블을 분해하는 것이다. 일반 컬럼이 후보키에 속한 속성을 결정하는 결정자일 경우에 일반 컬럼과 일반 컬럼에 의해 결정되는 후보키에 속한 속성을 별도의 테이블로 분리해야한다.
트랜잭션은 데이터베이스에서 하나의 논리적 기능을 수행하기 위한 작업의 단위를 말하며 데이터베이스에 접근하는 방법은 쿼리이므로, 여러 개의 쿼리들을 하나로 묶는 단위를 말한다.
트랜잭션은 ACID 특징을 갖는다.
'All or Nothing' 의 특징으로,
트랜잭션과 관련된 일이 모두 수행되었거나 되지 않았거나를 보장하는 특징이다. 트랜잭션에 속한 작업들이 수행되던 중 문제가 발생하여 롤백하는 경우에 트랜잭션에 속한 모든 작업들이 수행되지 않음을 보장한다.
만약 트랜잭션 단위로 여러 로직들을 묶을 때 외부 API를 호출하는 것이 있다면, 롤백이 일어났을 때 어떻게 해야할 것인지에 대한 해결 방법이 있어야하고 트랜잭션 전파를 신경써서 관리해야한다.
트랜잭션이 성공적으로 수행된 후에도 데이터베이스가 일관성 있는 상태를 유지해야 한다는 특징이다. 다시 말해, 트랜잭션이 일어난 이후의 데이터베이스는 데이터베이스의 제약이나 규칙을 만족해야 한다는 뜻이다.
참고.
원자성, 격리성, 지속성은 DB의 속성이지만, 일관성은 Application 의 속성이라 봐야 한다. 일관성을 성취하기 위해 원자성, 격리성, 지속성에 의존할 수 있지만 DB만으로 일관성이 달성되지 않는다.
Joe Hellerstein 은 하더와 로이터의 논문에서 ACID의 C는 약어를 만들기 위해 끼어들었고, 당시에 그리 중요하지 않았다고 말했다.
격리성은 모든 트랜잭션은 다른 트랜잭션으로부터 독립되어야한다는 특징이다. 복수의 병렬 트랜잭션은 서로 격리되어 마치 순차적으로 실행되는 것처럼 작동되어야 한다.
복수 개의 트랜잭션을 순차적으로 처리하면 쉽겠지만, 그렇게 할 경우 성능이 너무 나빠지므로 4개의 격리 수준으로 나뉘어 격리성을 보장한다.
트랜잭션을 순차적으로 진행시키는 것을 말한다. 여러 트랜잭션이 동시에 같은 레코드에 접근할 수 없다. 모든 이상현상이 발생하지 않지만 매우 엄격한 격리수준이고 동시에 같은 레코드에 접근하는 것을 막기 때문에 성능이 가장 떨어지고 데드락이 일어날 확률이 가장 높다.
특정 트랜잭션이 데이터를 조회하고자 할때, 자신이 생성되기 이전의 트랜잭션에서 커밋된 내용에 대해서만 조회할 수 있는 격리수준이다. MySQL에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다. 트랜잭션의 시작 시점을 추가적인 정보로 갖는 상태에서 이전의 트랜잭션이 커밋한 데이터를 읽을 수 있기 때문에, Dirty Read, Non-Repeatable Read는 발생하지 않지만 Phantom Read는 발생한다.
많은 상용 DB에서 기본값으로 설정된 격리수준으로, 트랜잭션의 변경 내용이 커밋되어야만 다른 트랜잭션에서 조회가 가능하다. 커밋된 데이터만 조회가 가능하기 때문에 Dirty Read는 발생하지 않지만, Non-Repeatable Read 와 Dirty Read는 발생한다.
트랜잭션의 변경내용이 커밋이나 롤백에 상관없이 다른 트랜잭션에 보여진다. Dirty Read, Non-Repeatable Read, Phantom Read 모두 발생한다. 가장 빠른 성능을 보여주지만 데이터 무결성이 깨질 수 있으므로 사용하지 않는 것이 이상적이다. 몇몇 행이 제대로 조회되지 않더라도 괜찮은 거대한 양의 데이터를 '어림잡아' 집계하는 데는 사용해도 좋다.
! Phantom Read
팬텀 리드란 같은 쿼리에 대한 결과 집합이 달라지는 현상이다. 예를 들어 "한 트랜잭션"이 특정 범위의 데이터를 조회할 때, "다른 트랜잭션"이 그 범위 상 데이터를 삽입 혹은 삭제하면 두 번째 쿼리에서 결과 집합이 다를 수 있습니다.
! Non-Repeatable Read
같은 트랜잭션 내에서 같은 데이터를 여러번 조회했을 때 읽어온 데이터가 다른 경우를 의미한다.
! Dirty Read
특정 트랜잭션에 의해 데이터가 변경되었지만, 아직 커밋되지 않은 상황에서 다른 트랜잭션이 해당 변경 사항을 조회할 수 있는 문제를 말한다.
Phantom Read와 Non-Repeatable Read의 차이점
https://github.com/woowacourse-study/2022-Real-MySQL/issues/8
성공적으로 수행된 트랜잭션은 영원히 반영되어야 한다는 특징이다. 중간에 DB에 오류가 발생해도 다시 복구되어야하고 트랜잭션에 대한 로그가 반드시 남아야한다는 의미이기도 하다. 데이터베이스에는 이를 위해 체크섬, 저널링, 롤백 등의 기능을 제공한다.
! 체크섬
중복 검사의 한 형태로, 오류 정정을 통해 송신된 자료의 무결성을 보호하는 단순한 방법
! 저널링
파일 시스템 또는 데이터베이스 시스템에 변경사항을 반영하기 전에 로깅하는것, 트랜잭션 등 변경사항에 대한 로그를 남기는 것