Giao thức máy khách MySQL không cho phép nhiều hơn một truy vấn "đang xử lý." Có nghĩa là, bạn đã thực hiện một truy vấn và bạn đã tìm nạp một số kết quả, nhưng không phải tất cả - sau đó bạn thử thực hiện một truy vấn thứ hai. Nếu truy vấn đầu tiên vẫn còn các hàng để trả lại, thì truy vấn thứ hai sẽ gặp lỗi.
Thư viện ứng dụng khách giải quyết vấn đề này bằng cách tìm nạp tất cả các hàng của truy vấn đầu tiên ngầm định khi lần tìm nạp đầu tiên, và sau đó các lần tìm nạp tiếp theo chỉ cần lặp lại các kết quả được lưu trong bộ nhớ cache. Điều này cho họ cơ hội để đóng con trỏ (liên quan đến máy chủ MySQL). Đây là "truy vấn được đệm". Điều này hoạt động giống như sử dụng fetchAll (), trong đó cả hai trường hợp phải cấp phát đủ bộ nhớ trong máy khách PHP để chứa toàn bộ tập kết quả.
Sự khác biệt là truy vấn được đệm giữ kết quả trong thư viện máy khách MySQL, vì vậy PHP không thể truy cập các hàng cho đến khi bạn tìm nạp () từng hàng một cách tuần tự. Trong khi đó fetchAll () điền ngay vào một mảng PHP cho tất cả các kết quả, cho phép bạn truy cập vào bất kỳ hàng ngẫu nhiên nào.
Lý do chính không để sử dụng fetchAll () là kết quả có thể quá lớn để vừa với memory_limit PHP của bạn. Nhưng có vẻ như kết quả truy vấn của bạn dù sao cũng chỉ có một hàng, vì vậy đó không phải là vấn đề.
Bạn có thể closeCursor () để "bỏ qua" một kết quả trước khi bạn tìm nạp hàng cuối cùng. Máy chủ MySQL nhận được thông báo rằng nó có thể loại bỏ kết quả đó ở phía máy chủ và sau đó bạn có thể thực hiện một truy vấn khác. Bạn không nên closeCursor () cho đến khi tìm nạp xong một tập kết quả nhất định.
Ngoài ra:Tôi nhận thấy rằng bạn đang thực hiện lặp đi lặp lại $ stmt2 bên trong vòng lặp, nhưng nó sẽ trả về cùng một kết quả mỗi lần. Về nguyên tắc di chuyển mã bất biến của vòng lặp ra khỏi vòng lặp, bạn nên thực hiện điều này một lần trước khi bắt đầu vòng lặp và lưu kết quả trong một biến PHP. Vì vậy, bất kể sử dụng truy vấn đệm hay fetchAll (), bạn không cần phải lồng các truy vấn của mình.
Vì vậy, tôi khuyên bạn nên viết mã của bạn theo cách này:
$sql ='SELECT temp_id FROM temp1';
$stmt2 = db::db()->prepare($sql);
$stmt2->execute();
$rs2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$stmt2->closeCursor();
$sql='SELECT COUNT(*) AS valid FROM cities_has_zipcodes
WHERE cities_id=:cities_id AND zipcodes_id=:zipcodes_id';
$stmt1 = db::db()->prepare($sql);
foreach($data AS $row)
{
try
{
$stmt1->execute($row);
$rs1 = $stmt1->fetchAll(PDO::FETCH_ASSOC);
$stmt1->closeCursor();
syslog(LOG_INFO,'$rs1: '.print_r($rs1[0],1).' '.rand());
syslog(LOG_INFO,'$rs2: '.print_r($rs2[0],1).' '.rand());
}
catch(PDOException $e){echo(sql_error($e));}
}
Lưu ý rằng tôi cũng đã sử dụng các tham số được đặt tên thay vì tham số vị trí, điều này làm cho việc chuyển $ row dưới dạng mảng giá trị tham số trở nên đơn giản hơn. Nếu các khóa của mảng khớp với tên tham số, bạn chỉ có thể chuyển mảng. Trong các phiên bản PHP cũ hơn, bạn phải bao gồm :
tiền tố trong các khóa mảng, nhưng bạn không cần tiền tố đó nữa.
Dù sao thì bạn cũng nên sử dụng mysqlnd. Nó có nhiều tính năng hơn, tiết kiệm bộ nhớ hơn và giấy phép của nó tương thích với PHP.