- [ backend/데이터베이스 ][redis] redisson으로 분산락 걸어서 동시성 문제 해결하기2024-11-19 12:00:41Repeatable Read 격리 수준으로 인한 동시성 문제 발생내가 진행중인 프로젝트에서 동시성 문제가 발생했다. 요구사항에 의해 하루에 한 번만 미션을 수행할 수 있다. 이를 위해 미션 인증 레코드를 생성하기 전에 오늘 인증 내역이 있는지 확인하고 INSERT 쿼리를 수행한다.@Transactionalpublic void createVerification(final CreateMissionVerificationCommand command) { MissionMember missionMember = missionMemberRepository.getMissionMember(command.memberId(), command.missionId()); // 유효성 검사 진행 (이미 레코드가 있는 경우..
- [ backend/데이터베이스 ][mysql] 성능 최적화 3편 (데이터 크기)2024-02-13 15:36:22데이터 구조 최적화 테이블을 설계할 때 적절한 데이터 타입을 설정하는 것이 매우 중요하다. 최소한의 데이터 크기를 사용함으로써 테이블이 차지하는 디스크 공간을 최적화할 수 있고, 데이터가 메모리에 로드될 때 메모리 공간을 적게 사용하기 때문에 더 많은 데이터를 캐싱할 수 있다. 데이터 크기 최적화 데이터 크기를 최적화하면 디스크에 저장되는 데이터 양을 줄일 수 있다. 이는 저장소 비용을 절감하고 데이터 전송 시간을 단축시킨다. 테이블 컬럼 최적화 작은 크기의 데이터 타입을 사용하여 디스크 공간과 메모리를 확보한다. 가능한 `NOT NULL`로 선언하여 각 값이 null인지 테스트하는 오버헤드를 제거한다. `TINYINT` `SMALLINT` `MEDIUMINT` `INT` `BIGINT` 바이트 1 2 ..
- [ backend/데이터베이스 ][mysql] 성능 최적화 2편 (트랜잭션)2024-02-06 20:39:51트랜잭션 최적화 트랜잭션은 데이터의 일관성과 안전성을 보장하는 핵심 요소다. 특히 다수의 데이터를 처리할 때 트랜잭션 범위를 어떻게 설정하느냐가 성능에 큰 영향을 미친다. 하지만 다수의 쿼리를 하나의 트랜잭션으로 처리하는 것이 반드시 성능 향상으로 이어질까? 한 트랜잭션에서 여러 쿼리를 처리하면 커밋이나 롤백이 발생하기 전까지 모든 변경사항이 보류된다. 그동안 다른 트랜잭션들이 해당 데이터에 접근하지 못하고 기다려야 하므로 트랜잭션의 처리 속도가 감소할 수 있다. 🚨 대량의 행을 삽입/수정/삭제한 후 롤백을 실행하는 것은 성능을 저하시킬 수 있다. 대규모 데이터 변경이 필요한 경우, 주기적으로 커밋을 실행하거나 작은 크기의 트랜잭션으로 나누는 것이 좋다. 한편, 각각의 쿼리를 개별적인 트랜잭션으로 처리하..
- [ backend/데이터베이스 ][mysql] 성능 최적화 1편 (인덱스/커버링 인덱스)2024-02-05 22:44:23데이터베이스 성능에는 테이블, 쿼리, 설정 등 다양한 수준의 요소들이 영향을 미친다. 최적화를 위해 소프트웨어, 하드웨어 수준에서 조절할 수 있지만 이 글에서는 하드웨어 최적화는 다루지 않을 것이다. 데이터베이스 최적화최적화 방법을 살펴보기 전에 아래 질문으로 어떤 점을 고려해야 하는지 간단히 알아보자.테이블은 올바른 데이터 유형의 열을 가지고 있고 적절한 수의 열을 갖추고 있는가인덱스가 적절히 구성되어 있는가각 테이블에 적합한 스토리지 엔진을 사용하고 해당 엔진의 강점과 기능을 활용하고 있는가디스크 낭비를 줄이고 I/O 시간을 단축하기 위해 압축된 테이블을 사용하고 있는가동시성을 위해 적절한 락 전략을 사용하고 있는가메모리 캐싱 영역을 올바른 크기로 설정했는가 SQL문 최적화sql문은 데이터베이스를 조..
- [ backend/데이터베이스 ][mysql] InnoDB 체인지 버퍼2024-02-04 21:28:54체인지 버퍼 체인지 버퍼는 버퍼 풀에 존재하지 않는, 보조 인덱스 페이지*의 변경 내용을 캐시하는 데이터 구조다. DML 작업으로 인한 변경사항을 일시적으로 저장하고, 이후 다른 읽기 작업으로 인해 해당 페이지를 버퍼 풀에 가져올 때 변경 내용을 병합한다. *보조 인덱스 페이지 : 인덱스 순서와 레코드의 순서가 일치하지 않으므로 레코드의 위치를 나타내는 포인터를 저장한다. 데이터가 변경되면 정렬된 상태를 유지하기 위해 인덱스 페이지가 수정된다. 변경사항을 데이터베이스에 반영하면 보조 인덱스가 수정된다. 하지만 인덱스들은 디스크에 위치하므로 레코드가 변경될 때마다 보조 인덱스를 수정하는 I/O 작업이 발생한다. 이를 방지하기 위해 체인지 버퍼에 보조 인덱스 페이지의 변경 내용을 캐싱하여 불필요한 I/O 작..
- [ backend/데이터베이스 ][mysql] InnoDB 버퍼 풀2024-02-04 14:55:09프로젝트 진행 중에 DB 과부하를 완화하기 위해 자주 액세스되는 데이터를 Redis에 캐싱한 적이 있다. 하지만 `htop`* 명령을 사용하여 DB가 설치된 서버를 모니터링한 결과, 캐싱을 적용하기 전과 후의 CPU 사용량 차이가 거의 나타나지 않았다. 어째서 아무런 효과가 없었던 걸까?*htop : 리눅스 환경에서 사용되는 프로세스 모니터링 도구 버퍼 풀버퍼 풀은 InnoDB에서 사용되는 캐싱 영역으로, 자주 사용되는 데이터를 메모리에 캐시하여 처리 속도를 향상시킨다. 이는 페이지로 나누어져 다수의 레코드를 저장할 수 있으며 연결 리스트 형태의 페이지들로 구현되어 있다. 버퍼 풀은 LRU 알고리즘을 사용하여 드물게 사용되는 데이터를 캐시에서 제거한다. 자주 사용되는 데이터를 메모리에 유지하여 mysql..
- [ backend/데이터베이스 ][mysql] InnoDB 살펴보기 (장점/ACID/MVCC)2024-02-03 21:00:45InnoDB란? InnoDB는 mysql에서 사용되는 기본 스토리지 엔진으로, 데이터베이스 테이블을 관리하는 데 사용된다. InnoDB의 장점 어떤 장점이 있길래 InnoDB를 스토리지 엔진으로 사용하는 걸까? InnoDB Recovery - 하드웨어나 소프트웨어 이슈로 서버가 예기치 못하게 종료되어도 InnoDB의 crash recovery가 자동으로 수정을 마무리한다. Buffer Pool - 버퍼 풀*에 테이블과 인덱스를 캐시하여 자주 사용하는 데이터는 메모리에서 처리한다. Index - 레코드에 키를 설정하면 해당 컬럼을 활용한 연산들을 자동으로 최적화한다. Change Buffer - 체인지 버퍼*를 이용하여 삽입, 수정, 삭제 작업을 최적화한다. 위의 장점 외에도 정말 많은 장점들이 있다. 자..