grit.log
로그인
grit.log
로그인
OLTP기술 (트랜잭션,LOCK)
K
·
2022년 6월 16일
팔로우
0
SQL BOOSTER
0
SQL BOOSTER
목록 보기
8/12
1. 트랜잭션
반드시 한번에 처리되어야 하는 논리적 작업단위 (EX. 은행 계좌 이체 처리등)
COMMIT은 트랜잭션중 변경된 데이터를 모두반영하고 종료
ROLLBACK은 트랜잭션중 진행된 작업을 모두 취소하고 종료.
SQL문장에서 에러가나도 에러발생한 문장만 ROLLBACK시킬뿐 트랜잭션을 여전히 살아있음.
명시적으로 ROLLBACK을 실행해야만 트랜잭션 전체를 되돌릴 수 있다.
트랜잭션은 데이터 변경 SQL이 실행되는 순간 시작, 시작된 트랜잭션은 COMMIT이나 ROLLBACK을 만나기 전까지 유지
요점
트랜잭션은 한번에 이루어져야하는 작업단위
COMMIT이나 ROLLBACK으로 종료가 이루어진다.
COMMIT종료시 트랜잭션 변경사항은 모두 DB에 실제반영
ROLLBACK종료시 트랜잭션 시작 이전으로 복구
트랜잭션 내에서 에러가 발생했다고해서 자동 ROLLBACK이 수행되진않는다.
2. 트랜잭션 고립화 수준
하나의 트랜잭션에서 작업중인 데이터가 다른 트랜잭션에 영향을 받지 않는 정도.
하나의 트랜잭션에서 작업중인 데이터를 다른트랜잭션에서 어느정도까지 접근가능한 정도
고립화수준이 낮으면 서로 다른 트랜잭션간 접근이가능
고립화 수준이 높으면 조회만 한 데이터도 다른 트랜잭션이 변경 못함
고립화 수준 : READ UNCOMMITTED - READ COMMITED - REPEATABLE READ - SERIALIZABLE READ
오라클의 기본 고립수준은 READ COMMITTED
2.1 READ COMMITTED : UPDATE -SELECT 테스트
세션1 변경 후 COMMIT안함 > 세션2 조회시 변경전데이터조회
세션1 변경 후 COMMIT안함 > 세션2 동일데이터 변경 불가. 대기상태(WAIT)
2.2 READ COMMITTED : INSERT-INSERT테스트
세션1 ACC4 INSERT COMMIT안함 > 세션2 ACC4 INSERT COMMIT안함 > 세션2 WAIT
> 세션1 COMMIT > 세션2 오류 PK필드에 동일한 ACC4입력으로인한 오류
세션1 ACC5 INSERT > 세션2 ACC99 INSERT (NO WAIT) > 세션2 ACC5 INSERT (WAIT)
> 세션1 COMMIT > 세션 2 중복에러 > 세션2 ROLLBACK < 세션2 ACC99 INSERT까지 취소
2.3 READ-COMMITTED특징
한 트랜잭션 변경중데이터는, 다른트랜잭션에서 변경전 데이터만 조회가능
한트랜잭션이 변경중 데이터는 다른 트랜잭션에서 동시변경 불가 (WAIT상태됨)
동일 PK, UNIQUE KEY 데이터가 동시입력되면 후행트랜잭션은 대기상태
에러가발생해도 트랜잭션 전체 ROLLBACK안됨.
3. 락(LOCK)
데이터에 잠금을 걸어놓는장치, 데이터를 잠근 세션 외에 다른세션들은 잠긴데이터에 접근불가.
잠금을 통해 고립회 수준을 구현할 수 있다.
데이터 변경하면 해당 ROW에 락을 걸고 트랜잭션이 COMMIT또는 ROLLBACK할때까지 유지
2.1 2.2 2.3의 테스트에서 WAIT가 발생하는것이 선행 트랜잭션에서 LOCK을걸었기 때문
3.1 SELECT ~ FOR UPDATE
SELECT는 수행중인 트랜잭션 이전 데이터를 가져오므로 값의 차이가발생
SELECT ~ FOR UPDATE사용지 동시접근하는 데이터의 트랜잭션이 완료될때까지 WAIT하므로
동시발생 트랜잭션에 의한 값 오류방지가능.
NOWAIT 옵션 : 대기상태에 빠지자 마자 예외 발생
WAIT SECONDS옵션 : 대기할 초를 설정, 해당시간초과시 예외 발생
예외 발생시 트랜잭션을 ROLLBACK처리하고 나오거나 재처리 유도가능, 업무에 맞게 사용
꼭 종료(COMMIT, ROLLBACK)해줘야함
3.2 대기(WAIT) 상태
대기상태 세션이 많아지면 시스템이 장애로 빠질수 있음.
대부분 시스템은 DB연결 및 접근에 폴링(Polling)처리.
폴링은 WAS에서 특정 수만큼 세션을 DB와 미리 연결해놓고 여러명의 사용자가 세션을 공유해 사용하는 방식
DB와 연결을 맺는 작업은 WAS와 DB모두 많은 자원을 소모하므로 폴링방식 사용이 일반적
폴링을 사용하는 구조에서 연결된 세션이 모두 대기상태에 빠지면 시스템은 더는 작동하지 않음
세션이 대기상태에 빠지는것은 느린SQL과 종료(COMMIT OR ROLLBACK)되지 않은 락에 의해서
느린 SQL이많을수록 세션을 사용하기위한 대기시간이 길다.
느린것보다 더무서운것은 제대로 종료되지않은 트랜잭션, 락으로 인해 세션이 무한정대기상태에 빠질 수 있음.
시스템 동시성 높이려면 불필요한 SELECT~FOR UPDATE피하고 트랜잭션은 항상 제대로 종료
3.4 데드락(DEAD-LOCK,교착상태)
시스템 개발 후 가장 잡아내기 어려운 에러중하나가 데드락
첫 세션이 두번째 세션의 작업이 끝나기를 기다리고있고, 두번째 세션도ㅗ 첫번째 세션의 작업이 끝나기를 기다리는상태 (상호대기)
락은 데이터정확성을 위해 기다리는(정상적인) 상태지만, 데드락은 더는 트랜잭션을 진행할 수 없는 상태.
세션1에서 ACC1을 SELECT FOR UPDATE, 세션2에서 ACC2를 SELECT FOR UPDATE
> 트랜잭션 종료전에 세션1에서 ACC2를 UPDATE시도, 세션2에서 ACC2을 UPDATE시도
> DEAD LOCK
바로위 예제상황을 막기 위해서는 ACC1과 ACC2에 동시에 락을 생성하면된다.
아래처럼 하면 세션1에서 처리하는동안 세션2는 대기가 되고 세션1종료후 세션2수행됨.
SELECT T1.ACC_NO, T1.BAL_AMT FROM M_ACC T1
WHERE T1.ACC_NO IN ('ACC1','ACC2') FOR UPDATE;
3.5 트랜잭션 최소화
대기세션이 많을수록 시스템은 느려지므로 데이터 변경이 포함된 트랜잭션은 최적화가 필요
SQL단위로 최적화가 필요하며, 유사반복실행되는 SQL을 합쳐서 트랜잭션길이 최소화해야한다.
줄이기위해 SQL복잡도가 올라가는것은 유지보수관점에서좋지않다
다른개발자가 알아볼수있는선에서 복잡하지 않게 SQL을 구현해야 한다.
3.6 방어로직
SELECT ~ FOR UPDATE 사용시 조회시점부터 락을 생성해 동시성을 떨어트리는 단점이있음
방어로직을 사용하면 동시성을 떨어트리지 않고, 데이터 정확성 확보가능
조회 시점에 잔액을 저장해놓고, 변경시점에 잔액이 변경되지 않았을때만 UPDATE
테이블에 최종변경일시와 같은 변경 기록 컬럼을 추가해 사용할 수 있음.
조회시점과 변경시점에 최종변경일시 값이 다르다면, 누군가 중간에 데이터를 변경한것이므로
예외 처리하면 된다.
데이터 조회시점에는 변경락을 발생시키지 않는것이 핵심.
3.7 불필요한 트랜잭션의 분리
트랜잭션의 주요 연관성이 떨어지는 작업을 분리하면 트랜잭션 실행시간을 줄일 수 있음.
이로인한 트랜잭션에서 만든 락을 빠르게 해소할 수 있으며 데이터베이스 동시성을 높일수있음
EX) 주문처리 트랜잭션에서 주문관련 처리는 모두 완료되었으나, 문자발송 로직이 문제가 생겨 락이발생하는 경우
K
늙어가면서 기억을 남기는 개발자
팔로우
이전 포스트
JOIN과 성능
다음 포스트
OLTP기술(문서번호 처리기술, 시퀀스와 ROWNUM)
0개의 댓글
댓글 작성