MYSQL DB 4가지 트랜잭션 격리레벨에 대해

2026. 1. 30. 16:10·데이터베이스

0. 들어가며

웹 애플리케이션에서 데이터베이스는 여러 사용자의 요청을 동시에 처리해야 합니다.
이 과정에서 여러 트랜잭션이 동시에 실행되며, 서로 같은 데이터를 읽고 수정하는 상황은 자연스럽게 발생합니다.

문제는 이러한 동시성 환경에서 데이터의 정합성을 어떻게 보장할 것인가입니다.


모든 트랜잭션을 순차적으로 처리하면 정합성은 보장되지만 성능이 급격히 저하되고 반대로 동시성을 최대한 허용하면 성능은 좋아지지만 예기치 않은 데이터 불일치가 발생할 수 있습니다.

 

 

이러한 균형을 조절하기 위해 데이터베이스는 트랜잭션 격리 레벨(Isolation Level) 이라는 개념을 제공합니다.
격리 레벨은 트랜잭션들이 서로의 변경 사항을 어디까지 허용할지 그리고 어떤 시점의 데이터를 기준으로 읽을지를 결정하는 기준이 됩니다.

 

MySQL은 이러한 요구를 충족하기 위해 네 가지 트랜잭션 격리 레벨을 제공하며 각 격리 레벨은 성능과 정합성 사이에서 서로 다른 선택지가 있습니다.

 

 

이 글에서는 MySQL에서 제공하는 네 가지 트랜잭션 격리 레벨을 중심으로 각 레벨의 동작 방식과 특징, 그리고 어떤 상황에서 선택하는 것이 적절한지 정리해보겠습니다.

 


1. 트랜잭션 격리 레벨이란 무엇인가

1. 트랜잭션 격리 레벨이란 무엇인가

트랜잭션 격리 레벨을 이해하기 위해서는 먼저 동시성 문제가 무엇인지 알아야 합니다.

데이터베이스는 수십, 수백 개의 트랜잭션을 동시에 처리합니다. 만약 각 트랜잭션이 완전히 독립적이라면 문제가 없겠지만, 현실은 그렇지 않습니다. 여러 트랜잭션이 같은 데이터를 읽고 쓰려고 할 때, 그들이 서로의 변경사항을 어떻게, 언제 볼 수 있는지가 매우 중요해집니다.

트랜잭션 격리 레벨은 이를 해결하기 위해  동시에 실행되는 트랜잭션들이 서로의 변경 사항을 어디까지, 어떤 시점을 기준으로 볼 수 있는지를 정의하는 규칙입니다. 이것은 본질적으로 시간에 대한 규칙입니다.

 

 

생각해보면 트랜잭션마다 보는 시간이 다를 수 있습니다. A 트랜잭션은 자신이 시작한 시점의 데이터를 보고, B 트랜잭션은 현재 시점의 데이터를 봅니다. 누가 옳고 그른가요? 정답은 없습니다. 비즈니스 요구사항에 따라 다릅니다. 실시간 재고 현황을 보여줘야 하는 모니터링 시스템이라면 최신 데이터를 보는 것이 중요하고, 회계 결산처럼 일관된 시점의 데이터로 계산해야 하는 경우라면 트랜잭션 시작 시점의 스냅샷을 유지하는 것이 중요합니다.

 

 

격리 레벨은 이런 선택의 문제입니다. 격리를 느슨하게 설정하면 성능과 동시성은 좋아지지만, 데이터 정합성은 약해집니다.
반대로 격리를 엄격하게 설정하면 정합성은 높아지지만, 성능과 동시성은 희생됩니다. 이것은 트레이드오프입니다.

 

SQL-92 표준은 네 가지 격리 레벨을 정의합니다. READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE입니다.

MySQL은 이 네 가지를 모두 지원하며, 기본값으로 REPEATABLE READ를 사용합니다. 각각을 자세히 살펴보겠습니다


2. READ UNCOMMITTED - 정합성을 포기한 극단적 성능

READ UNCOMMITTED는 트랜잭션 격리 레벨 중 가장 낮은 단계입니다. 이름에서 알 수 있듯이 커밋되지 않은 데이터도 읽을 수 있습니다. 다른 트랜잭션이 변경한 데이터를 아직 커밋하지 않았더라도, 그 변경사항을 즉시 볼 수 있다는 의미입니다.

 

 

이것이 어떤 의미인지 구체적인 상황을 통해 이해해보겠습니다.

A 트랜잭션이 계좌 잔액을 100만원에서 0원으로 변경했습니다. 아직 커밋하지 않은 상태입니다. 이 시점에 B 트랜잭션이 잔액을 조회하면 0원이 보입니다. 그런데 A 트랜잭션이 롤백했습니다. 실제로는 잔액이 여전히 100만원인데, B 트랜잭션은 0원이라는 값을 읽은 것입니다.

-- A 트랜잭션
START TRANSACTION;
UPDATE account SET balance = 0 WHERE id = 1;  -- 100 → 0

-- B 트랜잭션 (READ UNCOMMITTED)
START TRANSACTION;
SELECT balance FROM account WHERE id = 1;  -- 0원이 조회됨

-- A 트랜잭션
ROLLBACK;  -- 잔액은 다시 100만원

-- 하지만 B는 이미 0원을 읽었음

이것을 Dirty Read라고 합니다. 더러운 데이터, 즉 아직 확정되지 않은 데이터를 읽었다는 뜻입니다.

B 트랜잭션은 실제로 존재하지 않는 상태의 데이터를 기반으로 의사결정을 하게 됩니다. 만약 B가 이 정보를 바탕으로 "잔액이 부족합니다"라는 메시지를 사용자에게 보여줬다면, 사용자는 혼란스러울 것입니다.

 

 

READ UNCOMMITTED는 트랜잭션이라는 시간 개념을 거의 무시합니다. 메모리에 현재 보이는 값을 그대로 읽을 뿐, 그것이 커밋될 것인지 롤백될 것인지 전혀 고려하지 않습니다. 이것은 정합성을 완전히 포기하고 성능만을 추구하는 극단적인 선택입니다.

 

 

그렇다면 이 격리 레벨을 언제 사용해야 할까요? 사실 거의 사용하지 않습니다.

데이터 정합성이 중요하지 않고, 대략적인 수치만 빠르게 확인하면 되는 경우에만 고려할 수 있습니다.

 

예를 들어 개발 환경에서 성능 테스트를 할 때나, 실시간 대시보드에서 대략적인 수치만 보여줘도 되는 경우입니다. 하지만 프로덕션 환경에서 비즈니스 로직에 이 격리 레벨을 사용하는 것은 매우 위험합니다.

 

 


3. READ COMMITTED - 최신성을 우선하는 균형점

READ COMMITTED는 커밋된 데이터만 읽을 수 있는 격리 레벨입니다.
이것은 READ UNCOMMITTED의 문제점인 Dirty Read를 해결합니다. 다른 트랜잭션이 변경한 데이터를 보려면, 그 트랜잭션이 반드시 커밋되어야 합니다.

 

이것이 어떻게 동작하는지 같은 상황으로 다시 살펴보겠습니다. A 트랜잭션이 계좌 잔액을 100만원에서 0원으로 변경했지만 아직 커밋하지 않았습니다. 이 상태에서 B 트랜잭션이 잔액을 조회하면 여전히 100만원이 보입니다. A가 커밋하지 않았기 때문입니다. A가 커밋한 후에야 B는 0원을 볼 수 있습니다.

-- A 트랜잭션
START TRANSACTION;
UPDATE account SET balance = 0 WHERE id = 1;

-- B 트랜잭션 (READ COMMITTED)
START TRANSACTION;
SELECT balance FROM account WHERE id = 1;  -- 100만원 (A가 커밋 전이므로)

-- A 트랜잭션
COMMIT;

-- B 트랜잭션
SELECT balance FROM account WHERE id = 1;  -- 0원 (A가 커밋했으므로)

여기서 중요한 점은 B 트랜잭션이 같은 쿼리를 두 번 실행했는데 결과가 달라진다는 것입니다.
첫 번째 조회에서는 100만원이었지만, 두 번째 조회에서는 0원입니다. 같은 트랜잭션 안에서 같은 데이터를 읽었는데 결과가 다른 것입니다. 이것을 Non-Repeatable Read라고 합니다.

 

READ COMMITTED는 내부적으로 MVCC(Multi-Version Concurrency Control)를 사용합니다.
MVCC는 데이터의 여러 버전을 유지하는 기술입니다. 데이터가 변경될 때, 이전 버전을 Undo Log에 보관하고 새로운 버전을 생성합니다. READ COMMITTED에서는 SELECT를 실행할 때마다 새로운 Read View를 생성하여, 그 시점에 커밋된 최신 데이터를 읽습니다.

 

 

이것의 장점은 다음과 같습니다.
항상 최신의 커밋된 데이터를 볼 수 있습니다. 실시간으로 변화하는 데이터를 반영해야 하는 애플리케이션에 적합합니다. 또한 락을 최소화하여 동시성이 매우 높습니다. 읽기 작업이 쓰기 작업을 막지 않고, 쓰기 작업도 읽기 작업을 막지 않습니다.

 

 

하지만 단점도 있습니다. 트랜잭션 내부의 일관성이 약합니다.
같은 트랜잭션 안에서 같은 쿼리를 실행해도 결과가 달라질 수 있기 때문입니다.

 

예를 들어 계좌 이체 로직을 생각해봅시다. A 계좌에서 출금하고 B 계좌에 입금하는 과정에서, A 계좌의 잔액을 두 번 조회했는데 결과가 다르다면 로직이 복잡해질 수 있습니다.

 

 

그래서 READ COMMITTED는 주로 조회 위주의 작업에 사용됩니다. 통계를 내거나, 모니터링 시스템에서 현재 상태를 확인하거나, 읽기 전용 API에서 최신 데이터를 보여줘야 할 때 적합합니다. PostgreSQL과 Oracle의 기본 격리 레벨이 READCOMMITTED인 이유도 이것입니다. 높은 동시성과 최신 데이터 반영을 중요하게 여기는 것이죠.


4. REPEATABLE READ - MySQL이 선택한 균형점

 

REPEATABLE READ는 MySQL의 기본 격리 레벨입니다.
이것은 READ COMMITTED의 문제점인 Non-Repeatable Read를 해결합니다. 같은 트랜잭션 안에서는 같은 쿼리를 여러 번 실행해도 항상 같은 결과를 보장합니다.

 

이것이 가능한 이유는 트랜잭션이 시작될 때 스냅샷을 생성하고, 트랜잭션이 끝날 때까지 그 스냅샷을 유지하기 때문입니다.

READ COMMITTED에서는 SELECT를 실행할 때마다 새로운 Read View를 생성했지만, REPEATABLE READ에서는 트랜잭션 시작 시점에 한 번만 Read View를 생성하고 이후의 모든 SELECT는 같은 Read View를 사용합니다.

 

-- A 트랜잭션 (REPEATABLE READ)
START TRANSACTION;
SELECT balance FROM account WHERE id = 1;  -- 100만원

-- B 트랜잭션
START TRANSACTION;
UPDATE account SET balance = 0 WHERE id = 1;
COMMIT;

-- A 트랜잭션
SELECT balance FROM account WHERE id = 1;  -- 여전히 100만원
COMMIT;

-- 이제 조회하면
SELECT balance FROM account WHERE id = 1;  -- 0원

A 트랜잭션은 시작 시점의 데이터를 계속 봅니다. B가 잔액을 0원으로 변경하고 커밋했지만, A는 여전히 100만원을 봅니다. A가 커밋된 후에야 새로운 트랜잭션에서 0원을 볼 수 있습니다. 이것이 트랜잭션의 일관된 읽기(Consistent Read)입니다.

 

 

내부적으로 이것은 MVCC와 Undo Log를 통해 구현됩니다.

데이터가 변경되면 이전 버전은 Undo Log에 체인 형태로 보관됩니다. 트랜잭션이 데이터를 읽을 때, 자신의 시작 시점보다 나중에 커밋된 버전은 무시하고 Undo Log를 따라가며 자신이 볼 수 있는 버전을 찾습니다. 이렇게 과거의 특정 시점 스냅샷을 재구성하는 것입니다.

 

 

REPEATABLE READ의 장점은 트랜잭션 내부의 일관성이 강력하다는 것입니다. 복잡한 비즈니스 로직을 처리할 때, 같은 데이터를 여러 번 읽어도 결과가 변하지 않는다는 것을 보장받을 수 있습니다. 계좌 이체처럼 여러 단계의 검증과 계산이 필요한 작업에서 중간에 데이터가 변하면 로직이 복잡해지는데, REPEATABLE READ는 이런 걱정을 덜어줍니다.

 

 

하지만 완벽하지는 않습니다. Phantom Read라는 문제가 있습니다. 이것은 새로운 행이 삽입되는 경우에 발생합니다. MVCC는 기존 행의 변경은 제어할 수 있지만, 아직 존재하지 않던 행의 삽입은 막을 수 없습니다.

 

-- A 트랜잭션
START TRANSACTION;
SELECT COUNT(*) FROM orders WHERE status = 'PENDING';  -- 10건

-- B 트랜잭션
START TRANSACTION;
INSERT INTO orders (status) VALUES ('PENDING');
COMMIT;

-- A 트랜잭션
SELECT COUNT(*) FROM orders WHERE status = 'PENDING';  -- 11건?

표준 REPEATABLE READ에서는 이런 일이 발생할 수 있습니다. 하지만 MySQL의 InnoDB 스토리지 엔진은 이 문제를 락을 통해 해결합니다. Gap Lock과 Next-Key Lock이라는 특별한 락 메커니즘을 사용합니다.

 

Gap Lock은 인덱스 값 사이의 빈 구간에 락을 거는 것입니다.

예를 들어 id가 1, 3, 5인 행이 있을 때, 2와 4 사이의 빈 공간에도 락을 겁니다. 그래서 다른 트랜잭션이 id=2나 id=4인 행을 삽입하려고 하면 대기하게 됩니다.

Next-Key Lock은 Record Lock과 Gap Lock을 결합한 것입니다. 특정 레코드와 그 앞의 간격에 동시에 락을 겁니다. 범위 조건으로 데이터를 조회할 때 자동으로 적용되어, Phantom Read를 방지합니다.

 

-- A 트랜잭션
START TRANSACTION;
SELECT * FROM orders WHERE id BETWEEN 10 AND 20 FOR UPDATE;
-- id 10~20의 레코드와 그 사이의 간격에 락이 걸림

-- B 트랜잭션
INSERT INTO orders (id, ...) VALUES (15, ...);  -- 대기함

 

이런 락 메커니즘 덕분에 MySQL의 REPEATABLE READ는 대부분의 경우 Phantom Read를 방지합니다. 하지만 락이 있다는 것은 대기가 발생할 수 있다는 의미이기도 합니다. 특히 범위 조건을 사용하는 쿼리가 많은 시스템에서는 Gap Lock으로 인한 대기 시간이 성능에 영향을 줄 수 있습니다.

 

 

그럼에도 불구하고 REPEATABLE READ는 정합성과 성능의 좋은 균형점입니다. 대부분의 애플리케이션에서 필요한 수준의 격리를 제공하면서도, 적절한 동시성을 유지합니다. 그래서 MySQL이 이것을 기본값으로 선택한 것입니다.

 


5. SERIALIZABLE - 완벽한 격리의 대가

SERIALIZABLE은 가장 높은 격리 레벨입니다. 이름에서 알 수 있듯이, 모든 트랜잭션을 직렬화하여 순차적으로 실행한 것처럼 보이게 합니다. 동시에 실행되는 트랜잭션들이 있더라도, 그 결과는 어떤 순서로든 하나씩 실행했을 때와 같습니다.

 

이것은 동시성을 사실상 포기하는 것입니다. SELECT 쿼리에도 락을 걸어서, 다른 트랜잭션이 그 데이터를 변경할 수 없게 만듭니다. 범위 조건이 있다면 전체 범위에 락을 걸어서, 그 안에 새로운 행이 삽입되는 것도 막습니다.

-- A 트랜잭션 (SERIALIZABLE)
START TRANSACTION;
SELECT * FROM orders WHERE status = 'PENDING';
-- 모든 PENDING 주문과 그 범위에 락이 걸림

-- B 트랜잭션
UPDATE orders SET status = 'PROCESSING' WHERE id = 100;  -- 대기
INSERT INTO orders (status) VALUES ('PENDING');  -- 대기

A 트랜잭션이 단순히 조회만 했지만, B 트랜잭션은 그 데이터를 변경할 수도 없고 같은 범위에 새로운 데이터를 삽입할 수도 없습니다. A가 커밋하거나 롤백할 때까지 대기해야 합니다.

 

SERIALIZABLE의 장점은  모든 동시성 문제를 해결합니다. Dirty Read, Non-Repeatable Read, Phantom Read 모두 발생하지 않습니다. 데이터 정합성이 완벽하게 보장됩니다. 트랜잭션이 마치 세상에 혼자 있는 것처럼 동작할 수 있습니다.

 

하지만 대가가 큽니다. 성능이 크게 떨어집니다. 많은 트랜잭션이 서로를 기다리게 되고, 처리량이 감소합니다. 특히 읽기 작업이 많은 시스템에서는 치명적일 수 있습니다. 모든 SELECT에 락이 걸리므로, 읽기와 쓰기가 서로를 막게 됩니다.

 

 

또한 데드락의 위험이 높아집니다. 두 트랜잭션이 서로가 가진 락을 기다리는 상황이 더 자주 발생할 수 있습니다. 데드락이 발생하면 한 트랜잭션이 자동으로 롤백되고, 애플리케이션에서 재시도 로직을 구현해야 합니다.

 

 

그렇다면 SERIALIZABLE은 언제 사용해야 할까요? 데이터 정확성이 절대적으로 중요하고, 성능보다 정합성을 우선해야 하는 경우입니다. 회계 결산 작업, 정산 배치, 마감 처리 같은 작업이 그렇습니다. 이런 작업은 실시간으로 처리될 필요가 없고, 조금 느리더라도 정확해야 합니다.

@Transactional(isolation = Isolation.SERIALIZABLE)
public void processMonthlySettlement() {
    // 월별 정산 로직
    // 정확한 금액 계산이 절대적으로 중요
    // 처리 시간은 상대적으로 덜 중요
}

또한 SERIALIZABLE은 일시적으로 사용할 수도 있습니다. 평소에는 REPEATABLE READ를 사용하다가, 특정 중요한 작업에서만 SERIALIZABLE을 사용하는 것입니다.

 

스프링에서는 @Transactional 어노테이션의 isolation 속성으로 트랜잭션마다 격리 레벨을 지정할 수 있습니다.


6. 격리 레벨 선택 전략 - 비즈니스 요구사항에 맞는 선택

지금까지 네 가지 격리 레벨을 살펴봤습니다. 그렇다면 실제 프로젝트에서는 어떤 격리 레벨을 선택해야 할까요? 이것은 "무조건 높은 게 좋다"는 문제가 아닙니다. 비즈니스 요구사항과 시스템 특성에 맞는 적절한 선택이 필요합니다.

 

 

먼저 애플리케이션의 특성을 분석해야 합니다. 읽기와 쓰기의 비율은 어떠한가요? 실시간성이 중요한가요, 아니면 일관성이 중요한가요? 동시 사용자가 얼마나 많은가요? 데이터 정합성 오류가 발생했을 때 비즈니스에 미치는 영향은 얼마나 큰가요?

 

대부분의 경우, MySQL의 기본 격리 레벨인 REPEATABLE READ가 좋은 선택입니다. 이것은 충분한 격리를 제공하면서도 합리적인 성능을 유지합니다. 특별한 이유가 없다면 기본값을 사용하는 것이 좋습니다. MySQL 개발자들이 오랜 시간 동안 많은 사용 사례를 고려하여 선택한 값이기 때문입니다.

 

하지만 특정 기능이나 쿼리에서는 다른 격리 레벨이 더 적합할 수 있습니다. 실시간 대시보드처럼 최신 데이터를 보여줘야 하고 약간의 불일치는 허용되는 경우, READ COMMITTED를 사용할 수 있습니다.

@Transactional(isolation = Isolation.READ_COMMITTED)
public DashboardData getDashboardData() {
    // 실시간 통계를 보여주는 대시보드
    // 최신 데이터 반영이 중요하고
    // 조회 시점마다 값이 달라져도 괜찮음
    return dashboardRepository.getStatistics();
}

 

반대로 재무 보고서를 생성하는 기능처럼 일관된 시점의 데이터로 계산해야 하는 경우, REPEATABLE READ나 SERIALIZABLE을 사용해야 합니다.

@Transactional(isolation = Isolation.REPEATABLE_READ)
public FinancialReport generateMonthlyReport(YearMonth month) {
    // 월별 재무 보고서 생성
    // 트랜잭션 동안 일관된 데이터 필요
    List<Transaction> transactions = transactionRepository.findByMonth(month);
    return calculateReport(transactions);
}

 

또한 격리 레벨만으로 해결되지 않는 문제도 있습니다. 앞서 본 재고 차감 문제는 격리 레벨을 높여도 완전히 해결되지 않습니다. 여러 트랜잭션이 같은 데이터를 읽고 각각 수정하려고 할 때, Lost Update 문제가 발생할 수 있기 때문입니다. 이런 경우에는 명시적인 락을 사용해야 합니다.

@Transactional
public void decreaseStock(Long productId, int quantity) {
    // 비관적 락으로 명시적으로 행을 잠금
    Product product = productRepository.findByIdWithLock(productId);
    
    if (product.getStock() < quantity) {
        throw new InsufficientStockException();
    }
    
    product.decreaseStock(quantity);
}
-- JPA의 LockModeType.PESSIMISTIC_WRITE
SELECT * FROM product WHERE id = ? FOR UPDATE;

FOR UPDATE 구문은 선택한 행에 베타적 락을 겁니다. 다른 트랜잭션은 이 행을 읽을 수는 있지만 수정할 수 없고, FOR UPDATE로 다시 선택할 수도 없습니다. 첫 번째 트랜잭션이 커밋하거나 롤백할 때까지 대기해야 합니다.

이렇게 격리 레벨과 락을 적절히 조합하여 사용하는 것이 중요합니다. 격리 레벨은 전체적인 동시성 제어의 기준을 정하고, 락은 특정 데이터에 대한 세밀한 제어를 제공합니다.


마치며

 

처음 격리 레벨을 접했을 때는 READ COMMITTED, REPEATABLE READ와 같은 용어들이
그저 암기해야 할 설정 값처럼 느껴졌습니다. 하지만 내부 동작 방식과 발생 가능한 문제들을 함께 살펴보면서,
각 격리 레벨이 왜 존재하는지 그리고 왜 데이터베이스가 단 하나의 정답을 제공하지 않는지 이해하게 되었습니다.

 

특히 MySQL의 기본 격리 레벨이 REPEATABLE READ로 설정되어 있는 이유가 인상 깊었습니다.
정합성과 성능 사이에서 어느 한쪽으로 치우치지 않고 대부분의 웹 서비스 환경에서 무난하게 동작할 수 있도록 설계된 선택이라는 점에서 “기본값은 결코 가볍게 정해지지 않는다”는 생각이 들었습니다.

또한 격리 레벨을 높이면 무조건 안전할 것이라는 막연한 생각이 반드시 옳지는 않다는 점도 인상적이었습니다.
SERIALIZABLE은 모든 정합성 문제를 해결해 주지만, 그만큼 동시성을 희생하게 되며 이는 곧 성능 문제로 이어집니다.

 


결국 격리 레벨은 기술적인 문제가 아니라 업무 특성과 시스템 성격을 이해한 뒤 내려야 하는 설계 결정이라는 점을 다시 한 번 느끼게 되었습니다.

 

 

이번 정리를 통해 트랜잭션 격리 레벨을 "필요하면 조정하는 옵션”이 아니라 시스템의 동작 방식을 정의하는 중요한 기준으로 바라보게 되었습니다.
앞으로는 단순히 기본값을 사용하는 데서 그치지 않고, 왜 이 격리 레벨을 선택했는지 스스로 설명할 수 있는 개발자가 되고자 합니다.

저작자표시 비영리 (새창열림)

'데이터베이스' 카테고리의 다른 글

MySQL SQL 파서(Parser)와 옵티마이저(Optimizer) 내부 동작 정리  (0) 2026.02.06
데이터베이스 락의 모든 것 - 공유 락, 배타 락, 그리고 분산 락  (1) 2026.02.01
MySQL 스토리지 엔진 완전 정복 - InnoDB, MyISAM, ARCHIVE의 선택과 이해  (0) 2026.01.30
'데이터베이스' 카테고리의 다른 글
  • MySQL SQL 파서(Parser)와 옵티마이저(Optimizer) 내부 동작 정리
  • 데이터베이스 락의 모든 것 - 공유 락, 배타 락, 그리고 분산 락
  • MySQL 스토리지 엔진 완전 정복 - InnoDB, MyISAM, ARCHIVE의 선택과 이해
깊은바다속꼬북이
깊은바다속꼬북이
  • 깊은바다속꼬북이
    CodeBlossom
    깊은바다속꼬북이
  • 전체
    오늘
    어제
    • 분류 전체보기 (53) N
      • 라이징 캠프 (4)
      • 객채지향 개발론 (3)
      • 스프링 (10) N
      • 네트워크 (2)
      • 자바 (16)
      • 자료구조 (3)
      • 운영체제 (0)
      • 데이터베이스 (4)
      • 디자인패턴 (7)
      • JSP (1)
      • 개발 알쓸신잡 (2)
      • 일반 교양 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    spring
    트랜잭션 전파레벨
    프로그램밍 언어
    디자인 패턴
    한국어 검색
    백엔드
    어댑터 패턴(Adapter Pattern)
    디자인패턴
    MySQL 파서
    자바 Socket 클래스
    java
    개발 철학
    MySQL 옵티마이저
    mockito라이브러리
    JVM
    jvm 클래스 로더
    템플릿 메서드 패턴(Template Method Pattern)
    GC
    자료구조
    싱글턴 패턴(Singleton Pattern)
    개발자 철학
    객체지향
    jit-compiler
    java data area
    스프링
    전략 패턴(Strategy Pattern)
    java 버전별 특징
    JUnnit5
    junnit5프레임워크
    개발 교훈
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
깊은바다속꼬북이
MYSQL DB 4가지 트랜잭션 격리레벨에 대해
상단으로

티스토리툴바