Search

MySQL Insert vs Update Cost 고찰

비용과 락에 대한 관점

1. Insert에서의 비용

1.
작업의 본질: insert는 새로운 데이터를 데이터베이스에 추가하는 작업이며, 일반적으로 해당 데이터의 위치를 찾고 데이터를 쓰는 것으로 마무리됩니다. 반면, update는 기존 데이터를 찾아서 읽고, 수정한 후에 다시 쓰는 과정을 포함합니다. 이 과정은 insert보다 더 많은 단계를 필요로 합니다.
2.
데이터 검색: update 작업은 기존 데이터를 검색해야 하므로, 해당 데이터를 찾는 데 시간이 걸릴 수 있습니다. 이는 특히 인덱스가 없거나 데이터베이스가 매우 큰 경우 더욱 두드러질 수 있습니다. insert는 이러한 검색 단계가 필요 없습니다.
3.
데이터 무결성 및 제약 조건: update 작업은 기존 데이터를 변경하기 때문에 데이터 무결성을 유지하기 위한 추가적인 제약 조건 검사가 필요할 수 있습니다. 예를 들어, 외래 키 제약 조건이나 트리거 등이 update 작업을 느리게 만들 수 있습니다. insert 작업도 이러한 제약 조건 검사가 필요하지만, 기존 데이터와의 상호 작용이 덜하기 때문에 일반적으로 덜 복잡합니다.

2. UPDATE 쿼리에서의 락

데이터 베이스의 격리 수준에 대해서 먼저 조회해봅니다.
`SELECT @@tx_isolation;` —> `REPEATABLE-READ`
Python
복사
MariaDB에서 REPEATABLE READ 격리 수준(isolation level)을 사용할 때, UPDATE 쿼리와 SELECT 쿼리에서 다음과 같은 락이 수행됩니다
UPDATE 쿼리는 행에 대해 읽기 잠금(Read Lock)과 쓰기 잠금(Write Lock)을 모두 획득합니다.
해당 행에 대한 다른 트랜잭션의 읽기나 쓰기 작업을 차단하여, 일관성 있는 데이터 상태를 유지합니다.
UPDATE는 해당 행을 수정하므로, 다른 트랜잭션이 해당 행을 읽거나 변경할 수 없도록 합니다.
분할 업데이트: 큰 테이블의 경우, 한 번에 많은 행을 업데이트하는 대신 작은 배치로 나누어 업데이트를 수행할 수 있습니다.
업데이트 트랜잭션이 오래 걸릴 경우, 해당 트랜잭션에 의해 락이 걸린 행이나 테이블을 조회하는 다른 사용자의 쿼리는 대기 상태가 될 수 있습니다
하지만 벌크 업데이트를 수행하면서, 트랜잭션 범위를 얼마나 잡느냐에 따라 해당 테이블에 락이 걸려 동시성 오류가 발생합니다.
따라서 트랜잭션을 행하는 행의 범위는 비지니스 룰에 따라 적정선을 타협하는 것이 중요합니다
또한 격리수준을 완화하는 것도 가능하지만 이는 권장되는 방법이 아닙니다.
자주 업데이트되는 칼럼에 인덱스를 거는 것도 하나의 방법이 될 수 있지만, 이는 인덱스와 쓰기 작업 성능, 디스크 공간과 같은 트레이드 오프를 고려해야합니다.

2. SELECT 쿼리에서의 락

REPEATABLE READ에서의 일반적인 SELECT 쿼리는 비공유 읽기 잠금(Non-Exclusive Read Lock)을 사용하지 않습니다.
즉, SELECT 쿼리만 수행하는 경우에는 다른 트랜잭션이 동일한 행을 읽을 수 있습니다.
그러나 SELECT ... FOR UPDATE 또는 SELECT ... LOCK IN SHARE MODE 구문을 사용하면, 각각 쓰기 잠금과 공유 읽기 잠금을 획득합니다.

REPEATABLE READ 격리 수준의 특징

REPEATABLE READ에서는 한 트랜잭션 내에서 수행되는 모든 읽기 작업이 트랜잭션이 시작될 때의 일관된 상태를 반영합니다.
다른 트랜잭션이 변경한 내용이 커밋되더라도 현재 진행 중인 트랜잭션에서는 변경 전의 데이터를 볼 수 있습니다.
해당 작업을 언두 로그를 통해 읽게 됩니다.
이는 팬텀 읽기(Phantom Read)를 방지하지만, 간격 잠금(Gap Lock)을 사용하여 특정 레코드 범위에 대한 삽입을 차단할 수 있습니다.

주의사항

격리 수준에 따라 성능과 일관성 간의 트레이드오프가 존재합니다.
데이터베이스의 성능과 일관성 요구사항에 따라 적절한 격리 수준을 선택해야 합니다.
격리 수준의 설정은 데이터베이스 전역 설정 또는 세션별 설정으로 조절할 수 있습니다.