재인쇄 주소 : 클릭하면 링크가 열립니다
데이터베이스에서 SQL을 하나씩 처리한다고 알고 있습니다. 상품 구매 과정은 다음과 같다고 가정합니다.
sql1: 상품 재고 조회
if(inventory amount> 0)
{
//주문 생성...
sql2:inventory-1
}
동시성이 없는 경우 위의 프로세스는 매우 완벽해 보입니다. 두 사람이 동시에 주문하고 재고가 1개만 있다고 가정합니다. sql1 단계에서 두 사람이 쿼리한 재고는 > 0이므로 최종적으로 sql2를 실행하고 재고가 발생합니다. 최종적으로 -1이 되어 과매도 상태가 되며, 재고를 보충하거나 사용자 불만을 기다립니다.
이 문제를 해결하기 위한 더 인기 있는 아이디어:
1. 추가 단일 프로세스를 사용하여 대기열을 처리하고 주문 요청을 대기열에 넣은 다음 하나씩 처리합니다. 동시성 문제는 없습니다. 예, 그러나 추가 백그라운드 프로세스 및 대기 시간 문제는 고려되지 않습니다.
2. 대략적으로 인벤토리를 쿼리한 다음 즉시 인벤토리에 1을 추가하고 주문이 생성된 후 인벤토리를 다시 쿼리한 후 인벤토리를 업데이트하여 예상 인벤토리가 맞는지 확인하는 것을 의미하는 데이터베이스 낙관적 잠금입니다. 수량은 유지되며, 일치하지 않을 경우 롤백되며 사용자에게 재고가 부족하다는 메시지가 표시됩니다.
3. 업데이트 결과에 따라 판단 조건 업데이트를 추가할 수 있습니다. sql2에서 Inventory>0이 반환되면 인벤토리가 부족하여 트랜잭션이 롤백된다는 의미입니다. .
4. 파일 독점 잠금을 사용하여 주문 요청을 처리할 때 잠금에 실패하면 현재 다른 주문이 처리되고 있음을 의미합니다. 기다리거나 사용자에게 직접 메시지 "server" Busy"
이 기사에서는 4번째 해결 방법에 대해 설명합니다. 대략적인 코드는 다음과 같습니다.
//Blocking(waiting) ) 모드
?
4 5 6
8 9
|
$fp<code>= fopen ( "lock.txt" ,
"w+" ); if ( 군집<code>( $fp ,LOCK_EX)) { //..주문 처리 무리 ( $fp ,LOCK_UN); } fclose( $fp);
|
<?php $fp = fopen ("lock.txt" ,
"w+" ); if ( 군집<code>( $fp ,LOCK_EX
| LOCK_NB)) { //..주문 처리 무리 ( $fp ,LOCK_UN); } else { code><code>echo "시스템이 사용 중입니다. 나중에 다시 시도하십시오." ; } fclose( $fp );
|