準備されたステートメントから宣言されたパフォーマンスを取得する試みに関するレポート

更新:記事のタイトルから「失敗」という単語が削除されました。 以下の詳細!



SQLインジェクションに対する保護に関連する典型的な誤解についての私の記事で 、とりわけ、サーバーで作成された式は宣言された有効なスクリプトに従ってPHPで機能しないという事実に注意してください-prepare()once、execute()1000 times。



理論的には、1つのスクリプトを実行するだけで機能します。 しかし、多くの同一のリクエストを実行する多くのスクリプト(プロのプログラマーによって作成された)を知っていますか? 私も知りません 繰り返される要求(いくつかの複数の更新)-わずかな割合で、ほとんどの場合、要求は一意です(同じスクリプト内)。

したがって、固有のリクエストでは、prepare()が最初に実行され、次にexecute()、そしてスクリプトが安全に終了します。そのため、次のHTTPリクエストの処理を開始したら、prepare()を再度実行します。 むしろ、反対。

コメントに正しく記載されているように、データベース接続を長時間保持するコンソールスクリプトおよびデーモンの形式で例外について言及する必要がありました。 ただし、PHPスクリプトの大部分はまだフロントエンドで実行され、数十件のリクエストを行った後に死にます。



しかし、開始間で準備されたリクエストを何らかの方法でキャッシュする方法は本当にありませんか?



そして、アイデアが思いつきました!



しかし、まだいくつかの矛盾がありましたが、HPCカンファレンスを非常にうまく立ち上げました。 そして、私の期待は私を欺きませんでした。したがって、この機会を利用して、活発な参加と貴重な相談をしてくれたセルゲイ・アヴェリンとコスティア・オシポフに深く感謝したいと思います。



実質的な部分に移りましょう。



したがって、タスク:

新しいPHPスクリプトで準備されたリクエストにアクセスしたいと思います。



ここには2つの主な問題があります。

  1. 準備されたステートメントは1つの接続内でのみ有効であり、そのように配置されています。 問題は、一見して解決されます。
  2. 準備された式ハンドルはオブジェクトとして実装されます。 オプションはありません-オブジェクトを別のスクリプトに転送することは不可能です


今後は、すべてが逆になったと言います。2番目の問題は簡単に解決され、最初の問題は克服できない障害であることが判明しました。

しかし、まず最初に。



最初の問題は、永続的な接続を使用して、どのように明らかに解決されます。

結局、前のスクリプトと同じ接続を参照しています。 つまり、理論的には、以前の呼び出しで作成された環境全体にアクセスする必要があります。



2番目の問題も解決され、非常に簡単になりました。

実際、Mysqlには準備された表現の2つのバリエーションがあります-比較的言えば、「バイナリ」と「ストリング」です!

前者が私たちに合わない場合、後者がまさに私たちに必要なものです!



「バイナリ」の準備された式はAPIを介して機能し、準備されたクエリハンドラはクラスの形式でのみ使用でき、データは、データベースがクエリ結果を返すものに似たバイナリパッケージでサーバーに送られます。 ドライバーを大幅に変更しないと、ドライバーにアクセスできません。



ただし、「文字列」または「SQLプリペアドステートメント」は通常のSQLクエリであり、 ドキュメントに例として記載されています。

PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
SET @a = 3;
SET @b = 4;
EXECUTE stmt1 USING @a, @b;

      
      





SQL !

prepare , execute — ? — :



mysql_pconnect($host,$user,$pass); // -  pconnect!

mysql_query("PREPARE stmt2 FROM 'SELECT ?+? AS sum'") or trigger_error(mysql_error());
mysql_query("SET @a = 6") or trigger_error(mysql_error());
mysql_query("SET @b = 8") or trigger_error(mysql_error());
$res = mysql_query("EXECUTE stmt2 USING @a, @b") or trigger_error(mysql_error());
$row = mysql_fetch_array($res);
var_dump($row);

      
      





PREPARE, … . !



, « prepare() — execute()» .

, , . , , , .

, , mysqli.

. , , «» — : , . mysqli C API mysql_change_user(). , , , , .



,

, .



.

- , , , . . , — , . — , , .



, :

prepared statements , . « » ( native prepard statements), SET .



: BVadim , mysqli MYSQLI_NO_CHANGE_USER_ON_PCONNECT. , , prepared !

, , .



All Articles