Perl DBIx :: транзакции класса с отсутствующей фиксацией

#perl #transactions #moose #dbix-class

#perl #транзакции #moose #dbix-класс

Вопрос:

Я борюсь с непоследовательным поведением модуля Perl DBIx:: Class. Я написал простой чистый класс Perl, который определяет член класса ‘schema’, который является просто ссылкой на предварительно инициализированный / подключенный объект DBIx :: Class:: Schema и метод для добавления некоторых данных в базу данных:

 sub new {
    my $class = shift;
    my $params;
    if(1 == scalar @_ amp;amp; 'HASH' eq ref($_[0])) {
        $params = shift;
    } else {
        my %params = @_;
        $params = %params;
    }

    my $self = {
        schema => $params->{schema}
    };

    bless $self, $class;

    return $self;
}


sub addToQueue {
    my $self = shift;
    my $params;
    if(1 == scalar @_ amp;amp; 'HASH' eq ref($_[0])) {
        $params = shift;
    } else {
        my %params = @_;
        $params = %params;
    }
    
    #some parameter constraints checks
    ....
    
    $self->{schema}->txn_do(sub {
        $self->{schema}->resultset('SOME_QUEUE')->create($params);
    });

    # this row is necessary if this method is called from programs, which uses moose
    $self->{schema}->txn_commit();
 
    return;
}
  

Если я вызываю метод addToQueue из одной программы на Perl (использует Moose), я должен добавить строку кода

 self->{schema}->txn_commit();
  

чтобы действительно запустить команду фиксации БД. Если я вызываю метод из другой программы на Perl (не использует Moose), код завершается ошибкой с сообщением:

Использование неинициализированного значения $ msg в подстановке (s///) в /usr/local/share/perl/5.20.2/DBIx/Class/Exception.pm строка 58. Использование неинициализированного значения $msg в конкатенации (.) или строки в /usr/local/share/perl/5.20.2/DBIx/Class/Exception.pm строка 68. DBIx::Class::Storage::txn_commit(): отказ от фиксации без запущенной транзакции

Если я удалю дублированную команду фиксации, она будет работать для программы, отличной от Moose, но программа, использующая Moose, пропустит фиксацию, и созданная запись не будет записана в базу данных.

Кто-нибудь знает об этой проблеме?

Комментарии:

1. Что вы подразумеваете под программой Moose ? Пожалуйста, покажите нам, как подключается схема, и сообщите нам, какой компонент database engine вы используете.

2. Программа, которая включает в себя модули Moose, например: использовать Moose; использовать пространство имен ::autoclean; использовать MooseX::AutoImmute;

Ответ №1:

Из документации для txn_do ,

ПРЕДУПРЕЖДЕНИЕ: если вы подключены, AutoCommit => 0 транзакция считается вложенной, и вам все равно нужно будет вызвать «txn_commit», чтобы записать ваши изменения, когда это необходимо. Вы также захотите подключиться, auto_savepoint => 1 чтобы заставить работать частичный откат, если драйвер хранилища для вашей базы данных поддерживает его.

Рекомендуется подключение с AutoCommit => 1 помощью.

Я подозреваю, что вы используете AutoCommit => 0 , когда вам нужно дополнительное txn_commit .

Комментарии:

1. Вы правы. Проблема заключалась в том, что устаревший код манипулировал состоянием автоматической фиксации с помощью чистой команды SQL, поэтому значение dbh-> {AutoCommit} стало непоследовательным.

Ответ №2:

Короткий ответ: вы совершаете транзакцию дважды. txn_do автоматически фиксируется при выходе из блока, когда не генерируется исключение. Пожалуйста, опубликуйте пример кода, который загружает Moose и журнал из DBIC_TRACE=1, который показывает, что фиксация не запускается.