관계형 데이터베이스·SQL과 트랜잭션
테이블 관계와 제약 조건으로 데이터의 의미를 표현하고, 트랜잭션과 매개변수화된 질의로 일관성과 안전성을 확보합니다.
개념부터 찾아보기
정의·역할·동작 원리를 독립 페이지에서 확인하세요. 본문의 밑줄 용어에도 설명이 있습니다.
이 노트에서 설명할 수 있게 되는 것
- 행·키·제약 조건과 인덱스의 역할을 구분한다.
- 여러 변경을 트랜잭션으로 묶어 성공·실패 상태를 추적한다.
- 결과 정확성과 질의 성능·동시성 문제를 별도로 관찰한다.
01테이블·키·제약조건으로 자료의 관계를 정의하기
- 테이블·행테이블의 행은 개별 자료, 열은 이름과 자료형을 가진 속성이다.
- 기본키·행기본키는 행을 유일하게 식별한다. 외래키는 같은 테이블 또는 다른 테이블의 참조 가능한 키와 연결되어 참조 무결성을 검사한다. 같은 테이블에서 부모 행을 가리키는 자기 참조도 가능하다.
- NOT NOT 은 값이 없음을 허용할지, UNIQUE는 중복을 허용할지, CHECK는 조건을 만족해야 하는지를 표현한다.
- CHECK와 이 예시의 amount CHECK (amount >= 0)만으로 이 금지되지는 않는다. 에서 CHECK는 false를 거부하므로 값이 필수인 설계라면 NOT 을 별도로 선언한다.
- DB 의 필요성애플리케이션에서만 유효성을 검사하면 동시 요청이나 다른 접속 경로가 그 규칙을 우회할 수 있으므로 핵심 데이터 불변 조건은 DB 제약으로도 표현한다.
- 예를 들어 orders의 customer_id가 customers에 존재해야 한다면 외래키가 관계의 일관성을 검사한다.
- 열이름 문자열을 모든 주문에 복사해 연결하면 같은 이름의 다른 사람이나 이름 변경을 처리하기 어렵다.
- 적절한 키로 연결하고 필요한 중복은 목적을 알고 선택한다.
- 는 이런 논리 구조이고 파일 시스템의 디렉터리 이름과 같은 개념은 아니다.
- 는 불필요한 중복과 갱신 이상을 줄이기 위한 설계 방법이다.
- 테이블모든 정보를 한 테이블에 넣는 편의와 실제 변경·조회 요구 사이의 비용을 함께 고려한다.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(80) NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER REFERENCES customers(id),
amount DECIMAL(12,2) CHECK (amount >= 0)
);교육용 예시. 실제 요청·발송·설정 변경을 실행한 결과가 아니다.
02SELECT의 행 선택·열 선택·JOIN·집계
- WHERE·행WHERE는 조건에 맞는 행을 선택하고 SELECT 목록은 결과의 열이나 표현식을 정한다.
- 의 결합 조건은 지정한 관계 조건으로 두 입력의 행을 결합한다.
- 잘못된 조합 수조건이 없거나 잘못되면 조합 수가 예상보다 크게 늘어날 수 있다.
- 는 같은 그룹 값을 묶고 SUM·COUNT 등은 그룹별 결과를 계산한다.
- 를 지정하지 않은 결과의 행 순서는 일반적으로 보장하지 않는다.
- ·집계 예제아래 쿼리는 고객과 주문을 고객 키로 연결한 뒤 고객별 주문액을 계산한다.
- INNER·LEFT INNER 이므로 주문이 없는 고객은 결과에 나타나지 않는다. 주문 없는 고객까지 포함하려면 LEFT 과 처리의 의미를 따로 설계한다.
- 열은 빈 문자열이나 숫자 0과 다르며 비교에 IS 을 사용한다.
- COUNT(*)와 COUNT(column)도 을 세는 방식이 다르다.
SELECT c.id, c.name, SUM(o.amount) AS total
FROM customers AS c
JOIN orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY total DESC;교육용 예시. 실제 요청·발송·설정 변경을 실행한 결과가 아니다.
03SQL 문장에서 실행 계획과 데이터 접근까지
- DBDB는 연결을 인증하고 문장을 파싱하여 문법, 이름, 자료형, 객체 권한을 해석한다.
- ·옵티마이저는 통계와 사용 가능한 를 바탕으로 접근 경로와 순서 등의 실행 계획을 선택한다.
- 스토리지 엔진의 접근스토리지 엔진은 버퍼 캐시와 데이터 페이지를 이용해 실제 행을 읽고 변경한다.
- SELECT·테이블모든 SELECT가 전체 테이블을 임시 View로 만든 뒤 권한을 검사하는 과정이라는 설명은 정확하지 않다.
- ·행는 특정 키로 필요한 행 위치를 빠르게 찾기 위한 추가 구조다.
- 열·B-tree 계열 는 범위·정렬 탐색에 쓰일 수 있지만 모든 조건에서 항상 선택되는 것은 아니다.
- 테이블·행작은 테이블이나 많은 행을 읽는 조건에서는 순차 탐색이 더 유리할 수 있다.
- INSERT·UPDATE·DELETE는 관련 도 유지해야 하므로 를 무조건 많이 만드는 것은 읽기·쓰기 비용의 균형을 무시한다.
- EXPLAIN·ANALYZEEXPLAIN의 추정 계획과 실제 실행을 수반할 수 있는 EXPLAIN ANALYZE를 구별한다.
EXPLAIN SELECT * FROM orders WHERE customer_id = 7;
# 실제 문법과 출력 열은 DBMS에 따라 다르다.
# 예상 행 수, 접근 방식, 사용 인덱스를 계획으로 읽는다.교육용 예시. 실제 요청·발송·설정 변경을 실행한 결과가 아니다.
04트랜잭션과 동시성: 재고 차감·주문 저장을 한 단위로
- 단위은 여러 변경을 한 논리 단위로 묶어 COMMIT 또는 ROLLBACK한다.
- 재고재고만 줄고 주문이 저장되지 않는 중간 상태가 최종 상태로 남지 않게 하는 것이 원자성의 예다.
- 일관성·격리·지속성일관성은 제약과 업무 규칙을 지킨 상태로 전환한다는 뜻이고, 격리는 동시에 실행되는 작업이 서로 관찰하는 범위를 다루며, 지속성은 성공 확정된 변경의 보존을 다룬다.
- 각 특성은 엔진·설정·장애 모델에 영향을 받는다.
- 영향받은 행 수아래 조건부 UPDATE에서 영향받은 행이 1인지 확인한 뒤 주문을 저장한다.
- 재고·행재고가 없으면 0행이 바뀌므로 주문 생성을 진행하지 않고 되돌린다.
- SELECT·재고SELECT로 재고를 읽고 나중에 무조건 감소시키는 방식은 두 사용자가 같은 재고를 보고 경쟁할 수 있다.
- 잠금·MVCC·격리 수준과 재시도 설계가 이 문제에 관여한다.
- Deadlock 후 재시도deadlock으로 한 이 중단되었다면 전체 업무 단위를 적절히 다시 시도해야 한다.
BEGIN;
UPDATE inventory SET stock = stock - 1
WHERE product_id = 42 AND stock > 0;
-- 애플리케이션이 영향받은 행 수 1을 확인한 경우에만 다음 단계
INSERT INTO orders (id, customer_id, amount) VALUES (1001, 7, 12000);
COMMIT;
-- 중간 단계 실패 경로에서는 COMMIT 대신 ROLLBACK교육용 예시. 실제 요청·발송·설정 변경을 실행한 결과가 아니다.
05MVCC의 행 버전과 문장별 스냅샷
- 적용 범위의 를 기준으로 한다. 다른 DBMS나 격리 수준에 이 규칙을 그대로 적용하지 않는다.
- 가시성 판단갱신 중인 행에는 이전 상태와 새 상태를 구별할 정보가 있다. SELECT는 자기 스냅샷에서 보이는 버전을 읽으며, 다른 세션의 미커밋 변경을 그대로 읽지 않는다.
- 문장 경계의 보통 SELECT는 각 명령 시작 시점까지 커밋된 자료를 본다. 같은 에서 연속한 두 SELECT도 그 사이 다른 세션이 커밋하면 다른 결과를 얻을 수 있다.
- UPDATE가 다른 이 변경 중인 행을 만나면 결과를 기다릴 수 있다. 상대가 커밋하면 최신 행에 WHERE 조건을 다시 적용하여 변경 대상을 결정한다.
- 격리 수준의 선택는 의 첫 비제어 문장에서 잡은 스냅샷을 계속 사용한다. 더 강한 격리는 충돌 오류와 전체 재시도도 함께 설계해야 한다.
06재고 1개를 두 세션이 동시에 차감하는 추적
- 초기 조건가상 상품 id=7의 stock은 1이다. A와 B가 각각 별도 에서 같은 조건부 UPDATE를 실행하며 를 사용한다고 가정한다.
- A의 변경A가 먼저 행을 잡아 stock을 0으로 바꾼다. 아직 커밋하지 않았으므로 B의 보통 SELECT가 1을 보더라도 B가 재고를 확보했다는 뜻은 아니다.
- B의 대기B의 UPDATE는 같은 행의 변경이 끝나기를 기다린다. 이 대기를 무시하고 주문부터 확정하면 DB의 조건부 차감을 업무 규칙에 연결하지 못한다.
- A 커밋 이후A가 커밋하면 B는 최신 stock=0에 stock>=1을 다시 대입한다. 조건이 거짓이므로 B의 영향받은 행 수는 0이고 주문 생성으로 진행하지 않는다.
- A 롤백의 분기A가 롤백했다면 stock은 다시 1인 상태로 평가할 수 있어 B가 차감할 수 있다. 대기 자체와 최종 실패를 같게 취급하지 않고 명령 결과를 읽는다.
UPDATE products
SET stock = stock - 1
WHERE id = 7 AND stock >= 1;실행하지 않은 교육용 . 영향받은 행 수와 결과를 애플리케이션에서 검사한다.
07EXPLAIN의 비용·실행 횟수·행 수 읽기
- 단위 구분cost=0.30..8.00의 값은 계획 비교용 비용 단위이며 밀리초가 아니다. actual time은 실행 측정치이므로 두 숫자를 바로 빼서 오차를 계산하지 않는다.
- 반복 횟수가상 노드가 actual time=0.010..0.040 rows=2 =100이면 한 번당 평균 2행을 내보냈고 전체 출력은 약 200행이다. 노드 시간도 반복 횟수를 고려한다.
- 포함 시간상위 노드의 시간에는 하위 작업이 포함될 수 있다. 모든 노드의 시간을 단순 합산하면 같은 일을 중복 계산한다.
- 추정 오차의 의미예상 rows=1인데 실제 평균 rows=200이면 선택도·통계·조건의 상관관계 등을 조사한다. 가 존재한다는 사실보다 실제 읽은 양과 반복 구조가 중요하다.
- 실행의 부작용EXPLAIN ANALYZE는 실제 실행한다. 변경 질의나 부작용이 있는 함수는 단순 조회 점검으로 취급하지 않으며, 여기의 출력은 실행하지 않은 해석 예시다.
08View·권한·매개변수 질의가 만드는 경계
- ViewView는 이름을 붙여 저장한 질의 정의로, 필요한 열이나 관계를 하나의 논리 객체로 제공할 수 있다.
- 매 SELECT의 결과 집합을 모두 View라고 부르지 않는다.
- View·행View의 실행 권한과 기반 테이블 권한은 DBMS의 보안 모델에 따라 다르며 앱 계정에 관리자 권한을 주는 대신 필요한 작업만 부여한다.
- 접속 성공과 특정 테이블의 수정 허용도 별개 단계다.
- 열은 입력값을 문자열에 결합해 값이 명령 구조로 해석될 때 발생한다.
- 매개변수는 명령 구조와 데이터를 분리해 전달한다.
- 테이블값 바인딩은 테이블 이름·정렬 방향 같은 식별자나 키워드를 아무 위치에나 대체하는 기능이 아니므로 이런 선택은 허용 목록으로 구성한다.
- 예제아래는 DB-API의 SQLite 방식 물음표 자리표시자 예이며 다른 드라이버는 %s 등 규약이 다를 수 있다.
cursor.execute(
"SELECT id, name FROM customers WHERE id = ?",
(customer_id,),
)
rows = cursor.fetchall()
# customer_id는 SQL 코드 조각이 아니라 값으로 전달된다.교육용 예시. 실제 요청·발송·설정 변경을 실행한 결과가 아니다.
09연결 확인과 오류 기록의 범위
- 테이블·아래 상수 조회는 연결과 기본 질의 처리를 확인하지만 실제 업무 테이블 권한이나 성공까지 증명하지 않는다.
- 오류 응답의 정보 노출오류 응답에 질의문과 내부 구조를 노출하지 않고, 로그에서도 인증 정보와 개인정보를 보호한다.
SELECT 1 AS connection_check;연결한 데이터베이스에서 상수 조회만 수행하는 기본 확인 예시이다.
MariaDB 연결 성공 뒤 SQL 문법·선택 DB 상태 읽기
접속 성공, 구문 오류, 현재 DB, 전송 방식의 정보를 실제 클라이언트 출력에서 분리한다.
실습 구성과 전제
- 두 사진은 다른 세션·계정의 조회 결과다. 권한이 같은 한 세션의 연속 출력처럼 읽지 않는다.
- 실습 계정은 준비된 DB 서버의 최소 조회 권한을 사용한다. -p 뒤에 실제 암호를 붙여 명령 기록에 남기지 않는다.
로그인과 SQL 파싱을 구별한다
- 프롬프트까지 들어왔다는 것은 해당 연결의 인증이 완료되었다는 뜻이다. 그 뒤 show database의 ERROR 1064는 구문 단계에서 난 오류다.
- 복수형 SHOW DATABASES로 고치면 목록이 반환된다. 목록은 현재 계정이 볼 수 있는 DB 범위를 반영하므로 서버의 모든 DB가 반드시 보인다고 단정하지 않는다.
SHOW DATABASES; SELECT VERSION(), CURRENT_USER(), DATABASE();접속한 세션에서 서버 버전·권한 계정·선택 DB를 읽는 조회 예시다.
원본 크기로 보기 ↗- 로그인 후 MariaDB 프롬프트와 10.5.29 서버 버전이 표시된다.
- show database는 1064 오류를 내고 show databases는 네 행의 목록을 반환한다.
확인 기준구문 오류를 인증 실패로 처리하지 않는다. 서버 응답을 받은 시점과 실패한 문장을 함께 기록한다.
현재 데이터베이스와 접속 경로를 읽는다
- status 화면에는 접속 사용자, 연결 방식, 문자 집합 등이 따로 나온다. Current database가 비어 있으면 기본 DB를 선택하지 않은 상태이며, 인증 실패가 아니다.
- 별도 사진은 UNIX 소켓 연결이므로 SSL Not in use를 곧바로 원격 구간의 평문 전송 증거로 해석하지 않는다. 전송 경로를 먼저 구분해야 한다.
원본 크기로 보기 ↗- Connection 항목은 Localhost via UNIX socket이고 Current database는 비어 있다.
- SSL Not in use와 여러 utf8mb4 문자 집합 항목이 각각 별도 행으로 보인다.
확인 기준현재 세션의 권한과 전송 방식을 확인한 뒤 결과를 해석한다. socket 접속과 접속은 계정 매칭·보안 조건이 달라질 수 있다.
스키마 선택 후 이름 해석을 확인한다
- 테이블 이름만 쓸 때는 현재 DB를 기준으로 찾는다. USE로 DB를 선택하거나 DB명.테이블명으로 명시하면 어떤 객체를 조회했는지 분명해진다.
- 목록 표시 권한, 테이블 읽기 권한, 테이블 존재 여부는 다르다. SELECT DATABASE()가 인 경우에도 SELECT 1 같은 특정 DB에 의존하지 않는 질의는 실행될 수 있다.
SELECT DATABASE(); USE labdb; SELECT DATABASE(); SHOW TABLES;labdb는 준비한 실습 DB 이름이다. 출력은 실제 실행 세션에서 확인한다.
확인 기준재구성한 labdb가 실제 준비된 경우에만 USE를 적용한다. Unknown database·table does not exist·access denied를 서로 다른 원인으로 분류한다.
실습에서 확인한 동작 원리
- 접속 성공 뒤에도 문법, 객체 선택, 개별 권한 단계에서 각각 오류가 발생한다.
- 현재 DB와 연결 방식은 status·DATABASE() 같은 명시적 조회로 확인하며 화면 하나의 성공을 확대하지 않는다.
설정·출력 추가로 확인하기 27장
아래 화면을 펼쳐 위 실습의 설정값, 명령과 확인 기준을 비교해 보세요. 각 묶음은 별도 실습 기록입니다.
실습 화면 묶음 01 1장
원본 크기로 보기 ↗- 「전체 사진」 문맥에 삽입된 원본 설정·관리 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
실습 화면 묶음 02 15장
원본 크기로 보기 ↗- 「mariaDB」 문맥에 삽입된 원본 설정·관리 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 에 삽입된 원본 학습 화면이다. MariaDB 클라이언트에서 지정한 사용자로 접속한 뒤 서버 버전과 SQL 입력 프롬프트를 확인하는 화면이다.
원본 크기로 보기 ↗- 「mariaDB」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB 명령어」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB 명령어」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB 명령어」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB 명령어」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB 명령어」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB 명령어」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB 명령어」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 에 삽입된 원본 학습 화면이다. phpMyAdmin 사용자 추가 화면에서 접속 호스트·인증 방식·데이터베이스 권한·전역 권한·자원 제한을 설정하는 예시이다.
원본 크기로 보기 ↗- 「phpmyadmin」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
원본 크기로 보기 ↗- 「mariaDB」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
실습 화면 묶음 03 1장
원본 크기로 보기 ↗- 「nmap -sC : 기본 NSE 스크립트를 실행.」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
실습 화면 묶음 04 1장
원본 크기로 보기 ↗- 학습 원본 · MariaDB 서비스·쿼리 로그 설정의 DB 개론에 수록된 화면·도식이다.
실습 화면 묶음 05 1장
원본 크기로 보기 ↗- 학습 원본 · MariaDB 서비스·쿼리 로그 설정의 DB 개론에 수록된 화면·도식이다.
실습 화면 묶음 06 1장
원본 크기로 보기 ↗- 학습 원본 · MariaDB 서비스·쿼리 로그 설정의 DB 개론에 수록된 화면·도식이다.
실습 화면 묶음 07 1장
원본 크기로 보기 ↗- 학습 원본 · MariaDB 서비스·쿼리 로그 설정의 DB 개론에 수록된 화면·도식이다.
실습 화면 묶음 08 1장
원본 크기로 보기 ↗- 학습 원본 · MariaDB 서비스·쿼리 로그 설정의 DB 개론에 수록된 화면·도식이다.
실습 화면 묶음 09 1장
원본 크기로 보기 ↗- 학습 원본 · MariaDB 서비스·쿼리 로그 설정의 DB 개론에 수록된 화면·도식이다.
실습 화면 묶음 10 1장
원본 크기로 보기 ↗- 학습 원본 · MariaDB 서비스·쿼리 로그 설정의 DB 개론에 수록된 화면·도식이다.
실습 화면 묶음 11 1장
원본 크기로 보기 ↗- 「mariadb-server.cnf , root 계정 생성」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
실습 화면 묶음 12 1장
원본 크기로 보기 ↗- 「mariadb」 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
실습 화면 묶음 13 1장
원본 크기로 보기 ↗- 문서 문맥에 삽입된 원본 실습·개념 참고 화면이다. 관계형 데이터베이스·SQL과 트랜잭션 학습 내용과 함께 당시 구성·설정·관찰 결과를 비교할 수 있다.
동작·명령 참고 문서
10두 변경을 하나의 트랜잭션으로 묶기
- 두 변경의 일관성재고에서 한 개를 차감하고 주문 한 건을 기록하는 업무를 생각한다. 첫 변경만 성공하고 두 번째가 실패하면 재고와 주문이 서로 맞지 않는 상태가 될 수 있다.
- 성공 확정·중간 취소 안에서 필요한 조건을 확인하고 두 변경을 수행한 뒤 커밋하면 하나의 처리 단위로 확정할 수 있다. 오류가 발생하면 해당 의 변경을 롤백하여 중간 결과가 최종 상태로 남지 않도록 한다.
- 오류 후 상태 규칙실제 오류 뒤 처리 방식은 DBMS와 드라이버의 상태 규칙에 맞춰야 한다.
- 원자성만으로 모든 동시성 문제가 해결되지는 않는다.
- 동시 요청의 갱신 충돌두 요청이 같은 남은 재고를 읽은 뒤 각각 수정하면 설계에 따라 중복 판매나 갱신 손실이 생길 수 있다.
- 잠금·격리 수준조건부 갱신, 적절한 잠금, 격리 수준, 제약 조건을 조합하고 경쟁에서 실패한 요청의 재시도 정책을 정한다.
- ·한 안에서 지킨 일관성은 제약과 업무 로직이 올바르게 작성됐다는 전제에도 의존한다.
- 보장 조건라는 약어를 붙였다는 이유로 잘못된 업무 코드를 DB가 자동 교정하지는 않는다.
- 시작재고 변경과 주문 기록을 하나의 경계에 넣는다.
- 재고 조건 확인·차감동시성 정책에 맞춰 재고를 차감하되 아직 커밋하지 않는다.
- 주문 기록 시도주문 삽입에서 제약 조건 위반이 발생하는 상황을 가정한다.
- 오류 전달애플리케이션이 오류와 상태를 확인한다.
- ROLLBACK이 에서 확정하지 않은 변경을 취소한다.
- 취소 결과 확인중간 변경을 성공으로 보고하지 않고 해당 주문 실패를 처리한다.
설명과 함께 보는 보조 도식
주문 기록 실패와 트랜잭션 롤백
주문 삽입 단계의 제약 오류로 트랜잭션을 취소하는 하나의 실패 경로다. 커밋 성공 경로와 연속된 동작이 아니다.
트랜잭션 시작
재고 변경과 주문 기록을 하나의 경계에 넣는다.
- 상태
- 확정 전
전체 단계를 한 번에 읽기
- 01
트랜잭션 시작
재고 변경과 주문 기록을 하나의 경계에 넣는다.
- 상태
- 확정 전
- 02
재고 조건 확인·차감
동시성 정책에 맞춰 재고를 차감하되 아직 커밋하지 않는다.
- 재고 변경
- 미확정
- 03
주문 기록 시도
주문 삽입에서 제약 조건 위반이 발생하는 상황을 가정한다.
- 실패 위치
- 주문 삽입
- 04
오류 전달
애플리케이션이 오류와 트랜잭션 상태를 확인한다.
- 업무 전체
- 아직 성공 아님
- 05
ROLLBACK
이 트랜잭션에서 확정하지 않은 변경을 취소한다.
- 결과
- 재고 차감도 취소
- 06
취소 결과 확인
중간 변경을 성공으로 보고하지 않고 해당 주문 실패를 처리한다.
- 최종
- 부분 변경이 확정되지 않음
11느린 질의와 잘못된 결과의 구분
- 관계와 결과 행 수같은 행이 예상보다 많이 나오는 경우에는 조건과 관계의 다대일·다대다 구조를 먼저 확인한다.
- 로 못 고치는 오류성능이 느리다는 이유로 만 추가해도 잘못된 관계 연산은 고쳐지지 않는다.
- 선택도·실행 계획행 수와 필터 선택도, 정렬·집계 범위를 확인한 뒤 실행 계획의 실제 접근 방식을 읽는다.
- 결과와 처리 비용 사용 여부 자체가 목표가 아니라 필요한 결과를 적절한 비용으로 구하는 것이 목표다.
- 작은 테이블에서는 전체 읽기가 합리적인 선택일 수도 있다.
- 잠금응답 지연은 질의 자체의 연산량뿐 아니라 잠금 대기, 연결 풀 고갈, 네트워크와 디스크 지연에서도 생긴다.
- 실행 시간·잠금 대기실행 시간과 대기 시간을 분리하고 오래 열린 이 다른 작업을 붙잡고 있는지 확인한다.
- 입력 값입력 값은 바인딩하고 식별자·정렬 방식처럼 질의 구조에 영향을 주는 요소는 허용 범위를 정한다.
- 실행 계획운영 DB에서 실행 계획을 확인할 때 실제 실행을 수반하는 옵션의 영향도 구분해야 한다.
- 조회처럼 보이는 진단이 무거운 업무 질의를 재실행할 수 있다.
| 구성·관찰 대상 | 관찰 내용 | 해석 |
|---|---|---|
| 키·관계·제약 | 중복과 잘못된 참조 | |
| 경계·격리·잠금 | 부분 변경·동시성 충돌 | |
| 실행 계획 | 읽은 행·연산·정렬 | 질의 비용과 선택 |
| 대기 상태 | 연결·잠금·I/O | 계산 밖의 지연 |
함께 보는 학습 자료
아래 공식 자료를 본문의 개념·예제와 함께 읽어 보세요. 자료별로 확인할 위치와 관찰할 내용을 적었습니다.
PostgreSQL 격리 수준과 경쟁 UPDATE 추적
13.2.1 의 두 세션 UPDATE 설명부터 읽고 13.2.2와 비교한다. 현재 사이트의 재고 차감 예제에 대기·재평가·재시도 조건을 대입할 수 있다.
- 보통 SELECT가 문장 시작 시점의 스냅샷을 쓰는 조건
- 경쟁 UPDATE 커밋 뒤 WHERE를 다시 검사하는 이유
- 에서 전체 재시도가 필요한 경우
이해했는지 확인하기
- 기본 키·외래 키·제약 조건의 목적을 설명한다.
- 트랜잭션 경계와 동시성 영향을 확인한다.
- 입력 값은 매개변수로 전달하고 식별자는 제한한다.
