전체 글 131

AOP Self Invocation(자기 호출) 문제로 인한 트랜잭션 미분리 현상

1. 개요아래 코드의 목적은 격리 수준 REPEATABLE_READ를 실제로 테스트 해보는 것이다.기대했던 결과는 이렇다.1) updateDuringSelectTwice 메서드에서 Toy 데이터를 조회한다.2) 중간에 새로운 트랜잭션을 생성하고 해당 Toy 데이터를 수정한다.3) 다시 똑같은 Toy 데이터를 조회하는데, 격리수준 REPEATABLE_READ이므로 name이 수정된 데이터가 아닌 트랜잭션이 시작할 때 당시의 데이터가 조회될 것이다.@Slf4j@Servicepublic class Service { private final ToyRepository toyRepository; @Transactional(isolation = Isolation.REPEATABLE_READ) publ..

트러블슈팅 2024.08.07

동일 Transaction 내 롤백 마크로 인한 장애 전파

1. 문제 상황Controller에서 클라이언트의 요청을 처리하는 메인 로직(mainLogic)과 부수적인 역할의 서브 로직(subLogic)이 하나의 try-catch 문으로 묶여 있는 상태subLogic은 클라이언트 요청처리와 무관하기 때문에 subLogic에서 에러가 발생해도 클라이언트 요청은 정상 처리가 되었기 때문에 errorResponse를 반환하면 안됨아래는 문제의 Controller 메서드를 간략화해서 나타낸 것public Response contorollerMethod(Request request){ try{ mainLogic(request); subLogic(request); return response; } catch(Exception e) ..

트러블슈팅 2024.07.28

[MySQL] MVCC(Multi Version Concurrency Control)

MySQL의 InnoDB 스토리지 엔진은 잠금을 사용하지 않는 일관된 읽기 제공을 위해 MVCC 기능을 제공한다.이를 위해 언두 로그(Undo log)를 사용하며 이를 통해 하나의 레코드에 여러 버전이 존재할 수 있게 된다. 예시데이터 수정 중 데이터 읽기 요청이 왔을 때, 언두 로그의 데이터와 레코드의 데이터 2가지 버전이 존재한다.UPDATE 쿼리에 의해 기존 데이터는 언두 로그에 기록되고 레코드는 새로운 데이터로 변경된다.아직 COMMIT 이나 ROLLBACK이 되지 않은 상태에서 SELECT 요청이 들어온다.격리 수준(Isolation Level)이 READ_UNCOMMITED인 경우 커밋되지 않은 레코드의 데이터를 읽는다.격리 수준이 READ_COMMITED 이상인 경우 기존 데이터(언두 로그의..

[MySQL] 쿼리 실행 구조

쿼리 실행 구조쿼리 파서전처리기옵티마이저쿼리 실행기 핸들러1 ~ 4는 MySQL 엔진(실행 엔진) 영역이고 5는 스토리지 엔진 영역이다. 1. 쿼리 파서쿼리 파서는 요청 받은 쿼리 문장을 *토큰으로 분리해 트리 형태 구조로 만들어내는 작업을 수행한다.*토큰 : MySQL이 인식할 수 있는 최소 단위기본적인 문법 오류가 있을 경우 쿼리 파서가 확인 후 오류 메시지를 반환한다. 2. 전처리기쿼리 파서가 만든 파서 트리를 기반으로 쿼리 문장에 구조적인 문제점 여부를 확인한다.각 토근에 테이블 이름, 칼럼 이름, 내장 함수 같은 개체를 매핑해 해당 객체의 존재 여부와 객체 접근 권한 등을 확인한다.존재하지 않거나 접근 권한이 없는 개체의 토큰이 걸러지는 단계이다. 3. 옵티마이저쿼리를 어떻게 가장 저렴한 비용으..

MySQL 메모리 할당

1. 글로벌 메모리 영역스레드의 개수와 상관 없이 하나의 메모리 공간만 할당된다.(필요에 따라 2개 이상 할당할 수도 있다)모든 스레드에 의해 공유되는 영역이다. 글로벌 메모리 영역 종류테이블 캐시InnoDB 버퍼Inno DB 어댑티브 해시 인덱스InnoDB 리두 로그 버퍼 2. 로컬 메모리(세션 메모리) 영역클라이언트 스레드가 쿼리를 처리하는 데 사용하는 메모리 영역스레드별로 독립적으로 할당되며 절대 공유되지 않는다.경우에 따라 할당되지 않을 수 있다. 예를 들어 커넥션 버퍼, 결과 버퍼처럼 항상 할당되는 경우와 조인 버퍼, 정렬 버퍼처럼 필요할 때만 할당되는 경우가 있다. 로컬 메모리 영역 종류정렬 버퍼(Sort buffer)조인 버퍼바이너리 로그 캐시네트워크 버퍼

포그라운드 스레드와 백그라운드 스레드

1. 포그라운드 스레드(클라이언트 스레드)사용자의 요청을 처리하기 때문에 클라이언트(사용자) 스레드라고 부른다. 생명주기MySQL 서버에 접속된 클라이언트의 요청을 처리하기 때문에 스레드의 개수는 적어도 접속한 클라이언트 수만큼 존재한다.사용자의 요청을 처리하면 스레드 캐시(Thead cache)로 되돌아가 새로운 요청을 기다린다. 기능 범위사용자의 커넥션을 담당한다.요청받은 데이터를 데이터 버퍼나 캐시로부터 읽어온다.만약, 버퍼나 캐시에 없는 경우 디스크나 인덱스 파일로부터 데이터를 읽어온다.MyISAM 테이블은 디스크 쓰기 작업까지 처리한다. 2. 백그라운드 스레드백그라운드 스레드는 InnoDB의 여러 작업을 담당한다. a. 버퍼의 데이터를 디스크에 기록(쓰기)데이터 읽기는 주로 클라이언트 스레드에서..

[Java] Stack 구현해보기

1. 소개 정수 배열을 이용해 Stack을 구현해보았다. 기본 크기는 1이며 스택의 크기를 초기화할 수 있도록 생성자를 만들었다. 주요 메서드인 push, pop, pick 메서드와 스택의 크기를 구하는 size를 구현했다 2. 생성자 멤버 변수로는 다음 데이터의 위치(index)를 나타내는 top과 정수 배열인 stack이 있다. //MyStack의 멤버 변수 int top; int[] stack; 기본 크기는 1이며, 크기는 초기화 가능하게 만들었다. public MyStack() { top = 0; stack = new int[1]; } public MyStack(int size) { top = 0; stack = new int[size]; } 3. PUSH() 새로운 데이터를 추가하는 push 메..

개발공부/Java 2023.04.11

[Spring] Tomcat 서버 포트 번호 변경

Spring boot에는 Tomcat 서버가 내장되어 있으며 defalut port로 포트 번호 8080을 사용한다. 하지만 다른 곳에서 해당 포트 번호를 사용할 경우 정상적으로 작동하지 않을 수 있다. 이를 해결하기 위해 2가지 방법을 생각할 수 있다. 1. 8080 포트를 사용하는 어플리케이션을 종료한다. 2. Tomcat 서버가 사용하는 포트 번호를 변경한다. 여기선 2번째 방법을 살펴볼 예정이다. Spring boot 프로젝트 안에 'application' 파일이 존재할 것이다. 보통 src 폴더 - main 폴더 - resources 폴더 안에 application.properties 또는 application.yml이라는 이름으로 있다. application은 스프링 부트 프로젝트의 설정을 명..

개발공부/Spring 2023.04.08

[디자인 패턴] 어댑터 패턴(Adapter pattern)

어댑터 패턴 호환되지 않는 클래스를 호환 가능하도록 변환해주는 역할의 클래스를 생성하는 방법이다. 기존 클래스의 수정 없이 어댑터 클래스를 추가해줌으로 재사용성을 높여주는 방법이다. (ex. 220v를 110v로 변환, 3극 이어폰 단자를 4극으로 변환하는 등 기존 제품을 변형하지 않고 어댑터를 추가해 다른 기기와 호환성을 높인다) 어댑터 클래스 사용 예 220V 제품을 110V 콘센트에 연결할 수 있도록 어댑터 클래스를 만들었다. 1. 어댑터는 110V 콘센트의 구현체로 만들어 110V와 호환이 가능하게 만든다. 2. 생성자를 통해 어댑터에 220V 제품을 객체를 만들어준다. 3. 그리고 110V 콘센트에 연결하는 메서드(connect)를 오버라이딩하여 220V 제품 연결 메서드로 만든다. public..

개발공부/Java 2023.03.31

[디자인패턴] 싱글톤 패턴(Singleton pattern)

싱글톤 패턴 디자인 패턴 중 생성 패턴의 한 종류로 특정 객체가 1개만 존재해야할 때 사용하는 패턴이다. 즉 객체를 필요할 때마다 생성하지 않고 기존의 객체를 계속해서 재사용하는 것으로 서로 자원을 공유할 때 사용된다. (ex. 여러 사용자가 1대의 프린터는 사용하는 경우) 스프링의 경우 객체를 Bean이라는 이름으로 싱클톤 패턴으로 관리한다. 싱글톤 패턴 사용 방법 최초 호출 때만 객체를 생성하고 그 뒤로는 생성된 객체를 계속 재사용하기 때문에 아래의 조건이 필요하다. 1. 객체를 static으로 선언해 어디서든 호출이 가능하게 한다. 2. 생성자를 private으로 선언해 외부에서 새로운 객체를 생성하는 것을 막는다. 3. getInstance() 메서드를 통해 기존의 객체를 호출할 수 있도록 한다...

개발공부/Java 2023.03.31