Why does this PHP code hang on calls to mysql_query()? - php

I'm having trouble with this PHP script where I get the error
Fatal error: Maximum execution time of 30 seconds exceeded in /var/www/vhosts/richmondcondo411.com/httpdocs/places.php on line 77
The code hangs here:
function getLocationsFromTable($table){
$query = "SELECT * FROM `$table`";
if( ! $queryResult = mysql_query($query)) return null;
return mysql_fetch_array($queryResult, MYSQL_ASSOC);
}
and here (so far):
function hasCoordinates($houseNumber, $streetName){
$query = "SELECT lat,lng FROM geocache WHERE House = '$houseNumber' AND StreetName = '$streetName'";
$row = mysql_fetch_array(mysql_query($query), MYSQL_ASSOC);
return ($row) ? true : false;
}
both on the line with the mysql_query() call.
I know I use different styles for each code snippet, it's because I've been playing with the first one trying to isolate the issue.
The $table in the first example is 'school' which is a table which definitely exists.
I just don't know why it sits there and waits to time out instead of throwing an error back at me.
The mysql queries from the rest of the site are working properly. I tried making sure I was connected like this
//connection was opened like this:
//$GLOBALS['dbh']=mysql_connect ($db_host, $db_user, $db_pswd) or die ('I cannot connect to the database because: ' . mysql_error());
if( ! $GLOBALS['dbh']) return null;
and it made it past that fine. Any ideas?
Update
It's not the size of the tables. I tried getting only five records and it still timed out. Also, with this line:
$query = "SELECT lat,lng FROM geocache WHERE House = '$houseNumber' AND StreetName = '$streetName'";
it is only looking for one specific record and this is where it's hanging now.

It sounds like MySQL is busy transmitting valid data back to PHP, but there's so much of it that there isn't time to finish the process before Apache shuts down the PHP process for exceeding its maximum execution time.
Is it really necessary to select everything from that table? How much data is it? Are there BLOB or TEXT columns that would account for particular lag?
Analyzing what's being selected and what you really need would be a good place to start.

Time spent waiting for mysql queries to return data does not count towards the execution time. See here.
The problem is most likely somewhere else in the code - the functions that you are blaming are possibly called in an infinite loop. Try commenting out the mysql code to see if I'm right.

Does your code timeout trying to connect or does it connect and hang on the query?
If your code actually gets past the mysql_query call (even if it has to wait a long time to timeout) then you can use the mysql_error function to determine what happened:
mysql_query("SELECT * FROM table");
echo mysql_errno($GLOBALS['dbh']) . ": " . mysql_error($GLOBALS['dbh']) . "\n";
Then, you can use the error number to determine the detailed reason for the error: MySQL error codes
If your code is hanging on the query, you might try describing and running the query in a mysql command line client to see if it's a data size issue. You can also increase the maximum execution time to allow the query to complete and see what's happening:
ini_set('max_execution_time', 300); // Allow 5 minutes for execution

I don't know about the size of your table, but try using LIMIT 10 and see if still hangs.
It might be that your table is just to big to fetch it in one query.

Unless the parameters $houseNumber and $streetName for hasCoordinates() are already sanitized for the MySQL query (very unlikely) you need to treat them with mysql_real_escape_string() to prevent (intentional or unintentional) sql injections. For mysql_real_escape_string() to work properly (e.g. if you have changed the charset via mysql_set_charset) you should also pass the MySQL connection resource to the function.
Is the error reporting set to E_ALL and do you look at the error.log of the webserver (or have set display_erorrs=On)?
Try this
function hasCoordinates($houseNumber, $streetName) {
$houseNumber = mysql_real_escape_string($houseNumber);
$streetName = mysql_real_escape_string($streetName);
$query = "
EXPLAIN SELECT
lat,lng
FROM
geocache
WHERE
House='$houseNumber'
AND StreetName='$streetName'
";
$result = mysql_query($query) or die(mysql_error());
while ( false!==($row=mysql_fetch_array($result, MYSQL_ASSOC)) ) {
echo htmlspecialchars(join(' | ', $row)), "<br />\n";
}
die;
}
and refer to http://dev.mysql.com/doc/refman/5.0/en/using-explain.html to interpret the output.

-If you upped the execution time to 300 and it still went through that 300 seconds, I think that by definition you've got something like an infinite loop going.
-My first suspect would be your php code since mysql is used to dealing with large sets of data, so definitely make sure that you're actually reaching the mysql query in question (die right before it with an error message or something).
-If that works, then try actually running that query with known data on your database via some database gui or via the command line access to the database if you have that, or replacing the code with known good numbers if you don't.
-If the query works on it's own, then I would check for accidental sql injection coming from with the $houseNumber or $streetName variables, as VolkerK mentioned.

Related

mysql_insert_id() returns 0 rarely

I am maintaining a server that runs for around 1 year. Nothings gonna be wrong previously. However, suddenly, there is an error in mysql_insert_id(), which returns 0, instead of normal row id from the database. Here's are the core of the code.
$sql = "INSERT INTO $db_table (name,email) VALUES('$name','$email')";
mysql_query($sql);
$current = mysql_insert_id();
Also notice that even if there are no changes in the code, the program runs smoothly again after the error has happened. It seems strange to me.
Here is my possible explanation. Since I am hosting in a public server, where many are using the same MYSQL server. Will it be that when mysql_query($sql), the server then swap the process and let another guy to run another SQL command, which may be for example, a SELECT statement, and after their execution, it swaps back to my own code and continue executing, which results in 0?
Please help. Thanks.
to be sure use the resource_identifier as parameter in mysql_queryand mysql_insert_id.
If you don't, the last connection to the mysql server is used, as you thought.
$resource = mysql_connect(...);
$sql = "INSERT INTO $db_table (name,email) VALUES('$name','$email')";
mysql_query($sql, $resource);
$current = mysql_insert_id($resource);
Please consider using mysqli oder PDO since mysql_* functions are deprecated and are going to be removed in future PHP-Versions

Getting a basic PDO statement to execute

I am attempting to get the following PDO statement to work and running into issues. When I am trying to get the number of rows, I keep getting 0, yet I know there should be 1 row. When I ran it as a mysqli statement( before trying to change it to PDO) it worked perfectly.
Here is the code:
require_once ('pdo.php');
$isbn = $_POST['isbn'];
// check to see if the isbn is a "problem" isbn or not
$problem = $conn->prepare("select isbn, note from problem where isbn = :isbn");
$problem->bindParam(":isbn", $isbn);
$problem->execute();
print_r($problem);
$num_rows = $problem->rowCount();
print_r($num_rows); die;
EDIT: Here is pdo.php:
<?php
function db_connect()
{
$db = new PDO("mysql:host=localhost; db=bookcell_BCOS_final", "xxxxx", "xxxxx");
return($db);
}
?>
I know that my connection works, but I get 0 for $num_rows. What mistakes am I making here?
Besides a little quirk and a optimalisation your code looks fine to me. The posted value isbn could be the reasong that you are getting no data:
$problem = $conn->prepare("select isbn, note from problem where isbn = :isbn");
$problem->bindParam(":isbn", $_POST['isbn'], PDO::PARAM_STR); // <-- thats what parameter binding is for
$problem->execute();
print_r($problem);
$num_rows = $problem->rowCount(); // <-- gives the number of rows, not columnCOunt
print_r($num_rows); die;
The Syntax for $num_rows = $problem->columnCount(); is totally correct. You may try,
$problem->execute(array("isbn" => $isbn));
instead of bindParam.
for getting the no. of rows, you need to use pdo::rowCount() -- manual here
In PDO to verfiy if your execute statement did work, check the return value (bool):
$success = $problem->execute();
if (!$success) {
$arr = $problem->errorInfo();
print_r($arr);
}
Also you might be looking for rowCount() instead of columnCount() but I think the error handling is your furthermost issue.
Additionally you can make PDO throw an exception each time an error appears, compare:
Switching from PHP's mysql extension to PDO. Extend class to reduce lines of code
How do I raise PDOException?
Depending on the database driver and the mode it's running, PDO may not be able to give you a row count. Look carefully at the documentation for PDOStatement::rowCount():
If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.
This is because in many cases the database uses a cursor rather than fetching the full results and buffering them (which is how the old mysql_* functions behave). In this case the database doesn't know how many rows there are until you have looked at all the rows. Think of a cursor as something like a filesystem pointer--you can't know the filesize until you seek to the end of the file.

SQLSRV with Linked Server

My issues basically revolves around me needing/preferring to use PHP's sqlsrv to access a sql-server 2000 database. I've worked on the project already using that with a sql server 2005 to run all the queries through and switching to something like the ODBC PHP drivers would be a pretty big headache right now. So now I have the original SQL Server 2000 database and 2005 installed on the same computer and I've created a linked server between the 2. Testing it out in Management Studio Express worked by running a simple query to one of the tables.
Now, I'm using the exact same query in PHP using sqlsrv_query and running into an error. My PHP code to test this out looks like this
$connectionOptions = array("UID"=>"user","PWD"=>"password");
$res = sqlsrv_connect("(local)\SQLExpress", $connectionOptions);
if(!$res) die("ERRORS : " . print_r(sqlsrv_errors()));
echo "SELECT * FROM [ServerName].DB.dbo.Table<br/>";
$res = sqlsrv_query($res,"SELECT * FROM [ServerName].DB.dbo.Table");
if($res===false){
die("ERRORS : " . print_r(sqlsrv_errors()));
}else{
var_dump($res);
$ary = sqlsrv_fetch_array($res);
}
var_dump($ary);
echo "<hr>";
var_dump(sqlsrv_errors());
The problem with this code is that the result of of sqlsrv_query doesn't return false but returns resource(11) of type unknown. So running fetch_array on that result tells me that an invalid parameter was passed to sqlsrv_fetch_array. I'm not sure what to do at this point. Is there just a problem running a query on a linked server through sqlsrv?
seems no error in your code.
Please try the fetch_array in a loop and update the result.
while($row = sqlsrv_fetch_array($result))
{
echo($row['field_name']);
}
also remove var_dump($ary);
Usually even if there is any error in the data display using '$row', the error message will show problem with 'sqlsrv_fetch_array'.
Well I figured out the problem. In my haste to make some code to test out whether or not the linked server worked, I just used the same variable name for the result of sqlsrv_connect and sqlsrv_query. Turns out, that was the whole problem. I switched the variable names so that the connection object is $Link and the query stays as $res. Now, I get the access to the database that I was trying to get through 2005 into 2000. So in the future, I definitely will name my variables a bit more carefully so I don't bang my head against the wall for hours.

automatically executing mysql query from php not working

I'd like to automatically execute the following PHP script to autmoatically delete a row in table after 3 days. However, the script seems not working, even though the query already yield the correct result. I've tried to run it manually, and it also worked. I'm not sure whether I've written the script correctly, but here's the code:
<?php
require_once('../../resources/db_connect.php');
$query = "DELETE FROM user_orders WHERE date_order < DATE_SUB(CURDATE(), INTERVAL 3 DAY) AND ID_status_order = 1";
$result = #mysql_query($query);
?>
I'm using xampp on Windows. I've tried to execute it via Windows Task Scheduler, but I don't think it's working. Any other idea?
Cheers
Hidding errors are not good enough. Thry and remove the # first and see what errors you are having. Come back and give the errors.
echo mysql_query($query) or mysql_error()
You aren't doing any error checking, and with the # in front of commands even actively suppressing errors. Use this to check for errors with your query or database connection:
mysql_query($query) or die(mysql_error());
If you want to check your query but don't want it to delete everything, add another condition to it:
... AND 1=0
which is always false, thus nothing gets deleted. MySQL will still check your query and give you errors, if e.g. some fields or the table are unknown.

mysql query occasionally returns nothing

We have a function used within our PHP/MySQL application which returns basic configuration information, it contains a simple select query and looks like this:
public function getConfigurationValue($field)
{
$res = mysql_query("SELECT `cfg_value` FROM `ls_config` WHERE `cfg_name` = '".mysql_real_escape_string($field)."'");
$cfg = htmlspecialchars(mysql_result($res,0));
return $cfg;
}
This problem we are having is that occasionally, seemingly at random, this query throws a mysql error on mysql_result saying that "supplied argument is not a valid mysql result resource". In our debugging we have determined though that this is not because $field is not being passed. Essentially, for a reason we cannot determine a perfectly valid query fails and returns no results causing an empty result set and the subsequent error. If the error was due to the mysql connection failing the script would have died well before this. Also, this function may be called 50-100 times on some page loads but it only tends to fail once on each load.
Please let me know if you need any other information to work this out.
Thanks.
searching for php "supplied argument is not a valid mysql result resource" reveals that to get the actual error, you'd need to call mysql_error, and the error that you get is because the result of the query is FALSE - this value not being a valid mysql result resource.
i.e. in short you have something like:
$res = FALSE; # should contain the mysql result but does not, due to error.
$cfg = htmlspecialchars(mysql_result($res,0)); # the attempt to call mysql_result on invalid argument errors out.
So you'd want to use something like this:
$query = "SELECT * FROM cats WHERE id=$id";
$qr1 = mysql_query ($query)
or die ("Query failed: " . mysql_error() . " Actual query: " . $query);
You might want to give this a shot and see what the underlying error message says.
Given that the error is "MySQL server has gone away", There can be multitude of reasons for it - this article would be a good start to investigate. Searching suggests also some php-related and stack-specific bugs, so it looks like you might need to debug it with a closer attention.
Maybe try to duplicate the setup on another box and then start experimenting with the versions/settings, and see if any of the already reported scenarios match your case. Unfortunately, seems there's no single simple answer to this.

Categories