Skip to content

Latest commit

 

History

History
784 lines (479 loc) · 42.7 KB

DataBase.md

File metadata and controls

784 lines (479 loc) · 42.7 KB

DataBase

Transaction

ACID가 무엇인지 설명해주세요.

Atomic(원자성)

  • 트랜잭션과 관련된 작업들이 부분적으로 실행되다가 중단되지 않는 것을 보장하는 능력
    • 중간 단계까지 실행되고 실패하는 일은 없다.
    • 구매자의 돈이 빠졌지만 판매자의 돈이 들어오지 않는 경우

Consistency(일관성)

  • 트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 것
    • 트랜잭션 작업 처리 결과는 항상 일관성 있어야 한다.
    • 마이너스 통장을 허락하지 않는다면 조건에 위배되면 트랜잭션 종료

Isolation(독립성)

  • 트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것
    • 둘 이상의 트랜잭션이 동시 실행되고 있을 때 다른 트랜잭션이 끼어들 수 없다.
    • 구매자의 돈이 빠졌지만 판매자의 돈이 아직 안들어왔는데 다른 트랜잭션이 끼어들 수 없다.

Durability(지속성)

  • 트랜잭션이 성공적으로 완료되어 commit 되었다면 결과는 데이터베이스에 영구히 반영되어야 한다.
은행에서 돈을 뽑을 때 관점에서 ACID Isolation 관점에서 설명해주세요.

내가 돈을 5만원 뽑았는데 내 통장에 돈이 5만원 빠지기 전에 다른 트랜잭션이 끼어들 수 없다.

트랜잭션 격리레벨에 대해서 설명해주세요.
스크린샷 2021-11-25 오후 10 25 08
  • READ UNCOMMITTED

    • 가장 격리가 낮은 단계입니다. 다른 트랜잭션에서 커밋하지 않은 데이터도 조회할 수 있다는 문제점이 존재합니다. 그래서 사용하지 않습니다.
  • READ COMMITTED

    • Oracle DBMS 에서 기본적으로 사용하고 있는 격리 수준이며, 다른 트랜잭션에서 데이터를 변경했더라도 COMMIT 한 데이터만 보입니다. 하지만 이 격리 레벨에서도 NON-REPEATABLE READ의 문제점이 존재합니다. NON-REPEATABLE READ란 같은 쿼리를 같은 트랜잭션에서 2번 실행했는데 결과가 다른 부정합을 말합니다.
    • 즉, A 트랜잭션에서 같이 쿼리를 2번 실행합니다. A 트랜잭션에서 쿼리를 첫 번째로 실행한 후에, B 트랜잭션에서 해당 쿼리가 조회하는 row 의 값을 Update 했습니다. 그러면 A 트랜잭션에서 같은 쿼리를 두 번째 조회했을 때는 첫 번째 실행했을 때와 결과가 다를 것입니다. 이렇게 하나의 A 트랜잭션 안에서 같은 쿼리를 여러 번 실행했을 때 결과가 다른 현상을 NON-REPEATABLE-READ 라고 합니다.
  • REPEATABLE READ

    • MySQL InnoDB 에서 기본적으로 사용되고 있는 격리 수준입니다. 바이너리 로그를 가진 MySQL 장비에서는 최소 이 격리 수준을 사용해야 합니다.
    • 자신의 트랜잭션 번호보다 낮은 트랜잭션 번호에서 변경된 것만 보게 됩니다.
    • InnoDB 스토리지 엔진은 트랜잭션이 ROLLBACK 될 가능성에 대비해 변경되기 전 레코드를 언두 공간에 백업해두고 실제 레코드 값을 변경합니다. 이러한 방식을 MVCC 라고 합니다. 사실 READ COMMITTED 도 MVCC 를 이용해 COMMIT 되기 전의 데이터를 보여준다. 두 개의 차이는 언두 영역에 백업된 레코드의 여러 버전 가운데 몇 번째 이전 버전까지 찾아 들어가야 하는지에 있습니다.
    • 하지만 이 격리 수준에서도 PHANTOM READ 부정합 문제가 발생합니다. PHANTOM READ 는 보이지 않았던 결과가 보이는 것이다.
    • REPEATABLE READ 격리 수준은 트랜잭션이 시작할 때 보다 이전 트랜잭션에서 커밋된 데이터만 조회하기 때문에 중간 트랜잭션에서 데이터를 바꿨어도 Undo 영역에서 조회하기 때문에 문제가 발생하지 않는다! 다른 트랜잭션에서 INSERT, DELETE 한 경우에 데이터가 변경된 것이 아니라 새로 추가된 것이기 때문에 REPEATABLE READ 에서도 PHANTOM READ 가 발생한다.
    • PANTHOM READ를 방지하기 위해서는 쓰기 잠금을 걸어야 한다.
    • InnoDB 에서는 갭 락, 넥스트 키 락 때문에 PHANTOM READ가 발생하지 않는다.
  • SERIALIZABLE

    • 가장단순한 격리수준이면서 동시에 가장 엄격한 격리 수준이다. 그만큼 동시 처리 성능도 다른 트랜잭션 격리 수준보다 떨어진다. InnoDB 테이블에서 기본적으로 순수한 SELECT 작업은 아무런 레코드 잠금도 설정하지 않고 진행된다. 하지만 트랜잭션 격리 수준이 SERIALIZABLE로 설정되면 읽기 작업도 공유 잠금을 획득해야만 하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경하지 못하게 된다. 즉, 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없는 것이다.

트랜잭션이 무엇인지 설명해주세요

트랜잭션이란 쿼리를 하나의 묶음 처리해서 만약 중간에 실행이 중단됐을 경우, 처음부터 다시 실행하는 Rollback을 수행하고, 오류없이 실행을 마치면 commit을 하는 실행 단위를 의미합니다.

트랜잭션을 사용하는 이유 또는 필요한 이유가 무엇이라고 생각하시나요?
  • 트래픽이 많이 몰려서 동시에 여러 클라이언트에 DB 서버로 접근한다면 데이터베이스의 부정합이 많이 발생할 수 있습니다.
  • 부정합이 발생하지 않으려면 프로세스를 병렬로 처리하지 않도록 하여 한 번에 하나의 프로세스만 처리하도록 하면 되는데, 이는 효율이 너무 떨어집니다. 트랜잭션을 사용하지 않으면 부정합을 방지하고자 일렬로 처리해야 합니다. 이는 성능상 너무 좋지 않기 때문에 부정합도 방지하고 성능의 이점도 가져갈 수 있도록 트랜잭션을 사용합니다.
  • 그리고 하나의 논리적인 단위에서 에러가 발생했을 때 롤백 해야 하는 문제를 해결할 수 있고, 커밋이 되면 데이터가 영구적으로 저장되도록 할 수 있는 특징이 있습니다.
트랜잭션 격리레벨이 높아질수록 속도가 느려지나요?
트랜잭션 고립레벨이 올라간다고 왜 동시성 처리가 떨어지나요?

SERIALIZABLE: 가장단순한 격리수준이면서 동시에 가장 엄격한 격리 수준이다. 그만큼 동시 처리 성능도 다른 트랜잭션 격리 수준보다 떨어진다. InnoDB 테이블에서 기본적으로 순수한 SELECT 작업은 아무런 레코드 잠금도 설정하지 않고 진행된다. 하지만 트랜잭션 격리 수준이 SERIALIZABLE로 설정되면 읽기 작업도 공유 잠금을 획득해야만 하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경하지 못하게 된다. 즉, 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없는 것이다.


Index

인덱스란 무엇인지 설명해주세요.

인덱스는 말 그대로 책의 맨 처음 또는 맨 마지막에 있는 색인(목차)이라고 할 수 있다. DBMS 에서 검색 속도를 향상시키기 위해 인덱스를 사용합니다. 하지만 인덱스를 사용함으로써 INSERT, UPDATE 성능은 희생해야 합니다.

카디널리티 값은 높아야 인덱스 사용에 유용합니다. ex) 주민번호는 카디널리티 값이 높습니다.(사람마다 개인의 고유 값이기 때문에 중복되지 않음) 하지만 성별은 일반적으론 남자/여자 정도만 있기 때문에 중복이 많이 되는 값이기 때문에 카디널리티 값이 낮습니다.

인덱스를 통해 실제 데이터를 읽어오는 작업은 비용이 드는 작업이기 때문에, 테이블 크기의 20~25% 이상 인덱스를 통해 읽어야 한다면 그냥 테이블을 읽는 것이 더 나을 수 있다.

InnoDB 같은 경우는 세컨더리 인덱스가 데이터를 찾아올 때는 프라이머리 키를 통해서 찾아야 하는 과정을 거치게 된다.

잘 적용된 index란 무엇인가요?
  • 카디널리티(Cardinality)가 가장 높은 것을 잡아야 한다는 점입니다.

  • 카디널리티(Cardinality): 해당 컬럼의 중복된 수치를 나타냅니다.

    • 예를 들어 성별, 학년 등은 카디널리티가 낮다고 얘기합니다. 반대로 주민등록번호, 계좌번호 등은 카디널리티가 높다고 얘기합니다.(겹칠 수 없는 고유 값이기 때문에)
  • 인덱스로 최대한 효율을 뽑아내려면, 해당 인덱스로 많은 부분을 걸러내야 하기 때문입니다. 인덱스를 생성할 대는 카디널리티가 높은 칼럼부터 낮은 순서대로 인덱스 생성해야 합니다.

B-Tree 인덱스에 대해서 설명해주세요.
스크린샷 2021-12-01 오후 12 24 56
  • Binary Search 자료구조의 한계를 극복하기 위해 나온 자료구조 입니다. 즉, B-Tree는 한 노드에 많은 자식 노드를 가질 수 있기 때문에 아무리 대용량 데이터여도 Depth4 ~ 5 정도가 된다는 특징이 있습니다.
  • B-Tree는 데이터베이스의 인덱싱 알고리즘 가운데 가장 일반적으로 사용되고, 가장 먼저 도입된 알고리즘 입니다. (Binary(X), Balanced Tree)
  • B-Tree는 컬럼의 원래 값을 변형시키지 않고 인덱스 구조체 내에서는 항상 정렬된 상태로 유지하고 있습니다.
  • 인덱스의 리프 노드는 항상 실제 데이터 레코드를 찾아가기 위한 주소 값을 가지고 있습니다.
  • B-tree의 장점 한 가지는 '어떤 값에 대해서도 같은 시간에 결과를 얻을 수 있다'인데, 이를 균일성이라고 한다.

인덱스 키 값의 크기

InnoDB 스토리지 엔진은 디스크에 데이터를 저장하는 가장 기본 단위를 페이지 또는 블록이라고 하며, 디스크의 모든 읽기 및 쓰기 작업의 최소 작업 단위가 된다.

B-Tree는 Binary가 아니라 Balanced-Tree이다. 만약에 Binary-Tree 였다면 하나의 노드당 자식 노드를 최대 2개 밖에 가질 수 없게 되고, 인덱스 검색이 상당히 비효율적일 것이다.

인덱스 페이지는 16KB 정도인데, 이정도면 자식 노드를 585개 저장할 수 있다. 만약 페이지 크기가 늘어나게 되면 자식 노드를 가질 수 있는 개수가 줄어들게 된다. 즉, 한번에 디스크에서 읽어올 수 있는 데이터 수가 줄어드는 것이다. (여러번 디스크 읽기를 해야 함)


B-Tree 깊이

B-Tree의 깊이는 MySQL에서 값을 검색할 때 몇 번이나 랜덤하게 디스크를 읽어야 하는지와 직결되는 문제다. 결론적으로 인덱스 키 값의 크기가 커지면 커질수록 하나의 인덱스 페이지가 담을 수 있는 인덱스 키 값의 개수가 적어지고, 그 때문에 같은 레코드 건수라 하더라도 B-Tree의 깊이가 깊어져서 디스크 읽기가 더 많이 필요하게 된다는 것을 의미한다.


카디널리티(기수성)

인덱스는 카디널리티가 높아야 잘 설계된 인덱스라고 할 수 있다. 카디널리티는 중복된 값의 수인데, 예를들어 주민번호 같은 것은 카디널리티 값이 놓고, 성별은 카디널리티 값이 낮다고 할 수 있다.

즉, 이렇게 중복된 값이 없을 수록 검색 대상이 줄어들기 떄문에 효율적이다.

index를 사용할 때 index를 사용하지 못하는 검색 조건은 어떤게 있나요?

NOT-EQUAL로 비교된 경우(<>, Not In, Not Betweenm Is Not Null)

  • WHERE column <> 'N' (<>는 != 를 의미함)
  • WHERE column NOT IN (1, 2, 3)
  • WHERE column IS NOT NULL

LIKE %??(앞부분이 아닌 뒷부분 일치) 형태로 문자열 패턴 비교

  • WHERE column LIKE '%승환'
  • WHERE column LIKE '_승환'
  • WHERE column LIKE '%승%'

스토어드 함수나 다른 연산자로 인덱스 컬럼이 변형된 후 비교된 경우

  • WHERE SUBSSTRING(colimn, 1, 1) = 'X'
  • WHERE DAYOFMONTH(column) = 1

NOT-DETERMINISTIC 속성의 스토어드 함수가 비교 조건에 사용된 경우

  • WHERE column = deterministic_function()

데이터 타입이 서로 다른 비교(인덱스 컬럼의 타입을 변환해야 비교가 가능한 경우)

  • WHERE char_column = 10 (char 타입의 컬럼과 숫자를 비교)

문자열 데이터 타입의 콜레이션이 다른 경우

  • WHERE utf8_bin_char_column = euckr_bin-char_column

다중 컬럼 인덱스가 어떤 조건에서 사용될 수 있고, 어떤 경우에는 절대 사용될 수 없는지?

  • 작업 범위 결정 조건으로 인덱스를 사용하지 못하는 경우

    • column_1 컬럼에 대한 조건이 없는 경우
    • column_1 컬럼에 비교 조건이 위의 인덱스, 사용 불가 조건 중 하나인 경우
  • 작업 범위 결정 조건으로 인덱스를 사용하는 경우

    • column_1 ~ column_(i - 1) 컬럼까지 동등 비교 형태(= or IN) 으로 비교
    • 크다 작다 형태(> or <)
    • LIKE로 좌측 일치 패턴(LIKE '승환%')
인덱스 삽입, 삭제, 수정, 검색 중에서 각각 어떤 특징이 있나요?

인덱스 키 추가

B-Tree에 저장될 위치가 정해지면 레코드의 키 값과 대상 레코드의 주소 정보를 B-Tree의 리프 노드에 저장한다. 만약 리프 노드가 꽉 차서 더는 저장할 수 없을 때는 리프 노드가 분리되어야 하는데, 이는 상위 브랜치 노드까지 처리의 범위가 넓어진다. 이러한 작업 탓에 B-Tree는 상대적으로 쓰기 작업에 비용이 많이 드는 것으로 알려져 있다.


인덱스 키 삭제

B-Tree 키 값이 삭제되는 경우는 상당히 간단한다. 해당 키 값이 저장된 B-Tree 리프 노드를 찾아서 그냥 삭제 마크만 하면 작업이 완료된다.


인덱스 키 변경

인덱스 키 값은 그 값에 따라 저장될 리프 노드의 위치가 결정되므로 B-Tree의 키 값이 변경되는 경우에는 단순히 인덱스상의 키 값만 변경하는 것은 불가능하다. B-Tree의 키 값 변경 작업은 먼저 키 값을 삭제한 후, 다시 새로운 키 값을 추가하는 형태로 처리된다.


인덱스 키 검색

INSERT, UPDATE, DELETE 작업을 할 때 인덱스 관리에 따르는 추가 비용을 감당하면서 인덱스를 구축하는 이유는 바로 빠른 검색을 위해서다.

인덱스 검색하는 작업은 B-Tree의 루트 노드부터 시작해 브랜치 노드를 거쳐 최종 리프 노드까지 이동하면서 비교 작업을 수행하는데, 이 과정을 트리 탐색 이라고 합니다.

  • 대표적으로 MySQL에서 검색 쿼리를 만들 때 Like %Keywork%를 사용하고 있다. 이처럼 %가 앞에 붙으면 인덱스를 타지 못하고 검색한다는 특징이 있다. B-Tree 인덱스는 앞부분이 100% 일치하는 경우에만 인덱스를 활용할 수 있다.
  • 인덱스의 키 값에 변형이 가해진 후 비교되는 경우에는 절대 B-Tree의 빠른 검색 기능을 사용할 수 없다. 즉, 함수나 연산을 수행한 결과로 정렬한다거나 검색하는 작업은 B-Tree의 장점을 이용할 수 없다.
  • InnoDB 테이블에서 지원하는 레코드 잠금이나 넥스트 키락이 검색을 수행한 인덱스를 잠근 후 테이블의 레코드를 잠그는 방식으로 구현되어 있다. 따라서 UPDATE, DELEETE 문장이 실행될 때 테이블에 적절히 사용할 수 있는 인덱스가 없다면 불필요하게 많은 레코드를 잠그게 된다.
복합 인덱스란 무엇인가요?

A, B 컬럼을 인덱스로 설정할 때 복합인덱스라 한다. 두 번째 컬럼은 첫 번째 컬럼에 의존해서 정렬되어 있다. 즉, 두 번째 컬럼 정렬은 첫 번째 컬럼이 똑같은 레코드에서만 의미가 있다.

해시 인덱스란 무엇이고 어떤 특징이 있나요?

해시 인덱스는 B-Tree 만큼 범용적이지 않지만 고유의 특성과 용도를 지닌 인덱스 가운데 하나다. 해시 인덱스는 동등 비교 검색에는 최적화되어 있지만 범위를 검색한다거나 정렬된 결과를 가져오는 목적으로는 사용할 수 없다. 일반적인 DBMS에서 해시 인덱스는 메모리 기반의 테이블에 주로 구현되어 있으며 디스크 기반의 대용량 테이블용으로는 거의 사용되지 않는다는 특징이 있다.

Primary Index vs Secondary Index 차이가 무엇인가요?

클러스터(Cluster)란 여러 개를 하나로 묶는다는 의미로 주로 사용되는데, 클러스터드 인덱스도 크게 다르지 않다. 인덱스에서 클러스터드는 비슷한 것들을 묶어서 저장하는 형태로 구현되는데, 이는 주로 비슷한 값들을 동시에 조회하는 경우가 많다는 점에서 착안된 것이다. 여기서 비슷한 값들은 물리적으로 인접한 장소에 저장되어 있는 데이터들을 말한다.

클러스터드 인덱스는 테이블의 프라이머리 키에 대해서만 적용되는 내용이다.프라이머리 키 값이 비슷한 레코드끼리 묶어서 저장하는 것을 클러스터드 인덱스라고 표현한다. 클러스터드 인덱스에서는 프라이머리 키 값에 의해 레코드의 저장 위치가 결정되며 프라이머리 키 값이 변경되면 그 레코드의 물리적인 저장 위치 또한 변경되어야 한다. 그렇기 때문에 프라이머리 키를 신중하게 결정하고 클러스터드 인덱스를 사용해야 한다.

클러스터드 인덱스는 테이블 당 한 개만 생성할 수 있다. 프라이머리 키에 대해서만 적용되기 때문이다, 이에 반해 non 클러스터드 인덱스는 테이블 당 여러 개를 생성할 수 있다.

InnoDB 테이블에서 세컨더리 인덱스는 실제 레코드의 저장 주소가 아니라 프라이머리 키 값을 저장하도록 구현되어 있다. 즉, 세컨더리 인덱스를 통해서 데이터를 조회하기 위해서는 세컨더리 인덱스 -> 프라이머리 인덱스 -> 실제 데이터로 접근해야 한다.

클러스터링 인덱스의 장점과 단점은 무엇인가요?
  • 장점

    • 프라이머리키로 검색할 때 처리 성능이 매우 빠름(특히 범위 검색할 때 매우 빠름)
    • 테이블의 세컨더리 인덱스가 프라이머리 키를 가지고 있기 때문에 인덱스로만 처리할 수 있는 경우가 많음(이를 커버링 인덱스라고 함)
  • 단점

    • 테이블의 모든 세컨더리 인덱스가 클러스터링 키를 갖기 때문에 클러스터링 키 값의 크기가 클 경우 전체적으로 인덱스의 크기가 커짐
    • 세컨더리 인덱스를 통해 검색할 때 프라이머리 키로 다시 한번 검색해야 하므로 처리 성능이 느림
    • INSERT 할 때 프라이머리 키에 의해 레코드의 저장 위치가 결정되기 때문에 처리 성능이 느림
    • 프라이머리 키를 변경할 때 레코드를 DELETE 하고 INSERT 하는 작업이 필요하기 때문에 처리 성능이 느림
B- Tree를 쓰면 왜 조회할 때 이득을 보는지 설명해주세요.

B-Tree는 Binary Tree가 아닌 Balanced Tree의 약자입니다. 즉, 하나의 부모 노드에 엄청나게 많은 자식 노드를 가질 수 있게 됩니다. 즉, B+ Tree를 사용하면 아무리 대용량의 데이터여도 깊이가 5 정도 밖에 나오지 않기 때문에 검색할 때 훨씬 효율적이라는 특징이 있습니다.

만약에 Binary-Tree 였다면 깊이가 말도 안되게 깊어지기 때문에 검색하기에 불가능한 수준이 될 것입니다. B-Tree에서 깊이는 디스크에서 읽어와야 하는 횟수와 연결되는 것이기 때문에 매우 중요한 개념이다.


Redis

Redis 특징에 간단하게 설명해주세요.

Redis는 key-value store NOSQL DB입니다. 싱글스레드로 동작하며 다양한 자료구조를 지원합니다. 데이터의 스냅샷 혹은 AOF 로그를 통해 복구가 가능해서 어느정도 영속성도 보장됩니다.

Redis vs Memcached 차이점에 대해서 설명해주세요.
  • Redis싱글 스레드 기반으로 동작하고, Memcached멀티스레드를 지원해서 멀티 프로세싱이 가능합니다.

  • Redis는 다양한 자료구조를 지원하고, Memcached는 문자열 형태로만 저장합니다.

  • Redis는 여러 용도로 사용할 수 있도록 다양한 기능을 지원합니다.

  • Redis는 스냅샷, AOF 로그를 통해서 데이터 복구가 가능합니다.

캐시를 사용할 때 주의해야할 점이 무엇일까요?

아무래도 캐시는 빠른 저장소고 필연적으로 사이즈가 작기 때문에 유용할 것 같은 데이터만 남겨두고 필요 없는 데이터는 적절히 삭제해서 공간을 확보할 수 있도록 신경써야 합니다.

레디스를 사용할 때 주의해야 할 점이 무엇일까요?

레디스에 너무 많은 데이터를 저장하면 OutOfMemoryException이 발생할 수 있기 때문에 TTL 같은 것을 설정해서 제거하거나 필요 없는 데이터를 제거하면서 메모리 관리할 수 있을 것 같습니다.

레디스가 싱글스레드여서 발생하는 문제점은 무엇이 있을까요?

싱글스레드 이기 때문에 오래 걸리는 작업을 하는 것을 조심해야 합니다.

레디스 샤딩이 무엇에 대해서 설명해주세요.
레디스 클러스터에 대해서 설명해주세요.

Lock

공유 잠금(Shared Lock)

공유 잠금이 설정되어 있는 동안 다른 트랜잭션이 데이터를 변경할 수 없다. 레코드나 간격을 읽을 때 다른 트랜잭션이 변경하지 못하게 하는 용도의 잠금 즉, 읽기 전용 작업

베타적 잠금(Exclusive Lock)

다른 트랜잭션이 읽거나 수정할 수 없다. 즉, 해당 트랜잭션에서 그 레코드나 간격을 변경하기 위해 획득해야 하는 잠금

  • 공유 잠금은 내가 읽는 동안 남들이 내가 읽고 있는 데이터를 변경하거나 삭제하지 못하게 하는 장치
  • 베타적 잠금은 내가 쓰기를 하는 동안 남들이 쓰지 못하게 하는 것
낙관적 락이랑 비관적 락 이 무엇인지 아는지?

낙관적 락(optimistic lock)

낙관적 락DB 충돌 상황을 개선할 수 있는 방법 중 2번 째인 수정할 때 내가 먼저 이 값을 수정했다고 명시하여 다른 사람이 동일한 조건으로 수정할 수 없게 만드는 것입니다.

DB 관점에서 락을 잡는 것이 아니라 애플리케이션 관점의 Lock 입니다. 즉, 업데이트 할 때마다 디비에 버전을 명시합니다. 같은 버전으로 업데이트를 진행한다면 실패하도록 만듭니다.


비관적 락(pessimistic lock)

비관적 락은 REPEATABLE READ, SERIALIZABLE 격리 수준에서만 사용 가능합니다. 비관적 락이란 트랜잭션이 시작될 때 Shared Lock, Exclusive Lock을 걸고 시작하는 방법입니다. 즉, Shared Lock을 걸게 되면 Write를 하기위해서는 Exclusive Lock을 얻어야 하는데 Shared Lock이 다른 트랜잭션에 의해서 걸려 있으면 해당 Lock을 얻지 못해 업데이트를 할 수 없습니다.

즉, 수정하기 위해서는 해당 트랜잭션을 제외한 모든 트랜잭션이 Commit 되어야 합니다.

낙관적락과 비관적락은 어느 상황에 사용해야 할까요?
  1. 낙관적 락: 낙관적 락은 트랜잭션을 필요로 하지 않습니다. 따라서 성능적으로 비관적 락 보다 좋습니다. 하지만 충돌이 나서 롤백을 해주어야 한다면 직접 수동으로 해줘야 한다는 특징이 있습니다.
  2. 비관적 락은 트랜잭션이 존재하기 때문에 충돌이 나도 롤백이 알아서 됩니다.

즉, 충돌이 많다면 비관적 락을 사용하는 것이 좋고, 충돌이 적다면 낙관적 락을 사용하는 것이 좋습니다.

MySQL InnoDB Lock 특징들에 대해서 설명해주세요.

InnoDB 스토리지 엔진은 레코드 기반의 잠금 기능을 제공하며, 잠금 정보가 상당히 작은 공간으로 관리되기 때문에 레코드 락이 페이지 락으로, 또는 테이블 락으로 레벨업되는 경우는 없다.

스크린샷 2022-03-20 오후 6 14 06

레코드 락

레코드 자체만을 잠그는 락이라고 한다. 다른 상용 DBMS와의 차이는 InnoDB 스토리지 엔진은 레코드 자체가 아니라 인덱스를 잠근다는 것이다. 인덱스가 없는 테이블이더라도 자동 생성된 클러스터 인덱스를 이용해 잠금을 설정한다.


갭 락

다른 DBMS와의 차이가 갭 락이다. 갭 락은 레코드 자체가 아니라 레코드와 바로 이니정한 레코드 사이의 간격만을 잠그는 것을 의미한다. 갭락의 역할은 레코드와 레코드 사이의 간격에 새로운 레코드가 생성되는 것을 제어하는 것이다.


넥스트 키 락

레코드 락과 갭 락을 합쳐 놓은 형태의 잠금을 넥스트 키 락이라고 한다. STATEMENT 포맷의 바이너리 로그를 사용하는 MySQL 서버에서는 REPEATABLE READ 격리 수준을 사용해야 한다. 변경을 위해 검색하는 레코드에는 넥스트 키 락 방식으로 잠금이 걸린다.

InnoDB의 갭 락이나 넥스트 키 락은 바이너리 로그에 기록되는 쿼리가 레플리카 서버에서 실행될 때 소스 서버에서 만들어 낸 결과와 동일 결과를 만들어내도록 보장하는 것이 주 목적이다. (넥스트 키 락과 갭 락으로 인해 데드락이 발생하거나 다른 트랜잭션을 기다리게 만드는 일이 자주 발생한다.)


자동 증가 락

MySQL에서는 자동 증가하는 숫자 값을 추출하기 위해 AUTO_INCREMENT 라는 컬럼 속성을 제공한다. AUTO_INCREMENT 컬럼이 사용된 테이블에 동시에 여러 레코드가 INSERT 되는 경우, 저장되는 각 레코드는 중복되지 않고 저장된 순서대로 증가하는 일련변호 값을 가져야 한다. InnoDB 스토리지 엔진에서는 이를 위해 내부적으로 AUTO_INCREMENT 락이라고 하는 테이블 수준의 잠금을 사용한다.

MySQL InnoDB 잠금과 인덱스의 연관관계에 대해서 설명해주세요.

InnoDB의 잠금은 레코드를 잠그는 것이 아니라 인덱스를 잠그는 방식으로 처리된다. 즉, 변경해야 할 레코드를 찾기 위해 검색한 인덱스의 레코드를 모두 락을 걸어야 한다.

만약에 UPDATE 쿼리 하나를 실행하기 위해서 인덱스를 통해서 250건의 데이터를 조회했다고 하면, 250건의 데이터가 모두 잠기게 된다. 즉, 하나를 업데이트 하기 위해서 250건의 데이터가 잠기게 되니 동시성이 떨어지게 된다.

그러면 만약에 테이블의 인덱스가 하나도 없다면 테이블을 풀 스캔하면서 UPDATE 작업을 하고, 이 과정에서 테이블에 있는 30여만 건의 모든 레코드를 잠그게 된다. 즉, MySQL InnoDB 에서는 인덱스 설계가 중요한 이유이다.

MySQL InnoDB에서 외래키의 Lock 관련 특징에 대해서 설명해주세요.

MySQL에서 외래키는 InnoDB 스토리지 엔진에서만 생성할 수 있으며, 외래키 제약이 설정되면 자동으로 연관되는 테이블의 컬럼에 인덱스까지 설정된다. 외래키가 제거되지 않는 상태에서는 자동으로 생성된 인덱스를 삭제할 수 없다.

  • 테이블의 변경(쓰기 잠금)이 발생하는 경우메나 잠금 대기가 발생한다.
  • 외래키와 연관되지 않은 컬럼의 변경은 최대한 잠금 대기를 발생시키지 않는다.

자식 테이블의 변경이 대기하는 경우

자식 테이블의 외래 키 컬럼의 변경(INSERT, UPDATE은 부모 테이블의 확인이 필요한데, 이 상태에서 부모 테이블의 해당 레코드가 쓰기 잠금이 걸려 있으면 해당 쓰기 잠금이 해제될 때까지 기다리게 하는 것이다.

자식 테이블의 외래키가 아닌 컬럼의 변경은 외래키로 인한 잠금 확장이 발생하지 않는다.


부모 테이블의 변경 작업이 대기하는 경우

부모 테이블에서 특정 row를 삭제하는 경우 이 쿼리는 자식 테이블의 레코드에 대한 쓰기 잠금이 해제될 때까지 기다려야 한다. 이는 자식 테이블이 생성될 때 정의된 외래키의 특성(ON DELETE CASCADE) 때문에 부모 레코드가 삭제되면 자식 레코드도 동시에 삭제되는 식으로 작동하기 때문이다.

물리적으로 외래키를 생성하면 자식 테이블에 레코드가 추가되는 경우 해당 참조키가 부모 테이블에 있는지 확인한다. 하지만 물리적인 외래키의 고려 사항은 이러한 체크 작업이 아니라 이러한 체크를 위해 연관 테이블에 읽기 잠금을 걸어야 한다는 것이다. 또한 이렇게 잠금이 다른 테이블로 확장되면 그만큼 전체적으로 쿼리의 동시 처리에 영향을 미친다.

데드락이 무엇인지 설명해주세요.
읽기 잠금과 쓰기 잠금의 차이는 무엇인가요?
  • 데이터를 읽기 전에 트랜잭션은 읽기 잠금을 설정한다. 데이터를 쓰기 전에는 쓰기 잠금을 설정한다.
  • 읽기 잠금은 쓰기 잠금과 충돌을 일으키며, 쓰기 잠금은 읽기 잠금 및 쓰기 잠금과 충돌을 일으킨다.
  • 트랜잭션은 같은 데이터 항목에 대하여 다른 트랜잭션과 충돌을 일으키는 잠금이 없을 경우에만 잠금을 설정할 수 있다.
  • 트랜잭션은 데이터 항목 x에서 쓰기 잠금이 없는 경우에만 x에서 읽기 잠금을 설정할 수 있다.
  • 트랜잭션은 데이터 항목 x에서 읽기 잠금과 쓰기 잠금이 없는 경우에만 x에서 쓰기 잠금을 설정할 수 있다.

Query

INNER JOIN과 OUTER JOIN의 차이를 말해주세요.

INNER 조인은 서로 교집합이 해당하는 부분만을 가져옵니다.

반면에 OUTER JOIN에는 LEFT OUTER JOIN, RIGHER OUTER JOIN이 있는데 LEFT OUTER JOIN이면 교집합 + 왼쪽에 해당하는 것들을 가져옵니다. 즉, 겹치는 것이 없더라도 NULL을 채워서 가져옵니다.

Union 과 JOIN 의 차이는 무엇인가요?
  • Union

    • 각 쿼리의 결과 합을 반환하는 합집합 (중복제거)
    • UNION ALL : 각 쿼리의 모든 결과를 포함한 합집합 (중복제거 안함)
  • Join

    • Inner join (교집합)
    • Outer Join (합집합)
쿼리가 실행되는 순서를 설명해주세요.
  • FROM - WHERE - GROUP BY - HAVING - SELECT - ORDER BY
드라이빙, 드라이븐 테이블이 무엇인지 설명해주세요.

SELECT A, B FROM A JOIN B ON A.aId = b.aId

만약 위와 같이 조인을 한다면 옵티마이저가 상황에 따라 드라이빙 테이블을 다르게 선택할 수도 있지만, 그런 경우가 아니라면 앞에 있는 A가 드라이빙 테이블, B가 드리븐 테이블이 된다.

MySQL은 정렬을 수행할 때 소트 버퍼를 사용하는데 무엇인지 설명해주세요.

MySQL은 정렬을 수행하기 위해 별도의 메모리 공간을 할당받아서 사용하는데, 이 메모리 공간을 소트 버퍼(Sort Buffer)라고 한다. 소트 버퍼는 정렬이 필요한 경우에만 할당되며, 버퍼의 크기는 정렬해야 할 레코드의 크기에 따라 가변적으로 증가하지만 최대 사용 가능한 소트 버퍼 공간은 sort_buffer_size 라는 시스템 변수로 설정할 수 있다. 소트 버퍼를 위한 메모리 공간은 쿼리의 실행이 완료되면 즉시 시스템으로 반납한다.


Etc

데이터베이스 정규화에 대해서 설명해주세요.
  1. 1차 정규화 : 하나의 컬럼에는 하나의 값만 들어가야 한다. ,를 구분해서 값을 넣지 않음

  2. 2차 정규화 : 식별자(기본키)가 여러 개 일 때 식별자(기본 키) 일부에만 종속되는 어트리뷰트는 제거해야 한다.

  3. 3차 정규화 : 식별자(기본키)가 아닌 속성에 다른 속성에 종속되는 어트리뷰트가 존재하면 안된다.

  4. BCNF(Boyce-Codd) 정규형

  • 여러 후보 키가 존재하는 릴레이션에 해당하는 정규화 내용이다. 복잡한 식별자 관계에 의해 발생하는 문제를 해결하기 위해 제 3 정규형을 보완하는데 의미가 있다. 비주요 애트리뷰트가 후보키의 일부를 결정하는 분해하는 과정을 말한다.
  • 각 정규형은 그의 선행 정규형보다 더 엄격한 조건을 갖는다.
  • 모든 제 2 정규형 릴레이션은 제 1 정규형을 갖는다.
  • 모든 제 3 정규형 릴레이션은 제 2 정규형을 갖는다.
  • 모든 BCNF 정규형 릴레이션은 제 3 정규형을 갖는다.
  • 수많은 정규형이 있지만 관계 데이터베이스 설계의 목표는 각 릴레이션이 3NF(or BCNF)를 갖게 하는 것이다.
언두 영역이란 무엇인가요?
  • 언두 영역은 UPDATE 문장이나 DELETE 문장으로 데이터를 변경했을 때 변경되기 전의 데이터(이전 데이터)를 보관하는 곳입니다.
MVCC 란 무엇인가요?

일반적으로 레코드 레벨의 트랜잭션을 지원하는 DBMS가 제공하는 기능이며, MVCC의 가장 큰 목적은 잠금을 사용하지 않는 일관된 읽기를 제공하는 데 있습니다. InnoDB 스토리지 엔진은 트랜잭션이 ROLLBACK될 가능성에 대비해 변경되기 전 레코드를 언두 공간에 백업해두고 실제 레코드 값을 변경합니다. 이러한 방식을 MVCC 라고 합니다.

데이터베이스 키
  • 슈퍼키 : 테이블에서 각 행을 유일하게 식별할 수 있는 하나 또는 그 이상의 속성들의 집합. 슈퍼키는 유일성만 만족하면 슈퍼키가 될 수 있다.(최소성은 만족하지 않습니다.)
  • 후보키 : 테이블에서 각 행을 유일하게 식별할 수 있는 최소한의 속성들의 집합. 유일성, 최소성을 동시에 만족해야 한다.
  • 기본키(PK: Primary Key):
    • 튜플을 대표하도록 선정된 후보키입니다.
    • 후보키 중에서 하나를 기본키로 선택하여 지정합니다.
  • 외래키(foreign key)
    • 특정 릴레이션의 기본키를 참조하는 속성 집합
    • 기본키와 외래키는 릴레이션간의 연관성을 표현
    • 의미적 연관성이 있음에도 다른 릴레이션으로 분류된 튜플 사이의 연결고리 역할

key

복제(Replication)가 무엇인지 설명해주세요.

1212

  • 복제는 2대 이상의 MySQL 서버가 동일한 데이터를 담도록 실시간으로 동기화하는 기술

  • 일반적으로 MySQL 복제에는 INSERT, UPDATE와 같은 쿼리를 이용해 데이터를 변경할 수 있는 MySQL 서버와 SELECT 쿼리로 데이터를 읽기만 할 수 있는 MySQL 서버로 나뉜다.

  • 전자를 마스터(master) = 쓰기 작업 후자를 슬레이브(Slave) = 읽기 작업라고 함

마스터 슬레이브가 무엇인지 설명해주세요.

마스터(Master)

  • MySQL의 바이너리 로그가 활성화되면 어떤 MySQL 서버든 마스터가 될 수 있다.
  • 쓰기 전용

슬레이브(Slave)

  • 마스터 서버가 바이너리 로그를 가지고 있으면 슬레이브 서버는 릴레이 로그를 가지고 있다.

  • 읽기 전용

  • 슬레이브 서버의 I/O 스레드는 마스터 서버에 접속해 변경 내역을 요청하고, 받아 온 변경 내역을 릴레리 로그에 기록한다. 슬레이브 서버의 SQL 스레드가 릴레이 로그에 기록된 변경 내역을 재실행 함으로써 슬레이브 데이터를 마스커와 동일한 상태로 유지함


슬레이브는 하나의 마스터만 설정 가능

  • MySQL 복제에는 하나의 슬레이브는 하나의 마스터만 가질 수 있다.

  • 하나의 마스터에 N개의 슬레이브가 일반적인 형태


마스터와 슬레이브의 데이터 동기화를 위해 슬레이브는 읽기 전용으로 설정

  • 슬레이브는 읽기 전용으로 하기

슬레이브 서버용 장비는 마스터와 동일한 사양이 적합

  • 오히려 마스터보다 슬레이브 사양이 더 좋아야 함 (자주 변경이 있는 마스터 서버라면 특히 더!)

복제가 불필요한 경우에는 바이너리 로그 중지

  • 바이너리 로그를 작성하기 위해 MySQL은 큰 자원을 소모함
Scale Out vs Scale Up 이 무엇인지 설명해주세요.

Scale Out

  • 기존의 서버와 같은 사양 또는 비슷한 사양의 서버 대수를 증가시키는 방법으로 처리 능력을 향샹시키는 것을 말한다. 스케일 아웃 방식을 "수평 스케일"이라고 부르기도 하고, 확장이 스케일 업보다는 다소 유연하다.
  • 1’의 처리 능력을 가진 서버에 동일한 서버 4대를 더 추가하여, 총 ‘5’의 처리 능력을 만드는 것이다. 서버가 여러 대가 되기 때문에 각 서버에 걸리는 부하를 균등하게 해주는 ‘로드밸런싱’이 필수적으로 동반되어야 한다.
  • 즉, 여러 대의 서버가 분산(나누어) 처리할 수 있도록 요청을 나누어주는 서비스

Scale Up

  • 성능이나 용량 증강을 목적으로 하나의 서버에 디스크를 추가하거나 CPU나 메모리를 업그레이드시키는 것을 말한다. 하나의 서버의 능력을 증강하기 때문에 수직 스케일링(vertical scaling)이라고도 한다.
  • 즉, 기존의 하드웨어를 보다 높은 사양으로 업그레이드하는 것을 말한다.
바이너리 로그가 무엇인가요?
  • 바이너리 로그 파일은 데이터베이스 변경(테이블 생성, 삭제 등) 및 테이블 변경(insert, update, delete ..) 사항들이 기록되는 바이너리 형태의 파일입니다.
  • 바이너리 로그의 내용을 기반으로 하여 마스터 서버에서 슬레이브 서버로 데이터를 전송하고 복제할 수 있으며, 데이터를 복원하는데 사용하기도 합니다.
데이터베이스에서 가용성을 보장하기 위해 어떤방식을 쓰나요?

Master, Slave 로 나눠서 Replication 할 수 있습니다.

Master 에서 Slave 로 Replication 하면 왜 가용성이 좋아지나요?

마스터에서 쓰기 작업을 하고, 슬레이브에서 읽기 작업을 하면서 동시성 처리 보장하면서 읽기 성능을 향상 시킬 수 있습니다.

파티셔닝이란 무엇인가요?

하나의 DBMS가 많은 테이블을 관리 하기 힘들어지고, 속도도 저하

=> 파티셔닝 등장

  • 파티셔닝 : 큰 테이블이나 인덱스를 관리하기 쉬운 단위로 분리하는것
  • 장점
    • 특정 DML과 쿼리의 성능을 향상시키며, Data Write 환경에서 효율적이다
    • 많은 Insert가 있는 OLTP 시스템에서 특히 경합을 더 줄일 수 있다
RDB vs NoSQL 차이점에 대해서 설명해주세요.

RDBMS

  • RDBMS는 데이터베이스를 이루는 객체들의 릴레이션을 통해서 데이터를 저장하는 데이터베이스입니다. SQL을 사용해 데이터의 저장, 질의, 수정, 삭제를 할 수 있으며 데이터를 효율적으로 보관하는 것을 목적으로 하고 구조화가 굉장히 중요합니다.

  • 장점으로는 명확한 데이터 구조를 보장하고, 중복을 피할 수 있습니다.

NOSQL

  • NOSQL은 RDBMS에 비해 자유로운 형태로 데이터를 저장합니다. 또한 수평확장을 할 수 있고 분산처리를 지원합니다. 다양한 형태의 NOSQL 데이터베이스가 있고, 대표적으로 key-value store, bigtable, dynamo, document db, graph db 등이 있습니다.

  • 둘은 대체될 수 있는 것이 아니고, 각각 필요한 시점에 적절히 선택해서 사용해야 합니다. 둘 다 같이쓰는 상호보완적인 존재가 될 수도 있습니다.