본문 바로가기

전체 글

(11)
[nestjs] transaction 라이브러리 분석하기 - 3 이번 글에서는 아래의 목적을 달성하기 위해 typeorm-transacional이 해둔 작업을 보겠습니다. 트랜잭션을 위한 코드를 wrapper에게 완전히 위임하고, 서비스 계층에선 비지니스 로직에만 집중하고 싶다. 아래 3개의 화두가 중요합니다. typeorm-transactional은 트랜잭션을 위한 코드를 넣어둔 wrapper를 어떻게 구현했는지? myEntityManager은 어디서 어떻게 얻어왔는지? typeorm-transactional에서 트랜잭션 안에서 또 다른 트랜잭션(=nested transaction)을 어떻게 생성하는지? 아래 예시코드를 보면 메서드에 @Transacional 데코레이터가 붙어 있습니다. export class UserService { constructor( @Inj..
[nestjs] transaction 라이브러리 분석하기 - 부록 이 부록은 typeorm의 repository.extend() 메서드를 분석, 수정하여 typeorm에 PR 날린 과정을 담고 있습니다. typeorm 깃허브 예제를 보면, 아래와 같이 repository.extend 메서드를 이용하여 customRepository를 만듭니다. const Sample33CustomRepositoryConnection = new DataSource({ type: "sqlite", database: "./temp/sqlitedb-1.db", logging: true, synchronize: true, }) export const PostRepository = Sample33CustomRepositoryConnection.getRepository( Post, ).extend(..
[transaction 동시성 문제⑥] 테스트 이 시리즈는 데이터베이스 동시성 문제를 겪은 경험과 그 해결책에 대한 내용이 담겨 있습니다. 해결-2 에서는 트랜잭션 동시성 문제를 해결하였습니다. 하지만 데드락이 발생하는 문제를 겪었습니다. 그래서 데드락-2 에서는 데드락 문제를 해결하는 여러 방법에 대해 고민해보았고, 결국 쿼리 순서를 바꿔서 해결하는 방법을 선택했습니다. 이번 글에서는 이 해결방법이 실제로 잘 적용되는지 확인해보겠습니다. 먼저 Cabinet 엔터티의 정의입니다. @Version 어노테이션 덕분에 (속성 값 변경시) version 값이 자동으로 +1 증가됩니다. @Entity @Table(name = "CABINET") @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter publi..
[nestjs] transaction 라이브러리 분석하기 - 2 이 시리즈는 typeorm-transactional 라이브러리를 분석하게 된 계기와 분석한 내용이 담겨있습니다. 이전 글에서는 '중복을 제거 하겠다'는 목적을 좀 더 아래와 같이 구체화 하였습니다. wrapper에게 트랜잭션을 위한 코드를 완전히 위임하고, Service 계층에선 비지니스 로직에만 집중하고 싶다. Service 계층에서 dataSource나 repository 객체들을 DI 받아서 사용하고 싶다. 이렇게 DI 받은 객체들이 실질적으로 사용하는 queryRunner는 모두 동일했으면 좋겠다. 또한, 이러한 목적을 이룰 수단인 wrapper와 cls에 대한 개념을 배경지식으로 알게 되었습니다. 이번 글에서는 typeorm-transactional에서 이러한 배경지식을 이용하여 우리의 목적을 ..
[transaction 동시성 문제⑤] 데드락 - 2 이 시리즈는 데이터베이스 동시성 문제를 겪은 경험과 그 해결책에 대한 내용이 담겨 있습니다. 이전 글에서는 해결방법-2 글에서 발생한 데드락이 왜 발생한 것인지 추측해보았습니다. 하지만 틀린 추측이었습니다. 이번 글에서는 데드락이 왜 발생했는지 정확한 원인을 짚어보겠습니다. 일단 외래키 제약에 대해 알아보겠습니다. mysql 공식문서에서는 외래키 제약을 이렇게 정의합니다. MySQL supports foreign keys, which permit cross-referencing related data across tables, and foreign key constraints, which help keep the related data consistent" help keep the related data..
[nestjs] transaction 라이브러리 분석하기 - 1 이 시리즈는 typeorm-transactional 라이브러리를 분석하게 된 계기와 분석한 내용이 담겨있습니다. 이전 글에서는 typeorm에서 트랜잭션을 관리하는 방법을 간단히 설명하였습니다. 그리고 typeorm에서 트랜잭션을 관리할 때 단점으로 중복이 많이 발생함을 지적하였습니다. 마지막으로 그에 대한 해결책 설계와 구현 실패, 그리고 typeorm-transactional 라이브러리를 소개했습니다. 이번 글에서는 중복을 제거하겠다는 우리의 목적을 구체화하고, 이 목적을 달성할 수 있는 방법에 대해 알아보겠습니다. typeorm에서 트랜잭션을 관리할 때의 단점으로 2가지를 제시했었습니다. 비지니스 로직을 위한 코드가 아닌, 트랜잭션을 위한 코드가 추가됩니다. 그리고 여러 군데에 걸쳐서 중복이 발생하..
[transaction 동시성 문제④] 데드락 - 1 이 시리즈는 데이터베이스 동시성 문제를 겪은 경험과 그 해결책에 대한 내용이 담겨 있습니다. 이전 해결방법-2 글에서는 해결방법-1 보다 발전된 낙관적 락 구현 방법을 얘기했습니다. 하지만 이 방법은 치명적인 단점인 데드락 발생 문제가 있습니다. 이번 글에서는 데드락이 왜 발생했는지 원인과 시나리오를 살펴보겠습니다. 먼저 데드락이 무엇인지 간단하게 살펴보겠습니다. 멀티쓰레드 환경에서 공유자원이 있을 때, 동시성 문제가 발생할 수 있습니다. 이 문제를 예방하기 위해 lock 기법을 도입할 수 있습니다. 공유자원에 접근하기 위해선 lock이라는 특수한 자원을 획득해야 하고, 공유자원에 대한 읽기, 수정 작업이 끝나면 lock을 내려 놓습니다. 이렇게 한 쓰레드가 lock을 획득하면, 이 쓰레드가 lock을 ..
[transaction 동시성 문제③] 해결 - 2 이 시리즈는 데이터베이스 동시성 문제를 겪은 경험과 그 해결책에 대한 내용이 담겨 있습니다. 해결 방법 - 2 lentHistory 테이블은 그대로 둡니다. lent_history_id user_id cabinet_id started_at ``` cabinet에 version 컬럼, activeLentCount 컬럼 추가합니다. cabinet_id status version max_user active_lent_count ``` 이렇게 테이블을 수정하고 기존 동시성 문제 시나리오를 다시 살펴보겠습니다. cabinet 동시성 문제 1 전제: N번 공유사물함은 최대 3명이 빌릴 수 있습니다. 현재 2명이 대여 중입니다. lent_history_id user_id cabinet_id started_at ```..