スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | スポンサー広告

MySQL+ODBCでプリペアド・ステートメントがエミュレーションだったという話

MySQL+ODBCでプリペアド・ステートメントがエミュレーションだったという話

MySQLではver4.1からプリペアド・ステートメント(prepared statement)が実装されています。
これは、実行するSQL文をあらかじめ「準備」しておくことによって、性能面およびセキュリティ面を向上させる機能です。

MySQL5.1のプリペアド・ステートメント

しかし、接続方法(特にODBC)によってはプリペアド・ステートメントを使っているつもりでも、その効果を十分に受けていない場合があります。


まずはプリペアド・ステートメントについて簡単に解説しておきます。
通常であれば、SQLは以下のような文字列を「実行」させます。
以下、それっぽい擬似コードで説明します。


sql_exec("SELECT * FROM TABLE1 WHERE DATA1=3")


TABLE1という名前のテーブルから、DATA1という欄の値が3の行をひっぱってこい、という意味です。

プリペアド・ステートメントを使うと、以下のような感じです。


s = sql_prepare("SELECT * FROM TABLE1 WHERE DATA1=?") // 準備
sql_setparam(s, 1, 3); // 最初のパラメータに数値3を入れる
sql_exec(s) // 実行


1行目の'?'マークに注意してください。?マークの場所に何か入るよ、
という状態でprepare(準備)しておき、後でその場所にパラメータをセットします。

性能面では、ステートメントsを保存しておけば、SQL文を解釈するための負荷が1回で済みますので、
何度も同じ(パラメータだけが違うような)SQL文を実行する場合、負荷が減ります。さらに、MySQLネイティブAPIを使用すれば、通信にバイナリプロトコルを使用することができ、より高速になります。
(なお、逆にクエリーキャッシュが効かなくなるという問題点もあるようです→リンク

セキュリティ面では、最近流行りのSQLインジェクション攻撃に対する有効な防御手段になります。
なぜかというと、prepareを使わない場合、上記3の位置に変数値を入れたい場合、
以下のような感じになるかと思います。


sql_exec("SELECT * FROM TABLE1 WHERE DATA1=" + data)


dataが文字列だったとすると、攻撃者はなんとかして変数dataに余計な文字列を入れようとするかもしれません。dataがたとえば "3;DROP DATABASE;" のような文字列だったとすると、このSQL文を実行するとデータベース全体が突然消滅してしまいます。dataの中身をチェックするルーチンを入れれば良いのですが、全部の変数にチェックを入れるのは案外面倒な話です。

プリペアド・ステートメントであれば、? マークの場所にはSQLとして1つの値と解釈されるものしか入りませんので、このような攻撃は不可能です。


しかし!ここで1つ罠があったりします。MySQL DBへの接続手段によっては、特にODBC接続では、上記のような(サーバー側の)プリペアド・ステートメントの恩恵を十分に受けることができません。

接続手段としてODBCを使っている場合、プリペアを行うためにSQLPrepare()というAPIが存在しますが、ドライバ自体がプリペアド・ステートメントのエミュレーション機能を持っており、そこで「普通のSQL文」に変換されてしまいます。これでは、セキュリティ面のほうの恩恵は受けられますが、性能面では普通のSQL実行と変わらなくなってしまいます。ドライバが対応していればサーバーサイドのプリペアド・ステートメントが使えるはずですが、MySQLでの対応状況は以下のような感じです。

MySQLの場合、ODBCドライバは 以下の2つです。
MySQL Connector/ODBC 3.51.* (現在3.51.16)
MySQL Connector/ODBC 5.00.* (現在5.00.11beta)

現在安定版となっている3.51系列は上記エミュレーション動作です。5.00のほうはサーバー側のプリペアド・ステートメント機能がベータ中に実装されるという話ですが、まだベータですのであまり重要なプロジェクトには使いにくいですし、Windows版しかないのも気になります。

つまり、MySQL+ODBCでのサーバー側プリペアド・ステートメント機能の対応状況はこうなっています。
MySQL Connector/ODBC 3.51.* (現在3.51.16)   :×(クライアント側エミュレーション動作)
MySQL Connector/ODBC 5.00.* (現在5.00.11beta) :×?(将来実装:beta中に?)

JavaやPHP用のドライバのほうはサーバーサイドのプリペアド・ステートメントが既に実装されているようなのですが、ODBCでのサポートはやや遅れているようです。
なお、Java(JDBC: Connector/J)では設定(emulateUnsupportedPstmts)によってプリペアド・ステートメントの実装をエミュレーションまたはサーバーサイドに切り替えることができるようです。

ODBCも早めになんとかしてほしいところですが・・・。

キーワード:
server-side prepared statement
emulated prepared statement
スポンサーサイト

テーマ:プログラミング - ジャンル:コンピュータ

2007.06.19 | Comments(0) | Trackback(0) | プログラミング

新しい記事へ <<  | HOME |  >> 古い記事へ

広告:

カテゴリ展開メニュー

  • 未分類(13)
  • Lua(38)
  • プログラミング(11)
  • 食べ物(3)
  • SPAM(2)
  • ゲーム開発(4)
  • GIS/GPS/GoogleMaps(2)
  • スポーツ(1)
  • Skype API(1)
  • AR(1)

はてブ ランキング

ブログ全体: このWikiのはてなブックマーク数

プロフィール

はむ!

Author:はむ!
よく使う言語・環境:
C++,C,Lua,java,VBA,DB
たまにPHPとかjavascript
血液型:O型

メール: lua%ham.nifty.jp
(%を@に変えてください)
ついったー: @hammmm

Lua関連アンテナ

ブロとも申請フォーム

この人とブロともになる

全記事表示リンク

全ての記事を表示する

ブログ内検索


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。