[sequelize] transaction

tastestar·2022년 5월 20일
0

Database

목록 보기
16/18

Transaction

프로젝트 진행과정 중에, 하나의 API에서 데이터베이스에 여러개 접근해야하는 일이 생겼습니다.

await todo_list.update({is_complete : true},
                { where : { id : req.query.id,
                    is_complete : 0
                }})

await damage_log.increment(
                { log : 0.5 },
                { where : {
                    user_id : req.body.user_id,
                    raid_id : req.body.raid_id}})
            await raid.increment(
                { hit_damage : 0.5},
                { where : {
                    id : req.body.raid_id}})
            await monster.decrement(
                { hp : 0.5},
                { where : {
                    id : req.body.monster_id}})

일일히 then.catch 를 하려다보니 코드가 길어지고.. 이걸 어떻게 깔끔하게 정리할 수 있을지 생각하던 중에 sequelize에 transaction이라는 걸 알게되었습니다.

trnasaction 란?

트랜잭션이란 하나의 작업을 수행하는데 필요한 데이터베이스 연산을 모아놓은 것입니다. 데이터베이스에서 논리적인 작업의 단위여고 데이터베이스에서 장애가 발생했을 때 데이터를 복구하는 작업의 단위입니다. 트랜잭션의 모든 명령문이 완벽하게 처리되거나 하나도 처리되지않아야 데이터베이스가 모순이 없는 일관된 상태를 유지할 수 있습니다.

1. 트랜잭션의 특정

(1) 원자성

트랜잭션을 구성하는 연산들은 모두 정상적으로 실행되거나 하나도 실행되지않아야합니다. 만약 트랜잭션을 수행하다 장애가 발생하면 지금까지 실행한 연산 처리를 모두 취소하고 트랜잭션 이전 상태로 되돌려 원자성을 보장해야합니다.

(2) 일관성

트랜잭션이 수행되기 전과 후에 데이터가 일관된 상태로 유지되어야합니다. 트랜잭션 수행 도중에는 일시적으로 일관된 상태가 아닐 수 있지만 수행 후에는 일관된 상태가 됩니다.
이 특징이 바로 일관성입니다.

(3) 고립성

현재 수행 중인 트랜잭션이 완료될 때까지 트랜잭션이 생성한 중간 연산 결과에 다른 트랜잭션들이 접근할 수 없습니다.

(4) 지속성

트랜잭션이 성공적으로 완료된 후, 데이터베이스에 반영된 결과는 어떠한 경우에도 손실되지않고 영구적이어야 합니다. 시스템 장애가 생기더라도 트랜잭션 작업 결과가 유지되어야 합니다. 이러한 특징이 바로 지속성입니다.

2. 트랜잭션 연산

3. sequelize transaction 적용

시퀼라이즈는 트랜잭션을 2가지 방법으로 제공합니다.

  • unmanaged transaction
const t = await sequelize.transaction();
try(
await todo_list.update({is_complete : true},
                { where : { id : req.query.id,
                    is_complete : 0
                },
                 transaction : t
})

await damage_log.increment(
                { log : 0.5 },
                { where : {
                    user_id : req.body.user_id,
                    raid_id : req.body.raid_id}
                },
			transaction : t
)
            await raid.increment(
                { hit_damage : 0.5},
                { where : {
                    id : req.body.raid_id}},
            	transaction : t
            )
			await t.commit();
)
catch (err) {
	await t.rollback();
}

umanaged는 일일히 commit과 rollback 위치를 지정하는 방법입니다.

  • managed transaction
try {
	await sequelize.transaction( async (t) => {
    	await todo_list.update({is_complete : true},
                { where : { id : req.query.id,
                    is_complete : 0
                },
                 transaction: t, 
                })

            await raid.increment(
                { hit_damage : 0.5},
                { where : {
                    id : req.body.raid_id}},
            	transaction: t, 
            )
            await monster.decrement(
                { hp : 0.5},
                { where : {
                    id : req.body.monster_id}},
            	transaction: t, 
            )
    })
}
catch (err) {
}

자동으로 트랜잭션이 실행됩니다
여기에서는 commit(), rollback()을 직접 사용해서는 안됩니다.

출처

https://crmrelease.tistory.com/99
https://overcome-the-limits.tistory.com/528
https://merrily-code.tistory.com/214
https://velog.io/@leesilverash/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EC%82%AC%EC%9A%A9%EB%B2%95-sequelize

profile
책을 읽고 공부하는 걸 기록해두는게 재밌는 개발자 입니다!

0개의 댓글