JVM Heap의 Layout
·
JVM
자바는 객체를 위주로 돌아가는 언어인데 이 객체들은 힙에 저장된다.내가 저장하는 객체들이 어떻게 저장되어 있는지 알아볼 필요가 있다.시작하기에 앞서 JDK 9부터 기본 GC로 G1 GC가 사용되고 있다.그래서 이 글은 G1 GC를 기반으로 한다.Heap은 이렇게 나뉜다일단 힙은 여러 구역으로 나뉜다.G1 GC도 기존의 GC들이 그랬듯이 Eden, Survivor, Old 가 있고, 기존 GC들과 다른 점이 있다면 거대 객체를 저장하기 위한 Humongous가 있다.또 하나 다른 점이 있다면, 기존에는 위와 같이 각 영역들이 고정된 크기로 연속된 주소에 있었지만 G1 GC는 단순히 수천 개의 region으로 분할하여 사용한다.위 이미지에 보이는 조각들이 모두 각각 하나의 region이다.이 region들은..
새벽에만 실패하는 테스트
·
트러블 슈팅
무려 2년 전에 생성된 이슈다.잘 돌아가던 CI가 간헐적으로 실패하기 시작했다.CI가 터지는 이유는 빌드 과정에서 테스트가 하나 실패하고 있기 때문이었다. 당시에는 스터디 서비스를 새로 개발하던 시기라서 당장 급한 신규 기능 구현에 집중해야 했고, 그래서 해당 테스트에 @Disabled를 붙여두기로 했다.실패하는 테스트는 '일자기준으로_주문목록_조회시_조회된다'라는 테스트였는데, 조회 기능이 문제없이 잘 동작하기도 했기 때문에 @Disabled를 붙여둔 이 테스트는 깃허브에 이슈만 생성된 채로 잊혀졌고 2년이나 지나서 원인을 파악하게 되었다.문제 상황로컬에서 빌드를 할 때는 단 한 번도 테스트 때문에 실패한 적이 없었다.실패한 경우는 모두 Github Actions에서 빌드될 때였다.한 가지 특징적이었던..
MySQL InnoDB의 Lock
·
DB
같은 MySQL이라도 스토리지 엔진에 따라 제공하는 락의 종류가 다르고 동작 방식도 다르다.이전에 기본 스토리지 엔진이었던 MyISAM이 테이블 기반의 락을 제공했던 것과 달리,InnoDB는 레코드 기반의 락을 제공한다.테이블 기반 락은 단 하나의 레코드가 필요할 때도 테이블 전체를 잠그는 것을 말하는데, 당연히 비효율적인 방식이다.이와 달리 레코드 기반 락은 필요한 레코드만, 혹은 범위로 락을 적용할 수 있다.이를 granularity가 높다고 하는데, 세밀하게 락을 걸 수 있다는 의미로 받아들이면 된다.이렇게 granularity가 높아지면 동시성 측면에서 이점이 있다. 조금 더 자세히 보면, "row 자체를 잠그는 것이 아니고 인덱스 레코드를 잠그는 것"이다.이 표현이 처음에는 되게 헷갈리는 포인트..
상상도 못한 DB Connection 고갈의 원인
·
트러블 슈팅
센트리에서 CannotCreateTransactionException이 발생했다는 메일이 왔다.트랜잭션 생성을 못한다는 것은 서버가 죽지는 않았어도 사실상 식물인간 상태라는 의미이기 때문에 꽤 중대한 예외라고 생각해서 바로 서버의 로그를 열어봤다.2026-06-10T09:51:52.043+09:00 WARN 1 --- [pool-3-thread-1] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection org.postgresql.jdbc.PgConnection@11111111 (This connection has been closed.). Possibly consider using a shorter ..
MySQL InnoDB Index
·
DB
많은 서비스에서 사용되는 MySQL은 5.5 버전부터 InnoDB를 기본 스토리지 엔진으로 사용하고 있다.이 InnoDB에서는 인덱스를 어떻게 관리하는지, 쿼리가 들어왔을 때는 어떻게 인덱스를 활용하는지를 알아보고자 한다.인덱스의 종류인덱스는 크게 두 가지로 나뉜다.clustered index와 secondary index다.Clustered Index먼저 clustered index는 테이블에서 단 하나만 존재하는데, 주로 기본 키(primary key)가 이에 해당한다.단 하나만 존재한다고 해서 꼭 하나의 column으로만 이루어져야 하는 것은 아니고 composite key처럼 두 개 이상의 column으로 구성된 하나의 조합이 clustered index가 될 수도 있다. 이 clustered i..
DB 트랜잭션 (3) - Isolation Level
·
DB
데이터베이스에서 isolation을 보장하기 위해 트랜잭션들을 순차적으로(serial 하게) 실행하면 정합성은 보장되겠으나 성능 저하가 심할 것이다.수십, 수백만 건의 데이터가 있는 환경이라면 더더욱 성능 저하가 뚜렷해진다.그래서 적당한 선에서 정합성도 유지하고 성능도 높이기 위해 조절이 필요하다.Isolation levelIsolation level에는 4가지가 있다.Read Uncommitted, Read Committed, Repeatable Read, 그리고 Serializable이다.가장 느슨한 Read Uncommitted에서는 Dirty Read, Non-Repeatable Read, Phantom Read 현상이 발생할 수 있다.Read UncommittedRead Uncommitted는 ..
DB 트랜잭션 (2) - 2PL & MVCC
·
DB
지난 글에서는 어떤 Schedule이 안전한지 판단하는 방법을 알아봤다.그런데 매번 이 알고리즘으로 현재의 Schedule이 안전한지 판단하는 것은 비효율적이므로애초에 안전한 Schedule을 만드는 것이 좋을 것이다.Concurrency Control Algorithm2-Phase Locking말 그대로 트랜잭션을 두 단계로 나눠서 관리하는 것이다.lock을 획득할 수 있는 growing phase, lock을 놓아주고 commit/rollback 할 수 있는 shrinking phase이다.lock을 놓아준 뒤에는 다시 lock을 얻으려고 하지 않기 때문에 2PL을 적용한다면 Serializability를 보장할 수 있다.Shared Lock & Exclusive Lock2PL에서는 읽기나 쓰기를 할..
DB 트랜잭션 (1) - Schedule, Conflict, Serializability
·
DB
트랜잭션의 유명한 네 가지 속성인 ACID 중 Isolation을 보장하기 위한 가장 간단한 방법은하나의 트랜잭션이 실행되는 동안 다른 트랜잭션은 실행되지 않도록 하는 것이다.하지만, 이렇게 했을 때 성능의 저하가 너무 커져서 비효율적이다.두 개 이상의 트랜잭션이 병행적으로 실행되면서도 서로에게 영향을 주지 않고 독립적으로 실행될 수 있도록 하면Isolation도 보장하면서 성능도 챙길 수 있을 것이다.Schedule데이터베이스는 하나의 트랜잭션에서 여러 개의 operation을 처리한다.예를 들어 데이터 A에 대해 read를 수행하고, write를 수행하는 식이다.이제 여러 트랜잭션이 있는 경우를 생각해보자.먼저 트랜잭션 1에서는 데이터 A에 대해 read와 write를 하고, 데이터 B에 대해서도 r..