• ベストアンサー

DB切断のタイミング(perlでは切断されない?)

perlのDBIからMySQLに接続しています。 一連の処理の中で、disconnectをしても実際には暗黙的にプログラム終了時に切断されるので、厳密にはdisconnectは不要とのこと(この認識が間違っていたらご指摘ください)。 実際に試してみたら、切断した後でも同じデータベースハンドルが使用できました。 で、問題は、一連の処理の中でセッションはどのように扱われるのでしょう。切断されることなく同じセッションが使いまわされるのでしょうか? 具体的には、以下のようなことで悩んでいます。 接続→SELECTで必要データを取得→切断 という処理をするサブルーチンがあり、このサブルーチンをメインルーチンから複数回呼び出しています。つまりロジック的には接続と切断を何度も繰り返すような流れになっています。 これはこれで期待通りの動作をするのですが、何度も接続・切断を繰り返すより、メインルーチンで一度だけ接続しておいて、そのデータベースハンドルを引数と一緒にサブルーチンに渡す、そしてメインルーチンで最後に切断、という仕様に変更したほうが、効率が良いのでは、と考えました。 しかし、ロジック的には接続・切断を繰り返しているように見えても、実際にはそれぞれ一回ずつしか行われていないのなら、カプセル化という意味ではサブルーチンの中で接続・切断を書いた方が良さそうに思えます。 実際のところ、終了処理などのタイミングが良く解っていないのがいけないのですが、どなたか、どちらが良いのか、実際に切断がいつ行われるのか、ご存知でしたら、よろしくお願いいたします。

  • SV576
  • お礼率83% (40/48)
  • Perl
  • 回答数3
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • zebedeer
  • ベストアンサー率66% (80/121)
回答No.3

>ロジック的には では、package hogeの下でconnectして、$dbhはhogeのpackage変数として持ってみては? package hoge; use DBI; $dbh = DBI->connect unless $dbh; sub new {}; sub DESTROY{#必要であれば $dbh->disconnect if $dbh; } この方法ならmod_perl環境でも使いまわせるので良いかもしれません。 (まぁ、mod_perl+DBIならApache::DBI使うか)

SV576
質問者

お礼

なるほど。おっしゃるとおりです。 サブルーチンかメインルーチンか、にばかり気を取られて、モジュール自体のスコープを忘れていました…。 これなら呼び出し側から隠蔽されるし、接続も保持されますね。 大変助かりました。 ありがとうございます。

その他の回答 (2)

  • zebedeer
  • ベストアンサー率66% (80/121)
回答No.2

>厳密にはdisconnectは不要 使い方によってはdisconnectが必要ですが、使い方によってはdisconnectは不要です。 (AutoCommitやfinish、commit等の使い方によって) >切断されることなく同じセッションが使いまわされるのでしょうか? この辺はDBDに依存すると思います。 >何度も接続・切断を繰り返すより、メインルーチンで一度だけ接続 基本的にこっちの方が効率が良いです。 (ただし、DBDによっては、悪いことはなくても変わらないかも) ちなみに私は開始時にDBI->connectして終了時に$dbh->disconnectしています。 ($dbhはグローバル変数に保存)

SV576
質問者

お礼

ご回答ありがとうございます。 やはり接続・切断はメインルーチンで管理したほうが良いでしょうか。 サブルーチンとは言っても外部のモジュールファイルに入れているので、なるべくならメインの方では「(DBを意識する必要なく)情報を取ってくるだけ」に見えたほうがいいと考えたのですが、やはり効率などの面では良くないのですね(実装によっては変わらないとしても)。 ロジック的にはどう思われますか?上記のようにサブルーチンをカプセル化することと、それをすることによる影響の、すりあわせと言いますか、判断材料としては、やはり呼び出す回数などでしょうか。

  • angband
  • ベストアンサー率51% (86/168)
回答No.1

DBIのマニュアルによると disconnectは接続を切断すると明記されていますので、 基本的には切断されると思うのですが、実装上すぐに切断しないのかもしれない ですね。 MySQLでdisconnectが不要と言われるのは、昔のテーブルタイプでは、 トランザクションをサポートしていないために、disconnect呼び出し時に 特に処理がないために、プログラム終了->(勝手に)切断 でも問題が ないということみたいです。(MySQLのマニュアルより) ただこの質問の内容については、マニュアルに記載されていることよりも さらに深い実装に関することなので、今現在DBIが使っているパフォーマンス上の トリック(DBIオブジェクトがすぐに接続を破棄しないように見える)に依存した プログラムを作らない方がよいのではないでしょうか。 回答になってないかと思いますが、検証という意味では、プログラムを disconnectの呼び出し前後で止めて、コマンド mysqladmin processlistで どのスレッドがどのDBに接続してるか調べることで、タイミングは 調べられるのではないでしょうか。

SV576
質問者

お礼

ご回答ありがとうございます。 確かに、おっしゃるように実装などに依存した作りは良くないかもしれませんね。 今回悩んでしまったのは、質問文にも書いたようにカプセル化の観点からなんですよね。 サブルーチンとは言っても外部のモジュールファイルに入れているので、その主旨から言えば、メインのスクリプトからはDBの接続などを意識することなく、もっと言えば、DBの存在すら知らなくても、ただ情報が取り出せる、ような作りにしたかったからです。 やはりロジック的に正道な方法で、メインルーチンで接続→サブルーチンに渡す…、最後にメインルーチンで切断、というのが良いでしょうか。 ただ、ご指摘いただいたことを逆に考えれば、効率などを気にしなければ、接続・切断を繰り返そうと、一向に問題はないわけですよね。 ロジック的に、あるいはスマートな方法は、どちらだと思われますか?

関連するQ&A

  • データベースのタイミングについて

    PHPでとあるデータベースに接続したいのですが、 本番のサーバーのため、 処理を慎重に行いたいと思います。 データベースの処理の流れがよくわかっていないのですが、 処理としては データーベースを接続する Beginする テーブルを作成 大丈夫だったら  コミットする 大丈夫じゃなかったら  ロールバックする Endする データベースを切断する という処理でいいのでしょうか?? また、データベース上に同じテーブル名などがある場合は CREATを実行したときにエラーを返してくれるのでしょうか??

    • ベストアンサー
    • PHP
  • php と perl

    perlで掲示板を作成する際はだいたい、 ####メインルーチン if($FORM['mode']="write";){&write;} elsif($FORM['mode']="usr_delete";){&usr_delete;} elsif($FORM['mode']="user_edit";){&usr_edit;} elsif($FORM['mode']="admin";){&admin;} … &html; exit; ####サブルーチン sub write { #書き込み処理 } sub usr_delete { #削除処理 } … といったように記述しますよね。 これをphpでも同じように、 //メインルーチン switch ($_POST['mode'])  case "write":   write();  case "delete":   delete();   … //サブルーチン function write(){…} function delete(){…} … と書くのは効率的ではないでしょうか。 効率とは"速さ"や"実装の仕方として適切ではないかどうか"、という意味です. 他サイトで配布されているphpのスクリプトに目を通すと、そう記述しているものがあまりみられませんでした。 もう1つ疑問なのですが、掲示板のスクリプトにクラスを使っているサイトが多々ありました。もちろんつかってないスクリプトなどもありましたが、掲示板作成をする際、クラスを使うメリットはあるのですか?

    • ベストアンサー
    • PHP
  • My Sqlのデータベースを扱うサブルーチン

    はじめてMy SQLで開発しようと考えています。 いままでテキストファイルでした。 &reamfile; foreach @txt{  処理 } &writefile; とテキストファイルの読み込み書き込みはすべてサブルーチンを 利用していましたので楽でした。 これに代わるサブルーチンで開発することは可能でしょうか? 今後の流れは &データベース接続 ↓ &読み込み ↓ &データベース切断 ↓ 処理 ↓ &書き込み というサブルーチンであっていますよね? もしできましたらそんな便利なサブルーチンのスクリプトを 教えてください。 また、テーブルの作成はサーバーのPhpMyAdminでもできるんですが、 Perlスクリプト&SQLで作成しておいた方がよいでしょうか?

  • データベースの切断について

    初めて質問させていただきます。 現在、C/S系のシステム開発で、プログラミング言語はJavaサーブレットを、データベースはDB2を使用してWeb画面を使用したシステム開発を行っています。 Javaサーブレットで、JDBC-ODBCを使用してデータベースへ接続するように、また切断の際もプログラムの中で切断できるようにプログラミングをしているのですが、Web画面のブラウザにある×マークで画面を閉じてもデータベースの接続は切断されるのでしょうか? 色んなサイトを探し回ったのですが、良い資料がありませんでした。 お分かりの方がいらしたら、是非ご教授お願い致します。

  • ターミナルサービスマネージャの切断、ログオン、リセットの違いを教えてください。

    私はWindowsのターミナルサービスを使用しています。 ターミナルサービスマネージャで切断とログオフとリセットがありますが、どう違うのでしょうか?? ○切断はセッションを残したまま接続を切断 ○ログオフは起動しているアプリを終了してユーザー情報を保存して接続を切断 ○リセットは起動しているアプリを終了してそのまま接続を切断 上記でよろしいのでしょうか?? 有力と思われる情報を見たことがないので、どなたか教えてください。

  • リモートデスクトップが勝手に切断されます。

    自宅PC(Windows7 ultimate 64bit)に会社PC(XP professional 32bit)から 接続していますが、接続して1、2分で「セッションがリモート コンピュータからログオフしたため、リモート セッションは切断されました。管理者または別のユーザーがセッションを終了した可能性があります。」というエラーメッセージが出て切断されてしまい困っています。何度再接続しても同じです。 ユーザーは私しかいませんので他人が自宅PCを操作しているわけでもありません。しかし、自宅に帰って確認すると、自宅PCはパスワード入力画面になっている筈ですが、普通にデスクトップが表示されています。 ちなみにポート番号を変えたもう一台のPC(Vista ultimate 32bit)へ接続した場合は勝手に切断されることはありません。

  • PerlでSocketを閉じずに再利用する方法

    インターネット上の情報を参考に作成したCGIでPerlのソケットを用いて通信を行っておりますが、CGIが呼び出されるたびに以下のような動作を行っております。 ソケット生成 -> ソケット接続 -> HTTP通信 -> ソケット切断 このうち、ソケットの接続におおよそ200ミリ秒ほどかかり、このレイテンシを減らすため、ソケットはCGIが呼び出されるたびに生成、接続するのではなく、最初からセッションを張った状態で、CGIが呼び出されるとHTTP通信部分のみを行うようにすることはできますでしょうか。 現在試したこととして、1回目の呼び出しでソケットをクローズせずに処理を終了し、2回目でソケットの生成、接続をせずに直接HTTP通信をしようとしてもうまくいきませんでした。 Perl、ネットワークプログラミング初心者なもので恐縮ですが、何卒よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • connect タイムアウトのデフォルト

     Perl を使って HTTP 経由で HTML ファイルを取得するロジックを組んでいます。  通常、コネクト時のタイムアウト処理にはシグナルを使用しますが、これだとルーチンの呼び出し元に戻れません。  タイムアウトしたら終了せずに次の処理へ進む、というロジックを組みたいのですが、シグナルを設定しなかった場合、処理はちゃんと戻ってくるでしょうか。  本当ならこのくらい自分で確認すりゃいいんですが、なんせ「戻ってこないホスト」に心当たりがないので確認できないのです(^_^;  もしくは、シグナルのコールバック関数から元のルーチンへ戻る方法でもいいのです。  何かご存知の方がいらっしゃいましたら、よろしくお願いします。

    • ベストアンサー
    • Perl
  • リファレンスについて 1

    リファレンスについて、いろいろ文献を調べて勉強中です。 自分の中では下記のように解決しているのですが、あってるかどうか聞いてください。 『ようはVBで言う参照渡し(ByRef)と同じで、値そのものを渡すのではなくアドレスを渡すので、サブルーチンで値が変更されてしまうとメインルーチンでの値も変わってしまう』

    • ベストアンサー
    • Perl
  • ループ処理の中におけるDB接続について(java)

    ループ処理の中におけるDB接続について、接続→切断を繰り返すと処理速度が落ちますよね。 これを回避するにはSQLでできる限り取得するのが良いと思われますが、その他にプログラムで 回避することはできますかね? whileの中でさらにSQLを使用する必要があります。 どなたかご教授願います。

専門家に質問してみよう