Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: [DB] MySQL과 함께 동시성 제어 알아보기 #19

Merged
merged 3 commits into from
Jan 16, 2025
Merged

Conversation

hjch0211
Copy link
Contributor

@hjch0211 hjch0211 commented Jan 2, 2025

개요

  • 2주차 내용입니답. 해외갈 일있어서 미리 날려요
  • 간단하게 MySQL과 동시성 제어를 정리해보았습니다.
  • 차주에 좀 더 세세하게 해볼 것 같습니답

체크리스트

  • PR 제목을 Commit Convention에 맞게 작성
  • Label 추가
  • 리뷰어 팀 등록했나요?
  • Assignee 등록했나요?


table lock : 기본적인 잠금. `동시성이 낮지만 가장 낮은 오버헤드`를 가진 전략. lock의 범위가 테이블. 성능 향상을 위해 일부 동시 쓰기 작업을 허용하기도 함

low lock : 스토리지 엔진에서 구현. `동시성이 높지만 가장 높은 오버헤드`를 가진 전략. lock의 범위가 행.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

row lock 오타 같아요

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정했습니답

MySQL은 지금까지 많은 스토리지 엔진을 제공했지만, 요즘은 InnoDB가 최고의 표준이고 권장되는 엔진임. 다음의 트랜잭션 기본 요소는 InnoDB의 구현을 기반함

- AUTOCOMMIT : 트랜잭션이 아닌 단일 쿼리는 트랜잭션으로 처리되어 즉시 커밋
- explicit locking과 implicit locking : InnoDB는 기본적으로 2-phase locking을 사용하여 lock의 획득과 해제를 관리. 이 때 lock 설정을 우리가 쿼리를 통해 작성해줄 필요가 없음(implicit locking). 또한 InnoDB의 경우 "LOCK TABLE"과 같은 명령을 지원하여 명시를 할 수 있음(Explicit locking)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mysql은 2PL을 사용하지 않나요? 그럼 어떻게 ACID를 보장할 수 있나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MySQL은 스토리지 엔진을 InnoDB를 사용하고, InnoDB는 기본적으로 2PL을 사용한다고 합니다.


InnoDB는 MVCC를 사용하여 높은 동시성을 구현하고 SQL 표준 격리를 모두 구현

InnoDB는 다른 엔진과 다른 독특한 인덱싱을 구현. 따라서 키 검색을 빠르게 할 수 있음. 하지만 보조 인덱스에 기본 키 열을 포함하고 있어, `키의 값이 크면 인덱스도 커짐`. 따라서 키값은 작게 관리가 필요 -> PK는 increament로 구현하고 필요하다면 `surrogate key를 만들어 6자리 한영조합 키를 만드는게 좋다고 생각`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보조 인덱스에 기본 키 열을 포함하고 있어, 키의 값이 크면 인덱스도 커지는 동작이 다른 db에서는 일반적이지 않은건가요? 기존의 db들과 비교하여 무엇이 다른지 궁금해요!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한 번 훑어보려고 하다가 일이 커져버렸네요ㅠㅠ... 인덱스 부분은 특징만 언급하고 넘어갈까 했었습니다. 정리해서 찾아본 결과 추가해두었어요. 정확한 내용찾느라 시간이 많이 지났네요ㅠ


MySQL은 Client -> DB서버(연결 핸들링, 파서, 옵티마이저) -> 스토리지 엔진으로 구성

각 클라이언트의 연결은 단일 스레드를 할당하여 진행. 서버는 미리 스레드 캐시(스레드 풀과 비슷하지만 다름)를 유지 관리함
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

스레드 풀은 기존 스레드 재사용, 스레드 캐시는 기존 메모리 재사용 이렇게 이해하면 될까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

스레드 캐시는 책의 뒷편에 나와있었네요. 추가 설명해두었습니다.

책에서 설명하기는 스레드 캐시는 이미 사용된 스레드를 캐시에 저장해두었다가 빼서 쓰는 방식이라고 하네요

3. REPEATABLE READ : Non-reapeatable read 방지. MySQL에서는 스토리지 엔진에서 구현됨(MVCC). `트랜잭션이 시작된 스냅샷 데이터`를 기준으로 조회를 수행. phantom read는 막지 못함. MySQL의 방식
4. SERIALIZABLE : 읽는 행과 함께 관련된 행까지 락을 걸어 phantom read까지 막음. 오버헤드가 많아 데이터 무결성이 엄격하게 지켜져야 하는 곳에서 사용

데드락이 발생하면 대부분의 DBMS는 타임아웃이나 교착 상태 탐지를 이용해 데드락에 대응함. 스토리지 엔진마다 데드락에 대응하는 방법이 다르며 MySQL에서 많이 사용하는 InnoDB의 경우 순환 종속성 탐지를 통해 데드락을 방지하고, 발생하면 롤백을 시키는 방법을 사용
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

데드락이 발생하면 어떤 식으로 롤백을 하나요?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

책에서는 '배타적 행 락'이 가장 적은 트랜잭션을 롤백한다고 합니다. 쉽게 말하면 가장 롤백하기 쉬운 트랜잭션을 롤백시킨다고 합니다.

Copy link
Contributor

@chaeyeon0130 chaeyeon0130 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

db마다 격리 수준에 차이가 있다니.. 잘 확인하고 사용해야겠네요
아주 유익한 내용 정리해주셔서 감사합니다! 2편이 있다면, 각 격리 수준이 해결한 문제와 해결하지 못한 문제들에 대해 더 자세히 알고 싶네요!:)

Comment on lines +53 to +59
### MVCC(Multiversion Concurrency Control)

서로 다른 트랜잭션에서 행의 다중버전(non-repeatable read 문제의 행)을 처리하기 위해 사용. MySQL뿐만아니라 오라클, PostgreSQL 등에서 사용(표준이 없어 차이는 있음)

트랜잭션마다 id를 할당하고, 시작된 시점의 데이터를 스냅샷으로 저장하여 읽기 작업을 수행. undo로그와 redo로그도 작성하여 롤백이나 스냅샷 생성에 도움을 줌

MVCC는 row lock의 변형이라고 생각하면 됨. 대부분의 경우 lock을 걸 필요가 없어 오버헤드가 낮고, repeatable read와 read commited 격리 수준에서만 작동
Copy link
Contributor

@chaeyeon0130 chaeyeon0130 Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serializable 수준에서는 mvcc를 사용하지 않는 걸까요? 둘다 읽기 부정합을 해결하기 위한 격리 수준과 수단 같아서 적합한 조합이지 않나 싶어서요!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 책에 내용이 나와있네요. serializable 수준에서는 개별 행이 아닌 반환하는 모든 행을 잠기 때문에 호환이 안된다고 합니다.


MySQL은 지금까지 많은 스토리지 엔진을 제공했지만, 요즘은 InnoDB가 최고의 표준이고 권장되는 엔진임. 다음의 트랜잭션 기본 요소는 InnoDB의 구현을 기반함

- AUTOCOMMIT : 트랜잭션이 아닌 단일 쿼리는 트랜잭션으로 처리되어 즉시 커밋
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 오토커밋은 보통 디폴트가 활성화인가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 맞습니답. 오토커밋이라는 내용은 단일 쿼리를 내부적으로 트랜잭션으로 바꿔서 처리한다는 이야기였어요.

SELECT * FROM customer;
->
TRANSACTION;
SELECT * FROM customer;
COMMIT;

@hjch0211
Copy link
Contributor Author

hjch0211 commented Jan 8, 2025

제가 해외가서 밤에 해볼까했는데 생각보다 너무 힘드네요ㅠㅠㅠ 1주일만 미뤄서 화요일까지 답변 달겠습니다.. SQL 공부중이라 더 좋고 명확한 답변을 드리려면 공부가 필요할 것 같아요...😂


InnoDB는 MVCC를 사용하여 높은 동시성을 구현하고 SQL 표준 격리를 모두 구현

InnoDB는 다른 엔진과 다른 독특한 인덱싱을 구현. 따라서 키 검색을 빠르게 할 수 있음. 하지만 보조 인덱스에 기본 키 열을 포함하고 있어, `키의 값이 크면 인덱스도 커짐`. 따라서 키값은 작게 관리가 필요 -> PK는 increament로 구현하고 필요하다면 `surrogate key를 만들어 6자리 한영조합 키를 만드는게 좋다고 생각`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uuid를 기본키로 사용하는 것에 대해서는 어떻게 생각하시나요?

Copy link
Contributor Author

@hjch0211 hjch0211 Jan 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위 내용에 따르면 UUID는 36자의 문자열을 저장하므로 좋지 않을 것이라 생각합니답. 다른 관점에서는 (요구사항에 따라 결국 다를 것 같긴해요), UUID를 PK로 저장하면 매 번 참조하고 있는 테이블은 똑같이 큰 값을 저장해야 하므로 불필요하다고 생각합니다. PK는 increment로 두고, 클라이언트용 대체키를 36자가 아닌 더 짧은 값을 넣어도 되지 않을까합니다. 개인적으로 일단 6자리 한영 조합만 해도 20억인가 30억인가 했으니 충분하지 않을까 생각합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants