현재 위치: > 최신 기사 목록> 동시성 문제를 방지하기 위해 트랜잭션 격리 수준을 설정하는 데 PDO :: 시작 추출을 어떻게 사용해야합니까?

동시성 문제를 방지하기 위해 트랜잭션 격리 수준을 설정하는 데 PDO :: 시작 추출을 어떻게 사용해야합니까?

gitbox 2025-08-22

1. 거래 격리 수준은 무엇입니까?

트랜잭션 격리 수준은 트랜잭션이 실행될 때 다른 트랜잭션의 데이터 수정을 정의합니다. 다른 분리 수준은 다양한 정도의 데이터 격리를 제공하며 일반적인 분리 수준은 다음과 같습니다.

  • 커밋되지 않은 것을 읽으십시오
    하나의 트랜잭션이 다른 트랜잭션에서 저지른 데이터를 읽도록 허용하면 더러운 판독 값이 발생할 수 있습니다.

  • Commited를 읽으십시오
    더러운 판독 값을 피하고 반복 할 수없는 판독 값이 발생할 수 있습니다.

  • 반복 가능한 읽기
    트랜잭션의 모든 쿼리가 동일한 데이터를 반환하고 반복 할 수없는 판독을 피하도록하지만 팬텀 판독 값이 여전히 발생할 수 있습니다.

  • 직렬화 가능
    더러운 읽기, 반복 할 수없는 독서 및 팬텀 독서를 완전히 피하기 위해 연속적으로 실행되도록 강제 거래를 수행하지만 성능은 크게 영향을받습니다.

2. PDO를 사용하여 트랜잭션 격리 수준을 설정하십시오

PDO는 트랜잭션이 시작되기 전에 트랜잭션 격리 수준을 설정할 수 있습니다. 이 작업은 일반적으로 SQL 문에 의해 수행됩니다. 구체적인 방법은 SET TRANSACTION DERENTACT 문을 사용하여 PDO :: beginTransaction ()을 호출하기 전에 필요한 격리 레벨을 설정하는 것입니다. 예를 들어:

 <span><span><span class="hljs-comment">// 만들다 PDO 예</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-string">'mysql:host=localhost;dbname=test'</span></span><span>, </span><span><span class="hljs-string">'username'</span></span><span>, </span><span><span class="hljs-string">'password'</span></span><span>);

</span><span><span class="hljs-comment">// 트랜잭션 격리 수준을 설정하십시오“반복 가능”</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">exec</span></span><span>(</span><span><span class="hljs-string">"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"</span></span><span>);

</span><span><span class="hljs-comment">// 거래를 시작하십시오</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">beginTransaction</span></span><span>();

</span><span><span class="hljs-comment">// 데이터베이스 작업을 수행합니다</span></span><span>
</span><span><span class="hljs-comment">// ...</span></span><span>

</span><span><span class="hljs-comment">// 거래를 제출하십시오</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">commit</span></span><span>();
</span></span>

위의 코드에서 트랜잭션 격리 수준을 설정하면 트랜잭션 격리 수준을 반복 가능한 읽기로 설정합니다. 이는 현재 트랜잭션에서 실행 된 쿼리가 다른 트랜잭션이 그 사이의 데이터를 수정하더라도 항상 동일한 결과를 반환한다는 것을 의미합니다.

3. 동시성 문제에 대한 일반적인 거래 격리 수준 예방

다른 트랜잭션 격리 수준은 동시성 문제에 다른 영향을 미칩니다. 동시성 문제를 예방하는 데 따른 구체적인 증상은 다음과 같습니다.

  • 커밋되지 않은 것을 읽으십시오
    이 격리 수준에서 트랜잭션은 다른 트랜잭션이 커밋되지 않은 데이터를 읽을 수있어 더러운 판독 값을 유발하여 일관성이없는 데이터를 유발할 수 있습니다. 동시성 문제는 다른 거래의 운영에 대한 제한이 없기 때문에 발생하기 쉽습니다.

  • Commited를 읽으십시오
    이 격리 수준은 트랜잭션이 커밋 된 데이터 만 읽을 수 있기 때문에 더러운 읽기 문제를 피합니다. 그러나 반복 할 수없는 읽기를 가질 수 있습니다. 즉, 트랜잭션이 동일한 데이터를 두 번 읽으면 데이터가 변경 될 수 있습니다. 데이터 일관성이 높지 않은 일부 시나리오에서는이 격리 수준이 성능과 일관성의 균형을 맞출 수 있습니다.

  • 반복 가능한 읽기
    반복 가능한 읽기 격리 수준은 트랜잭션의 모든 쿼리가 반복 할 수없는 읽기를 피하고 일관된 데이터를 반환하도록합니다. 그러나 팬텀 읽기가 발생할 수 있습니다. 즉, 다른 트랜잭션은 현재 트랜잭션 쿼리간에 새로운 데이터를 삽입합니다. 이 격리 수준은 동시 쓰기 작업을보다 엄격하게 제어하여 데이터 일관성을 향상시키는 데 도움이됩니다.

  • 직렬화 가능
    직렬화 격리 수준은 가장 엄격하며, 트랜잭션 직렬화를 강요하여 더러운 읽기, 반복 할 수없는 독서 및 판타지 독서를 포함한 모든 동시성 문제를 피합니다. 이 격리 수준은 성능에 큰 영향을 미치며 일반적으로 엄격한 일관성이 필요한 시나리오에 적합합니다.

4. 비즈니스 요구에 따라 거래 격리 수준을 선택하는 방법은 무엇입니까?

적절한 거래 격리 수준을 선택하려면 특정 비즈니스 요구에 따라 트레이드 오프가 필요합니다.

  • 고성능이 필요하지만 높은 데이터 일관성이 필요하지 않은 응용 프로그램 시나리오 인 경우 제출 된 격리 수준을 읽을 수 있습니다. 이렇게하면 동시 트랜잭션이 데이터를 수정할 수 있도록 더러운 읽기를 피할 수 있습니다.

  • 반복 가능한 읽기는 대부분의 응용 프로그램에서 더 나은 선택입니다. 반복 할 수없고 더러운 판독을 방지 할 수 있으며 데이터 일관성을 보장하면서 성능 손실이 비교적 작습니다.

  • 데이터의 엄격한 일관성과 낮은 동시성을 보장 해야하는 시스템에서는 직렬화 된 격리 수준을 선택할 수 있습니다. 성능은 좋지 않지만 모든 동시성 문제를 완전히 피할 수 있습니다.

5. 예 : 동시성 문제를 방지하기위한 실제 적용

사용자의 계정 잔액이 동시 운영으로 인해 오류가 발생하지 않도록 해야하는 은행 시스템을 개발한다고 가정 해 봅시다. 반복 가능한 읽기 격리 수준을 설정하여 다른 트랜잭션에 의해 한 트랜잭션의 잔액이 수정되는 것을 방지 할 수 있습니다.

 <span><span><span class="hljs-comment">// 만들다 PDO 예</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-string">'mysql:host=localhost;dbname=bank'</span></span><span>, </span><span><span class="hljs-string">'root'</span></span><span>, </span><span><span class="hljs-string">'password'</span></span><span>);
</span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">exec</span></span><span>(</span><span><span class="hljs-string">"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"</span></span><span>);

</span><span><span class="hljs-comment">// 거래를 시작하십시오</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">beginTransaction</span></span><span>();

</span><span><span class="hljs-comment">// 계정 잔액을 확인하십시오</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"SELECT balance FROM accounts WHERE account_id = ?"</span></span><span>);
</span><span><span class="hljs-variable">$stmt</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">execute</span></span><span>([</span><span><span class="hljs-number">1</span></span><span>]);
</span><span><span class="hljs-variable">$balance</span></span><span> = </span><span><span class="hljs-variable">$stmt</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">fetchColumn</span></span><span>();

</span><span><span class="hljs-comment">// 특정 비즈니스 로직을 실행하십시오</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$balance</span></span><span> &gt; </span><span><span class="hljs-number">100</span></span><span>) {
    </span><span><span class="hljs-comment">// 공제 작업</span></span><span>
    </span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"UPDATE accounts SET balance = balance - 100 WHERE account_id = ?"</span></span><span>);
    </span><span><span class="hljs-variable">$stmt</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">execute</span></span><span>([</span><span><span class="hljs-number">1</span></span><span>]);
}

</span><span><span class="hljs-comment">// 거래를 제출하십시오</span></span><span>
</span><span><span class="hljs-variable">$pdo</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">commit</span></span><span>();
</span></span>

이 예에서는 다른 트랜잭션의 수정으로 인해 쿼리 밸런스가 변경되지 않도록 반복 가능한 읽기 격리 레벨이 설정되어 데이터 불일치를 피할 수 있습니다.

6. 요약

PDO :: BeginTransaction ()은 PHP에서 데이터베이스 트랜잭션을 관리하는 데 도움이되는 강력한 도구입니다. 합리적인 트랜잭션 격리 수준 설정과 결합하여 동시성 문제를 효과적으로 방지하고 데이터 일관성과 무결성을 보장 할 수 있습니다. 개발 과정에서 성능과 데이터 일관성의 관계의 균형을 맞추기 위해 비즈니스 요구에 따라 적절한 거래 격리 수준을 선택해야합니다.

  • 관련 태그:

    PDO