PHP에서 데이터베이스 작업에 MySQLI Extension을 사용할 때 MySQLI_STMT :: 준비는 전처리 진술의 핵심 방법입니다. SQL 주입을 효과적으로 방지하고 실행 효율을 향상시킬 수 있습니다. 그러나 트랜잭션 처리에서 MySQLI_STMT :: 준비 할 때는 종종 일부 함정이 발생하여 트랜잭션이 제출하거나 롤백 할 수 없으며 데이터 불일치도 발생합니다. 이 기사는 이러한 일반적인 함정을 자세히 분석하고 해당 솔루션을 제공합니다.
트랜잭션은 데이터베이스 관리의 일련의 운영으로 이러한 작업이 성공하거나 모두 실패해야합니다. MySQLI 의 트랜잭션 컨트롤을 사용하면 다음 방법을 일반적으로 다음과 같습니다.
$mysqli->begin_transaction();
$mysqli->commit();
$mysqli->rollback();
mysqli_stmt :: 준비는 SQL 문과 사전 컴파일을 바인딩합니다. SQL 문이 합법적이고 바운드 매개 변수가 올바른지 확인하는 데 올바르게 사용됩니다.
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);
}
거래에서 준비가 실패하면 롤백 및 후속 작업을 중지하십시오.
포인트 : 때때로 개발자는 $ stmt = $ mysqli-> repay ($ sql)를 실행합니다. $ mysqli-> begin_transaction ()을 호출하기 전에. 그러나 특정 MySQL 버전 또는 구성에서 전처리 명세서가 자동으로 암시 적으로 커밋되어 트랜잭션 효과가 유효하지 않습니다.
해결하다 :
먼저 거래를 시작한 다음 준비를 실행하십시오.
$mysqli->begin_transaction();
$stmt = $mysqli->prepare($sql);
// 후속 바인딩 및 실행
포인트 : 전처리 문은 한 번에 여러 SQL 문을 작성하는 것을 지원하지 않습니다. $ SQL 에 세미콜론으로 여러 문장이 포함되어 있으면 준비가 실패합니다.
해결하다 :
매번 단일 SQL 명령문 만 준비하고 필요한 경우 여러 문장을 별도로 실행하십시오.
구덩이 지점 : 유형 불일치 또는 바인딩되지 않은 모든 자리 표시 자와 같은 매개 변수 바인딩 오류는 실행 실패를 일으키고 트랜잭션은 결국 실패합니다.
해결하다 :
바운드 매개 변수의 유형과 수가 올바른지 확인하십시오.
$stmt->bind_param('si', $name, $id);
그리고 bind_param 의 반환 값을 확인하십시오.
구덩이 지점 : 거래가 끝나기 전에 $ stmt-> close ()가 호출되지 않으면 연결 리소스가 해제되지 않아 후속 트랜잭션 운영에 영향을 줄 수 있습니다.
해결하다 :
트랜잭션이 종료되기 전에 $ stmt-> close ()를 호출하여 자원이 제 시간에 해제되도록하십시오.
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();
}
<?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();
?>
거래가 시작된 후에는 항상 준비하십시오 .
준비 , BIND_PARAM 의 반환 값을 확인하고 실행하십시오 .
각 준비는 단일 진술 만 처리합니다.
예외가 발생하면 거래를 롤백하십시오.
전처리 명세서 리소스를 닫습니다.
위의 사양에 따라 MySQLI_STMT :: 트랜잭션 프로세싱을 준비하여 데이터 일관성 및 코드 견고성을 보장하는 데있어 일반적인 함정을 효과적으로 피할 수 있습니다.