테이블에 DML이 들어오면 교착 상태 방지를 위해 잠금이 수행되고, 잠금되어있는 동안에는 다른 DML이 수행될 수 없다. 결국 동일 테이블(A 테이블에서 A 테이블)로 트리거를 발생 시키는 것은 불가능.
CREATE DEFINER=`cube`@`%` TRIGGER on_comment_insert
AFTER INSERT
ON Board FOR EACH ROW
BEGIN
IF NEW.isComment = 1 THEN
UPDATE Board SET Board.commentCnt = Board.commentCnt + 1
WHERE Board.idx = NEW.parentIdx ;
-- CALL update_board_commentCnt(NEW.parentIdx, 1);
END IF;
END
근데 AFTER INSERT인데 그럼 DML이 종료된 이후에 실행되어야 맞는 것 아닌가?
⇒ 트리거는 쿼리문이 완전히 실행되기 전에 실행된다. 그 증거로 바뀌기 이전의 데이터와 바뀔 데이터를 가져올 수 있는 old.필드명, new.필드명이 있다. 쿼리문이 완전히 종료되는 COMMIT 또는 ROLLBACK이 일어나기 전까지 테이블은 데이터 무결성을 위해 LOCK 상태이기 때문에 동일 테이블을 Trigger로 수정할 수 없다.
댓글 테이블에 insert가 일어날 경우 board 테이블의 어느 게시판에 해당하는 댓글인지 검사한 후 클라이언트로부터 전달받은 parentIdx와 일치하는 레코드의 commentCnt를 더하거나 빼준다.
트리거는 머리 속 DB 설계가 지속적으로 남아있지 않다면 많이 사용할 수록 유지보수가 어렵게 되고, 재귀 또는 반복문이 많을 경우 큰 성능 저하를 야기할 수 있다.
그렇기 때문에 이 부분은 아예 트리거를 사용하지 않고 쿼리를 요청할 때 commentCnt 값을 더하거나 뺀 값으로 쿼리를 요청하면 된다.