최대 공약수


// Greatest Common Divisior
int GCD(int a, int b){
    while(b != 0){
        int c = a % b;
        a = b;
        b = c;
    }
    return a;
}




최소 공배수



// Least Common Multiple
int LCM(int a, int b){
    return a * b / GCD(a, b);
}




'수학' 카테고리의 다른 글

조합( combination )이란?  (0) 2023.01.28
순열( permutation )이란?  (0) 2023.01.28
십육진법( Hexadecimal )이란?  (0) 2022.10.09
이진법( Binary )이란?  (0) 2022.10.07

Functional Dependency란?

 

  •  Functional Dependency는 한 테이블에 있는 두 개의 attribute(s) 집합 사이의 종속 관계를 의미합니다.




Functional Dependency 예시

 

empl_id empl_name birth_date position salary dept_id

 

  • X = { empl_id }

 

  • Y = { empl_name, birth_date, position, salary }

 

  • 두 tuple의 X 값이 같다면 Y값도 같다는 것이 성립됩니다.

 

  • X 값에 따라 Y 값이 유일하게 결정될 때 'X가 Y를 함수적으로 결정한다.', 'Y가 X에 함수적으로 의존한다.' 라고 표현할 수 있으며 이러한 제약 관계를 Functional Dependency( FD )라고 합니다.

 

  • 'X-> Y' 로 표현할 수 있습니다. 기호에서 X는 left-hand side, Y는 righte-hand side로 부릅니다.

 

  • 만약 Y에 dept_id까지 포함되어 있고, 한 임직원이 여러 부서에 속한다면은 X -> Y는 성립되지 않습니다.




Functional Dependency 파악 방법

 

  • 테이블의 스키마를 보고 의미적으로 파악해야 하며, 테이블의 state를 보고 FD를 파악해서는 안 됩니다. 즉, 테이블의 데이터 값을 보고 함수적으로 종속된다는 판단하면 안 됩니다.




X -> Y not means Y -> X

 

  • {empl_id} -> {empl_name} 이라고 해서 {empl_name} -> {empl_id}로 성립되지 않습니다. 경우에 따라서 {empl_id} -> {SSN}은 {SSN} -> {empl_id}가 성립됩니다.




{} -> Y

 

proj_id proj_name company
1001 ... ez.
1002 ... ez.
1003 ... ez.

 

  • {} -> Y의 의미는 Y값은 언제나 하나의 값만을 가진다는 의미로서 위와 같이 테이블이 설계되었을 때 company는 언제나 같은 값이기 떄문에 '{} -> {company}'로 표현할 수 있습니다.




Trivial functional dependency

 

  • X -> Y일 때 Y가 X의 부분집합일 경우 trivial functional dependency라고 부릅니다.

 

  • {a, b, c} -> {c} is trivial FD

 

  • {a, b, c} -> {a, c} is trivial FD

 

  • {a, b, c} -> {a, b, c} is trivial FD




Non-trivial functional dependency

 

  • X -> Y일 때 Y가 X의 부분집합이 아닐 경우 trivial functional dependency라고 부릅니다.

 

  • Y에 X와 공통된 attribute가 하나도 없을 경우

 

  • {a,b,c} -> {b,c,d} is non-trivial FD

 

  • {a,b,c} -> {d,e} is non-trivial FD & completely non-trivial FD




Partial functional dependency

 

  • X -> Y일 때 X의 proper subset이 Y를 결정 짓는다면 partial FD라고 부릅니다.

 

  • {empl_id, empl_name} -> {birth_date}일 때 {empl_id} -> {birth_date}가 성립된다면 prtial FD입니다.

 

 

 

proper subset

 

  • proper subset은 X의 부분 집합이지만 X와 동일하지 않은 집합을 의미합니다.

 

  • X = {a, b, c}일 때 {a, c}, {a}, {}는 모두 X의 proper subset입니다.




Full funtional dependency

 

  • X -> Y일 때 X의 proper subset이 Y를 결정 지을 수 없다면 full FD라고 부릅니다.

 

  • {stu_id, class_id} -> {grade}일 때 X의 proper subset이 Y를 결정지을 수 없습니다.




Insert anomalies


empl_id empl_name birth_date position salary dept_id dept_name dept_leader_id
1 MESSI ... ... ... 1001 DEV 1
2 JINHO ... ... ... 1001 DEV 1
3 JENNY ... ... ... null null null
4 null null null null 1002 QA null
5 YUGIN ... ... ... 1002 QA 5

  • 위와 같이 스키마가 설계되었을 때 아래와 같은 이상현상이 발생될 수 있습니다. ( empl_id는 primary key입니다. )




중복 데이터 문제


  • dept_id, dept_name, dept_leader_id 속성은 중복 데이터이며, 중복 데이터는 저장 공간을 낭비시킵니다.

  • 개발자의 실수로 인한 데이터 불일치 가능성이 존재합니다.




null 값을 많이 써야되는 문제점


  • 3번째 튜플을 보면 아직 부서 배정을 받지 못하여 dept_id, dept_name, dept_leader_id의 속성이 null 값으로 채워진 것을 볼 수 있습니다.

  • 4번째 튜플을 보면 아직 부서원이 없는 부서를 insert할 때 직원 관련된 속성은 null 값으로 채워야하며, primary key에는 임시로 값을 넣어줘야 합니다.

  • 5번째 튜플로 신생 부서의 부서원을 추가하였다면 신생 부서 생성을 위한 튜플 4번을 삭제해야하는 추가적인 작업이 필요합니다.




Deletion anomalies


empl_id empl_name birth_date position salary dept_id dept_name dept_leader_id
1 MESSI ... ... ... 1001 DEV 1
2 JINHO ... ... ... 1001 DEV 1
3 JENNY ... ... ... null null null
5 YUGIN ... ... ... 1002 QA 5

  • 위와 같이 스키마가 설계되었을 때 아래와 같은 이상현상이 발생될 수 있습니다. ( empl_id는 primary key입니다. )




의도하지 않은 데이터 삭제


  • 4번째 튜플을 삭제하게 될 경우 QA부서에 대한 데이터 또한 삭제되는 문제가 발생됩니다.




Update anomalies


empl_id empl_name birth_date position salary dept_id dept_name dept_leader_id
1 MESSI ... ... ... 1001 DEV 1
2 JINHO ... ... ... 1001 DEV1 1
3 JENNY ... ... ... null null null

  • 위와 같이 스키마가 설계되었을 때 아래와 같은 이상현상이 발생될 수 있습니다. ( empl_id는 primary key입니다. )




데이터 불일치 현상


  • 만약, DEV 부서 이름이 DEV -> DEV1로 변경되었다면, 프로그래머의 실수로 JINHO가 속한 튜플만 변경될 수도 있습니다. 이렇게 될 경우 부서 정보의 데이터 불일치 현상이 발생될 수 있습니다.




다음과 같은 테이블 설계가 좋지못한 이유


empl_id empl_name birth_date position salary dept_id dept_name dept_leader_id
1 MESSI ... ... ... 1001 DEV 1
2 JINHO ... ... ... 1001 DEV 1
3 JENNY ... ... ... null null null
4 null null null null 1002 QA null
5 YUGIN ... ... ... 1002 QA 5

  • 두 가지 이상의 관심사인 employee, department에 대한 정보가 한 테이블에 있기 때문입니다. 그래서 위 테이블을 다시 설계를 한다면 employee와 department 테이블을 나눠서 설계헤야합니다.




Spurious Tuples


  • department_project

dept_id proj_id proj_name proj_location
1001 2001 Beautiful Jeju Jeju
1001 2003 Busan romance Haeundae
1002 2002 Wedding at Jeju Jeju
1003 2004 Again 2002 Gwanghwamun




  • department_location

dept_name proj_location
feelm Jeju
feelm Haeundae
Picachoo Jeju
MovieMove Gwanghwamun

  • 위와같이 사진 촬영회사의 DB 테이블을 설계하였다고 가정하였을 때 아래와 같은 이상 현상이 발생될 수 있습니다.




select * from department_project natural join department_location


dept_id proj_id proj_name proj_location dept_name
1001 2001 Beautiful Jeju Jeju feelm
1001 2003 Busan romance Haeundae feelm
1002 2002 Wedding at Jeju Jeju Picachoo
1003 2004 Again 2002 Gwanghwamun MovieMove
1001 2001 Beautiful Jeju Jeju Picachoo
1002 2002 Beautiful Wedding Jeju feelm

  • 위 테이블은 natural join을 했을 때 결과입니다. 하지만, 두 번째, 다섯 번째 튜플을 보면 동일한 dept_id인데도 불구하고 dept_name이 다른 것을 확인할 수 있습니다. 이러한 튜플은 세 번째 여섯 번째 튜플 또한 같습니다. 즉, 잘못된 테이블 설계로 인해서 가짜 튜플이 생성된 것을 확인할 수 있습니다.




null 값이 많아짐으로 인한 문제점들


  • null 값이 있는 column으로 join하는 경우 상황에 따라 예상과 다른 결과가 발생될 수 있습니다.

  • null 값이 있는 column에 aggregate function을 사용했을 때 주의가 필요합니다. ( attribute를 대상으로 count를 사용할 경우 null 값은 카운팅하지 않습니다. )

  • 불필요한 storage를 낭비합니다.




CORS( Cross-Origin Resource Sharing )란?

 

  • CORS( Cross-Origin Resource Sharing )는 추가 HTTP 헤더를 사용하여 다른 출처와 자원을 공유할 수 있도록 브라우저에게 알려주는 정책입니다. CORS 동작 방식에 따라서 Preflight Request, Simple Request, Credential Request로 나뉩니다. 이러한 정책이 필요한 이유는 브라우저의 SOP( Same-Origin Policy ) 보안 때문이며, SOP는 아래에서 설명하겠습니다.




출처( Origin )란?

 

 

  • 출처( Origin )란 위 URI 구성에 나와있듯이 Protocol, Host, Port를 묶어서 표현한 것을 의미합니다.




SOP( Same-Origin Policy )

 

  • 현재 출처와 다른 출처( Origin )와의 리소스를 공유하는 것을 제한하는 정책입니다.




SOP가 필요한 이유

 

 

  • SOP(Same-Origin Policy)가 필요한 대표적인 이유로는 XSS(Cross-Site Scripting) 공격이 있습니다. XSS는 해커가 서버에 악의적인 스크립트를 심어서 사용자가 이를 조회했을 때 해커가 작성한 스크립트를 실행하여 자신의 세션 정보와 같이 중요한 정보가 해커의 서버로 송신되는 상황을 방지하기 위함입니다. 

    SOP는 동일한 Origin을 대상으로만 Request를 허용하기 때문에 위와같이 사용자가 해커가 심어놓은 스크립트를 실행한다 하더라도 사용자의 정보가 다른 Origin으로 탈취되는 상황을 방지할 수 있습니다.




CORS가 필요한 이유

 

  • 모든 요청을 동일한 서버에 한다면 CORS는 필요하지 않습니다. 하지만, 아래와 같은 이유로 CORS를 이용하여 다른 출처로 요청하여 리소스를 공유하는 상황이 생길 수 있습니다.




프론트와 백엔드의 서버 분리

 

  • 현대 웹 애플리케이션는 빠른 서비스를 위해 서버가 크게 프론트와 백엔드로 나누어졌습니다. 클라이언트 측에서 요청을 하는 순간 프론트 서버의 응답을 받아 랜더링이 되고, 데이터는 백엔드 서버에 요청하여 받아오게 되는 흐름은 다른 출처간의 리소스 공유를 막는 SOP 때문에 처리의 한계를 가졌습니다.




다른 출처의 데이터 사용

 

  • 웹 구현시 REST API를 통해 다른 출처의 데이터를 요청해 리소스를 공유하는 경우가 많아졌습니다.




마이크로 서비스 아키텍쳐

 

  • 트래픽양이 증가하면서 서버 한대로는 물리적으로 버티기 힘들어졌고 여러개 서버의 필요성이 대두되었습니다. 예를들어서 A 서버는 로그인 처리를 위한 서버, B 서버는 주문만 받는 서버처럼 하나의 서버가 특정 기능만을 수행하도록 분할하여 관리할 수 있습니다.




Preflight Request

 

  • 기본적으로 브라우저는 요청을 보낼 때 바로 보내지 않고, 먼저 Preflight Request를 보내 서버와 잘 통신되는지 확인 후 본 요청을 보냅니다. Preflight Request를 보낼 때 HTTP 메소드를 OPTIONS로 하여 요청합니다.




Prefligh Request를 이용한 통신 과정

 

 

1. 자바스크립트의 fetch() 메서드를 통해 리소스를 요청합니다.




2. 브라우저는 서버로 OPTIONS 메서드로 Preflight Request를 보냅니다.

 

  • Origin 헤더에 자신의 출처를 넣습니다.

 

  • Access-Control-Request-Method 헤더에 실제 요청에 사용할 메소드를 설정합니다.

 

  • Access-Control-Request-Headers 헤더에 실제 요청에 사용할 헤더들을 설정합니다.




3. Preflight Request를 받은 서버는 어떤 것을 허용하는지에 대한 정보를 헤더에 담아 응답합니다.

 

  • Access-Control-Allow-Origin 헤더에 허용되는 Origin을 설정합니다.

 

  • Access-Control-Allow-Methods 헤더에 허용되는 메소드들의 목록을 설정합니다.

 

  • Access-Control-Allow-Headers 헤더에 허용되는 헤더들의 목록을 설정합니다.

 

  • Access-Control-Max-Age 헤더에 해당 예비 요청이 브라우저에 캐시될 수 있는 시간을 초 단위로 설정합니다.




4. 응답받은 브라우저는 헤더를 확인하여 해당 요청이 안전한지 확인하고 본 요청을 보냅니다.




5. 이후 요청에는 Access-Control-Max-Age에 설정된 시간만큼 캐시하여 Preflight Request를 생략합니다.




Simple Request

 

  • Simple Request는 메서드와 헤더 정보들을 확인하여 보안적으로 안전한 요청이라면 Preflight Request를 생략하고 바로 서버에 본 요청을 하는 방식입니다.

    이 요청을 받은 서버는 응답 헤더에 Access-Control-Allow 헤더들을 설정하여 응답하면 브라우저가 CORS 정책 위반 여부를 검사합니다. 즉, 조건에 맞다면 Preflight Request를 생략하고 응답 데이터의 Access-Control-Allow 헤더들이 올바른지 확인하여 응답 거부 여부를 결정합니다.




Simple Request를 이용한 통신 과정

 

 

  • Simple Request는 아래 3가지 조건을 충족할 때만 Reflight Request를 생략하여 이루어지며, 아래와 같이 까다로운 조건 때문에 Simple Request가 되는 경우가 상당히 드뭅니다.




Simple Request 4 가지 조건

 

  • 요청의 메소드는 GET, HEAD, POST만 허용합니다.

 

  • Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width 헤더일 경우에만 적용됩니다.

 

  • Content-Type 헤더가 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용합니다.


  • 클라이언트가 credentials 옵션을 설정하지 않아야 합니다. (즉, 자격 증명 정보를 서버로 전송하지 않아야 합니다.)




Credential Request

 

  • 인증된 요청은 클라이언트에서 서버에게 자격 인증 정보( Credential )를 실어 요청하는 것을 말합니다. 여기서 말하는 자격 인증 정보란 쿠키에 저장되어 있는 SessionID 또는 Authorization 헤더에 설정하는 JWT와 같은 Token 값 등을 말합니다. 이러한 인증된 요청을 다른 출처로 요청할 때에는 서버는 Access-Control-Allow 헤더에 더 구체적인 응답이 필요합니다.

 




인증된 요청을 하는 방법

 

옵션 값
설명
same-origin(기본값) 같은 출처간의 요청에만 인증 정보를 담음
include 모든 요청에 인증 정보를 담음
omit 모든 요청에 인증 정보를 담지 않음




credentials 설정

 

fetch("https://example.com:8888", {
  method: "POST",
  credentials: "include",
  body: JSON.stringify({
    name: "devhun",
  }),
});




인증된 요청에 대한 서버 응답 방법

 

  • 서버도 마찬가지로 인증된 요청에 대해서는 일반적인 CORS 요청과는 다르게 처리해야합니다. 응답 헤더를 아래와 같이 설정하지 않는다면 응답 받은 브라우저는 CORS 정책에 의해 요청이 거부됩니다.




응답 헤더 설정

 

  • 응답 헤더의 Access-Control-Allow-Credentials 항목을 true로 설정해야 합니다.

 

  • 응답 헤더의 Access-Control-Allow-Origin의 값에 와일드 카드("*")는 사용할 수 없습니다.

 

  • 응답 헤더의 Access-Control-Allow-Methods의 값에 와일드 카드("*")는 사용할 수 없습니다.

 

  • 응답 헤더의 Access-Control-Allow-Headers의 값에 와일드 카드("*")는 사용할 수 없습니다.




SQL 표준에서 정의한 transaction 3가지 이상 현상

 

Dirty read

 

 

  • 위와 같이 다른 트랜잭션에서 수행한 Commit 되지 않는 변화를 읽은 후 해당 데이터가 다시 rollback되어 자신의 트랜잭션이 commit한 데이터에 일관성이 깨지는 이상 현상을 Dirty read라고 합니다.




Non-repeatable read( 또는 Fuzzy read )

 

 

  • 같은 데이터를 두 번 이상 읽었지만 다른 트랜잭션에 의해서 값이 달라지는 현상을 말합니다. 이처럼 다른 트랜잭션에 의해서 중간에 처리 결과가 바뀌는 현상은 isolation을 위반한 것으로 볼 수 있습니다.




Phantom read

 

 

  • 같은 조건으로 두 번 이상 읽었는데 중간의 다른 트랜잭션에 의해서 없던 데이터가 생기는 현상을 말합니다.




이상 현상 예방과 처리량( throughput )

 

  • Dirty read, Non-repeatable read, Phantom read와 같은 이상 현상들을 예방할 수 있지만, 그렇게 한다면 제약 사항이 많아져서 동시 처리 가능한 트랜잭션 수가 줄어들어 결국 DB의 전체 처리량(throughput)이 하락하게 됩니다. 그래서 isolation level을 통해서 일부 이상 현상은 허용하여 사용자가 필요에 따라서 적절하게 선택할 수 있도록 할 수 있습니다.




isolation level

 

Isolation level Dirty read Non-repeatable read Phantom read
Read uncommitted O O O
Read committed X O O
Repeatable read X X O
Serializable X X X

 

 

 

  • Serializable level은 위 세 가지 현상 뿐만 아니라 이상 현상 자체가 발생하지 않는 level을 의미합니다.

  • 세 가지 이상 현상을 정의하고 어떤 현상을 허용하는지에 따라서 각각의 isolation level이 구분됩니다. 그렇기 때문에 개발자는 isolation level을 통해 전체 처리량(throughput)과 데이터 일관성 사이에 어느 정도 타협을 볼 수 있습니다.




SQL 표준에서 정의한 이상 현상 외에 추가적인 이상 현상

 

  • 1995년에 SQL 표준에서 정의한 이상 현상에 대한 비판 논문이 발표되었으며 아래 3가지 비판 내용을 담고 있습니다.




SQL 표준에서 정의한 이상 현상 비판 내용

 

  • 세 가지 이상 현상의 정의가 모호한 모호하다.

 

  • 이상 현상을 세 가지 외에도 더 있다.

 

  • 상업적인 DBMS에서 사용하는 방법을 반영해서 isolation level을 구분하지 않았다.




추가적인 이상 현상

 

Dirty write

 

 

  • commit 안된 데이터에 write 하여 commit을 한 후 다른 트랜잭션에서 abort가 발생되었다면 write한 데이터가 사라지는 현상을 말합니다. 특히, rollback시 정상적인 recovery는 매우 중요하기 때문에 모든 isolation level에서는 dirty write를 허용하면 안 됩니다.




Lost update

 

 

  • commit되지 않은 데이터에 데이터를 쓴 후 다른 트랜잭션에 의해서 데이터가 덮어씌워지는 현상을 Lost update라고 합니다.




Dirty read의 추가적인 이상 사항

 

 

  • 위와 같이 데이터를 읽기만 하고 abort가 발생하지 않아도 x, y 데이터의 합이 100이 안 되는 것처럼 일관성이 깨지는 현상이 발생될 수 있습니다.




Read skew

 

 

  • 두 번째 트랜잭션은 x, y를 읽었을 뿐인데 데이터에 대한 일관성이 깨지는 현상을 Read skew라고 합니다.




Write skew

 

 

  • x + y >= 0 제약 조건이 있는데 다른 트랜잭션이 commit 하지 않은 데이터를 읽고 쓰기를 함으로써 제약 조건을 위반되는 상황을 말합니다.




Phantom read의 추가적인 이상 현상

 

 

  • 같은 조건으로 데이터를 두 번 이상 읽는것 뿐만 아니라 연관된 데이터를 각각 읽는 경우에도 Phantom read 현상이 발생될 수 있습니다.




SQL 표준의 이상 현상을 비판한 논문의 추가적인 isolation level

 

Snapshot isolation level

 

 

  • 각 트랜잭션마다 특정 시점의 스냅샷을 기준으로 operation을 수행하고 commit할 때 write write conflict가 발생했다면 먼저 commit된 트랜잭션만 인정하는 방식을 Snapshot isolation level이라고 합니다.

 

  • SQL 표준의 isolation level은 이상 현상을 정의하고 이상 현상을 얼만큼 허용하느냐에 따라서 isolation level을 구분한다면 Snapshot isolation level은 Concurrent Control의 동작 방식에 의해서 정의되었습니다.







동적 계획법( DP : Dynamic Programming ) 이란?


  • 다이나믹 프로그래밍은 하나의 큰 문제를 여러 개의 작은 문제로 나누어서 그 결과를 저장( 메모이제이션 )하여 다시 큰 문제를 해결할 때 사용하는 것으로 특정한 알고리즘이 아닌 하나의 문제해결 방법입니다.




메모이제이션( memoization )이란?


  • 메모이제이션이란 어떤 로직에 의한 결과값이나 상태값을 자료구조에 저장하여 재사용할 수 있도록 하는 것을 말합니다.




DP 적용 조건


참조 투명성을 가져야 합니다.


  • 입력을 제외한 외적 요소에 결과값이 영향을 미치지 않아야 합니다.




Overlapping Subproblem



  • 겹치는 부분 문제가 존재해야 합니다.




Optimal Substructure


  • 최적 부분 구조를 가지고 있어야합니다. 즉, 최적의 해가 전체적인 글로벌한 최적해가 되는 것을 말합니다.




현실적인 코딩 테스트에서 DP를 적용하기까지 생각 과정


1. 완전탐색 문제인데?




2. 경우의 수가 너무나 큰데?




3. 메모이제이션이 가능한가?


  • 저장해야할 메모이제이션이 너무 클 경우 그리디로 풀어야합니다.




자료 참조 : https://blog.naver.com/jhc9639/222349317111

그리디 알고리즘( Greedy Algorithm )이란?

 

greedy algorithm의 한계

 

  • 각 단계마다 지역적 최적의 해가 궁극적으로 전역 최적의 해가 되는 것을 말합니다. 지금의 state 혹은 idx에서 최선이라고 생각하는 해가 결국은 이 문제의 답이 되는 것입니다.




그리기 알고리즘 두 가지 조건

 

  • 최적 부분 구조를 가지고 있어야 합니다. 지금 이 state에서 최선을 다해 선택하는 해가 결국에는 전역적인 최적해로 이어져야 합니다.

 

  • 탐욕적 속성이 증명이 되어야 합니다. 보통 귀류법으로 증명을 합니다.




증명의 한계

 

  • 그리디 알고리즘으로 풀기 위한 조건을 확인하기 위해서 코딩 테스트에서 증명까지 하는 것은 다소 무리가 있습니다. 그렇기 때문에 문제를 파악했을 때 너무 큰 공간, 너무 큰 시간 복잡도를 요구하는 문제라면은 "무식하게 풀기 -> DP -> 그리디 알고리즘" 순서로 문제에 접근해야 합니다. DP도 공간 복잡도의 한계 때문에 적합하지 않는 경우가 있는데 그럴 경우 그리디 알고리즘을 이용해 접근할 수 있습니다.




자료 참조 : https://blog.naver.com/jhc9639/222319124359

 

[알고리즘 강의] 5주차. 그리디 라인스위핑 투포인터

안녕하세요. 큰돌입니다. 이번 주차에는 그리디 라인스위핑 투포인터를 알아보도록 하겠습니다. 이 3가지 ...

blog.naver.com

 

트랜잭션( Transaction )이란?

 

  • 트랜잭션(Transaction)은 하나 이상의 SQL 문을 나눠질 수 없는 논리적인 작업 단위로 묶어 처리하는 기능을 말합니다. 그렇기 때문에 transaction의 SQL문들 중에 일부만 성공해서 DB에 반영되는 일은 일어나지 않습니다.




트랜잭션 사용방법

 

J가 H에게 20만원을 이체하는 트랜잭션

 

-- 트랜잭션 시작을 의미
start transaction;

update account set money - 200000 where id = 'J';

update account set money + 200000 where id = 'H';

-- commit을 통해 지금까지 작업한 내용을 DB에 영구적으로 저장 후 트랜잭션 종료
commit;

 

  • start transaction 을 실행하면 autocommit은 off가 됩니다.

 

  • commit 또는 rollback을 실행하면 autocommit은 원래 상태로 돌아갑니다.




J가 H에게 30만원을 이체도중 롤백

 

-- 트랜잭션 시작을 의미
start transaction;

update account set money - 300000 where id = 'J';

-- 지금까지 작업들을 모두 취소하고 transaction 이전 상태로 되돌린 후 트랜잭션을 종료
rollback;




autocommit 이란?

 

-- autocommit 활성화 확인하는 SQL
select @@autocommit;

-- autocommit 비활성화
set autocommit = 0;

 

  • 각각의 SQL문에 대해서 자동으로 transaction 처리를 해주는 기능입니다. SQL문이 성공적으로 실행되면 commit 실패할 경우 rollback을 자동으로 진행합니다. ( MySQL에서는 autocommit이 default로 활성화되어 있습니다. )




트랜잭션의 ACID( Atomicity, Consistency, Isolation, Durability )란?

 

  • ACID는 Atomicity, Consistency, Isolation, Durability의 앞 글자를 딴 약자이며, 각각의 단어는 트랜잭션이 가져야 하는 속성을 의미합니다.




Atomicity( 원자성 )

 

  • 트랜잭션의 내부 SQL문들을 원자적으로 묶어 모두 성공하거나 모두 실패하는 결과만 나오는 속성을 의미합니다.




Consistency( 일관성 )

 

  • 트랜잭션 수행 도중 테이블에 등록된 constraints, trigger 등을 통해 DB에 정의된 rules을 트랜잭션이 위반했다면 rollback해야 합니다. 그 외에도 application 관점에서 트랜잭션이 consistent하게 동작하는지 개발자가 확인하여 commit해야 합니다.

 

  • 예를들어 50만원밖에 없는 H가 J에게 100만원을 입금하는 것을 트랜잭션으로 처리한다면 H는 100만원도 없기 때문에 Consistency를 유지할 수 없어 트랜잭션 도중 실패하여 rollback을 해야합니다.




Isolation( 독립성 )

 

  • 트랜잭션이 수행될 때 다른 트랜잭션에 의해 영향을 받지 않아야 하는 속성을 의미합니다.

 

  • 트랜잭션의 Isolation이 너무 엄격하면 DB의 퍼포먼스가 떨어질 수 있기 때문에 DBMS 종류에 따라서 isolation level을 제공합니다. isolation level이 낮으면 엄격한 격리성이 낮아져 트랜잭션의 동시성이 높아집니다. 하지만, 다른 트랜잭션에 의해서 예상치 못한 결과가 나올 수도 있기 때문에 신경써서 사용해야 합니다.




Durability( 영속성 )

 

  • commit된 트랜잭션은 DB에 영구적으로 반영되는 속성을 의미합니다.




SQL에서 Triger란?


  • 데이터베이스에서 어떤 이벤트가 발생되었을 때 자동적으로 실행되는 프로시저(procedure)을 의미합니다. 예를들어서 insert, update, delete가 발생했을 때 이것이 계기가 되어 자동적으로 실행되는 프로시저(procedure)를 의미합니다.




trigger 사용법


사용자의 닉네임 변경 이력을 저장하는 트리거


delimiter $$
create trigger log_user_nickname_trigger
before update
-- users 테이블을 대상
on users for each row
begin
    -- old는 update 되기 전의 tuple을 가리킴
    -- 또는 delete된 tuple을 가리킴
    insert into users_log values(old.id, old.nickname, now());
end
$$
delimiter ;




사용자가 마트에서 상품을 구매할 때마다 지금까지 누적된 구매 비용을 구하는 트리거


delimiter $$
create trigger sum_by_prices_trigger
after insert
on buy for each row
begin
    declare total int;

    -- new는 insert된 tuple을 가리킴
    -- 또는 update된 후의 tuple을 가리킴
    declare user_id int default new.user_id;

    select sum(price) into total from buy where user_id = user_id;
    update user_buy_stats set price_sum = total where user_id = user_id;
end
$$
delimiter ;




trigger 사용 시 주의사항


  • 서버 소스 코드에 있지 않고 RDBMS에 등록하여 해당하는 이벤트가 발생되었을 때 자동으로 호출되는 방식이기 때문에 어떤 동작이 일어나는지 파악하기 어렵고 문제가 생겼을 때 대응하기 어렵습니다.

  • 등록한 trigger가 많아지면 trigger에 의해 또 다른 trigger가 호출되는 복잡한 상황이 발생될 수 있습니다.

  • 과도한 trigger 사용은 DB 서버의 CPU 사용률을 증가시켜 부하가 발생될 수 있습니다.




트리 순회( tree traversal ) 순회 방법


  • 트리 순회( tree traversal )는 트리 구조에서 각각의 노드를 한 번씩만 체계적으로 방문하는 과정을 말합니다. 그리고 노드를 순회하는 순서에 따라서 후위 순회, 전위 순회, 중위 순회가 있습니다.




후위 순회( postorder traversal )


  • 후위 순회(postorder traversal)는 자식들 노드를 방문하고 자신의 노드를 방문하는 것을 말합니다.




후위 순회 pseudo code


postorder( node )
    if (node.visited == false)
        postorder( node->left )
        postorder( node->right )
        node.visited = true




전위 순회( preorder traversal )


  • 전위 순회( preorder traversal )는 먼저 자신의 노드를 방문하고 그 다음 자식 노드들을 방문하는 것을 말합니다.




전위 순회 pseudo code


preorder( node )
    if (node.visited == false)
        node.visited = true
        preorder( node->left )
        preorder( node->right )




중위 순회( inorder traversal )


  • 중위순회(inorder traversal)는 왼쪽 자식 노드를 먼저 방문 그다음의 자신의 노드를 방문하고 그 다음 오른쪽 자식 노드를 방문하는 것을 말합니다.

  • 이진 탐색 트리에서 오름 차순으로 접근할 때 중위 순회를 사용합니다.




중위 순회 pseudo code


inorder( node )
    if (node.visited == false)
        inorder( node->left )
        node.visited = true
        inorder( node->right )




+ Recent posts