회사에서 개발을 하던 도중 한 테이블의 특정 컬럼이 잘못되었다는 것을 발견했었다. 해당 컬럼이 잘못 들어간 것을 확인하고 나서 바로잡기 위해서 migration 스크립트를 만들어서 별도의 프로세스로 돌렸는데 DEAD_LOCK이 발생하면서 트랜잭션이 깨지는 문제가 발생하였다.
프로세스 A : 초단위로 a, b, c 테이블에 insert or update 하는 역할 + temp table 을 create 하고 데이터를 insert 했다가 d 테이블에 insert 하는 역할
프로세스 B : a 테이블을 처음부터 N개씩 읽고 필요한 데이터를 b에 insert or update 하는 역할
-> b 테이블에서 잘못 들어간 특정 컬럼을 바로잡기 위해서 프로세스 B를 돌리다가 DEAD_LOCK이 발생하면서 프로세스 A의 트랜잭션이 깨지는 문제가 발생
원인
1. transaction 안에서 create / delete 테이블을 함.
2. transaction 안에서 성능 개선을 위해 Promise.all 을 사용함
해결
1. transaction 안에서 create / delete 테이블을 하지 않게 하였다. create table, alter table, drop table 등의 DDL, DCL 은 auto commit이 되기 때문에 typeORM에서 하나의 트랜잭션으로 묶었다 한들 중간에 커밋된다.
2. typeORM 를 사용할 때 Promise.all로 insert/update/delete를 하면 안 된다. 퍼포먼스 때문에 promise.all로 처리하려고 했는데 promise.all을 사용하면 안 된다고 한다. (https://github.com/typeorm/typeorm/issues/1014)
export default class Test {
constructor(private connection: Connection) {}
async writeDB(a, b, c): Promise<void> {
await this.connection.transaction(async (entityManager) => {
try {
await entityManager.createQueryBuilder().insert().into(a).values(~~~).updateEntity(false).execute();
await entityManager.createQueryBuilder().insert().into(b).values(~~~).updateEntity(false).execute();
await entityManager.createQueryBuilder().insert().into(c).values(~~~).updateEntity(false).execute();
} catch(err) {
console.error(`db error`, err);
throw err;
}
});
}
}
}
'개발 이슈' 카테고리의 다른 글
sharp: Cannot find module '../build/Release/sharp-linuxmusl-x64.node' (0) | 2023.06.26 |
---|---|
AWS EKS 클러스터에 접속해서 특정 작업 또는 정보를 확인하기 (0) | 2023.05.13 |
The project you were looking for could not be found or you don't have permission to view it. 에러 (0) | 2023.05.08 |
API를 만들때는 속도도 중요하지만 Response size도 생각하자 (0) | 2023.04.11 |
모르는거 모아두는 곳 (0) | 2023.02.12 |