https://limkydev.tistory.com/100?category=974039


[DataBase] 트랜잭션이란? (Transaction)

Limky Lim-Ky 2017. 10. 6. 02:22

트랜잭션(Transaction) 개념


C나 Java와 같은 프로그래밍 언어로 작성된 응용 프로그램은 명령어들의 집합으로 볼 수 있는데, 이러한 프로그램들은 세부적으로 여러 개의 함수나 클래스 단위로 구성됩니다. 함수나 클래스들은 전적으로 프로그래머가 프로그래밍의 편리성과 효율성 중심으로 설계한 결과물입니다. 

그러나 데이터베이스 응용프로그램에서는 프로그램의 구성을 다른 관점으로 살펴 볼 수 있습니다. 예를 들어 은행 업무에 관련된 데이터베이스 응용 프로그램을 가정해봅시다. 이 프로그램은 계좌이체, 대출, 예금, 출금 등과 같이 은행에서 이루어지는 여러 가지 업무처리에 관련된 세부 프로그램들로 구성됩니다. 이러한 세부 프로그램들은 사용자 입장에서 보면 하나의 작업 단위가 됩니다. 그리고 이러한 작업들을 수행하기 위해서는 세부적으로 여러가지의 데이터베이스에 대한 연산(검색, 삽입, 삭제, 수정)들을 필요로 합니다. 



예를 들어 A계좌에서 B계좌로 일정 금액을 이체한다고 가정해봅시다. 이를 위해서는 그림과 같이 A계좌의 잔액을 확인하고 현재 금액에서 인출할 금액을 뺀 나머지 금액을 다시 저장합니다. 그런 다음 B계좌의 잔액을 읽어 들인 후 이체된 금액을 더하고 그 합을 다시 저장하면 계좌이체가 완료됩니다. 이러한 과정들이 모두 합쳐져 계좌이체라는 하나의 작업단위를 구성합니다. 데이터베이스에서는 이와 같은 하나의 논리적인 작업 단위를 구성하는 연산들의 집합을 트랜잭션이라 합니다. 이러한 관점에서 데이터베이스 응용 프로그램은 트랜잭션들의 집합으로 정의 할 수 있습니다.





트랜잭션(Transaction) 필요성


트랜잭션을 정의하는 이유는 무엇일까요? 그 동안 알지 못했지만, 우리는 현실에서 트랜잭션을 간접적으로 경험하고 있습니다. 계좌이체를 다시 생각해봅시다. 많은 사람들이 현금 인출기에서 카드를 이용하여 계좌이체를 한 경험이 있을 것입니다. 이때 현금 인출기를 작동하는 도중에 기계오류나 정전 등과 같은 예기치 않은 상황이 발생하여 카드가 나오지 않거나 기계가 멈추는 경우가 있습니다. 이때 가장 우려되는 것이 내 계좌에서는 금액이 빠져나간 것으로 기록되고 정작 상대방 계좌에는 이체가 되지 않는 상황입니다. 트랜잭션이란 바로 이러한 문제가 발생되지 않도록 하는 강력한 수단을 제공해주는 것입니다. 즉, 내 계좌에서 금액이 빠져나가기 전 상태로 돌아가던지, 아니면 상대방 계좌로 이쳬가 성공적으로 끝나도록 보장해줘야 합니다. 


계좌이체 과정에서 발생 할 수 있는 문제점을 좀 더 구체적으로 알아보기 위해 그림을 다시 봅시다. 이 그림에서 A계좌에서 이체할 금액을 인출한 다음 B계좌에 이체된 금액을 저장하기 전에 어떠한 이유로 해서 실행이 중단되었다고 가정해봅시다. 즉, 그림에서 마지막 명령문 WRITE t 가 실행되지 않은 상황을 의미합니다. 그러면 A계좌에는 이미 잔액이 인출된 결과가 저장되었지만, B계좌는 변경이 되지 않은 채로 남아있게 됩니다. 은행 업무에서 이러한 결과는 결코 발생되면 안됩니다. 즉, 계좌이체를 실행 할 때는 계좌이체에 정의된 모든 연산을 완벽하게 실행하던지, 아니면 모두 실행하지 않고 처음의 상태로 남아있어야 합니다.


또 다른 예로 은행에서 현금을 인출하는 과정을 살펴보면, 은행에서 예금을 인출하는 작업은 다음과 같은 연산으로 이루어집니다.


1. 예금 잔액을 확인한다.

2. 해당 인출금을 잔액에서 뺀다.

3. 인출금을 뺀 나머지를 새로운 잔액으로 저장한다.

4. 인출금을 지급한다.





만약 현재 잔액이 500원인 계좌에 대해 두 사람이 각각 A지점과 B지점에서 동시에 100원을 인출하는 작업을 진행한다고 가정해 봅시다. 이 상황은 위 그림과 같습니다. 이 그림을 보면 우선 A와 B에서 예금 잔액을 읽고 동시에 그 값이 500원이라는 것을 확인 합니다. 다음 두 지점에서 각각 잔액 500원에서 100원을 뺍니다. 그러면 A와 B모두 잔액이 400으로 계산되어, 400원을 각각 저장합니다. 마지막으로 100원을 A와 b 모두에서 지급합니다. 결국 A와 B지점에서 각각 100원씩 인출하여, 결국 200원을 인출한 셈이 되고 잔액은 400원이 됩니다. 이 상황도 올바르지 못합니다. 이러한 오류의 원인은 A지점에서 잔액으로 400을 저장하였고, B지점에서도 400원을 저장함으로써, 둘 중 하나가 다른 지점에서 저장한 잔액을 덮어 써버렸기 때문입니다. 결국 다중 사용자 환경에서 하나의 트랜잭션이 동시에 실행되는 다른 트랜잭션에 의해 영향을 받은 결과입니다.


따라서 지금까지 예를 든 상황과 같이 원하지 않는 결과가 발생되지 않도록 사전에 방지하기 위해서 트랜잭션은 필요합니다. 현재 대부분의 DBMS들은 이러한 상황을 방지하기 위한 기능을 갖추고 있습니다. 이를 위해 데이터베이스 개발자는 작업 단위들을 트랜잭션으로 적절히 정의해야 합니다. 즉, 트랜잭션을 정의하는 것은 전적으로 개발자의 의무이지만, 정의된 트랜잭션들에 대해서 위와 같은 문제가 발생하지 못하게 방지하는 것은 DBMS의 몫입니다. 





트랜잭션(Transaction)의 특징(지켜야 할 조건)


지금까지 설명한 내용을 토대로 트랜잭션의 특징을 정리해보겠습니다. 중요한 개념이기 때문에 꼭 암기해서 외워야합니다. DBMS는 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability) 이 만족해야 합니다. 

다음 조건들의 영어 첫 단어를 인용해 ACID 특성(ACID property)라고 합니다. 



  원자성(Atomicity)

트랜잭션 실행 도중에 문제가 발생했을 경우, 중단된 상태가 아닌 모두 실패하거나, 모두 완성 둘 중 하나의 상태가 되어야 합니다. 즉 100개 명령어로 구성된 트랜잭션 중 99개 완료 1개 실패가 된다면, 이는 무조건 실패로 간주하여 트랜잭션 시작 전 상태로 돌려야 합니다. 또한, 100개 모두가 성공했을 시 트랜잭션은 성공합니다. 따라서 중간상태란 없습니다.  

 일관성(Consistency)

일관성이란 트랜잭션 완료 후에도 데이터베이스가 일관된 상태로 유지되어야 합니다. 예를 들어 계좌이체를 성공적으로 실행했다면, A계좌의 잔액과 B계좌의 잔액의 합이 트랜잭션 실행 전의 합과 동일해야 합니다.  

 고립성(Isolation)

고립성이란 하나의 트랜잭션이 실행하는 도중에 변경한 데이터는 이 트랜잭션이 완료될 때까지 다른 트랜잭션이 참조하지 못하게 하는 특성입니다. 하나의 트랜잭션이 A라는 계좌에서 작업을 하고 있다면, 다른 트랜잭션이 A계좌에 대해 참조하거나 관여 할 수 없고 작업이 끝날 때까지 대기하거나 해야합니다. 

 지속성(Durability

지속성은 트랜잭션이 완료되면, 주기억장치가 아닌 디스크와 같은 보조기억장치에 저장되거나 그렇지 않더라도 시스템 장애가 회복되고 난 후에 어떠한 형태로든지 그 데이터를 복구 할 수 있게 해야함을 뜻합니다.  






트랜잭션(Transaction)의 상태



이제 앞서 설명했던 트랜잭션이 갖추어야 할 조건들 ACID 특성을 충족시키기 위해선 트랜잭션이 현재 어떤 상태인지 정의할 필요가 있습니다. 이에 따라 트랜잭션 각 상태에 따라 어떤 상황인지 알아봅시다. 




Active(활동)

트랜잭션이 실행 중에 있는 상태, 연산들이 정상적으로 실행 중인 상태

Failed(장애)

트랜잭션이 실행에 오류가 발생하여 중단된 상태 

Aborted(철회) 

트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태 

Partially Committed(부분 완료)

트랜잭션이 마지막 연산까지 실행했지만, Commit 연산이 실행되기 직전의 상태 

Committed(완료) 

트랜잭션이 성공적으로 종료되어 Commit 연산을 실행한 후의 상태 



https://limkydev.tistory.com/108

[DataBase] 키(Key)의 개념 및 종류

데이터 베이스 키(Key)의 개념 및 종류**

키(Key)는 데이터베이스에서 조건에 만족하는 튜플을 찾거나 순서대로 정렬할 때 다른 튜플들과 구별할 수 있는 유일한 기준이 되는 Attribute(속성)입니다.

*튜플 : 릴레이션을 구성하는 각각의 행, 속성의 모임으로 구성된다. 파일 구조에서는 레코드와 같은 개념, 튜플의 수 = 카디널리티(Cardinality) = 기수 = 대응수

<학생> 릴레이션**

학번 주민번호 성명 성별 
1001  810429-1231457김형석  
1002 800504-1546781 김현천  
1002 811216-2547842 류기선 여 
1003910322-1233445 홍영선 

<수강> 릴레이션

과목명 
1001 영어 
1001 전산 
1002 영어 
1003 수학 
1004 영어 
1004 전산 

1. 후보키 (Candidate Key)

* 릴레이션을 구성하는 속성들 중에서 튜플을유일하게 식별할 수 있는 속성들의 부분집합을 의미합니다.
*모든 릴레이션은 반드시 하나 이상의 후보키를 가져야합니다.
* 릴레이션에 있는 모든 튜플에 대해서유일성과 최소성을 만족시켜야합니다.
 
ex) <학생> 릴레이션에서 '학번'이나 '주민번호'는 다른 레코드를 유일하게 구별할 수 있는 기본키로 사용할 수 있으므로 후보키가 될 수 있습니다. 즉 기본키가 될 수 있는 키들을 후보키라고 합니다.

2. 기본키 (Primary Key)

* 후보키 중에서 선택한 주키(Main Key)
* 한 릴레이션에서특정 튜플을 유일하게 구별할 수 있는 속성* Null 값을 가질 수 없습니다. (개체 무결성의 첫번째 조건)
* 기본키로 정의된 속성에는 동일한 값이 중복되어 저장될 수 없습니다.(개체 무결성의 두번째 조건)
 
ex) <학생> 릴레이션에는 '학번'이나 '주민번호'가 기본키가 될 수 있고, <수강> 릴레이션에는 '학번'+'과목명'으로 조합해야 기본키가 만들어 질 수 있습니다. 왜냐면 <수강> 릴레이션에서는 '학번' 속성과 '과목명' 속성은 개별적으로 기본키로 사용할 수 없습니다. 다른 튜플들과 구별되지 않기 때문이지요..
ex) <학생> 릴레이션에서 '학번'을 기본키로 정의되면 이미 입력된 '1001'은 다른 튜플의 '학번' 속성 값으로 입력할 수 없습니다.

3. 대체키 (Alternate Key)

*후보키가 둘 이상일 때 기본키를 제외한 나머지 후보키들을 말합니다.* 보조키라고도 합니다.
 
ex) <학생> 릴레이션에서 '학번'을 기본키로 정의하면 '주민번호'는 대체키가 됩니다.

4. 슈퍼키 (Super Key)

*슈퍼키는 한 릴레이션 내에 있는 속성들의 집합**으로 구성된 키로서 릴레이션을 구성하는 모든 튜플 중 슈퍼키로 구성된 속성의 집합과 동일한 값은 나타내지 않습니다.
* 릴레이션을 구성하는 모든 튜플에 대해
유일성은 만족하지만, 최소성은 만족시키지 못합니다.**
 
ex) <학생> 릴레이션에서는 '학번', '주민번호', '학번'+'주민번호', '학번'+'주민번호'+'성명' 등으로 슈퍼키를 구성할 수 있습니다. 또한 여기서 최소성을 만족시키지 못한다는 말은 '학번'+'주민번호'+'성명' 가 슈퍼기인 경우 3개의 속성 조합을 통해 다른 튜플과 구별이 가능하지만, '성명' 단독적으로 슈퍼키를 사용했을 때는 구별이 가능하지 않기 때문에 최소성을 만족시키지 못합니다. 즉 뭉쳤을 경우 유일성이 생기고, 흩어지면 몇몇 속성들은 독단적으로 유일성있는 키로 사용할 수 없습니다. 이것을 최소성을 만족하지 못한다고 합니다.

5. 외래키 (Foreign Key)

* 관계(Relation)를 맺고 있는 릴레이션 R1, R2에서 릴레이션 R1이 참조하고 있는 릴레이션 R2의 기본키와 같은 R1 릴레이션의 속성
* 외래키는참조되는 릴레이션의 기본키와 대응되어 릴레이션 간에 참조 관계를 표현하는데 중요한 도구로 사용됩니다.
**외래키로 지정되면 참조 테이블의 기본키에 없는 값은 입력할 수 없습니다. *(참조 무결성 조건)
 
ex) <수강> 릴레이션이 <학생> 릴레이션을 참조하고 있으므로 <학생> 릴레이션의 '학번'은 기본키이고, <수강> 릴레이션의 '학번'은 외래키입니다. 즉 각 릴레이션의 입장에서 속성은 기본키가 되기도하고, 외래키가 되기도 합니다.
ex) <수강> 릴레이션의 '학번'에는 <학생> 릴레이션의 '학번'에 없는 값은 입력할 수 없습니다.

함수적 종속성은 정규화를 이해하기 위해 필요한 개념입니다.



1. 함수적 종속성


함수적 종속성은 애트리뷰트들 사이의 관계에 대한 제약조건으로 애트리뷰트 A가 B의 결정자이면, 다음의 조건을 따라야 합니다.


A이면 B이고 동시에 A이면 C일 수 없지만, B이면 반드시 A인 것은 아니다.


재미있는 말로하자면, A는 B라는 한명의 파트너만 만나야하지만 정작 A의 파트너인 B는 A이외의 파트너도 만날 수 있는 난봉꾼입니다. 때문에 A는 B에 종속적이라고 표현합니다.


예를들어 아래의 테이블에서 


사원번호와 이름이 각각 123456, 이진욱

사원번호와 이름이 각각 567890, 이진욱


인 동명이인의 사원이 존재한다고 합시다. 이때, 사원번호를 A속성, 이름을 B속성이라고 한다면, A이면 반드시 B이지만, B이면 반드시 A라고 할 수 없습니다. 따라서, B는 A를 종속하고 있습니다.


 


2. 결정자(determinant)


결정자는 주어진 릴레이션에서 다른 애트리뷰트를 고유하게 결정하는 하나 이상의 애트리뷰트입니다.


아래그림에서 사원릴레이션에 사원번호와 부서번호 2개가 결정자로 사원번호는 사원이름, 주소, 전화번호를 고유하게 결정하고 부서번호는 부서이름을 고유하게 결정합니다.


 


 

 


3. 완전함수적 종속성(FFD: Full Functional Dependency)


사원 릴레이션에 있는 2개의 결정자를 모두 종속하는 경우(직책)가 완전함수적 종속성이고 둘 중 하나의 결정자에만 종속되는 경우(사원이름, 주소, 전화번호는 사원번호에 부서이름은 부서번호)는 부분 함수적 종속성입니다. 



[완전함수적 종속성과 부분함수적 종속성 구분]

 

 


4. 이행적 함수적 종속성(transitive FD)


(1) fd1 : 학과이름과 학과전화번호는 학번에 부분적함수적 종속성


(2) fd3 : 학점은 학번과 과목번호에 완전함수적 종속성


(3) fd2 : 학과전화번호는 학번(결정자)에 의해 부분적 종속성을 가지면서 학번의 또다른 부분함수적 종속성인 학과이름에 함수적종속을 가지는데 이럴경우를 학과전화번호는 이행적 함수적 종속성을 가집니다. 


 


1. 식별자 정의

식별자란 하나의 엔티티(테이블) 내에서 각각의 인스턴스(로우)를 유일(Unique)하게 구분해 낼 수 있는 속성(컬럼) 또는 속성 그룹을 말하며, 하나의 엔티티는 하나 이상의 식별자를 반드시 보유하고 있어야만 한다. 즉, 쉽게 정리하면 중복 데이터가 없는 속성(컬럼)을 의미한다.



2. 식별자의 유형

1) 주식별자 / 보조식별자 : 대표성 여부


하나의 엔티티 내에서 식별자로 사용할 수 있는 하나 이상의 키들을 후보식별자라 하고, 그 중 엔티티의 대표성을 나타내는 유일한 식별자를 주식별자, 나머지를 보조식별자로 활용한다.


물리모델에서 주식별자는 PK 역할, 보조식별자는 유니크 인덱스로 지정


    예 )  사원 : 후보식별자 - 사번, 주민번호


                     주식별자 - 사번


                     보조식별자 - 주민번호 



2) 내부식별자 / 외부식별자 : 스스로 생성 여부


자신의 엔티티 내에서 스스로 생성되어 존재하는 식별자를 내부식별자, 다른 엔티티로부터 관계에 의해 주식별자 속성을 상속받아 자신의 속성에 포함되는 식별자를 외부식별자라한다.


외부식별자는 FK를 의미한다. 



3) 단일식별자 / 복합식별자 : 단일 속성 여부


주식별자의 구성이 한 가지 속성으로 이루어진 경우를 단일식별자, 두 개 이상의 속성으로 구성된 경우를 복합식별자라 한다.


복합실별자의 경우는 우선순위가 매우 중요하다. 





위의 테이블에서 주문번호와 상품코드를 복합시켜야만, 식별자로써의 기능을 하게 되는데 주문번호와 상품코드를 복합식별자라고 한다.



■ 자주 사용되는 속성은 우선순위가 높다. 


 db11.png

 

대체적으로 자식 엔티티의 PK의 우선순위의 앞 순위에 부모로부터 상속받은 속성을 두는 것이 좋다. 부모로부터 상속받은 PK의 속성은 SQL의 조인에서 반드시 사용되어지고 WHERE 절에서 사용 가능성이 높다.

 

  

■ 분포도가 좋은 속성은 우선순위가 높다.

분포도가 좋다는 의미는 사원번호, 주민번호와 같이 자료의 식별성이 뛰어난 속성으로 SQL 사용시 분포도가 좋은 속성으로 접근하면 그만큼 적은 범위의 자료에만 접근할 수 있다. 


구분 표시와 같은 속성은 분포도가 매우 낮은 속성이므로 우선순위가 낮다. 


PK가 사원구분 + 사원번호라면 조회 유형은 사원번호에 의한 경우, 사원번호 + 사원구분, 사원구분에 의한 경우인데, 사원번호에 의한 경우 인덱스를 사용할 수 없고,


사원구분에 의한 경우도 분포도가 매우 낮은 속성이므로 풀 스캔하는 것이 빠르다. 



■ ' = ' 조회를 하는 속성은 우선순위가 높다.


날짜와 같은 속성은 대부분이 기간을 조회하므로, 인덱스의 첫번째 속성이 LIKE 조회나 BETWEEN 조회를 하게 되어 인덱스를 사용하지 못하게 된다. 

 db12.png

퍼온글입니다. 원글 출처 : http://3months.tistory.com/193







데이터베이스 정규화 1NF, 2NF, 3NF, BCNF



정규화를 이해하기 위해서는 아래의 키워드들을 이해하고 있어야 하며, 정규화에 대한 사전 작업으로 다음의 스텝을 따라야할 필요가 있습니다.


1. 이해해야할 키워드

식별자와 비식별자의 구분(http://valuefactory.tistory.com/221?category=768571)

식별자그룹 : (복합식별자) 혹은 (주식별자+보조식별자)

비식별자그룹(일반 속성) : 식별자 그룹을 제외한 그 외의 속성(컬럼)들

종속관계(http://valuefactory.tistory.com/222?category=768571)



2. 정규화전 따라야할 스텝

a. 엔티티의 속성을 노트에 써봅니다.

b. 각 속성을 식별자 그룹과 비식별자 그룹으로 나눈 후, 식별자 그룹에 네모 박스를 그려줍니다.

c. 아래의 정규화과정에 따라, 정규화를 검증해봅니다.



데이터베이스 정규화란 데이터베이스의 설계를 재구성하는 테크닉입니다. 정규화를 통해 불필요한 데이터(redundancy)를 없앨 수 있고, 삽입/갱신/삭제 시 발생할 수 있는 각종 이상현상(Anamolies)들을 방지할 수 있습니다. 


데이터베이스 정규화의 목적은 주로 두 가지입니다.



1. 불필요한 데이터(data redundancy)를 제거한다.


2. 데이터 저장을 "논리적으로" 한다. 




여기서 2번 데이터 저장을 논리적으로 한다는 것은 데이터 테이블의 구성이 논리적이고 직관적이어야한다는 것입니다. 



우선 정규화를 안 했을 때의 문제점에 대해서 알아보겠습니다.




위와 같이 정규화가 되지 않은 구조의 테이블(Adam이라는 학생이 두 번 들어가 있습니다.)의 경우, 데이터 핸들링시 다양한 이상현상이 발생하게 됩니다.



1. Update : Adam의 Address가 변경되었을 때, 여러줄의 데이터를 갱신해야합니다. 이로인해 데이터의 불일치(inconsistency)가 발생할 수 있습니다.



2. Insert : 만약 학생이 아무 과목도 수강하지 않는다고 하면, Subject_opted 컬럼에는 NULL이 들어갈 것입니다. 



3. Deletion : 만약 Alex 학생이 과목 수강을 취소한다면 Alex의 레코드가 아예 테이블에서 지워져버립니다.



위와 같이 정규화가 제대로 되지 않은 테이블의 경우 갱신/삽입/삭제 시 다양한 문제점이 발생할 수 있습니다. 이를 테이블의 구성을 논리적으로 변경하여 해결하고자 하는 것이 바로 정규화입니다.



정규화의 법칙(Normalization Rule)은 1차정규화, 2차정규화, 3차정규화, BCNF, 4차정규화, 5차정규화로 나눌 수 있는데, 실무적으로 4차, 5차 정규화까지 하는 경우는 많지 않다고 합니다. 따라서 이 포스팅에서도 BCNF까지만 알아보겠습니다.




1. 1차 정규화


1차 정규형은 각 로우마다 컬럼의 값이 1개씩만 있어야 합니다. 이를 컬럼이 원자값(Atomic Value)를 갖는다고 합니다. 예를 들어, 아래와 같은 경우 Adam의 Subject가 Biology와 Maths 두 개 이기 때문에 1차 정규형을 만족하지 못합니다.




위의 정보를 표현하고 싶은 경우 이렇게 한 개의 로우를 더 만들게 됩니다. 결과적으로 1차 정규화를 함으로써 데이터 redundancy는 더 증가하였습니다. 데이터의 논리적 구성을 위해 이 부분을 희생하는 것으로 볼 수 있습니다.





2. 2차 정규화



2차 정규화의 조건

・2차 정규형은 엔티티의 모든 속성이 후보 식별자 전체에 종속적이어야 합니다.

・만약, 일반 속성중에서 후보 식별자 전체에 종속적이지 않고 속성 일부에 종속적인 속성이 존재할 경우, 이를 분리해야합니다.

・즉, 모든 비식별자 속성은 후보 식별자 속성에 완전함수 종속이 되야하며, 부분함수종속이 될 경우 이를 분리해야합니다.

・2차 정규형은 복합 식별자를 구성하는 속성이 두개 이상인 경우에만 대상이되고, 단일 속성으로 주식별자가 구성될 경우 대상이 아닙니다.






2차 정규화부터가 본격적인 정규화의 시작이라고 볼 수 있습니다. 2차 정규형은 테이블의 모든 컬럼이 완전 함수적 종속을 만족하는 것입니다. 이게 무슨 말이냐면 기본키중에 특정 컬럼에만 종속된 컬럼(부분적 종속)이 없어야 한다는 것입니다. 위 테이블의 경우 기본키는 (Student, Subject) 두 개로 볼 수 있습니다. 이 두 개가 합쳐져야 한 로우를 구분할 수가 있습니다. 근데 Age의 경우 이 기본키중에 Student에만 종속되어 있습니다. 즉, Student 컬럼의 값을 알면 Age의 값을 알 수 있습니다. 따라서 Age가 두 번 들어가는 것은 불필요한 것으로 볼 수 있습니다.




Student Table




Subject Table




이를 해결하기 위한 방법은 위처럼 테이블을 쪼개는 것입니다. 그러면 두 테이블 모두 2차 정규형을 만족하게 됩니다. 위 테이블의 경우 삽입/갱신/삭제 이상을 겪지 않게됩니다. 하지만 조금 더 복잡한 테이블의 경우, 갱신 이상을 겪기도하는데 이를 해결하는 것이 바로 3차 정규화입니다.




3. 3차 정규화



3차 정규화의 조건

・일반 속성 간의 함수적 종속 관계를 분해






이와 같은 데이터 구성을 생각해봅시다. Student_id가 기본키이고, 기본키가 하나이므로 2차 정규형은 만족하는 것으로 볼 수 있습니다. 하지만 이 데이터의 Zip컬럼을 알면 Street, City, State를 결정할 수 있습니다. 또한 여러명의 학생들이 같은 Zip코드를 갖는 경우에 Zip코드만 알면 Street, City, State가 결정되기 때문이 이 컬럼들에는 중복된 데이터가 생길 가능성이 있습니다. 정리하면 3차 정규형은 기본키를 제외한 속성들 간의 이행적 함수 종속이 없는 것 입니다. 풀어서 말하자면, 기본키 이외의 다른 컬럼이 그외 다른 컬럼을 결정할 수 없는 것입니다. 




3차 정규화는 2차정규화와 마찬가지로 테이블을 분리함으로써 해결할 수 있는데, 이렇게 두 개의 테이블로 나눔으로써 3차 정규형을 만족할 수 있습니다. 이를 통해 데이터가 논리적인 단위(학생, 주소)로 분리될 수 있고, 데이터의 redundancy도 줄었음을 알 수 있습니다.




4. BCNF


BCNF는 (Boyce and Codd Normal Form) 3차 정규형을 조금 더 강화한 버전으로 볼 수 있습니다. 이는 3차 정규형으로 해결할 수 없는 이상현상을 해결할 수 있습니다. BCNF란 3차정규형을 만족하면서 모든 결정자가 후보키 집합에 속한 정규형입니다. 아래와 같은 경우를 생각해보면, 후보키는 수퍼키중에서 최소성을 만족하는 건데, 이 경우 (학생, 과목) 입니다. (학생, 과목)은 그 로우를 유일하게 구분할 수 있습니다. 근데 이 테이블의 경우 교수가 결정자 입니다.(교수가 한 과목만 강의할 수 있다고 가정) 즉, 교수가 정해지면 과목이 결정됩니다. 근데 교수는 후보키가 아닙니다. 따라서 이 경우에 BCNF를 만족하지 못한다고 합니다. 3차 정규형을 만족하면서 BCNF는 만족하지 않는 경우는 언제일까요? 바로 일반 컬럼이 후보키를 결정하는 경우입니다. 


학생

과목 

교수 

학점 

 1

AB123

 김인영

 A

 2

 CS123

 Mr.Sim

 A

 3

 CS123

 Mr.Sim 

 A




 위와 같이 테이블이 구성된 경우에 데이터가 중복되고, 갱신 이상이 발생합니다. 예를 들어 Mr.Sim이 강의하는 과목명이 바뀌었다면 두 개의 로우를 갱신해야합니다. 이를 해결하기 위해서는 마찬가지로 테이블을 분리합니다.




교수 테이블


교수

과목

 김인영

AB123 

 Mr.Sim

CS123 




수강 테이블

학생

교수 

학점 

 1

 김인영

 A

 2

 Mr.Sim

 A

 3

 Mr.Sim

 A



참고


http://www.studytonight.com/dbms/database-normalization.php


http://pronician.tistory.com/922


・관계형 스키마 작성

-정형화가 잘 되어 있어서 7가지의 단계를 따라가면 er다이아그램이 관계형스키마로 맵핑된다.




・1단계 : 엔티티 타입을 관계형 스키마로 맵핑

-E1이라는 엔티티 타입이름이 테이블의 이름이 됨

-키애트리뷰트는 밑줄!





・2단계 : 위크 엔티티타입을 관계형 스키마로 맵핑

-참조하는 테이블의 기본키(PK)를 애트리뷰트로 가져와 fk를 준다.

-약한 엔티티타입은 pk가 될 수 있는 애트리뷰트가 존재하지 않기때문에 약한 엔티티타입의 부분키(PK1)와 참조하는 테이블의 기본키(PK)를 복합키로 생성하여 약한 엔티티타입의 기본키를 만든다.





・3단계 : 1:1 관계 타입의 변환

-1:1과 1:n 관계는 fk를 통해 서로 연결된다.

-er에서 두줄을 가지고 있는 쪽(전체참여)에 fk를 준다.





・4단계 : 1:n 관계 타입의 변환

-n쪽에다가 fk를 준다.





・5단계 : n:m 관계 타입의 변환

-1:1관계와 1:n관계에서는 한쪽에 fk를 주지만, n:m관계에서는 새로운 릴레이션R을 생성해 그 릴레이션에 fk를 준다.

-새로 생성된 릴레이션R은 양쪽의 엔티티타입에서 가져온 두개의 pk를 fk로 삼는다.(fk 2개)

-fk가 되는 두개의 애트리뷰트가 합쳐진 복합키가 릴레이션R의 기본키가 된다.



・6단계 : 다치 에트리뷰트를 관계형 스키마로 맵핑

-다치애트리뷰트를 제외한 애트리뷰트로 관계형 스키마를 생성한다.

-다치애트리뷰트는 따로 빼내어, 다치애트리뷰트의 이름으로된 릴레이션을 새로 만든다

-참조하는 테이블의 기본키를 새로운 릴레이션의 fk로 지정한다.

-참조하는 테이블의 기본키와 다치애트리뷰트외 이름으로된 애트리뷰트를 생성하고, 두 애트리뷰트의 복합키를 pk로 사용한다.




・7단계 : 3차 관계타입을 관계형 스키마로 매핑

-5단계와 동일







실제 ER모델링을 관계형 스키마로 맵핑해보자!


*관계형 스키마의 인풋이 되는 ER모델




















*완성된 모습의 관계형 스키마






















・개념적인 설계에서 논리적인 설계로 나아가기

-개념적인 설계에서 논리적인 설계로 맵핑을 해보자

-개념적 설계의 산출물인 er다이어그램은 인간이 이해하기 쉬운 것

-논리적 설계로 넘어가면서 점차 컴퓨터가 이해할 수 있는 모델들로 바꾸어야함

-논리적 모델로써 relational model을 사용함

-논리적 설계의 아웃풋은 relational schema

-개념적 설계에서 논리적 설계로 맵핑하는 과정은, db 설계 전반중 가장 정형화되고 기계적으로 가능함

-즉, 정해진 메뉴얼대로 하란대로만 하면됨. 이해하기 쉬움


・논리적 설계

-정의 : 개념적 설계의 아웃풋인 er다이아그램을 데이터베이스 관리 시스템에 매빙하는 것

-아웃풋은 relational schema





・용어설명을 통해 관계형 데이터베이스 알아보기


-테이블 네임 = 릴레이션 네임(테이블을 릴레이션이라고 부름) = (개념적 설계에서)엔티티 타입

-키어트리뷰트 = 기본키 = primary key(PK)

-관계(테이블 또는 릴레이션) : 흔히부르는 테이블이라는 이름으로 사용됨. 관계의 열은 어트리뷰트라고 하고, 행은 튜플이라고 부름

-튜플(레코드 또는 행) : 관계를 구성하는 각각의 행

-어트리뷰트(속성 또는 열)

-도메인 : 어트리뷰트가 취할 수 있는 같은 타입의 원자 값들의 집합. 예를 들어 나이라는 어트리뷰트에서 나이  를 integer 타입의 0~150으로 정한다면 각각 나이들의 집합이 도메인 

-후보키 :릴레이션에 이는 속성 중 유일성최소성을 만족하는 키로써, 후보키중 하나를 기본키로 사용함. 

-기본키(primary key) : 후보키 중에서 선정된 하나로 유일성최소성을 만족함. 기본키는 null값과 중복값이 인정되지 않음.

-슈퍼키 : 하나 이상의 어트리뷰트들의 합체로 이루어진 키. 

 예를 들어, 대학생 릴레이션에 이름과 학번이라는 어트리뷰트가 존재할 때 (이름+학번)을 하나의 키로 인정하고 사용함. 슈퍼키는 유일성을 가짐. (이름+학번)일 경우에 (이름+학번)이라는 키는 (학번)이라는 유일성을 가진 어트리뷰트 때문에 오직 하나만 존재할 것이기 때문. 

  그러나 슈퍼키는 최소성을 가지지 못함. 즉, (학번) 어트리뷰트만으로 각 튜플이 구분될 수 있는데, 굳이 학번에 이름을 합친(이름+학번)으로 해야하냐..

-외래키(foreign key) : 다른 릴레이션의 어트리뷰트를 참조해 연결해 주는 어트리뷰트를 외래키라고 함. 이때 외래키는 다른 릴레이션의 유일성을 가진 애트리뷰트를 참조해야함. 학생 릴레이션의 소속학과 애트리뷰트가 학과 릴레이션의 학과번호 애트리뷰트를 참조할 때, 학생 릴레이션의 소속학과 애트리뷰트는 외래키가됨



・관계형 데이터베이스의 제약조건

-★참조무결성 제약조건(referential integrity constraint) : 한 릴레이션에 있는 튜플이 다른 릴레이션에 있는 튜플을 참조하려면 반드시 참조되는 튜플이 해당 릴레이션 내에 존재해야 한다는 것.

 예를 들어, 학생 릴레이션의 소속학과 애트리뷰트에 5라는 튜플값이 존재한다고 하면, 이 외래키가 참조하는 학과 릴레이션의 학과번호 애트리뷰트에도 반드시 5가 존재해야한다.

-키제약조건 : 키 어트리뷰트의 값은 릴레이션 내의 각 투플을 유일하게 식별할수 있어야 한다.

-도메인 제약조건 : 각 애트리뷰트의 값은 반드시 도메인에 속하는 원자중 하나여야 한다.

-엔티티 무결성 제약조건 : 어떠한 기본키 값도 null을 가질 수 없다.



・제약조건 위배에 따른 처리

-삽입연산 : [201430010/곽나리/서울/5]를 학생 테이블에 넣고 싶은데, 참조하는 학과 테이블의 학과번호 애트리뷰트에서 5는 존재하지 않으므로 참조무결성 제약조건으로 인해 해당 데이터는 삽입될 수 없다.

-삭제연산 : 학과 테이블에서 2번(게임공학과)를 삭제하려고하면, 학과 테이블의 학과번호 애트리뷰트를 참조하고 있는 테이블이 존재하고 있기 때문에 삭제되지 않는다.(삭제해버릴시 참조무결성 제약조건을 위배함)

-수정연산 : 전요한의 소속학과를 5로 수정하려고 할 시 오류가 발생한다.


・논리적 설계

-논리적 설계의 단계(엔티티생성 -> 엔티티사이의 관계(식별자, 1:1/1:n 등 설정) -> 관계에서 세부사항을 정리(관계의 설명을 코멘트로 추가

-키어트리뷰트를 엔티티타입의 가장 위에 적어준다

-er에서는 관계를 선으로 표현한다.(자세한 내용은 er관계 포스트참고)






식별자(identifying, non-identifying)란?


idenfier.png



부모테이블의 유니크 키나 기본키(PK=primary key)로 지정된 컬럼이 자식테이블의 기본키 컬럼과 연결된 경우 실선으로 표기되고 식별 관계라고 한다.


부모테이블의 유니크 키나 기본키(PK=primary key)로 지정된 컬럼이 자식테이블의 일반 컬럼과 연결된 경우점선으로 표기되고 비식별 관계라고 합니다.






・물리적 설계

-데이터 타입을 설정한다.

-제약조건을 설정한다.




+ Recent posts