[Sequelize] error : transaction

Vorhandenheit ·2022년 6월 8일
0

Database

목록 보기
18/28

Error : transaction

1. try , catch 가 되지않음

transaction 을 사용한 이유는 여러개의 update를 돌릴 때, 하나가 실패했을 경우 원래대로 모두 다 돌리기위해 사용했지만 예상과는 다르게 update가 돌아가지않았습니다. 심지어 없는 id값을 집어넣어도 동작한다는 걸 확인하게 되었습니다

우선 update와 destroy는 try catch를 사용해서 error를 잡을려고 한다면 잡히지않습니다. 왜냐하면 update가 실패하면 반환값을 0을 보내기 때문입니다.

2. transaction의 lock

https://blog.sapzil.org/2017/04/01/do-not-trust-sql-transaction/

문제를 알아챈뒤에 이것저것 해결방법을 찾아보았는데, 찾지못했습니다.
단지 지금 위에서는 Executing 후 문자열이 따라오지만, 이것외에도 default가 적용되어서, error가 뜰경우 롤백하는게 아니라 트랜잭션이 나뉘어서 실행되는걸 확인했습니다.

SERIALIZABLE로 설정해봤다가 자동커밋을 꺼보기도했지만 해결돼지않았습니다.

...

여기까지와서 한가지 결론에 도달했습니다. transaction을 쓰지말자! , 싹지우고 나니 server에서 돌아갑니다. 단 update가 도중에 잘못될 경우 원래대로 돌아가지않지만요, 클라이언트에서 값을 제대로 보내야지요!
덕분에 그래도 이런 기술이있다는 걸 알게되었고, update와 destroy가 다른 method와 다르다는 점, 그리고 한 http에 여러개의 동작을 하면 안된다는 점, 락을 설정하는게 있다는 점, 다음에는 다르게 해야겠다는 걸 얻었습니다.

update({})
.then(data => {
	findOne
    res.json({findOneData})
})

이런식으로하면 안됩니다!, restful한지 한번 고민해보세요!

그래도 아쉬우니 transaction isolationlevel을 간단하게 정리보고 다음에 세밀하게 정리하겠씁니다.

3. 결론

https://www.codegrepper.com/code-examples/javascript/sequelize+transaction

프로젝트가 끝나고 해결하지못했던 부분을 해결해볼려고합니다.
결론적으로 transaction은 당연히 작동 안하는게 맞습니다!

try {
await User.findOne({ where : { id: 500} })
}
catch {}

id가 30까지 있는 데이터 베이스를 생각했을 때, 위와 같이 조합하면 try { } catch { }를 사용해서 에러를 잡는다고 했을 때 catch에 잡힐까요 ? 잡히지않을까요 ?
정답은 잡히지 않습니다. 비동기적으로 데이터를 받아올 때 단순히 findOne은 조회를 하고 없으니, catch로 에러를 띄우는게 아니라 null 값을 반환합니다.
transaction을 잘못사용했다고 생각했었는데, 애초에 비동기적 작업을 오해했기에 이런일이 생겼습니다. User에 없는 column값을 넣는다면 정상적으로 오류를 반환하고 rollback이 됨을 확인 할 수 있습니다.
Client에 값이 제대로 넘어오게 설정해놨다면 transaction을 사용할 필요가 없습니다!

Isolation Level

isolation level에는 READ UNCOMMITED, READ COMMITED, REPEATABLE READ, SERIALIZABLE 이 있습니다. isolation lavel이 높아질수록 더 lock을 세게 겁니다.

(1) READ UNCOMMITTED

트랜잭션에서 commit되지않은 데이터를 읽어올 수 있는 level 입니다.

  • 아직 commit되지않은 신뢰할 수 없는 데이터를 읽어올 수 있습니다. 이를 dirty read라고 합니다.
  • 한 트랜잭션에서 동일한 select 쿼리의 결과가 다를 수 있습니다(non-repeatable)
  • 이전의 select 쿼리의 결과에 없던 row가 생깁니다(phantom read)

(2) READ COMMITTED

다른 트랜잭션에서 commit된 데이터만 읽어올 수 있는 level입니다

  • 아직 commit되지 않은 신뢰할 수 없는 데이터는 읽어올 수 없습니다.

(3) REPEATABLE READ

MySQL InnoDB의 기본 isolation level입니다.

(4) SERIALIZABLE

동시성을 상당 부분 포기하고 안전성에 큰 비중을 준 isolation level입니다.

출처

https://jupiny.com/2018/11/30/mysql-transaction-isolation-levels/
https://blog.sapzil.org/2017/04/01/do-not-trust-sql-transaction/
https://suhwan.dev/2019/06/09/transaction-isolation-level-and-lock/
https://overcome-the-limits.tistory.com/528
http://52.78.22.201/tutorials/expressjs/expressjs_orm_four/

profile
읽고 기록하고 고민하고 사용하고 개발하자!

0개의 댓글