Spring 트랜잭션의 격리 수준에 대한 자세한 설명 ~ Spring 트랜잭션 Part 2

Spring 트랜잭션 격리 수준

트랜잭션 격리가 필요한 이유는 무엇입니까? 트랜잭션 격리가 없으면 여러 트랜잭션이 동시에 진행되는 경우 업데이트 손실, 더티 읽기, 반복 불가능한 읽기, 팬텀 읽기 등의 문제가 발생합니다.

1. 트랜잭션 격리로 인한 문제가 없습니다.

1. 업데이트가 손실되었습니다.

두 개 이상의 트랜잭션이 동일한 레코드 행을 업데이트하면 업데이트 손실이 발생합니다. 롤백 커버리지와 커밋 커버리지로 나눌 수 있습니다.

예를 들어, 트랜잭션 T1이 데이터를 쿼리하고, 트랜잭션 T2가 데이터를 쿼리하고, 트랜잭션 T1이 데이터를 수정하고 제출하고, 트랜잭션 T2가 데이터를 수정하는 경우, 이때 트랜잭션 T2가 커밋 또는 롤백을 수행하므로 트랜잭션 T1이 수정한 데이터는 다음과 같습니다. 덮어썼습니다.

2. 더러운 독서

더티 읽기(Dirty Reading)는 잘못된 데이터 읽기라고도 합니다. 한 트랜잭션은 다른 트랜잭션이 아직 커밋하지 않은 데이터를 읽습니다.

예를 들어, 트랜잭션 T1이 데이터 행을 수정했지만 아직 제출하지 않은 경우, 이때 트랜잭션 T2는 트랜잭션 T1이 수정한 데이터를 읽습니다. 그러다가 트랜잭션 T1이 어떤 이유로 롤백되므로 트랜잭션 T2가 읽은 데이터는 더티입니다.

3. 반복 불가능한 읽기

이는 동일한 트랜잭션 내의 동일한 데이터 행에 대한 여러 쿼리가 서로 다른 결과를 반환함을 의미합니다.

예를 들어, 트랜잭션 T1이 처음으로 특정 데이터 행을 쿼리한 후 트랜잭션 T2가 데이터 행의 특정 필드를 수정하고 데이터를 제출합니다. 트랜잭션 T1이 두 번째로 데이터 행을 쿼리하면 트랜잭션 T2의 수정된 결과를 얻습니다.

반복 불가능 읽기와 더티 읽기의 차이점은 더티 읽기는 커밋되지 않은 데이터를 읽는 반면, 반복 불가능 읽기는 커밋된 데이터를 읽는다는 것입니다. 물론 반복 불가능 읽기가 문제가 되지 않는 경우도 있지만 때로는 동일한 트랜잭션에서 데이터의 최신 상태를 쿼리하고 싶을 때도 있습니다.

4. 팬텀 독서

환상읽기는 가상읽기라고도 합니다. 동일한 트랜잭션에서 동일한 SQL 문을 여러 번 쿼리하면 데이터 양(항목 수)이 달라집니다.

예를 들어, 트랜잭션 T1이 테이블의 모든 행에 있는 데이터 항목을 "1"에서 "2"로 수정하는 경우, 트랜잭션 T2는 데이터 항목의 행을 테이블에 삽입하고 데이터 항목의 값은 여전히 ​​"1"입니다. "하고 데이터베이스에 제출했습니다. 트랜잭션 T1을 운영하는 사용자가 방금 수정된 데이터를 보면 아직 수정되지 않은 행이 하나 남아 있는 것을 발견할 수 있는데, 사실 이 행은 트랜잭션 T2에서 추가된 행입니다. 이것은 환상의 읽기입니다.

2. 트랜잭션의 격리 수준을 사용하여 문제를 해결합니다.

격리 수준 사용

@Transactional 주석은 격리 속성을 통해 트랜잭션 격리 수준을 설정합니다.

@Transactional(isolation=Isolation.DEFAULT)
public void methodA(){
    
    
// 业务逻辑 
// 操作数据库
}

3. 격리 속성에는 다음과 같은 5가지 값이 있습니다.

1、기본

이는 기본값으로, 연결된 데이터베이스에서 설정한 격리 수준과 일치함을 의미합니다.

2, READ_UNCOMMITTED

커밋되지 않은 읽기(더티 읽기, 반복 불가능한 읽기, 팬텀 읽기가 발생함)이며 기본적으로 사용되지 않습니다.

동일한 데이터 행에 대한 작업을 전제로 읽기 트랜잭션은 다른 읽기 트랜잭션과 쓰기 트랜잭션을 허용하며, 커밋되지 않은 쓰기 트랜잭션은 다른 쓰기 트랜잭션을 금지하지만 다른 읽기 트랜잭션을 허용합니다. 이 격리 수준은 업데이트 손실을 방지할 수 있지만 더티 읽기, 반복 불가능 읽기 및 가상 읽기를 방지할 수는 없습니다. 이 격리 수준은 "독점적 쓰기 잠금"을 통해 달성할 수 있습니다.

3、READ_COMMITTED

읽기 커밋(반복 불가능한 읽기 및 팬텀 읽기가 발생함)

동일한 데이터 행 운영을 전제로 읽기 트랜잭션은 다른 읽기 트랜잭션과 쓰기 트랜잭션을 허용하고, 커밋되지 않은 쓰기 트랜잭션은 다른 읽기 트랜잭션과 쓰기 트랜잭션을 금지합니다. 이 격리 수준은 업데이트 손실 및 더티 읽기를 방지할 수 있지만 반복 불가능한 읽기 및 팬텀 읽기를 방지할 수는 없습니다. 이 격리 수준은 "일시적 공유 읽기 잠금" 및 "배타적 쓰기 잠금"을 통해 달성할 수 있습니다.

4、REPEATABLE_READ

반복 판독(유령 판독이 발생할 수 있음)

동일한 행의 데이터 작업을 전제로 읽기 트랜잭션은 다른 쓰기 트랜잭션을 금지하지만(다른 읽기 트랜잭션은 허용), 커밋되지 않은 쓰기 트랜잭션은 다른 읽기 트랜잭션과 쓰기 트랜잭션을 금지합니다. 이 격리 수준은 업데이트 손실, 더티 읽기, 반복 불가능한 읽기를 방지할 수 있지만 가상 읽기를 방지할 수는 없습니다. 이 격리 수준은 "공유 읽기 잠금" 및 "독점 쓰기 잠금"을 통해 달성할 수 있습니다.

5, 직렬화 가능

직렬화 가능

엄격한 트랜잭션 격리를 제공합니다. 트랜잭션은 순차적으로 실행되어야 하며 트랜잭션은 하나씩만 실행할 수 있으며 동시에 실행할 수는 없습니다. 이 격리 수준은 업데이트 손실, 더티 읽기, 반복 불가능한 읽기 및 팬텀 읽기를 방지합니다. "행 수준 잠금"을 통해서만 트랜잭션 직렬화를 달성할 수 없는 경우 쿼리 작업을 방금 실행한 트랜잭션이 새로 삽입된 데이터에 액세스하지 못하도록 다른 메커니즘을 사용해야 합니다. 이 트랜잭션 격리 수준은 비효율적이고 데이터베이스 성능을 소모하므로 일반적으로 사용되지 않습니다.

4. 확장:

1. 공통 데이터베이스의 기본 트랜잭션 격리 수준

Oracle, SQL Server의 기본 격리 수준은 READ_COMMITTED입니다.
Mysql의 기본 격리 수준은 REPEATABLE_READ입니다.

2. 격리 수준 설정은 현재 연결에만 적용됩니다.

Mysql 명령 창을 사용하는 경우 창은 연결과 동일하며 현재 창에서 설정한 격리 수준은 현재 창의 트랜잭션에만 유효하며, JDBC 운영 데이터베이스의 경우 연결 개체는 링크에 해당하고 연결 개체 격리 수준 집합은 연결 개체에만 유효하며 연결된 다른 연결 개체와는 아무 관련이 없습니다.

3. 데이터베이스의 격리 수준 설정은 트랜잭션을 시작하기 전에 완료되어야 합니다.

mybatis의 트랜잭션:
sqlSession 객체의 commit 메소드와 Rollback 메소드를 통해 트랜잭션 제출 및 롤백을 구현합니다.

4. 격리 수준에 대한 일반적인 SQL 설정

현재 트랜잭션 격리 수준 보기: @@transaction_isolation;을 선택하세요.
현재 세션의 트랜잭션 격리 수준 설정: 세션 트랜잭션 격리 수준 XXX(격리 수준) 설정;

추천

출처blog.csdn.net/qq_42547733/article/details/128705149