트랜잭션 격리 수준은 트랜잭션이 실행될 때 다른 트랜잭션의 데이터 수정을 정의합니다. 다른 분리 수준은 다양한 정도의 데이터 격리를 제공하며 일반적인 분리 수준은 다음과 같습니다.
커밋되지 않은 것을 읽으십시오
하나의 트랜잭션이 다른 트랜잭션에서 저지른 데이터를 읽도록 허용하면 더러운 판독 값이 발생할 수 있습니다.
Commited를 읽으십시오
더러운 판독 값을 피하고 반복 할 수없는 판독 값이 발생할 수 있습니다.
반복 가능한 읽기
트랜잭션의 모든 쿼리가 동일한 데이터를 반환하고 반복 할 수없는 판독을 피하도록하지만 팬텀 판독 값이 여전히 발생할 수 있습니다.
직렬화 가능
더러운 읽기, 반복 할 수없는 독서 및 팬텀 독서를 완전히 피하기 위해 연속적으로 실행되도록 강제 거래를 수행하지만 성능은 크게 영향을받습니다.
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>-></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>-></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>-></span><span><span class="hljs-title function_ invoke__">commit</span></span><span>();
</span></span>
위의 코드에서 트랜잭션 격리 수준을 설정하면 트랜잭션 격리 수준을 반복 가능한 읽기로 설정합니다. 이는 현재 트랜잭션에서 실행 된 쿼리가 다른 트랜잭션이 그 사이의 데이터를 수정하더라도 항상 동일한 결과를 반환한다는 것을 의미합니다.
다른 트랜잭션 격리 수준은 동시성 문제에 다른 영향을 미칩니다. 동시성 문제를 예방하는 데 따른 구체적인 증상은 다음과 같습니다.
커밋되지 않은 것을 읽으십시오
이 격리 수준에서 트랜잭션은 다른 트랜잭션이 커밋되지 않은 데이터를 읽을 수있어 더러운 판독 값을 유발하여 일관성이없는 데이터를 유발할 수 있습니다. 동시성 문제는 다른 거래의 운영에 대한 제한이 없기 때문에 발생하기 쉽습니다.
Commited를 읽으십시오
이 격리 수준은 트랜잭션이 커밋 된 데이터 만 읽을 수 있기 때문에 더러운 읽기 문제를 피합니다. 그러나 반복 할 수없는 읽기를 가질 수 있습니다. 즉, 트랜잭션이 동일한 데이터를 두 번 읽으면 데이터가 변경 될 수 있습니다. 데이터 일관성이 높지 않은 일부 시나리오에서는이 격리 수준이 성능과 일관성의 균형을 맞출 수 있습니다.
반복 가능한 읽기
반복 가능한 읽기 격리 수준은 트랜잭션의 모든 쿼리가 반복 할 수없는 읽기를 피하고 일관된 데이터를 반환하도록합니다. 그러나 팬텀 읽기가 발생할 수 있습니다. 즉, 다른 트랜잭션은 현재 트랜잭션 쿼리간에 새로운 데이터를 삽입합니다. 이 격리 수준은 동시 쓰기 작업을보다 엄격하게 제어하여 데이터 일관성을 향상시키는 데 도움이됩니다.
직렬화 가능
직렬화 격리 수준은 가장 엄격하며, 트랜잭션 직렬화를 강요하여 더러운 읽기, 반복 할 수없는 독서 및 판타지 독서를 포함한 모든 동시성 문제를 피합니다. 이 격리 수준은 성능에 큰 영향을 미치며 일반적으로 엄격한 일관성이 필요한 시나리오에 적합합니다.
적절한 거래 격리 수준을 선택하려면 특정 비즈니스 요구에 따라 트레이드 오프가 필요합니다.
고성능이 필요하지만 높은 데이터 일관성이 필요하지 않은 응용 프로그램 시나리오 인 경우 제출 된 격리 수준을 읽을 수 있습니다. 이렇게하면 동시 트랜잭션이 데이터를 수정할 수 있도록 더러운 읽기를 피할 수 있습니다.
반복 가능한 읽기는 대부분의 응용 프로그램에서 더 나은 선택입니다. 반복 할 수없고 더러운 판독을 방지 할 수 있으며 데이터 일관성을 보장하면서 성능 손실이 비교적 작습니다.
데이터의 엄격한 일관성과 낮은 동시성을 보장 해야하는 시스템에서는 직렬화 된 격리 수준을 선택할 수 있습니다. 성능은 좋지 않지만 모든 동시성 문제를 완전히 피할 수 있습니다.
사용자의 계정 잔액이 동시 운영으로 인해 오류가 발생하지 않도록 해야하는 은행 시스템을 개발한다고 가정 해 봅시다. 반복 가능한 읽기 격리 수준을 설정하여 다른 트랜잭션에 의해 한 트랜잭션의 잔액이 수정되는 것을 방지 할 수 있습니다.
<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>-></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>-></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>-></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>-></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>-></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> > </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>-></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>-></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>-></span><span><span class="hljs-title function_ invoke__">commit</span></span><span>();
</span></span>
이 예에서는 다른 트랜잭션의 수정으로 인해 쿼리 밸런스가 변경되지 않도록 반복 가능한 읽기 격리 레벨이 설정되어 데이터 불일치를 피할 수 있습니다.
PDO :: BeginTransaction ()은 PHP에서 데이터베이스 트랜잭션을 관리하는 데 도움이되는 강력한 도구입니다. 합리적인 트랜잭션 격리 수준 설정과 결합하여 동시성 문제를 효과적으로 방지하고 데이터 일관성과 무결성을 보장 할 수 있습니다. 개발 과정에서 성능과 데이터 일관성의 관계의 균형을 맞추기 위해 비즈니스 요구에 따라 적절한 거래 격리 수준을 선택해야합니다.
관련 태그:
PDO