First, some background: I am working on a pre-2000 website that uses mysql_connect and mysql_* functions everywhere. It is not feasible to simply replace all of these at the moment.
I do, however, plan on slowly making the change to mysqli_* functions. I have run into an instance where I need to use mysqli_multi_query though, and was wondering if it would be better to:
Create a function that opens and closes the mysqli connection, while performing one mysqli_multi_query.
Create a function that opens a mysqli connection when needed, and only open the mysqli connection only on pages that need it.
Simply use the mysqli_connect() function the same way I am using the mysql_connect() function and have both connect at the beginning of my scripts and close at the end, on all pages.
The trouble I am having with deciding on these is that 1 limits the number of multi-queries I can do on one page (while also adding to the future code-cleanup that needs to be done), 2 also adds to the code-cleanup, albeit not quite as much as 1, and 3 might be either inefficient, or unsafe, although I would be able to clean-up as I run into the old queries.
This website gets over 1 million visitors per month.
Anyone know what would be "best-practice" in this scenario?
"best practice" seems to be to use PDO for your MySQL connections, according to recent articles turned up during a search on the topic (for example https://phpbestpractices.org/#mysql ) although I couldn't find any specific guidance on when to open those connections if they are not strictly required on that page.
I'd suggest going with your second choice, as the abstraction makes code more manageable and maintainable in the future, for you and for other devs. As far as I know, there is no specific drawback to using mysql_* and mysqli_* functions side-by-side, and it is recommended to use mysqli_* over mysql_* in all cases
( see http://www.php.net/manual/en/mysqlinfo.api.choosing.php, the section under 'recommended API').
However your code will not be as secure as it could be until you complete the transition.
I would say that whether or not to open connections when they are not strictly required is a judgement call for you to make - I'd lean towards only opening it when you need it on general principles of efficiency, however in practice when dealing with legacy code it may prove far more trouble than it's worth. If it doesn't slow your server down too much you could live with it, so long as you recognise it's not the most efficient way to go.
PHP offers three different APIs to connect to MySQL: mysql(outdated), mysqli, and PDO extensions.
You don't need to connect to the database on every request.
mysqli_connect() with p: host prefix
//or
PDO::__construct() with PDO::ATTR_PERSISTENT as a driver option
http://www.php.net/mysql_pconnect
In your case, I would use PDO type connection implemented as the singleton pattern with "permanent" connection options.
Included on top of the every script.
class Database {
private static $instance;
private $dsn = 'mysql:dbname=testdb;host=127.0.0.1';
private $user = 'dbuser';
private $password = 'dbpass';
public static function getInstance() {
if(!self::$instance) {
self::$instance =
new PDO($this->dsn,
$this->user,
$this->password,
array(PDO::ATTR_PERSISTENT)
);
}
return self::$instance;
}
}
That way you can get database instance with:
Database::getInstance();
...and don't flame me for using singletons in the legacy app! ;)
Related
I am searching for a efficient way to use PHP MySQL innoDB connection but not able to found conclusive information on the web.
As I know, persistent connection is much faster than non-persistent one,
we can set up the connection in following way:
$instance_mysqli = new mysqli('p:127.0.0.1', 'username', 'password', 'db');
However, from the official website, it said the default behavior is "reset" on reuse, which is slower. http://php.net/manual/en/mysqli.persistconns.php
The mysqli extension does this cleanup by automatically calling the
C-API function mysql_change_user(). The automatic cleanup feature has
advantages and disadvantages though. The advantage is that the
programmer no longer needs to worry about adding cleanup code, as it
is called automatically. However, the disadvantage is that the code
could potentially be a little slower, as the code to perform the
cleanup needs to run each time a connection is returned from the
connection pool.
So, there is no way to pass parameter to the above constructor to avoid "reset"? The only way is to recompile extension from source code as the document suggested?
And my anther question is... if mysqli is so smart that it can automatically reset connection by default, what is the point many people still use non-persistent connection, which is even slower.
The cost of a connection is quite small, whether it is persistent or not, whether there is cleanup or not.
Normally, one should acquire one connection at the beginning of the program, and keep it until the end. (There are some exceptions.)
The only time a connection is really noticeable is if you acquire a connection before each and every SQL query.
Bottom line: Worry about your indexes, system design, etc, not about acquiring the connection.
I currently create a DB connection via PDO for my website like so:
try {
self::$dbh = new PDO("mysql:host={$host};dbname={$dbName}", $dbUser, $dbPass);
self::$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
}
catch (PDOException $e) {
return $e->getMessage();
}
I've been reading about persistent connections so I wanted to add the persistent flag like so:
self::$dbh = new PDO("mysql:host={$host};dbname={$dbName}", $dbUser, $dbPass,
array(PDO::ATTR_PERSISTENT => true
));
From what I've been reading this could be dangerous if something happens mid query etc. It sounds like this isn't really a recommended method.
Are there any other alternatives to maintain a persistent DB connection with MySQL?
The reason to use persistent connections is that you have a high number of PHP requests per second, and you absolutely need every last fraction of a percent of performance.
Even though creating a new MySQL connection is really pretty inexpensive (compared to connecting to Oracle or something), you may be trying to cut down this overhead. Keep in mind, though, that most sites get along just fine without doing this. It depends on how heavy your traffic is. Also, MySQL 5.6 and 5.7 have made it even more efficient to create a new connection, so the overhead is lower already if you upgrade.
The risk described in the post you linked to was that session-specific states didn't get cleaned up as a given DB connection was inherited by a subsequent PHP request.
Examples of session state include:
Unfinished transactions
Temporary tables
User variables
Connection character set
This can even be a security problem, for instance if one PHP user populates a temp table with privileged information, and then another PHP user finds they can read it.
Fortunately, in the 4 years since #Charles gave his answer, the mysqlnd driver has addressed this. It now uses mysql_change_user(), which is like a "soft disconnect" that resets all those session state details, but without releasing the socket. So you can get the benefit of persistent connections without risking leaking session state from one PHP request to another. See http://www.php.net/manual/en/mysqlnd.persist.php
This needs the mysqlnd driver to be enabled, which it should be if you use any reasonably up to date version of PHP.
Why do you need a persistent connection? PHP is stateless and reinitializes every time you make a request, so there is mostly no advantages and quite more disadvantages (i.e. sudden disconnectons with no handlers) in working with a persistent connections.
BACKGROUND:
I am passing variables through AJAX to php file. The php file connects to a server and retrieves the result which it passes back to javascript. This happens every time a user clicks on the request button (about every 5 secs). Thus for each user, the php file (and so the mysql connection) is called once every 5 secs.
ISSUE:
As is apparent above, the number of mysql connections are impractically high.
QUESTION:
Is there a better architecture where instead of having so many mysql connections, I can rather have fewer connections.
I have read a little bit about mysql_pconnect. But what happens if I have to upgrade since I read somewhere that mysqli doesnt support it? How many queries can a single mysql_pconnect handle? If anyone suggests mysql_pconnect then how to implement it?
Is there a better architecture where instead of having so many
mysql connections, I can rather have fewer connections.
Don't really know, but I think that for you the proposed pconnect is the best available option. Unless you have either mysqli or PDO_mysql available now?
I have read a little bit about mysql_pconnect.
But what happens if I have to upgrade since I read somewhere that mysqli doesnt support it?
You would probably need to change method when upgrading beyond PHP 5.5.
How many queries can a single mysql_pconnect handle?
Unlimited, as long as the connection is kept alive. If there are no available free connections a new one is created.
If anyone suggests mysql_pconnect then how to implement it?
Change your current mysql_connect calls to mysql_pconnect. That should be all.
What you are looking for is singleton design pattern for database connections. But it has it's trade off too. Example code for singleton design for database would be as below.
define('DB_NAME', "test");
define('DB_USER', "root");
define('DB_PASS', "rootpass");
define('DB_HOST', "localhost");
class Connection{
private static $connection_;
private function __construct(){
$con = mysql_connect(DB_HOST, DB_USER, DB_PASS);
mysql_select_db(DB_NAME, $con);
Connection::$connection_ = $con;
}
public static function getConnection(){
if( !Connection::$connection_ )
new Connection;
return Connection::$connection_;
}
}
$con = Connection::getConnection();
Read more
php singleton database connection, is this code bad practice?
How static vs singleton classes work (databases)
You can find tons of example and information if you google. Hope this helps
So as I'm sure anyone who's been a regular on SO has noticed, the mysql_ functions are going to be deprecated and it is suggested that one use mysqli_ or PDO instead. Thus, I decided to transition over to mysqli by doing a simple find/replace in my code, replacing every mysql_ with mysqli_. This seemed to work okay in Dreamweaver, and I got no syntax errors or anything. All the new mysqli_ functions were colored blue, meaning that they were recognized as valid functions.
However, when I saved everything and ran the code, I noticed that any code having to do with mysql had become nonfunctional. Undoing the replace solved the problem.
Is my server perhaps not supporting the mysqli functions? I know that it's running php 5 and mysql 5. Is there perhaps something else that you have to add to the code? What am I missing?
It's a good time to switch now, since PHP 7.0 removed the ext/mysql functions from core.
Consider the following legacy code
$res = mysql_query($sql);
The mysql_ functions were lazy, in that it would use whatever connection was open. But mysqli_ is not only not lazy, it's an object, not a connection resource (which is what mysql_connect() would return). Look at these lines here for connecting to the database
$mysqli = new mysqli('host', 'username', 'password', 'db');
$mysqli = mysqli_connect('host', 'username', 'password', 'db');
Both of them give you the same thing...
Returns an object which represents the connection to a MySQL Server.
Yes, that's right. Even the procedural connection function returns an object. The simplest way to use it is directly in is object form
$mysqli->query($sql);
The procedural functions are simply wrappers for this. But they are NOT lazy. Check out the difference
mysqli_query($mysqli, $sql);
The single largest gotcha in this (why a simple find and replace of mysql_ with mysqli_ fails) is that most of the mysqli_ functions require you to pass the connection object as the first argument. It's also important to note that results are objects as well (mysqli_result class), although their procedural counterparts only require the result set so you can simply find/replace those.
Just to be complete, there's one other gotcha that's less common (this is really old code): mysql_result. This function has no equivalent in mysqli_. You should switch to the full row return functions like mysqli_fetch_assoc($result)
you might wanna check out http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers , which should tell you just about all you need to know about migrating mysql_ code, but to PDO, not MySQLi..
you Have to know There are many issues might had be done when you were replacing your code.
Check the installation of mysqli here.
check the configuration of mysqli here.
check the DB connection in tow ways :
** simple connection like natimysql:
$con = mysqli_connect("localhost","my_user","my_password","my_db");
But Now You have to use it like that
mysqli_query($con,"SELECT * FROM Table"); // $con is the connection which is must for executing the sql query
**my best way is dealing with it as new mysqli object like that :
$con = new mysqli('localhost', 'user', 'pass', 'demo');
now you will do it like that :
$sql = "SELECT * FROM Table";
$con->query($sql);
if you checked every query that you had done before You must find one of these errors specially the errors in the 3rd point
you can take a tour in its tutorial here , here or here
Surprised nobody has mentioned that the mysql_ and mysqli_ functions are not exact parallels, therefore a search and replace is bound to fail. Also mysqli_ will generally insist on the database connection parameter (when used in procedural mode, which is what you're aiming fo), where mysql_ would just grab whatever connection had been opened earlier in the code.
If you have debugging enabled, you should be able to work through the errors.
The most common 'gotcha' is that there is no mysqli equivalent of mysql_result(), which people often used when getting a single result. I'd be willing to bet your code is scattered with "mysqli_result()" calls, which will all fail.
That's the basic fix. The 'good' fix might be to use a dedicated class for all your SQL calls, so that there are only a handful of uses of the mysqli functions in your entire codebase, and all in a single file. That way when you refactor you don't need to search through mountains of files all with a variety of different uses of various mysqli functions.
If you "Need some authoritative sources for MySQL -> MySQLi migration" I can recommend a website called Google ;-) Type in "MySQL -> MySQLi migration".
For instance, this 'for Dummies' page shows you the differences between the various functions that you'll need to address to get your code working.
http://www.dummies.com/how-to/content/how-to-convert-mysqli-functions-to-mysql-functions.html
mysql_ functions are now deprecated
Nope, they aren't yet
I decided to transition over to mysqli by doing a simple find/replace in my code
the problem most likely lies in the fact that mysqli functions has reverse parameters order and require connection resource explicitly.
Nevertheless, even if you succeed with such a bulk replace, it will do not a slightest good to your code, so, you'd better keep it as is, despite of some errr... overenthusiastic campaign on this site.
There is no reason to hurry. You have at least 5 years until you'd start notice some inconvenience.
The goal of all this noise about mysql functions is not for changing some API to another but for making usual PHP codes slightly more sensible and safe. You won't reach neither of these goals with just search and replace - so, there is no reason to do it at all.
What you really need is a some intelligent way of handling queries, encapsulated in some library class, which will not only improve your experience with running SQL queries but also will move all the API functions into one place where they can be easily replaced to whatever API some folks will decide to force you to use.
I'm wondering if there are any negative performance issues associated with using a Singleton class to connect to MySQL database. In particular I'm worried in the amount of time it will take to obtain a connection when the website is busy. Can the singleton get "bogged down"?
public static function obtain($server=null, $user=null, $pass=null, $database=null){
if (!self::$instance){
self::$instance = new Database($server, $user, $pass, $database);
}
return self::$instance;
}
Even if you write that, each PHP request will still be a different connection. Which is what you want.
You can use a singleton to handle your database connection because even in only one request, your app may send several database queries and you will loose performance if you re-open database connections each time.
But keep in mind that you always have to write clever queries and request your database only for the data you need and as few times as possible. That will make it smooth !
It doesn't really matter from a MySQL performance standpoint whether or not you use singletons in this case as each request to that page will create its own object (singleton or not) and connection.