DBM :: Deep: проблемы с транзакциями - PullRequest
2 голосов
/ 26 февраля 2011

Я никогда не проводил транзакции (с точки зрения программирования), поэтому я не знаю, что-то не так с моим скриптом или что-то еще:

#!/usr/bin/env perl
use warnings;
use 5.012;
use DBM::Deep;

my $db = DBM::Deep->new( 'foo.db' );

my $trans = $db->supports( 'transactions' );
say 'Does ', $trans ? '' : 'NOT ', 'support transactions'; 

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->rollback;
$db->{key1} = 'value1';
$db->commit;

Вывод:

# Does support transactions
# DBM::Deep: Cannot allocate transaction ID at ./perl1.pl line 12

Часть комментария:

my $db = DBM::Deep->new( file => 'my.db', num_txns => 1 );

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->rollback;
$db->begin_work;
$db->{key1} = 'value1';
$db->commit;

Ответы [ 2 ]

1 голос
/ 15 июня 2015

Извините, что так долго отвечал на этот вопрос - я нашел его всего несколько дней назад. (Я поддерживаю DBM :: Deep.)

Проблема в том, что num_txns устанавливается только при создании файла. (Это из-за того, как файл DBM размещен на диске.) После создания файла DBM значение num_txns считывается из файла и игнорируется при вызове new(). Поэтому, если вы изменили свой вызов, указав num_txns, это не поможет, если вы не используете новый файл DBM.

Хотя я не могу изменить это поведение без существенного изменения работы файловой структуры DBM (что может быть хорошей идеей, но это огромная задача), вы должны были быть предупреждены и должна была быть лучшая документация. Я открыл https://github.com/robkinyon/dbm-deep/issues/12, чтобы отследить эту проблему и исправить ее.

1 голос
/ 26 февраля 2011

В соответствии с документацией команда rollback завершает транзакцию.

rollback () Отменяет сделанные в транзакции изменения в основной линии и завершает транзакцию.

Поэтому вам нужно начать новую транзакцию после отката.

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->rollback;
$db->begin_work;
$db->{key1} = 'value1';
$db->commit;

или вы можете сделать что-то вроде

sub my_rollback {
  my $db = shift;
  $db->rollback();
  $db->begin_work();
}

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
my_rollback $db;
$db->{key1} = 'value1';
$db->commit;

или немного черногомагия, вы можете сохранить стиль OO

sub my_rollback {
  my $db = shift;
  $db->rollback();
  $db->begin_work();
};
{
  no strict 'refs';
  *{'DBM::Deep::my_rollback'} = \&my_rollback;
}

$db->{key} = 'value';
$db->begin_work;
$db->{key1} = 'value2';
$db->my_rollback;
$db->{key1} = 'value1';
$db->commit;
...