2013-02-14 3 views
0

Я изо всех сил пытался справиться с этой проблемой весь день .. думал, что попрошу здесь, прежде чем я потеряю все свои волосы.Perl и Rose :: DB Postgres Сделки

Описание

Я использую Perl 5.10.1 с Rose :: DB и PostgreSQL 8.4 (на Debian Linux).

Мне нужно, чтобы мои объекты «транс» были в пределах одного блока транзакций (т. Е. Изменения либо все записаны, либо откат). Однако я просто не могу заставить его работать.

Я пробовал его с автоматическим включением и выключением AutoCommit.

В приведенном ниже примере код $ 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 OFF

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 ([email protected]) 
{ 
    warn "aborted: [email protected]"; 

    eval { 
     $db->rollback; 
    }; 
} 

Откат случай: работы (п O изменения, записанные в БД)

Зафиксировать случай: не перестает (никаких изменений, записанных в БД)

Сценарий 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 ([email protected]) 
{ 
    warn "aborted: [email protected]"; 

    eval { 
     $db->rollback; 
    }; 
} 

Откат случай : Сбой (изменения записаны в БД)

Commi t: Работы (изменения записаны в БД)

Любая помощь или совет, которые вы можете предложить, были бы очень признательны.

Заранее спасибо.

+0

Почему у вашего сценария 1 нет '$ db-> begin_work'? Вы уверены, что ваши два теста эквивалентны? – 2013-02-14 08:44:15

+0

В сценарии 1 нам не нужно begin_work, потому что мы не в режиме AutoCommit. Мы уже работаем. :) – ritter

+0

Я не уверен, что здесь достаточно вашего кода, чтобы рассказать, что происходит. Можете ли вы опубликовать полный упрощенный пример (включая создание соединения), который реплицирует проблему? – 2013-02-15 07:55:37

ответ

1

Возможно, вы открываете несколько подключений к базе данных. Поведение - это именно то, что можно было бы ожидать, если соединение, которое вы совершаете, не является тем же самым соединением, которое имеет транзакцию.

Я предлагаю вам пересмотреть свой поток программ, чтобы убедиться, что у вас есть только одно соединение.

+0

Привет, Дэн, спасибо за предложение. Это определенно проблема. Если вы не укажете соединение db в конструкторе объекта, оно либо сделает новое соединение (или использует существующий). Решение состоит в том, чтобы указать дескриптор db в конструкторе следующим образом: $ trans = My :: Trans (db => $ db); – ritter