1

私は一日中この問題に苦しんでいます..髪をすべて失う前に、ここで質問すると思いました.

説明

Rose::DB および PostgreSQL 8.4 (Debian Linux) で Perl 5.10.1 を使用しています。

「trans」オブジェクトを 1 つのトランザクション ブロック内に変更する必要があります (つまり、変更はすべて書き込まれるか、ロールバックされます)。しかし、私はそれを機能させることができません。

AutoCommit の ON と OFF の両方で試してみました。

以下のサンプル コードでは、$db は、スクリプトの開始時に確立された Rose::DB 接続です (使用: my $db = My::DB->new;)。すべての Rose::DB オブジェクトは基本クラス (My::Base) から継承します。この基本クラスには、DB 接続用の継承可能なサブがあります。

sub init_db
{
    My::DB->new_or_cached
}

DB 接続オブジェクト (My::DB) には、接続文字列と設定が含まれています。

_ _PACKAGE_ _->use_private_registry;

_ _PACKAGE_ _->register_db(
    driver          => 'pg',

database        => 'xx',
host            => 'localhost',
username        => 'xx',
password        => 'xx',

    connect_options => {
        AutoCommit      => 0,  -- changed to suit SCENARIO 1 and 2 below
        RaiseError      => 1,
    }
);

シナリオ 1: AutoCommit オフ

AutoCommit 0 と RaiseError 1

my $trans = shift;

eval {
    $trans->...        -- Make changes to object
    $trans->save;

    # die "testing";   -- Cause a rollback using "die"

    $db->commit or die $db->error;
};

if ($@)
{
    warn "aborted: $@";

    eval {
        $db->rollback;
    };
}

ロールバック ケース: 動作します (変更は DB に書き込まれません)

コミットケース:失敗(DB に変更が書き込まれません)

シナリオ 2: AutoCommit オン

AutoCommit 1 と RaiseError 1

my $trans = shift;

eval {
    $db->begin_work or die $db->error;

    $trans->...        -- Make changes to object
    $trans->save;

    # die "testing";   -- Cause a rollback using "die"

    $db->commit or die $db->error;
};

if ($@)
{
    warn "aborted: $@";

    eval {
        $db->rollback;
    };
}

ロールバック ケース:失敗(変更が DB に書き込まれる)

コミットケース : Works (DB に書き込まれた変更)

あなたが提供できる助けやアドバイスは大歓迎です。

前もって感謝します。

4

1 に答える 1

2

複数のデータベース接続を開いている可能性があります。コミットする接続がトランザクションを持つ接続と同じでない場合の動作は、まさに期待どおりです。

プログラムフローを再検討して、接続が1つしかないことを確認することをお勧めします。

于 2013-02-18T08:26:01.427 に答える