MySQL connection reuse problem - mysql

I am trying to reuse mysql connection. Hence I have a global variable in databasemanager.php class that returns a connection.
The problem is somehow on one particular page mysql is executing prior query as well.
Looks like there is some leftover query in connection object that gets executed if same connection is being reused . Is it possible ? how to solve this ..
function getDBConnection(){
global $conn;
if (!empty($conn)){
// echo $conn ;
return $conn;
}
$conn = mysql_connect($GLOBALS['HOSTNAME'],$GLOBALS['DBUSER'],$GLOBALS['DBPASS']);
if (!$conn) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db($GLOBALS['DBNAME'],$conn);
return $conn;
}
This how code lookslike

Have you looked into mysql_pconnect?
According to the documentation:
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()).

Related

Use same mysqli prepared statement for different queries?

Throughout some testings; a little question popped up. When I usually code database updates; I usually do this via callbacks which I code in PHP; to which I simply pass a given mysqli connection object as function argument. Executing all queries of for example three queries across the same single connection proved to be much faster than if closing and reopening a DB connection for each query of a given query sequence. This also works easily with SQL transactions, the connection can be passed along to callbacks without any issues.
My question is; can you also do this with prepared statement objects ? What I mean is, considering we successfully established a $conn object, representing the mysqli connection, is stuff like this legit? :
function select_users( $users_id, $stmt ) {
$sql = "SELECT username FROM users where ID = ?";
mysqli_stmt_prepare( $stmt, $sql );
mysqli_stmt_bind_param( $stmt, "i", $users_id );
mysqli_stmt_execute( $stmt );
return mysqli_stmt_get_result( $stmt );
}
function select_labels( $artist, $stmt ) {
$sql = "SELECT label FROM labels where artist = ?";
mysqli_stmt_prepare( $stmt, $sql );
mysqli_stmt_bind_param( $stmt, "s", $artist );
mysqli_stmt_execute( $stmt );
return mysqli_stmt_get_result( $stmt );
}
$stmt = mysqli_stmt_init( $conn );
$users = select_users( 1, $stmt );
$rappers = select_labels( "rapperxyz", $stmt );
or is it bad practice; and you should rather use:
$stmt_users = mysqli_stmt_init( $conn );
$stmt_rappers = mysqli_stmt_init( $conn );
$users = select_users( 1, $stmt_users );
$rappers = select_labels( "rapperxyz", $stmt_rappers );
During the testing; I noticed that the method by using a single statement object passed along callbacks works for server calls where I call like 4 not too complicated DB queries via the 4 according callbacks in a row.
When I however do a server call with like 10 different queries, sometimes (yes, only sometimes; for pretty much the same data used across the different executions; so this seems to be weird behavior to me) I get the error "Commands out of sync; you can't run this command now" and some other weird errors I've never experienced, like the amount of variables not matching the amount of parameters; although they prefectly do after checking them all. The only way to fix this I found after some research was indeed by using different statement objects for each callback. So, I just wondered; should you actually ALWAYS use ONE prepared statement object for ONE query, which you then may execute N times in a row?
Yes.
The "commands out of sync" error is because MySQL protocol is not like http. You can't send requests any time you want. There is state on the server-side (i.e. mysqld) that is expecting a certain sequence of requests. This is what's known as a stateful protocol.
Compare with a protocol like ftp. You can do an ls in an ftp client, but the list of files you get back depends on the current working directory. If you were sharing that ftp client connection among multiple functions in your app, you don't know that another function hasn't changed the working directory. So you can't be sure the file list you get from ls represents the directory you thought you were in.
In MySQL too, there's state on the server-side. You can only have one transaction open at a time. You can only have one query executing at a time. The MySQL client does not allow you to execute a new query where there are still rows to be fetched from an in-progress query. See Commands out of sync in the MySQL doc on common errors.
So if you pass your statement handle around to some callback functions, how can that function know it's safe to execute the statement?
IMO, the only safe way to use a statement is to use it immediately.

How can I skip all errors on an RDS replica instance?

I use certain my.cnf settings like this. Does RDS instance allow such options?
slave-skip-errors = 1062,1054
replicate-ignore-db=verv_raw
replicate-ignore-table=verv.ox_session
replicate-wild-ignore-table=verv_raw.ox%
replicate-wild-ignore-table=verv_raw.ox%
I am aware of the procedure that skips one error at a time.
CALL mysql.rds_skip_repl_error;
But what I am looking for is an option to skip all errors on slave. Is it possible in RDS environment?
I solved it by creating a mysql event scheduler like this :
CREATE EVENT repl_error_skipper
ON SCHEDULE
EVERY 15 MINUTE
COMMENT 'Calling rds_skip_repl_error to skip replication error'
Do
CALL mysql.rds_skip_repl_error;
/*also you can add other logic */
To set other global variables you can find and set those (if available for changing) in rds parameter group (you will have to create new parameter group and set the variable values).
As mentioned, this command only skips one replication error. I wrote a PHP script to loop through this and ran it once a minute via cron job (my replica was log jammed with a series of thousands of bad queries than went through on the main DB)
for($i = 1; $i <= 30; $i++) {
$db = new mysqli('someserver.rds.amazonaws.com', 'root', 'password');
$res = $db->query('CALL mysql.rds_skip_repl_error;');
if(!$res) {
//echo 'Query failed: ' . $db->error . "\n";
return;
}
//var_dump($res->fetch_assoc());
$db->close();
sleep(1);
}
You'll need to tinker with this some (not every server would tolerate only one second between calls and 30 calls per minute), but it does work (albeit in a brute force manner). You must create a new DB connection every time to run this. The loop opens, runs and then closes the connection.

mysql_query() keeps running after php exits

I've noticed that if I execute a long running mysql query with php using mysql_query() (I know I'm not supposed to use that) and then the php process gets killed then the query continues to run on the mysql server. This is not a persistent connection. The connection is made with:
$db = mysql_connect($host, $login, $pass, false);
$sql = 'SELECT COUNT(*) FROM `huge_table`';
$result = mysql_query($sql, $db);
For example, let's say I have a 1 billion row table and a php process does this for some reason:
SELECT COUNT(*) FROM `huge_table`
And then it times out (say because I'm running php-fpm with request_terminate_timeout=5), so it kills the process after 5 seconds to make sure it doesn't hog things.
Eventhough the process is killed, the query still runs on mysql even far after wait_timeout.
Is there anyway to make sure that if the php process exits for whatever reason it also kills any running queries that it made?
I'm using tokudb 5.5.38-tokudb-7.1.7-e which is mysql 5.5.38
crickeys, when a PHP script starts to execute and it gets to the part where it executes a MySQL query, that query is handed over to MySQL. The control of the query is no longer in PHP's hands....PHP at the point is only waiting for a response from MySQL then it can proceed. Killing the PHP script doesn't affect the MySQL query because well, the query is MySQL's business.
Put another way, PHP comes to the door, knocks, hands over the goods and waits for you to bring back a response so he can be on his way. Shooting him won't affect what's going on behind the door.
You could run something like this to retrieve the longest running processes and kill them:
<?php
$con=mysqli_connect("example.com","peter","pass","my_db");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SHOW FULL PROCESSLIST");
while($row = mysqli_fetch_array($result)) {
if ($row["Time"] > $max_excution_time ) {
$sql="KILL ".$row["Id"];
mysql_query($sql);
}
}
mysqli_close($con); ?>
Well you can use a destructor to call
mysql_close(); function.
I hope I understood your question...
You can use KILL.
KILL CONNECTION is the same as KILL with no modifier: It terminates the connection associated with the given thread_id.
KILL QUERY terminates the statement that the connection is currently executing, but leaves the connection itself intact.
You should KILL QUERY in the shutdown event, and then do a mysqli_close().
You might get some valuable information from this question about timeouts: Client times out, while MySQL query remains running?

Efficient way to connect to a database when multiple functions are running queries

I'm writing an application that has a functions.php file that a javascript file is accessing via Ajax. Currently I have each function connecting to the database, running queries, then closing the database. I know there has to be a more efficient way of doing this. I'd like to only input the database credentials once and then have all the functions use it. Whats the most efficient way to do this? I've read quite a few of the answers here on this topic but they're all different and I'm lost. Just point me in the right direction :)
Currently my functions are opening the database like this.
$db = new mysqli("hostname", "username", "password");
$db -> select_db("database name");
Or like this
mysql_connect("hostname", "username", "password");
mysql_select_db('database name') or die( "Unable to select database");
The simple answer is connection pooling. A connection pool is a pool of connections that are always connected to the database. You can set a high water mark and a low water mark for the number of connections.
When your application requests a connection from the pool it will then use one of the idle connections and reuse it. This is how you scale database connectivity.
You are using PHP so look at the following:
http://www.oracle.com/technetwork/topics/php/php-scalability-ha-twp-128842.pdf
http://php.net/manual/en/mysqlnd-ms.pooling.php
There is a lot of information around this on the net.
You can just check whether the database connection variable is already set:
if (!isset($db)) {
$db = new mysqli(...);
$db->select_db("database_name");
}
and similarly with mysql_connect (it returns a connection resource, so you can assign it to a variable, even though it's an optional argument to the other functions).
Another way is to use a function with a static variable:
function connect_db() {
static $db = new mysqli(...);
static $selected = $db->select_db("database_name");
return $db;
}
A third options is to connect to the database once at the beginning of the script, instead of in each function. Then either pass $db to each function, or access it with global $db;.

MYSQLI not playing nice with INSERT

So excuse the coding if it's not totally up to par, but I just got a hang of MYSQL and am switching to MYSQLI (procedural as I find it easier as I haven't learned object oriented yet, i'm new to this)
My problem is I have a simple 'Invoice' page on a small website that worked perfectly with MYSQL. When I switched to MYSQLI (I'm sure I am missing something obvious) I can echo all the variables, have checked for proper DB connection yet it will not INSERT anything into the DB.
This is the function in question, it is called after a "fill invoice" form is submitted, again, all the $_POST variables can be echoed in the function properly.
function createinvoice($billto,$cust,$addr,$desc,$desccost,$labcost,$comment){
$taxrate=".13";
$kaboom=str_replace(array("\r\n","\r","\n"),"<br />",$desccost); //keep original desccost for database
$kaboom=mysqli_real_escape_string(nl2br($kaboom));
$kaboom=nl2br($kaboom);
$lines=explode("<br />",$kaboom);
$matcost=0;
for($i=0;$i < count($lines);$i++)
{
$matcost=$matcost+$lines[$i];
}
$fullcost=$matcost+$labcost;
$taxdue = $fullcost*$taxrate;
$totaldue=$fullcost+$taxdue;
$desc=mysqli_real_escape_string($desc);
mysqli_query($con,"INSERT INTO invoice(customerID,customerName,customerAddr,description,desccost,material,labour,taxdue,totaldue,comment)
VALUES('$billto','$cust','$addr','$desc','$desccost','$matcost','$labcost','$taxdue','$totaldue','$comment')");
mysqli_free_result($result);
mysqli_close($con);
}
Edit: to show connection string
if(include("/../dbinvoice.php")){echo "DB file connected";}
$con = mysqli_connect($dbhostname, $dbuser, $dbpass, $dbname);
if (mysqli_connect_errno($con)){echo "No MYSQL connection: ".mysqli_connect_error();exit();}
Every time the page loads I get a message "DB file connected" showing it read the dbinvoice.php file and I don't get an error message with connect. I have verified with phpinfo() that mysqli is on my machine (webmatrix testing).