プロが教えるわが家の防犯対策術!

SQLを約1600回実行したら、5秒後にページを再読み込みします。

print "<html><body onload=\"setTimeout('location.reload()',5000)\">";

foreach ... {
  ...
  # 約1600回繰り返す
  @result = select("SQL文");
  ...
}

sub select{
  my @result = ();
  my($dbh, $sth);
  $dbh = DBI->connect('DBI:mysql:データベース:localhost', "ID", "パスワード") or return 0;
  $sth = $dbh->prepare("$_[0]");
  $sth -> execute() or return 0;
  $num_rows = $sth->rows;
  $num_of_fields = $sth->{NUM_OF_FIELDS};
  $result[0] = $sth->rows;
  for ($i=1; $i<=$num_rows; $i++) {
    @fetchrow_array = $sth->fetchrow_array;
    $result[$i] = join ',', @fetchrow_array
  }
  $sth -> finish();
  $dbh -> disconnect();
  return @result;
}

最初の1,2回は期待通りに動くのですが、
2,3回ほど再読み込みをすると、「読み込み中」のままになってしまいます。
(期待通りに動く場合、1回の読み込みは20秒程度です。)

タスクマネージャを見ると、
期待通りに動いているときは、CPU使用率が60%くらいになっていますが、
「読み込み中」のままの時は1%程度になっています。

SQLサーバーから応答がなくなっているのでしょうか?
(簡単なSQLにしてみても同じでした。)

原因がわかる方、よろしくお願いします。

WindowsXP SP2
Apache1.3
ActivePerl5.6
MySQL3.23

A 回答 (3件)

エラーの根本解決にはならないと思いますが、



foreach の外でconnect&disconnectして、select命令に$dbhを引き数として渡すようにしてはいかがでしょう? 用は、DB接続を約1600回から1回に減らすと言う案です。
    • good
    • 0
この回答へのお礼

>foreach の外でconnect&disconnectして、select命令に$dbhを引き数として渡すようにしてはいかがでしょう?

この方法でうまく動きました!

$dbh = DBI->connect(...);

foreach ... {
  ...
  # 約1600回繰り返す
  @result = select("SQL文", $dbh);
  ...
}

$dbh -> disconnect();

接続と実行を分けるところまで考えが回っていませんでした。

丁寧なアドバイスありがとうございました。

お礼日時:2007/06/12 13:42

Premature end of script headers は、Content-typeを出力する前に何らかの原因で別の文字列が出力されてしまうと出ることがあります。



return 0 する代わりに、 die DBI->errstr なんてしてみると、もうちょっと詳細のエラーメッセージ見れたりしません?

セッションはshow processlist で見れますが、今回は接続に失敗しているので、セッションは存在しないと思います。


後、前回の回答に書いた部分は試して頂けましたか?
    • good
    • 0
この回答へのお礼

>return 0 する代わりに、 die DBI->errstr なんてしてみると、もうちょっと詳細のエラーメッセージ見れたりしません?

Apacheのエラーログに以下のように残りました。

[Sat Jun 09 15:11:39 2007] [error] [client 192.168.0.6] DBI connect('データベース:localhost','',...) failed: Can't connect to MySQL server on 'localhost' (10048) at c:\\PROGRA~1\\APACHE~1\\apache\\cgi-bin\\プログラム名.CGI line 68\n
[Sat Jun 09 15:11:39 2007] [error] [client 192.168.0.6] Can't connect to MySQL server on 'localhost' (10048) at c:\\PROGRA~1\\APACHE~1\\apache\\cgi-bin\\プログラム名.CGI line 68.\n

10048というエラーがあるので調べてみましたが、
OS(WindowsXP、2003Server)に原因があるのかもしれません。

http://www.mysql.gr.jp/mysqlml/mysql/msg/13216
http://72.14.253.104/search?q=cache:-MRJssTOuB0J …

とりあえず、「MySQLからまとめてSELECT→perlで細かく処理」する方法を試してみます。


>後、前回の回答に書いた部分は試して頂けましたか?

$sth->rows の箇所は教えていただいたように修正しました。
ありがとうございました。

お礼日時:2007/06/09 15:35

補足をお願いしたいのですが、



(1) Apacheのエラーログには何も出てないですか?
(2) 読み込み中のときのアクセスに対するApacheのアクセスログ
は残ってますか?
(3) 読み込み中のとき、MySQLにセッションは張られていますか?


なお、今回の不具合と関係があるかは定かではないですが、このソースにまずいところがあります。それは$sth->rows です。このメソッドはDELETEやUPDATEでの使用を想定していて、SELECT 文では使用することはお勧めできないとドキュメントにも書いてあります。whileでfetchしても何も返って来なくなるまで回すのが普通のやり方です。

while(@row = $sth->fetchrow_array) {
# 処理
}

この回答への補足

遅くなって申し訳ありません。わかる範囲で調べてみました。


>(1) Apacheのエラーログには何も出てないですか?

[Thu Jun 07 12:06:12 2007] [error] [client 192.168.0.6] Premature end of script headers: c:/program files/apache group/apache/cgi-bin/プログラム名.cgi
[Thu Jun 07 12:06:12 2007] [error] [client 192.168.0.6] DBI connect('データベース:localhost','',...) failed: Can't connect to MySQL server on 'localhost' (10048) at c:\\PROGRA~1\\APACHE~1\\apache\\cgi-bin\\プログラム名.CGI line 67\n
[Thu Jun 07 12:06:12 2007] [error] [client 192.168.0.6] DBI connect('データベース:localhost','',...) failed: Can't connect to MySQL server on 'localhost' (10048) at c:\\PROGRA~1\\APACHE~1\\apache\\cgi-bin\\プログラム名.CGI line 67\n
[Thu Jun 07 12:06:12 2007] [error] [client 192.168.0.6] DBI connect('データベース:localhost','',...) failed: Can't connect to MySQL server on 'localhost' (10048) at c:\\PROGRA~1\\APACHE~1\\apache\\cgi-bin\\プログラム名.CGI line 67\n
...(同じように続く)

67行目はMySQLに接続しようとする場所です。
$dbh = DBI->connect('DBI:mysql:データベース:localhost', "ID", "パスワード") or return 0;

"Premature end of script headers" とあるので調べてみたら、
「Content-type: text/html\n\nを出力していない場合が考えられます」とありました。
最初の数行は以下のようなものです。

#!/Perl/bin/perl
require './jcode.pl';
require './cgi-lib.pl';
&ReadParse(*in);
print "Content-type: text/html\; charset=shift_jis\n\n";
...

また、「パーミッションを755にしたら解決した」という記事もあったのですが、
Windowsであることと、正しく処理できることもあることから、関係ないかと思います。


>(2) 読み込み中のときのアクセスに対するApacheのアクセスログは残ってますか?

192.168.0.6 - - [07/Jun/2007:12:04:52 +0900] "GET /cgi-bin/プログラム名.cgi HTTP/1.1" 200 382
192.168.0.6 - - [07/Jun/2007:12:05:04 +0900] "GET /cgi-bin/プログラム名.cgi HTTP/1.1" 200 382
192.168.0.6 - - [07/Jun/2007:12:06:12 +0900] "GET /cgi-bin/プログラム名.cgi HTTP/1.1" 500 605

1,2行目は期待通りに処理したときのもので、3行目が読み込み中のままになったときのものです。
(読み込み中が続いたので、途中で中止しました。)
500とあるのでサーバーエラーのようです。


>(3) 読み込み中のとき、MySQLにセッションは張られていますか?

どのように確認したらよいのかがわかりませんでした。

補足日時:2007/06/07 12:12
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!