현재 위치: > 최신 기사 목록> 루프에서 사용될 때 Next_result ()가 죽은 루프를 유발하는 이유 분석

루프에서 사용될 때 Next_result ()가 죽은 루프를 유발하는 이유 분석

gitbox 2025-04-29

개발자는 종종 데이터베이스 작업에 PHP를 사용할 때, 특히 MySQLI의 Multi_Query 설정 (Multi_Query) 기능을 사용할 때 종종 Next_Result () 기능을 사용합니다. 그러나 루프에서 부적절하게 사용하면 트리거되어 스크립트가 정상적으로 끝나지 않을 수 있습니다. 이 기사는 이러한 발생의 이유를 자세히 분석하고 신뢰할 수있는 솔루션을 제공합니다.

1. 문제가 다시 나타납니다

Multi_Query를 사용하여 여러 SQL 문을 실행하는 코드가 있다고 가정합니다.

 $mysqli = new mysqli("localhost", "user", "password", "database");

$sql = "
    SELECT * FROM users;
    SELECT * FROM orders;
    SELECT * FROM products;
";

if ($mysqli->multi_query($sql)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                print_r($row);
            }
            $result->free();
        }
        // 여기 열쇠가 있습니다
    } while ($mysqli->next_result());
}

이 코드에서는 순서대로 세 가지 선택 문을 실행하고 해당 결과 세트를 처리하려고합니다. next_result () 의 목적은 다음 결과 세트를 준비하는 것입니다.

문제는 다음과 같습니다. 마지막으로 next_result () 호출되는 경우 true 이지만 store_result ()가 false를 반환합니다 (더 이상 결과 세트가 없기 때문에)가 죽은 루프로 들어갑니다.

2. 왜 악의적 인주기가 있습니까?

next_result () 의 목적은 mysqli를 다음 결과 세트로 옮기고 부울을 반환하는 것입니다.

  • 진정한 반환은 더 많은 결과 세트 또는 성공적인 스위치가 있음을 의미합니다.

  • 거짓을 반환하면 더 이상 결과 세트가 없거나 오류가 발생하지 않습니다.

그러나 마지막 결과 세트가 빈 결과 세트 (예 : 마지막 명령문은 선택 이지만 결과가 없거나 업데이트 와 같은 비 쿼리 문) 인 경우, store_result ()는 false를 반환 하지만 next_result ()는 여전히 사실을 반환 할 수 있습니다.

3. 솔루션

? 방법 1 : 더 많은 결과 세트가 있는지 확인하십시오

more_results () 메소드를 사용하여 처리 할 수있는 결과 세트가 있는지 여부를 결정할 수 있습니다.

 $mysqli = new mysqli("localhost", "user", "password", "database");

$sql = "
    SELECT * FROM users;
    SELECT * FROM orders;
    UPDATE users SET status = 'active' WHERE id = 1;
";

if ($mysqli->multi_query($sql)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                print_r($row);
            }
            $result->free();
        } else {
            // 결과 세트가 아닙니다,아마도 UPDATE、INSERT 기다리다
            if ($mysqli->errno) {
                echo "MySQL 실수:" . $mysqli->error;
            }
        }

    } while ($mysqli->more_results() && $mysqli->next_result());
}

? 방법 2 : 최대 사이클 수 설정 (방어)

결과 세트 수를 완전히 결정할 수없는 경우 데드 루프를 방지하기 위해 최대 루프 수를 설정할 수 있습니다.

 $maxLoops = 10;
$loopCounter = 0;

if ($mysqli->multi_query($sql)) {
    do {
        if (++$loopCounter > $maxLoops) {
            echo "가능한 죽은 루프가 감지되었습니다,작업을 중단합니다";
            break;
        }

        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                print_r($row);
            }
            $result->free();
        }

    } while ($mysqli->next_result());
}

4. 요약

next_result ()를 사용하는 경우 완전히 신뢰할 수없는 반환 값에 특별한주의를 기울여야합니다. more_results () 와 함께 사용하려면 다음 결과 세트가있는 경우에만 계속하십시오. 그렇지 않으면, 특히 비 쿼리 명령문의 빈 결과 세트 또는 혼합 실행이있을 때 특정 SQL 실행 경로에서 죽은 루프를 쉽게 유발할 수 있습니다.

PHP 및 데이터베이스 운영에 대한 더 많은 모범 사례를 보려면 다음을 방문 할 수 있습니다.

https://gitbox.net/php-mysql-best-practices