본문 바로가기

전체 글

(81)
Real MySQL 9장 옵티마이저와 힌트 #2 (9.3~) 9.3 고급 최적화 MySQL 옵티마이저는 실행 계획을 수립할 때 통계 정보와 옵티마이저 옵션을 결합해서 최적의 실행 계획을 수립한다. 여기서 옵티마이저 옵션은 크게 조인과 관련된 옵티마이저 옵션과 옵티마이저 스위치로 구분할 수 있다. 9.3.1 옵티마이저 스위치 옵션 옵티마이저 스위치 옵션은 optimizer_switch 시스템 변수를 이용해서 제어한다. 9.3.1절 하위의 옵션들을 on, off, default로 설정하여 사용할 수 있다. 9.3.1.1을 제외한 모든 설정 옵션은 기본값이 on이다. 9.3.1.1 MRR과 배치 키 액세스(mrr & batched_key_access) MRR은 Multi Range Read를 줄여서 부르는 말이다. MySQL 서버는 조인 대상 테이블 중 하나로부터 레코.. 더보기
스프링 영속성 관리 (영속성 컨텍스트) 이번 장에서는 스프링의 영속성 관리, 영속성 컨텍스트에 대해서 살펴본다. JPA에서 가장 중요한 2가지 요소를 꼽자면 하나는 ORM (객체와 관계형 데이터베이스 매핑)이고 나머지 하나는 영속성 컨텍스트이다. 아래의 그림과 같이 하나의 트랜잭션이 시작이 되면 각 트랜잭션마다 EntityManagerFactory에서 EntityManager를 생성하여 각자의 영속성 컨텍스트가 생성이된다. 영속성 컨텍스트란? 엔티티를 영구 저장하는 환경이라는 뜻 아래의 코드와 같이 엔티티 매니저를 통해서 영속성 컨텍스트에 접근할 수 있다. entityManager.persist(entity) 엔티티의 생명주기 비영속(new/transient) 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태 Member member = new.. 더보기
Real MySQL 9장 옵티마이저와 힌트 #1 (~9.2) MySQL 서버에서 옵티마이저는 각 테이블에 있는 데이터가 어떻게 분포되어있는지 등의 통계정보를 가지고 최적의 실행계획을 수립한다. 9.1 개요 9.1.1 쿼리 실행 절차 쿼리 실행 절차는 크게 세 단계로 나눌 수 있다. SQL 문장을 분석하고 파스 트리를 만든다. SQL 문장의 문법적인 오류를 발견한다. 만들어진 파스트리를 확인해서 테이블과 인덱스를 어떤 식으로 읽을지를 선택한다. (최적화 및 실행 계획 수립) 복잡한 연산을 단순화한다. 조인이 있을 경우 읽는 순서를 정한다. 인덱스 통계정보를 이용해 사용할 인덱스를 결정한다. 가져온 레코드를 임시테이블에 넣고 다시 가공할지를 결정한다. 수립된 실행계획에 따라 스토리지 엔진에서 읽어오도록 요청한다. MySQL 엔진에서 스토리지 엔진으로부터 받은 레코드를.. 더보기
자바 예외 이해 (Checked, Unchekced) 자바 예외 이해 예외 계층 Object : 자바의 모든 객체는 Obejct를상속받는다. 예외도 마찬가지이다. Throwable : 최 상위 예외이다. Error : 메모리 부족이나 심각한 시스템 오류 등 복구불가능한 예외이다. Exception Checked : RuntimeException을 제외한 모든 예외를 체크예외라 한다. Unchekced : RuntimeException 하위의 모든 예외를 언체크예외라 한다. 예외 기본 규칙 예외는 폭탄돌리기와 같다. 예외를 처리하지 못하면 호출한 곳으로 예외를 던지고 예외를 처리할 수 있으면 처리하고 정상흐름으로 돌릴 수 있다. 예외를 처리하지 못하고 계속 던지면 어떻게 될까? 자바의 main() 쓰레드의 경우 에러 로그를 출력하면서 시스템이 종료된다. 웹 .. 더보기
JDBC와 트랜잭션 문제, 스프링의 해결책 이번 포스팅에서는 스프링에서 트랜잭션을 적용하기 위해서 어떠한 과정을 거쳐왔는지를 예제를 통해 학습해보자. 예제는 간단하게 계좌이체를 하는 코드이다. @RequiredArgsConstructor public class MemberServiceV2 { private final DataSource dataSource; private final MemberRepositoryV2 memberRepository; public void accountTransfer(String fromId, String toId, int money) throws SQLException { Connection con = dataSource.getConnection(); try { con.setAutoCommit(false); bizL.. 더보기
스프링 AOP 내부호출 문제와 한계 이번 포스팅에서는 스프링 AOP 를 적용했을 때 발생할 수 있는 문제와 한계점에 대해서 설명하고 스프링은 이러한 문제를 어떻게 해결했는지를 살펴본다. 대표적인 두 가지 문제는 다음과같다. 내부호출이 일어났을 때 프록시가 적용되지 않는 상황 JDK 동적 프록시를 사용했을 때 타입캐스팅이나 의존관계 주입에서 오류가 발생할 수 있다. 이 두 가지 문제 상황을 살펴보자. 프록시와 내부호출 문제 먼저 아래의 코드를 살펴보자. public class CallServiceV0 { public void external(){ log.info("call external"); internal(); //내부 메서드 호출 } public void internal() { log.info("call internal"); } } @.. 더보기
스프링 AOP 스프링 AOP 개념 애플리케이션의 실행로직은 크게 핵심기능과 부가기능으로 나뉘어진다. 이 부가기능을 보통 횡단관심사(cross-cutting-concerns)으로 부른다. 예를 들어 주문이라는 기능을 구현하기 위해 orderService라는 클래스를 만들었을 때 주문 로직은 핵심기능이다. 여기에 로그나 트랜잭션 기능을 추가하는 것은 부가기능을 더하는 것이라 볼 수 있다. 이 부가기능을 적용하는 것이 간단한 문제일까? 이 질문에 대해 여러 상황을 생각해보자. 우리는 부가기능이라고 하는 기능을 여러 핵심기능에 적용할 수 있을 것이다. 100개의 핵심기능에 로그나 트랜잭션을 추가하려고 한다면 쉽게 생각하면 100개의 부가기능로직을 각각의 소스코드에 추가해주어야 한다. 부가기능이 변경되는 상황이 발생하면 어떻게.. 더보기
빈 후처리기, BeanPostProcessor 빈 후처리기 남아있는 문제 이전 포스팅에서 프록시 팩토리를 사용해서 스프링이 지원하는 프록시를 만들고 어드바이저로 부가기능을 생성해보았다. 스프링 빈에서 프록시 객체로 등록하기 위해서 해당 스프링 빈 대신에 프록시 객체를 넣고 프록시 객체 내부에서 부가기능과 함께 실제 객체를 호출하는 식으로 작성을 했다. 이렇게 할 때 문제는 복잡한 빈 등록 설정을 해줘야 한다는 것인데 빈 등록을 할 때 프록시 객체를 넘겨서 설정을 해주는 과정이 번거롭다. 게다가 빈을 컴포넌트 스캔으로 자동 등록할 때에는 이런식으로 수동으로 등록하기가 어렵다. 위와 같은 문제를 해결하기 위해 빈 후처리기를 사용한다. 빈 후처리기 (BeanPostProcessor) 객체를 스프링 빈 저장소에 등록하기 전에 조작을 할 수 있게 해주는 인터.. 더보기