2017-07-18 6 views
2

私はApache2.2(worker)/ mod_perl 2.0.4/Apache :: DBI/CGI :: SessionとFirebird RDBMSを使用しています。DBIキャッシュステートメントがなくなり、CGI :: Sessionが貼り付けられました

また、Firebird RDBMSで動作するCGI :: Session :: Driver :: firebird.pmも書いています。 DB接続はApache :: DBIによってプールされ、CGI :: Session {Handle => $ dbh}への接続ハンドルを与えます。

DB接続の数は、ワーカープロセスの数と同じです。

私はProgramming with Apache::DBI and firebird. Get Stucked httpd on exceptionを3ヶ月前に投稿しました。 私はその問題の理由を見つけ、それを修正する方法を知りたいと思っています。

SQLエラーが発生すると、evalブロックは例外トランザクションとロールバックトランザクションをキャッチします。 その後、CGI :: Sessionはセッションオブジェクトをそれ以上取得しません。

prepare_cached文がCGI :: Session :: DBI.pmで失敗するためです。 CGI :: Session :: DBI.pmはprepare_cached($ sql、undef、3)を使用します。 '3'はキャッシュされたステートメントを使用する最も安全な方法ですが、この状況ではステートメントが見つからないことはありません。

これを修正するにはどうすればよいですか? prepare()文を使用するためにCGI :: Session :: DBI.pmを変更するリクエストを発行しますか? prepare()文を使用するには、store()、retrieve()、traverse()関数をfirebird.pmに書き込みますか?

それは他のprepare_cached()キャッチ例外後に失敗するつもりはあり

...


1)私は「新しいエラーを得たCGI ::セッション - > errstrは() にダイのステートメントを追加します( 2)私はsession-> load()の後にセッションオブジェクトをフラッシュする $ sessionが有効であれば、変更が行われます。エラーが発生した場合、$ sth-> executeは失敗します。 DBに格納されます。 3)begin_work()を{AutoCommit} = 0に置き換えます。 結果は同じです。私は通常、例外とロールバックをキャッチした後に$ dbhを使用できますが、新しいCGI :: Sessionはエラーを返します。 ------------------------------------------追加された2017/07/26 18 :47 JST

私にあなたの提案をしてください。

ありがとうございます。

+0

おそらく 'session-> flush'がセッションを終了しますか?おそらく1つは '$ sessid'から任意の値を削除すると予想されますか? –

+0

$ session-> flush()は例外を発生させません。 $ session-> flush()の後に別のクエリがうまくいきますが、次の "新しいCGI :: Session()"は空を返します。 CGI :: Session-> load()はundefを返します。 –

+0

私は$ session-> flush()を取り除いてもテストしましたが、次のCGI:Sessionは空を返しました。 –

答えて

2

あなたはCGIへのリクエストの変更の前に試すことができ、様々なもの::セッション::ドライバ:: DBI.pm ...

まず、問題が発生した場合new CGI::Sessionを診断するために呼ばれている方法を変更、ありますセッションが作成またはロードされたとき:

my $session = CGI::Session->new('dbi:firebird',$sessid,{Handle=>$dbh}) or die CGI::Session->errstr(); 

方法$sessionハンドルの内側ではなく、DB内のセッションにparamまたはdelete店の変化。 flushは、セッションハンドル内で行われた変更をDBに保存します。削除のみセッション - >のparamセット/更新またはセッションの後$session->flush()を使用します。

$session->param('p1','someParamValue'); 
$session->flush() or die 'Unable to update session storage!'; 

# OR 
$session->delete(); 
$session->flush() or die 'Unable to update session storage!'; 

$sessionハンドルを破壊しないflush方法は、(あなたがまだフラッシュ後$session->param('p1')を呼び出すことができます)。場合によっては、mod_perlは$sessionをキャッシュして、同じセッションを次回ロードしようとすると問題を引き起こします。そのような場合には、それはもはや必要いないときに破壊する必要がありますDBD::Firebird documentationが言うので、私はbegin_workメソッドを使用しないようであることを示唆している可能

undef($session) 

最後のものは、代わりにAutoCommitとトランザクション動作を制御する(つまり、双方向のトランザクションがなければならないのですevalのブロック内で制御される)とcommitさ:

eval { 
    # Setting AutoCommit to 0 enables transaction behavior 
    $dbh->{AutoCommit} = 0; 

    my $sql = "SELECT * FROM SAMPLETABLE" 
    my $st = $dbh->prepare($sql); 
    $st->execute(); 

    while (my $R = $st->fetchrow_hashref()) { 
     ... 
     } 

    $st->finish(); 
    $dbh->commit(); 
    }; 
if ([email protected]) { 
    warn "Tansaction aborted! [email protected]"; 
    $dbh->rollback(); 
    } 

# Remember to set AutoCommit to 1 after the eval 
$dbh->{AutoCommit} = 1; 

あなたは...あなたが見るべきであるFirebirdのために独自のセッションドライバを書いたかCGI /ドライバ/ sqlite.pmまたはCGI /ドライバ/ mysql.pmいくつかの取り出しメソッドを書く必要があるかもしれません。お間違えています...

これは役に立ちます!

+0

1)CGI :: Session-> errstr(): new():失敗しました:load():データを取得できませんでした:retrieve():$ sth-> executeがエラーメッセージ で失敗しました2)オブジェクト: $セッションが有効な場合、変更はDBに保存されます。 3){AutoCommit} = 0などを使用: 状況は同じです。私は通常、例外とロールバックをキャッチした後に$ dbhを使用できますが、新しいCGI :: Sessionはエラーを返します。 --- My Driver/firebird.pmにはinit()とtable_name()のみがあり、DBI.pmでstore/retrieveを使用します。私はfirebird.pmを書いてDBD :: Firebirdを読み込み、DSNを 'dbi:firebird'としました。 –

+0

firebird.pmにストアを追加し、取得し、「_cached」なしでトラバースします。それは正常に動作しています。 mysql.pmには、mk_dsn、init、table_name、storeがあります。 store()がDBI.pmの 'ON DUPLICATES'を使用するように変更されました。 DBI-> begin_work()が{AutoCommit}を0に変更しました。 回避方法が見つかりました。だから、なぜキャッシュされた文がなくなったのか知りたいのですが? –

+0

見つけたエラーで質問を更新できますか? – kidkamek

関連する問題