MySQL PHP PDO prepared statements - performance and security issues

I'm thinking of rewriting an open source application for my purposes in PDO and transactions using InnoDB (mysql_query and MyISAM now).

My question is: what cases are reasonable for using prepared statements?

Because wherever I read (even in many posts here), I have to use prepared statements every time and everywhere because of 1. security and 2. performance. Even the PHP manual recommends using prepared statements and not mentioning an exception.

You cannot deny the security mechanism. But, reflecting on this, it comes to mind that you need to prepare an expression each time, and then use it once. It does not make sense. Despite the fact that inserting some variables into one operator 1000 times, this makes sense, but it is obvious. But this is not what the usual eshop or board is based on.

So how to overcome this? Can I prepare my application statements and name them specifically? Can I prepare several different statements and use them by name? Because this is the only reasonable solution that I think of (except 1000x).

I found that this mysql_real_escape is called $ pdo-> quote, and also for a single query. Why not use this? Why worry about preparation?

And what do you think of this wonderful article? http://blog.ulf-wendel.de/2008/pdo_mysqlnd-prepared-statements-again/

Do you agree with the overhead caused by the preparation of applications?

thanks

+6
source share
4 answers

I think this falls into the category of "premature optimization."

How significant is overhead? Did you rate it? Does it affect the performance of your server in general?

Most likely, this is not so.


On the plus side, you have an undeniable win in terms of security (which should be a serious problem for any online store).

On the other hand, you risk that it can affect performance. In the link provided, this shows that poorly implemented PDO preparation leads to slightly lower performance than an unprepared application in some cases. The difference in performance for 5000 runs is 0.298 seconds.

Minor. Especially when you understand that "unprepared" requests are executed without input routines that are necessary to ensure security in a live environment. If you are not using prepared queries, you need some form of input deactivation to prevent SQL attacks, and depending on how you do this, you may need to massage the result sets.

There is no significant performance issue on the bottom line, but there is a significant security advantage. Therefore, a formal recommendation is to use prepared statements.

In your question you are talking about "general eshop". In "general eshop" there will never be enough traffic to worry about a performance issue, if any. Security issue on the other end ...

+9
source

My question is: what cases are reasonable for using prepared statements?

All of them. The community openly opposes the use of mysql_* functions.

Note: Suggested alternatives

Using this extension is not recommended. Instead, use the MySQLi extension or PDO_MySQL. See Also MySQL: choosing an API for more information.

Alternatives to this feature include:

a source

But, reflecting on this, it comes to mind that you need to prepare an expression each time, and then use it once .. It does not make sense

You trade Geo for Jaguar and you complain that you don't like Jaguar because you don't always use seat heaters. You do not have to consistently use each function of the library to make it good.

I found that this mysql_real_escape is called $ pdo-> quote, and also for a single query. Why not use this? Why worry about preparation?

If you use this function to create SQL statements, it is highly recommended that you use PDO :: prepare () to prepare SQL statements with bound parameters instead of using PDO :: quote () to interpolate user input into the SQL statement. Prepared statements with related parameters are not only more they are portable, more convenient, immune to SQL injection, but often run much faster than interpolated queries, as the server and client side can cache the compiled request form. a source

+7
source

My question is: what cases are reasonable for using prepared statements?

Well, actually, it's hard to say. Especially since you did not even indicate which open source application you are talking about here.

To give you an example: for an application with an ultra-lame guest book, PDO with ready-made applications would be an ideal choice, as well as for 99% of all other open source applications. But for some it can really make a difference. The important part is here: you did not say anything about the application.

Since the database does not matter to the application, it is also the other way round: the application is not inconsequential for the database.

So, you either need to share more about this โ€œmysteriousโ€ open source application that you are asking about, or you need to tell us exactly what you would like to know. Because in general it is simple: take a PDO. But, in particular, there are differences, so you need to tell us which application is specific, otherwise your question will already be given.

And btw., If the application is a mysql_ * style, it is much easier to just replace the mysqli_ * interface. If you really were transcribing, even just for fun, you would have noticed.

So better add more meat here or live with some inaccurate answers.

+2
source

Although this question is quite old, some topics have not actually been discussed, which should be presented here for others exploring the same thing as the OP.

To summarize everything below:

  • Yes always use preparation instructions
  • Yes uses PDO over mysqli over mysql. Thus, if you switch database systems, all you have to do is update the queries instead of queries, function calls and arguments, given that they support prepared statements.
  • Always sanitize user-provided data despite using prepared statements with parameters
  • Take a look at DBAL (Database Abstraction Layer) to make it easier to handle all of these factors and manipulate queries according to your needs.

There is a topic PDO :: ATTR_EMULATE_PREPARES that will increase the performance of calling cached queries in MySQL> = 5.1.21 when emulation is disabled, which is enabled by default. Value PHP will emulate the preparation before execution, sends it to the actual database. The time between emulated and non-emulated is usually insignificant if it does not work with an external database (and not with localhost), for example, in the cloud, which can have an abnormally high level of ping.

Caching depends on your MySQL settings in my.cnf, but MySQL optimization is beyond the scope of this publication.

 <?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 to emulate the client side and will always use MySQL to prepare statements. http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php

Despite the existence of similar functions, there are differences, and you may need functions that one API provides and the other does not. See the PHP link for choosing one API over another: http://www.php.net/manual/en/mysqlinfo.api.choosing.php

Thus, this is largely consistent with what you requested when defining your statements in applications, since cached requests will be cached on the MySQL server and do not need to be prepared for the entire application. Another advantage is that exceptions in your Query will be thrown in prepare () instead of execute (), which help in development to ensure that your queries are correct.

Regardless of whether there are real performance benefits when using training or not.

Another advantage of prepared statements works with transactions if you use InnoDB for MySQL. You can start a transaction, insert a record, get the last insert identifier, update another table, delete from another, and if something fails along the path that you can rollBack () before the transaction. Otherwise, copy the changes if you decide. For example, working with the new order and setting the last user serial number for the new order identifier and deleting the pending order, but the provided 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'm pretty puzzled, no one has touched on this. When sending any user-provided data to ANY system, including PHP and MySQL, sanitize and standardize it. Yes, prepared statements do provide some security when it comes to data shielding, but it is NOT 100% bullet proof.

Therefore, always using prepared instructions is much more profitable than without real loss of performance, as well as some advantages with caching, but you still need to sanitize your data provided by the user. One of the steps is to cast the variables to the type of the required data type that you are working with. Using objects will make this even easier, since you are working within the same model for data types, and do not remember it every time you work with the same data.

To add to the above, you should study the level of database abstraction that PDO uses. For example, Doctrine DBAL: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html

Additional benefits of working with DBAL + PDO are that

  • You can standardize and reduce the amount of work you have to do.
  • Help disinfect user-submitted data
  • Easily manage complex queries
  • Using Nested Transactions
  • Easily switch between databases
  • Your code becomes more portable and can be used in other projects.

For example, I extended PDO and redefined the query (), fetchAll (), and fetch () methods so that they always use prepared statements and so that I can write SQL statements inside fetch () or fetchAll () instead of writing everything 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 ) ?> 

For people offering the mysql_ * style, itโ€™s much easier to just replace the mysqli_ * API. This is not true. Most of the mysql_ * functions were left or arguments changed in mysqli_ * See: http://php.net/manual/en/mysqli.summary.php

However, you can get the converter released by Oracle to facilitate the process: https://wikis.oracle.com/display/mysql/Converting+to+MySQLi

Keep in mind that this is a text parser of the source text and is not 100% accurate, so check the changes before combining them. It will also add a significant portion of the overhead for the generated global variables.

0
source

Source: https://habr.com/ru/post/917248/


All Articles