This question already has answers here:
mysqli or PDO - what are the pros and cons? [closed]
(13 answers)
Closed 9 years ago.
I just finished an introduction course in PHP, and throughout the stackoverflow forum people have recommended that I switch to PDO, prepared statements or MYSQLi, I briefly checked the manual but most of it went over my head.
I've been using mysql_* functions up till now so these concepts are new to me. I think they are used to access and perform database specific actions, but I'm not sure.
So what is the difference between PDO, prepared statements and MySQLi, are they different features that accomplishes the same task? Are they compatible in a script or is it "choose one or the other"? And lastly which offers the best performance?
Update: Thanks for the answers, I'll be hunting for more PDO tutorials.
For reference I also found the following posts useful:
Which one is fast and light - mysqli or PDO
mysqli or PDO - what are the pros and cons?
At the basic level the mysql, mysqli and PDO extensions all answer the question how do I talk to the database? They all provide functions and functionality to connect to a database and send and retrieve data from it. You can use them all at the same time establishing several connections to the database at once, but that's typically nonsense.
mysql* is a very simple extension that basically allows you to connect to the database, send it SQL queries and not much else.
mysqli improves this (as the name suggests) by adding parameterized queries and a few other things into the mix.
PDO is an extension that abstracts several database drivers into one package, i.e. it allows you to use the same code to connect to MySQL, Oracle, MS SQL Server and a number of other databases without needing to use database specific extensions or rewrite your code when you switch databases (in theory at least). It also supports parameterized queries.
If you know you're going to be using MySQL exclusively, mysqli is a good choice. Especially since you can use it in a procedural way, what you're already used to from the mysql extension. If you're not familiar with OOP, that's helpful. Otherwise, PDO is a nice object oriented, flexible database connector.
* Note that the mysql extension is now deprecated and will be removed sometime in the future. That's because it is ancient, full of bad practices and lacks some modern features. Don't use it to write new code.
PDO is the "PHP Data Object." I mostly use PDO, so I can only speak on its merits:
Works for many more databases than just MySQL (may not matter to you)
Compiled C, so it's faster (supposedly)
Prepared statements (others have these, though)
SO seems to like it, so you can probably get a lot of help here at least
Various fetch/error handling modes you can set and change on the fly
You ask
So what is the difference between PDO, prepared statements and MySQLi ...
PDO and MySQLi are DB wrappers. "Prepared statements" is a different concept altogether. You can prepare a query that can be executed multiple times, and properly parameterized statements are SQL-Injection safe (though maybe not proof). The latter reason is most of the reason why you should be using PDO (or MySQLi), but prepared statements also bring a level of clarity to the queries.
/* mysql_* version */
mysql_connect("host");
$query = "SELECT column FROM db1.t1 WHERE id = ";
foreach ($_GET['id'] as $id) {
$id = mysql_real_escape_string($id);
$result = mysql_query($query . "'$id'";
while ($row = mysql_fetch_assoc($result)) {
echo "$row[column]\n";
}
}
//NOTE: it would probably be better to store the resource returned by
//mysql_connect and use that consistently (in query/escape)
/* PDO version */
$pdo = new PDO('mysql:host=HOST', 'user', 'pass');
$query = $pdo->prepare("SELECT column FROM db1.t1 WHERE id = ?";
foreach ($_GET['id'] as $id) {
$query->execute($id);
echo $query->fetch(PDO::FETCH_COLUMN);
}
//Notice that you skip the escape step.
You can do essentially the same with MySQLi, but I prefer PDO's syntax. It may be faster too, but I could be making that up. There's also the PEAR MDB2 that rarely gets spoken of, and I'm sure many more. Since PDO is built in, I would go with it.
If you're used to the mysql_xxx functions, then I would starting by moving across to the MySQLi extension instead.
You could use PDO instead if you wish, but this would only really be worth it in the first instance if you need to start supporting multiple databases. For your purposes, I'd suggest switching to MySQLi, as it'll be easier for you, and you won't be getting the benefits of PDO right away anyway.
The functions available with MySQLi are pretty much analogous to the mysql_xx functions you're used to; it's generally possible to take existing code, do a direct swap between them, and the code should continue working just fine.
So that's a good place to start -- get your code using mysqli_xxx instead of mysql_xxx`.
If possible, I'd recommend using the object oriented syntax rather than the procedural syntax. MySQLi supports both, and the procedural syntax will be closer to what you're used to, but the OO syntax is more flexible in the long run, and really isn't that much different once you're used to it.
Once you've got your code converted to using the MySQLi library, and you're comfortable with the basics, you're ready to start using the more advanced features like prepared statements. But get yourself comfortable with the basics first.
Coming from the same point of view as you. From my perspective I don't think the difference is truly noticeable (depending on what you're using it for). It looks like PDO is simply a database api that merges ALL of the other database api's into one. So if you needed to connect to a MS Sql server and MySQL server, you could simply call on the PDO api and specify the driver for the specific db. My guess is also that any future features and abilities in MySQL will be only available in PDO. So basically just use PDO to ensure that you have access to all the latest features.
One big advantage of PDO is platform independence. This means that you can migrate to a different DBMS at some point without having to recode all of your function calls. This is how things are typically done in Java (via JDBC), .Net (ADO) and most other environments. The advantage is not just that you can switch DBMS per se, it's also that you have only one API to learn.
As regards your question, the PDO layer provides the facility to do prepared statements. The idea behind prepared statements is that you create placeholders for the parts of your SQL statement that will not be known until run time. Many learners start off by creating SQL as a string which gets executed by calling mysqli::query($someQuery). This is problematic for many reasons, most prominent of which is the vulnerability to SQL injection (see stackoverflow.com/questions/5315351 for a similar question and answer). With PDO, you can avoid SQL injection and all of the problems of handling characters such as quotes, backslashes etc. The end result is that your code is more secure, readable and predictable.
If you've already figured out how to use mysqli then using PDO is not much different. The linked question and answer above shows an example of a query being submitted using PDO prepared statements which should act as a useful guide.
So what is the difference between PDO, prepared statements and MySQLi, are they different features that accomplishes the same task?
The difference is fairly simple.
PDO is usable with prepared statements and mysqli is not.
Just run some usual queries with both API using native prepared statements, and you will clearly see the difference.
Related
I have this very question to clear things up. I read some documentation and comments around but still somethings are just not clear enough.
I understand PDO offers more drivers which would certainly is a plus if you would ever change your database type.
As said on another post, PDO doesnt offer true prepared statements but mysqli does so it would be safer to use MYSQLI
Benchmarks looks similar, (did not test it myself but checked around on the web for a few benchmarks)
Being object oriented is not an issue for me since mysqli is catching up. But would be nice to benchmark procedural mysqli vs PDO since procedural is supposed to be slightly faster.
But here is my question, with prepared statement, do we have to use parameter binding with the data we use in our statement? good practice or have to? I understand prepared statements are good perfermance-wise if you run the same query multiple times but it is enough to secure the query itself? or binding parameters is a must? What exactly do the binding parameters and how it works to protect the data from sql injection? Also would be appreciated if you point our any misunderstanding about the statements I made above.
In short,
Binding is a must, being a cornerstone of protection, no matter if it is supported by a native driver or not. It's the idea of substitution that matters.
The difference is negligible in either safety and performance.
Performance is the last thing to consider. There is NO API that is considerable slower than other. It is not a class or a function that may cause whatever performance problem but a data manipulation or a bad algorithm. Optimize your queries, not mere functions to call them.
If you are going to use a raw bare API, then PDO is the only choice. While wrapped in a higher level class, mysqli seems more preferable for mysql.
Both mysqli and PDO lack bindings for the identifiers and keywords. In this case a whitelist-based protection must be implemented. Here is my article with the ready made example, Adding a field name to the SQL query dynamically
I dont have any previous experience with PDO, so my question may sound too simple.
I heard few times that PDO is better than mysql/mysqli in terms of security ,and since Codeigniter is supporting PDO driver, I decided to make the change in my new project.
but as I'm aware of Codeingiter doesn't use prepared statements, and (I think) it missed the point of using PDO, is that correct, and is it insecure?
So my question: is using PDO driver with codeigniter considered insecure?
And, does that mean I must take care of the basic security by myself?
All query calls are escaped in the simplified $this->db functions, such as delete() and get_where(). This adds some automated security.
If written too slobby, you may grant access to users to edit other users content for instance. So there's no magical solution to full security. The more detailed you are, the more correct your code will work for you.
If you need custom queries, you can do like this:
$int_user_id = 1;
$this->db->query("
SELECT *
FROM users
WHERE id = ?
", array($int_user_id));
Note: To implement IN () and LIKE, you need to escape accordingly, and not insert through array() and ?.
query()
escape()
1. Database Support
The core advantage of PDO over MySQL is in its database driver support. PDO supports many different drivers like CUBRID, MS SQL Server, Firebird/Interbase, IBM, MySQL, and so on.
2. Security
Both libraries provide SQL injection security, as long as the developer uses them the way they were intended. It is recommended that prepared statements are used with bound queries.
3. Speed
While both PDO and MySQL are quite fast, MySQL performs insignificantly faster in benchmarks – ~2.5% for non-prepared statements, and ~6.5% for prepared ones.
From what I know (CodeIgniter newbie ;)) it takes care of security pretty well with ActiveRecords. I don't know if it's using PDO or not, but it's pretty darn easy to use, queries look really clean, and it has query caching.
I am thinking of rewriting some open-source application for my purposes to PDO and transactions using InnoDB (mysql_query and MyISAM now).
My question is: Which cases are reasonable for using prepared statements?
Because everywhere I am reading is stated (even in many posts here) that I should use prepared statements every time and everywhere because of the 1. security and 2. performance. Even PHP manual recommends using prepared statements and not mentioning the escape-thing.
You can't deny the security mechanism. But thinking it over and over it comes to mind that having to prepare the statement every time and then use it once.. It doesn't make sense. While having to insert 1000 times some variables in single statement, that makes sense but it is obvious. But this is not what common eshop or board is built upon.
So how to overcome this? May I prepare my statements application-wide and to name them specifically? Can I prepare several different statements and to use them by name? Because this is the only reasonable solution I am thinking of (except the 1000x thing).
I found there is this mysql_real_escape called $pdo->quote as well for the purpose of single query. Why not to use this? Why to bother with preparing?
And what do you think of this excellent article?
http://blog.ulf-wendel.de/2008/pdo_mysqlnd-prepared-statements-again/
Do you agree with the overhead caused by preparing the statements?
Thanks
I think this falls in the "premature optimization" category.
How significant is the overhead? Have you measured it? Does it affect your server performance at all?
Odds are it doesn't.
On the plus side, you have an undeniable gain in terms of security (which should be a major concern for any internet-based shop).
On the downside, you have the risk that it might affect performance. In the link you provided, it shows that poorly implemented PDO preparation results in slightly lower performance than non prepared statement in some circumstances. Performance difference on 5000 runs is 0.298 seconds.
Insignificant. Even more so when you realize that the "non prepared" queries are run without the input sanitizing routines that would be required to make them safe in a live environment. If you don't use the prepared queries, you need some form of input sanitizing to prevent SQL attacks, and depending on how it is done, you may need to massage back the result sets.
Bottom line, there is no significant performance issue, but there is a significant security benefit. Thus the official recommendation of using prepared statements.
In your question, you speak of "the common eshop". The "common eshop" will never have enough traffic to worry about the performance issue, if there is one. The security issue on the other end...
My question is: Which cases are reasonable for using prepared statements?
All of them. The community is openly-opposed to the usage of mysql_* functions.
Note: Suggested alternatives
Use of this extension is discouraged. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API for more information.
Alternatives to this function include:
mysqli_connect()
PDO::__construct()
source
But thinking it over and over it comes to mind that having to prepare the statement every time and then use it once.. It doesn't make sense
You're trading in a Geo for a Jaguar and you're complaining that you don't like the Jaguar because you don't always use the seat-heaters. You don't have to be consistently using every function of a library to mean it's good.
I found there is this mysql_real_escape called $pdo->quote as well for the purpose of single query. Why not to use this? Why to bother with preparing?
If you are using this function to build SQL statements, you are strongly recommended to use PDO::prepare() to prepare SQL statements with bound parameters instead of using PDO::quote() to interpolate user input into an SQL statement. Prepared statements with bound parameters are not only more portable, more convenient, immune to SQL injection, but are often much faster to execute than interpolated queries, as both the server and client side can cache a compiled form of the query. source
My question is: Which cases are reasonable for using prepared statements?
Well actually, that's hard to say. Especially as you didn't even tell which open source application you speak about here.
To give you an example: For a ultra-lame guestbook app PDO with prepared statements will be the perfect choice, as well for 99% of all other open source apps out there. But for some this actually can make a difference. The important part here is: You have not told anything about the application.
As the database is not unimportant to an application, it's the other way round as well: the application is not unimportant to the database.
So you either need to share more about that "mysterious" open-source application you ask about or you need to tell us, what exactly you would like to know. Because generally, it's simple: Take PDO. But in specific, there are differences, so you need to tell us what the application in specific is, otherwise your question is already answered.
And btw., if the application is mysql_* style, it's much easier to just replace with mysqli_* interface. If you had done some actually rewriting, even just for fun, you would have seen that.
So better add more meat here or live with some not-so-precise answers.
While this question is rather old, some topics were not really discussed that should be outlined here for others researching the same as the OP.
To summarize everything below:
Yes always use prepare statements
Yes use PDO over mysqli over mysql. This way if you switch database systems all you need to do is update the queries instead of queries, function calls, and arguments given it supports prepared statements.
Always sanitize user supplied data despite using prepared statements with parameters
Look into a DBAL (Database Abstraction Layer) to ease working with all of these factors and manipulating queries to suit your needs.
There is the topic of PDO::ATTR_EMULATE_PREPARES which will increase the performance of calling cached queries in MySQL >= 5.1.21 when emulation is turned OFF, which is ENABLED by default. Meaning PHP will emulate the prepare before execute sends it to the actual database. The time between emulated and non-emulated is normally negligible unless working with an external database (not localhost), such as on a cloud, that may have an abnormally high ping rate.
The caching depends on your MySQL settings in my.cnf as well, but MySQL optimization outside the scope of this post.
<?php
$pdo = new \PDO($connection_string);
$pdo->setAttribute( \PDO::ATTR_EMULATE_PREPARES, false );
?>
So keep this in mind since mysqli_ does not provide an API for client side emulation and is always going to use MySQL for preparing statements.
http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
Despite having similar features there are differences and you may need features that one API provides while the other does not. See PHP's reference on choosing one API over the other: http://www.php.net/manual/en/mysqlinfo.api.choosing.php
So this pretty much goes along with what you asked with defining your statements application-wide, as cacheable queries would be cached on the MySQL server, and wouldn't need to be prepared application-wide.
The other benefit is that exceptions in your Query would be thrown at prepare() instead of execute() which aids in development to ensure your Queries are correct.
Regardless there is no real world performance benefits of using prepare or not.
Another benefit of prepared statements is working with Transactions if you use InnoDB for MySQL. You can start a transaction, insert a record, get the last insert id, update another table, delete from another, and if anything fails along the way you can rollBack() to before the transaction took place. Otherwise commit the changes if you choose to. For example working with a new order and setting the user's last order column to the new order id, and delete a pending order, but the supplied payment type did not meet the criteria for placing orders from the order_flags table, so you can rollBack() and show the user a friendly error message.
As for security, I am rather baffled no one touched on this. When sending any user supplied data to ANY system including PHP and MySQL, sanitize and standardize it.
Yes prepared statements do provide some security when it comes to escaping the data but it is NOT 100% bullet proof.
So always using prepared statements is far more beneficial than not with no real performance loss, and some benefits with caching, but you should still sanitize your user supplied data.
One step is to typecast the variables to the desired data type you are working with. Using objects would further ease this since you work within a single Model for the data types as opposed to having to remember it each time you work with the same data.
To add on to the above you should look into a database abstraction layer that uses PDO.
For example Doctrine DBAL: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html
The added benefits of working with a DBAL+PDO are that
You can standardize and shorten the amount of work you have to do.
Aid in sanitization of user supplied data
Easily manipulate complex queries
Use nested transactions
Easily switch between databases
Your code becomes more portable and usable in other projects
For example I extended PDO and overrode the query(), fetchAll(), and fetch() methods so that they would always use prepared statements and so that I could write SQL statements inside fetch() or fetchAll() instead of having to write everything out again.
EG:
<?php
$pdo = new PDOEnhanced( $connection );
$pdo->fetchAll( "SELECT * FROM foo WHERE bar = 'hi'", PDO::FETCH_OBJ );
//would automatically provide
$stmt = $pdo->prepare( "SELECT * FROM foo WHERE bar=?" );
$stmt->execute( array( 'hi' ) );
$resultSet = $stmt->fetchAll( PDO::FETCH_OBJ )
?>
As for people suggesting that mysql_* style, is much easier to just replace with mysqli_* API. It is not the case. A large portion of mysql_* functions were left out or had arguments changes with mysqli_*
See: http://php.net/manual/en/mysqli.summary.php
You can however get a converter released by Oracle to ease the process: https://wikis.oracle.com/display/mysql/Converting+to+MySQLi
Keep in mind that it is a file source text parser and is not 100% accurate so validate the changes before merging them. It will also add a significant amount of overhead for the globals it creates.
There seem to be a lot of choices for MySQL connection from PHP. I guess they all offer different feature sets. I just want to run a simple query, and so I'm attracted to the simplicity of mysql_connect(). Is this OK or are there any considerations I'm missing
Thhanks
If you just want to run a simple query, there really is no difference. If you're working on something bigger, use mysqli or PDO instead so you can use it's features. Especially prepared statements is something you really want to use.
I would just forget about the old mysql-library. Mysqli is not harder to use, but it's a big improvement.
Use mysqli instead. It has the same simplicity and it is the improved version of mysql_connect
See documentation here.
Even if you are dealing with a single query or a very simple project, use PDO.
It's how DB stuff it's done nowadays and will likely be done in the future. I think that learning the legacy libraries (mysql, mysqli) is not a good deal right now. The learning curve is quite the same, and with PDO you have a basis for doing anything you want (e.g. changing DBMS).
And, even if you choose to use the legacy, DBMS-bound libraries, please don't use mysql, and do use prepared statements (both mysqli and PDO have them). Don't do stuff like:
mysql_query("SELECT * FROM users WHERE username = '$username' AND password = '$password'");
I have designed a website before 5 years using PHP MySQL and still works fine without any issues. I heard MySQL is officially deprecated as of PHP 5.5 and has been removed as of PHP 7. Also, PHP offers three different APIs to connect to MySQL (like MySQL, MySQLi, and PDO). My web server is updated frequently.
I understood, I have to move to newer API like MySQLi or PDO for safety. Now I am confused whether to choose MySQLi or PDO. Also, Is there any compatibility/migrating options available for such case?
Lets take a look at both of these extensions.
PDO
PDO is database neutral - You only need to learn one API to work with dozens of databases
So if you decide to move to another database, the only thing you would be changing is the DSN(data source name).
Support of both name and '?' placeholders for prepared statements.
Drupal uses PDO.
Mysqli
On the other hand Mysqli is designed specifically for Mysql databases and is recommended by Mysql. Mysqli works with Mysql and MariaDB databases.
Support of only '?' placeholders for prepared statements.
Joomla uses Mysqli
Conclusion
There are many conflicting arguments weather Mysqli or PDO runs faster. Both Mysqli and PDO use the same underlying drivers to access the database making the performance not worth comparing.
So there is no clear winner when working with Mysqli or PDO. But let's say you use Mysqli and then later you want to use another database, it would be a difficult transition.
The main strength of PDO over Mysqli is name placeholders for prepared statements and which is why I chose PDO over Mysqli.
The answer is fairly simple.
If, like majority of PHP users, you are going to use database API functions right in the application code, without any intermediate wrapper, then PDO is your only choice, as it's a sort of wrapper already, automating many operations that with mysqli have to be done manually.
No, there are no migration options, because the very approach is changed dramatically: instead of placing variables right in the query, they have to be substituted in the query with special marks. There is no way to automate this process.
PDO and MySQli both are used for database connection and both have their own advantage. In closer look PDO wins the battle but if you really stick with only one database provider then my personal best choice is use MySQLi.
You will also extract some good points from: http://code.tutsplus.com/tutorials/pdo-vs-mysqli-which-should-you-use--net-24059