현재 위치: > 최신 기사 목록> MySQLI_STMT :: 거래에서 일반적인 함정을 준비합니다

MySQLI_STMT :: 거래에서 일반적인 함정을 준비합니다

gitbox 2025-05-29

PHP에서 데이터베이스 작업에 MySQLI Extension을 사용할 때 MySQLI_STMT :: 준비는 전처리 진술의 핵심 방법입니다. SQL 주입을 효과적으로 방지하고 실행 효율을 향상시킬 수 있습니다. 그러나 트랜잭션 처리에서 MySQLI_STMT :: 준비 할 때는 종종 일부 함정이 발생하여 트랜잭션이 제출하거나 롤백 할 수 없으며 데이터 불일치도 발생합니다. 이 기사는 이러한 일반적인 함정을 자세히 분석하고 해당 솔루션을 제공합니다.

1. 트랜잭션과 전처리 문의 기본 관계

트랜잭션은 데이터베이스 관리의 일련의 운영으로 이러한 작업이 성공하거나 모두 실패해야합니다. MySQLI 의 트랜잭션 컨트롤을 사용하면 다음 방법을 일반적으로 다음과 같습니다.

 $mysqli->begin_transaction();
$mysqli->commit();
$mysqli->rollback();

mysqli_stmt :: 준비는 SQL 문과 사전 컴파일을 바인딩합니다. SQL 문이 합법적이고 바운드 매개 변수가 올바른지 확인하는 데 올바르게 사용됩니다.

2. 일반적인 함정과 솔루션

1. 전처리 명세서에 의해 확인되지 않은 결과를 준비하십시오

PIT POINT : $ stmt = $ mysqli-> prepar ($ sql)를 호출 한 후 $ stmt가 false 인지 확인하지 않습니다. SQL 구문 오류 또는 기타 이유가 있으면 준비가 실패하면 트랜잭션이 계속 실행되고 후속 작업이 오류를보고하여 트랜잭션 예외가 발생할 수 있습니다.

해결하다 :

 $stmt = $mysqli->prepare($sql);
if ($stmt === false) {
    $mysqli->rollback();
    throw new Exception('Prepare failed: ' . $mysqli->error);
}

거래에서 준비가 실패하면 롤백 및 후속 작업을 중지하십시오.

2. 거래가 시작되기 전에 준비가 실행되었습니다

포인트 : 때때로 개발자는 $ stmt = $ mysqli-> repay ($ sql)를 실행합니다. $ mysqli-> begin_transaction ()을 호출하기 전에. 그러나 특정 MySQL 버전 또는 구성에서 전처리 명세서가 자동으로 암시 적으로 커밋되어 트랜잭션 효과가 유효하지 않습니다.

해결하다 :

먼저 거래를 시작한 다음 준비를 실행하십시오.

 $mysqli->begin_transaction();
$stmt = $mysqli->prepare($sql);
// 후속 바인딩 및 실행

3. 여러 SQL 문을 사용할 때 분리되지 않도록 준비하십시오

포인트 : 전처리 문은 한 번에 여러 SQL 문을 작성하는 것을 지원하지 않습니다. $ SQL 에 세미콜론으로 여러 문장이 포함되어 있으면 준비가 실패합니다.

해결하다 :

매번 단일 SQL 명령문 만 준비하고 필요한 경우 여러 문장을 별도로 실행하십시오.

4. 매개 변수를 바인딩하지 않으면 데이터 예외가 올바르게 발생합니다

구덩이 지점 : 유형 불일치 또는 바인딩되지 않은 모든 자리 표시 자와 같은 매개 변수 바인딩 오류는 실행 실패를 일으키고 트랜잭션은 결국 실패합니다.

해결하다 :

바운드 매개 변수의 유형과 수가 올바른지 확인하십시오.

 $stmt->bind_param('si', $name, $id);

그리고 bind_param 의 반환 값을 확인하십시오.

5. 전처리 진술을 닫는 것을 잊었습니다

구덩이 지점 : 거래가 끝나기 전에 $ stmt-> close ()가 호출되지 않으면 연결 리소스가 해제되지 않아 후속 트랜잭션 운영에 영향을 줄 수 있습니다.

해결하다 :

트랜잭션이 종료되기 전에 $ stmt-> close ()를 호출하여 자원이 제 시간에 해제되도록하십시오.

6. 오류 처리 및 예외 잡기를 무시합니다

PIT POINT : 예외 또는 오류가 발생하지 않아 거래가 제대로 커밋되거나 롤백되지 않습니다.

해결하다 :

Try-Catch 구조를 사용하여 예외를 포착 할 때 트랜잭션을 롤백합니다.

 try {
    $mysqli->begin_transaction();

    $stmt = $mysqli->prepare($sql);
    if ($stmt === false) {
        throw new Exception($mysqli->error);
    }

    $stmt->bind_param('si', $name, $id);
    $stmt->execute();

    $mysqli->commit();
} catch (Exception $e) {
    $mysqli->rollback();
    echo "Transaction failed: " . $e->getMessage();
}

3. 완전한 예

 <?php
$mysqli = new mysqli('gitbox.net', 'user', 'password', 'database');
if ($mysqli->connect_error) {
    die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}

try {
    $mysqli->begin_transaction();

    $sql = "UPDATE users SET name = ? WHERE id = ?";
    $stmt = $mysqli->prepare($sql);
    if ($stmt === false) {
        throw new Exception('Prepare failed: ' . $mysqli->error);
    }

    $name = 'Alice';
    $id = 123;
    if (!$stmt->bind_param('si', $name, $id)) {
        throw new Exception('Bind param failed: ' . $stmt->error);
    }

    if (!$stmt->execute()) {
        throw new Exception('Execute failed: ' . $stmt->error);
    }

    $stmt->close();

    $mysqli->commit();
    echo "Transaction succeeded.";
} catch (Exception $e) {
    $mysqli->rollback();
    echo "Transaction failed: " . $e->getMessage();
}

$mysqli->close();
?>

4. 요약

  • 거래가 시작된 후에는 항상 준비하십시오 .

  • 준비 , BIND_PARAM 의 반환 값을 확인하고 실행하십시오 .

  • 준비는 단일 진술 만 처리합니다.

  • 예외가 발생하면 거래를 롤백하십시오.

  • 전처리 명세서 리소스를 닫습니다.

위의 사양에 따라 MySQLI_STMT :: 트랜잭션 프로세싱을 준비하여 데이터 일관성 및 코드 견고성을 보장하는 데있어 일반적인 함정을 효과적으로 피할 수 있습니다.