PHP & mysqli: What is the difference between persistent connection and interactive? - php

What are the differences between the following:
// Persistent connection
$mysqli->real_connect("p:" . $host, $user, $pass, $db, null, null, 0);
and
// Interactive connection
$mysqli->real_connect($host, $user, $pass, $db, null, null, MYSQLI_CLIENT_INTERACTIVE);
or even this one...
// Interactive AND persistent
$mysqli->real_connect("p:" . $host, $user, $pass, $db, null, null, MYSQLI_CLIENT_INTERACTIVE);

Just my interpretation of the docs...
Persistent connections are kept open indefinitely. Non-persistent connections are not.
The mysql_pconnect() docs are a little more clear than the real_connect() docs:
mysql_pconnect() acts very much like mysql_connect() with two major differences.
First, when connecting, the function would first try to find a (persistent) link that's already open with the same host, username and password. If one is found, an identifier for it will be returned instead of opening a new connection.
Second, the connection to the SQL server will not be closed when the execution of the script ends. Instead, the link will remain open for future use ( mysql_close() will not close links established by mysql_pconnect()).
This type of link is therefore called 'persistent'.
Regarding MYSQLI_CLIENT_INTERACTIVE:
MYSQLI_CLIENT_INTERACTIVE
Allow interactive_timeout seconds (instead of wait_timeout seconds) of inactivity before closing the connection. The client's session wait_timeout variable will be set to the value of the session interactive_timeout variable.
Normally, non-persistent connections are closed after the number of seconds specified by the wait_timeout variable. With this flag, they are instead closed after the number of seconds specified by the interactive_timeout variable.
By my interpretation, that means that the MYSQLI_CLIENT_INTERACTIVE does not change the behavior of a persistent connection.

When you use the first one mysqli tries to find a (persistent) link that's already open with the same host, username and password (NOT PORT). If one is found, an identifier for it will be returned instead of opening a new connection.
The connection to the SQL server will NOT be closed when the execution of the script ends. Instead, the link will remain open for future use.

Related

Php + mysql - connection dies consistantly after 66,946 chars of query input

I've been trying to debug a randomly dropping mysql connection in my php project.
Things I've discovered so far:
Once the input over a single mysql connection (total chars used in queries over a single mysql connection) passes 66,946 chars, php just locks up indefinitely on the query that caused it to go over.
If I reconnect the mysql server occasionally rather than re-using the existing connection for the whole time, the mysql connection won't drop as long as I don't go over 66946 chars in the input for any single mysql connection.
It doesn't matter whether it's a single query, or a bunch of little queries. As soon as the "66947" threshold is passed on a single mysql connection, php hangs indefinitely.
It's not a memory issue. Php is only taking 10Mb of memory at most, and it has a max memory of 512Mb.
The mysql connection is remote, if that matters.
This exact code works on my local dev environment (with any length of query, same remote connection), but not on the production server with queries adding up to over 66,946 chars in length
The php version & config files for my dev environment and the live environment are identical, and both are running Ubuntu (well, locally it's technically WSL)
Switching between mysqli and PDO doesn't make a significant difference (just a different number of input chars before it crashes, less chars with PDO than mysqli)
(update): I also tried this script on another similar ubuntu host with the same version of PHP, using the same mysql host. It worked flawlessly there... so I'm really lost as to what the issue could be.
I've narrowed it down to this minimal reproduction case:
<?php
if ( ! empty($argv[1])) {
$count = intval($argv[1]);
}
if (empty($count) || $count < 34) {
$count = 34;
}
$longText = str_repeat("a", $count - 34);
$query = "select * from abcdef limit 1/* {$longText} */"; // where "abcdef" is my table name
$mysqliConnection = mysqli_connect("my_host", "my_username", "my_password", "my_database");
echo "query length: " . strlen($query);
$result = mysqli_query($mysqliConnection, $query);
echo "\n\nSuccess!\n\n";
providing the argument 66946 returns "success!" instantly, and 66947 just makes the production server hang indefinitely (but works fine in my local box!).
Why is there some mysterious input limit on my php mysql connections? How can I stop it (whatever "it" is) from limiting my php mysql connection input length?
You're probably looking for max_allowed_packet. It's defined in my.cnf.
Use SHOW VARIABLES LIKE 'max_allowed_packet'; to check it.
It turns out there was a misconfiguration in the routing table for the server. Fixing the routing table solved the issue.
Took many hours to come to this conclusion, everything was pointing to a php fpm or mysql setting being misconfigured, I didn't even think it could be a routing issue. Hopefully this helps someone in the future.

Can we use this simple method instead of using variable itself

I have marked many of developers using
$con1 = mysql_connect('localhost', 'username', 'password');
$rv1 = mysql_select_db('db1'); // not added connection
Instead
$con1 = mysql_connect('localhost', 'username', 'password');
$rv1 = mysql_select_db('db1', $con1); // added connection
Can I know the difference between this both?
Actually this both are giving same result
The mysql_ functions will implicitly use the last connection which was opened with mysql_connect, if you do not pass an explicit connection parameter. So, yes, in this case it's the same result whether you pass the parameter or not. You will get different results should you happen to open more than one connection using mysql_connect.
Note that implicitly relying on an open connection is bad practice, precisely because your application will screw up if you need to open more connections sometime later. Also note that the mysql_ API is dead, switch to mysqli or PDO.
Take a look at the PHP manual:
http://www.php.net/manual/en/function.mysql-select-db.php
Without a link identifier, mysql_select_db will use the last connection opened with mysql_connect or it will try to connect without any parameter. So the second one is safer and you could use multiple connections.
mysql_select_db and mysql_connect is deprecated though. You should switch to PDO or mysqli.
Taken from the documentation:
bool mysql_select_db ( string $database_name [, resource $link_identifier = NULL ] )
link_identifier
The MySQL connection. If the link identifier is not specified, the last link opened by mysql_connect() is assumed. If no such link is found, it will try to create one as if mysql_connect() was called with no arguments. If no connection is found or established, an E_WARNING level error is generated.
Basically it will used the last known connection object if none is provided. In your case, the last known connection was created on the previous line. This is an optional parameter so the function will operate in the same way if the connection is passed explicitly or not.
On a related note, please notice the big red warning at the top of the documentation page I have linked to. The mysql_* extensions are deprecated and it is recommended that you use a different extension. For a more detailed explanation, please take a look at this thread:
Why shouldn't I use mysql_* functions in PHP?

mysql_real_escape_string method really slow (nearly 1 second)

i do have a Query here (PHP with Zend Framework on a MySQL Database) using one POST Parameter as an argument in an SQL Statement.
So i do have a local XAMPP Installation on my development machine and the runtime of this small Script ist something like 150ms no matter if i pass the argument with or without using mysql_real_escape_string() on that argument before.
Then i do have a virtual server with BitNami-WAMP-Stack installed. When i run the Script there (100% same database content) it takes around 260ms without mysql_real_escape_string, this is not as "fast" (i know that 150ms isn't really fast at all) as my local machine but would be okay. But if i do add only one mysql_real_escape_string() to the argument from the POST variable the whole thing takes 1.2 seconds.
And i further noticed that every call to mysql_real_escape_string makes the script run around 1 second slower on the virtual server. On my local machine this does not have any effect.
How can this be? Is this a MySQL Setup thing or a PHP.ini thing or what? Because i do have the 100% same database and PHP source on both machines i guess it can only be parametrization?
Thanks for any help in advance!
EDIT:
So here is what i do, first connecting the DB (in Bootstrap.php):
$GLOBALS["db"]= new Zend_Db_Adapter_Pdo_Mysql(array(
'host' => "localhost",
'username' => "user",
'password' => "password",
'dbname' => "database"
));
And then later in want to query the database:
global $db;
$query = sprintf("SELECT * FROM table WHERE id = '%s'", mysql_real_escape_string($id) );
$db->query("SET NAMES 'utf8'");
$db->fetchAll($query);
I just made another test: when i add this simple test-line to my code, it makes the script ~600ms slower on the virtual machine:
mysql_real_escape_string("TEST");
use prepared statements to do this:
http://framework.zend.com/manual/en/zend.db.statement.html
The long-term solution must be switching to prepared statements, that is right. An equivalent to mysql_real_escape_string for PDO connections seems to be PDO::quote:
http://php.net/manual/de/pdo.quote.php
Any disadvantages compared to a mysql_real_escape_string based solution?
I had the same delay on first call mysql_real_escape_string method, solution in my case was information from manual: http://php.net/manual/en/function.mysql-real-escape-string.php
"A MySQL connection is required before using mysql_real_escape_string() otherwise an error of level E_WARNING is generated, and FALSE is returned. If link_identifier isn't defined, the last MySQL connection is used."
The only thing missig was information about delay if connection is not estabilished.
In your case I suppose that if you are using PDO for connection then you should use PDO::quote. If you are using mysql_pconnect/mysql_connect then you can use mysql_real_escape_string without delay.

Open new SQL Server connection in PHP

I have an open SQL Server connection and need to open and close another while maintaining the first connection. I CANNOT hold onto the resource ID for the original.
Connection A (may or may not be open)
Open connection B
Perform a few queries using connection B
Close connection B
Continue working with connection A
If you are using the below method to establish your connections you may not really have an 'A' and 'B' connection. It may also provide a way for you to recover the previously opened 'A' connection if you utilize the '$new_link' argument.
resource mssql_connect ([ string $servername [, string $username [, string $password [, bool $new_link ]]]] )
from php.net http://www.php.net/manual/en/function.mssql-connect.php
new_link
If a second call is made to mssql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned. This parameter modifies this behavior and makes mssql_connect() always open a new link, even if mssql_connect() was called before with the same parameters.
So basically if you create connection A and then connection B with new_link true then use and close connection B, your next call to mssql_connect with new_link false would return connection A.
I have not tested this but the documentation shows it to be possible and though it is probably not ment to solve your problem you may be able to use it for that.
I am however curious why you can not hold onto A as well as why you need the second connection.

How to connect to multiple databases in a single PHP page? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
How do you connect to multiple MySQL databases on a single webpage?
If I want to connect to one db do some query, and then later do another query from another DB. How do I do it? Do I just
mysql_pconnect("host:3306", "user", "password") or die(mysql_error());
mysql_select_db("Test") or die(mysql_error());
//do some query
mysql_pconnect("host2:3306", "user", "password") or die(mysql_error());
mysql_select_db("Test") or die(mysql_error());
//do another query
Is that how you do it? A couple of questions. Notice I used pconnect, does that affect calling it twice on the same page? Also, do I have to close the connection for the first one before calling the second one?
You need to store database connection link in separate variable. For example
$connection_1 = mysql_connect("host:3306", "user", "password") or die(mysql_error());
mysql_select_db("Test", $connection_1) or die(mysql_error());
$connection_2 = mysql_pconnect("host2:3306", "user", "password") or die(mysql_error());
mysql_select_db("Test", $connection_2) or die(mysql_error());
mysql_query("your query", $connection_1); // run query for first connection
mysql_query("your query", $connection_2); // run query for second connection
You need to store the resource returned from mysql_connect and use it when doing mysql_select_db.
$res1 = mysql_pconnect(...);
mysql_select_db("Test", $res1);
$res2 = mysql_pconnect(...);
mysql_select_db("Test", $res2);
Then use $res1 or $res2 when querying the corresponding db.
mysql_query("select * from test_table", $res1);
mysql_query("select * from test_table", $res2);
Is that how you do it?
This will leave your script with two open connections to different hosts until it ends.
You may reuse either of these connections by calling mysql_pconnect again.
Notice I used pconnect, does that affect calling it twice on the same page?
From the docs:
The function would first try to find a (persistent) link that's already open with the same host, username and password
Since your hosts are different, there will be two different connections
Also, do I have to close the connection for the first one before calling the second one?
You cannot explicitly close a connection open with mysql_pconnect.
You did RTM, right, because you're not using the $link_identifier?
http://us.php.net/mysql_select_db :
bool mysql_select_db ( string $database_name [, resource $link_identifier ] )
Sets the current active database on the server that's associated with the specified link identifier. Every subsequent call to mysql_query() will be made on the active database.
Parameters
database_name
The name of the database that is to be selected.
link_identifier The MySQL connection.
If the link identifier is not specified, the last link opened by mysql_connect() is assumed. If no such link is found, it will try to create one as if mysql_connect() was called with no arguments. If no connection is found or established, an E_WARNING level error is generated.
Whenever you have use the pconnect, you're sharing the connection (not only within the page, but possibly with other pages) -- in your case here, don't do that. You want isolated links, therefore isolated transactions. You should probably consider mysql_connect instead, and explicitly using the new_link parameter. Lastly, use the $link_identifier explicitly, so you are clear what you are connecting to.

Categories