안녕하세요. mysql로 프로젝트를 진행하던 중 궁금한 점이 있어서 문의를 남깁니다.
mysql 버전은 8 이며 InnoDB를 사용하고 있습니다.
현재 저는 delete 후 select 한 데이터를 insert 하려고 합니다.
delete -> insert into select 는 하나의 트랜잭션으로 묶어놓았습니다.
delete와 insert는 같은 테이블이며, select는 다른 여러 테이블들에서 데이터 값을 조합합니다.
1. 'REPEATABLE READ', 'SERIALIZABLE' 에서는 ER_LOCK_WAIT_TIMEOUT 이 발생합니다.
2. 'READ COMMITTED' 에서는 딜리트 되기 전의 값이 읽혀 삭제돼서 보이지 않아야 할 값도 insert 됩니다.
3. 'READ UNCOMMITED' 에서는 정상적으로 작동이 되나, 다른 트랜잭션의 커밋되지 않은 값도 읽히게 되어 위험하다고 판단이 됩니다.
락은 인서트 부분에서 발생하고 있습니다.
AFTER DELETE , AFTER INSERT 트리거를 생성하였을 경우엔 정상적으로 작동했습니다.
같은 트랜잭션 내의 커밋되지 않은 값만 읽어들이는 방법이 있을지 궁금합니다.
아니면 아예 트랜잭션을 풀고 작업을 진행해야 할까요?
delete 작업 중에 다른 트랜잭션에서 dml 트랜잭션이 들어와서 lock이 발생하는 것 같습니다.
차라리 delete 하는 작업중에 다른트랜잭션에서 수정하지 못하도록 lock(select for update)을 거는 것은 어떨런지요?
참고 : https://jinhokwon.github.io/mysql/mysql-select-for-update/
답변 감사합니다! lock은 insert 하는 부분에서 발생하고 있습니다! 이 부분을 안적었네요 죄송합니다.
제가 정확히 이해를 못한것일수도 있습니다만..
가능하다면 insert를 먼저 하고 delete를 하도록 순서를 바꾸는건 어떨지요?
아니면 말씀하신대로 delete/insert 트랜잭션을 분리하는 것이 방법일듯 합니다.
show processlist; 쿼리를 날려보면 LOCK 걸린 부분의 쿼리가 INSERT ... 로 표시되고 있습니다.
같은 테이블이라서 딜리트 후에 인서트를 해야만 원하는 값을 얻을 수 있어서 순서 변경은 불가능할 것 같습니다. ㅠㅠ
답변 감사합니다. 분리하도록 하겠습니다!
INSERT 시 LOCK이 발생하는건 동일한 PK를 사용할때인데..
확인해보셨는지요?
아하 그래서 LOCK이 발생했던 것 같습니다.
트랜잭션을 걸었던 이유도 같은 카테고리를 가지는 부분 전체를 삭제하고, 해당 카테고리 부분의 값을 다시 계산하여 넣었습니다.
mysql 에 sequence를 쓸수있다면 pk를 대체해보시고 안되면 auto increment를 사용하시면 문제가 없을것 같아요.
시퀀스를 사용하지 않고, 아이디를 각 카테고리와 이름에 두고 사용입니다. 따로 id 항목으로 구분하진 않고 있습니다!