-
2025.11.04 insert select not exists / event sourcing, current, historyTIL 2025. 11. 5. 00:11
MySQL :: MySQL 8.4 Reference Manual :: 17.7.3 Locks Set by Different SQL Statements in InnoDB
17.7.3 Locks Set by Different SQL Statements in InnoDB A locking read, an UPDATE, or a DELETE generally set record locks on every index record that is scanned in the processing of an SQL statement. It does not matter whether there are WHERE conditions in
dev.mysql.com
insert문으로 레이스컨디션을 해결할 때가 있다.
insert select not exists으로 해결하는 것인데, 서브쿼리에서 조회된 부분은 s lock, gap lock이 잡힌다.
insert부분은 insert intention lock이 잡히고.
서브쿼리 조건과 insert하는 값이 같다면 (ex. insert into sample (name) (select 'something' from (select 1 from sample where not exists name = 'something')); ) 동시 삽입을 제어할 수 있다.
tx1, tx2에서 동일한 쿼리를 실행 시 나중에 실행된 쿼리는 잠금대기를 하게 된다.
lock 보유를 보면 tx1이 record lock을가지고 있다. t2가 s lock을 획득하려다 잠금대기를 한다.
생각한 것은 tx1이 서브쿼리에 대해 s, gap lock을 획득, insert 범위에 대해 insert intention 획득.
tx2가 서브쿼리에 대해 s, gap lock획득(gap lock은 서로 호환) 이후 insert intention lock을 획득하려다 잠금대기할 줄 알았는데 실제 잠금은 tx2에서 쿼리 이후, tx1이 삽입하는 구간에 레코드 락은 가져간다.
insert는 insert값에 대해 x lock을 건다.
이후 tx2가 s lock을 걸 때 tx1의 x lock에의해서 잠금대기를 하게되는 구조이다.
그럼 INSERT INTO sample VALUES ('A') 를 각각실행하면?
x lock이라고 했는데 왜 s lock조회는 안되고 중복값 insert는되는가?
써있기를 next key lock이 아니고 index record lock이라는 것이다. gap lock을 안쓴다고 아니라고 분명히 써 있다.
그래서 uk아닌 이상 중복된 값은 다른 record index 엔트리라서 record lock을 걸지 않아 x lock이 서로를 막지 않는거로 이해했다.
서브쿼리가 있는 sql은 서브쿼리가 탐색하는 과정이 index 탐색 과정이고 이로 인해 기본 insert와 다르게 인덱스 엔트리를 탐색하기 때문으로 이해했다.
insert 는 각기 다른 index record 삽입이고, insert select의 서브쿼리는 인덱스 탐색이다.
그래서 x lock으로 인해 서브쿼리가 막히는 것.
---
Insert-only data pattern
I'm writing a specification for a system that requires a full data audit history. I've worked with a few nice auditing patterns before, but I'm leaning towards an insert-only pattern for this solu...
stackoverflow.com
장부 기록을 할 때 이벤트 소싱 처럼 테이블을 구현할 수 있다.
이전 장부 내역이 다음 장부 내역에 영향을 주고, 이어져 있는 구조이다.
다른 구조로는 현재 잔금을 current 테이블에 넣고, 기록을 histroy로 뺄 수 있다.
더 단순한 구조는 후자이다.
전자의 장점으로 생각했을 때, 장부를 임의로 수정 시 이전 장부 기록을 통해 어디서 문제가 발생했는지 알 수 있다는 것이다.
current에 경우, 누가 임의로 current를 수정하면 history를 통해 최신 값으로 수정하던지만 알 수 있을 뿐(이거면 충분한가?) 정확한 current의 값을 유추할 수 없을 거라 생각했다.
'TIL' 카테고리의 다른 글
2025.11.06 외부api 6 + 정산 (0) 2025.11.06 2025.11.05 ab test (0) 2025.11.05 2025.11.01~2 외부API 5 (0) 2025.11.01 2025.10.29 외부API 4 (0) 2025.10.29 2025.10.28 외부API 3 (0) 2025.10.28