#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:
ПРЕДУПРЕЖДЕНИЕ: если вы подключены,
AutoCommit => 0
транзакция считается вложенной, и вам все равно нужно будет вызвать «txn_commit», чтобы записать ваши изменения, когда это необходимо. Вы также захотите подключиться,auto_savepoint => 1
чтобы заставить работать частичный откат, если драйвер хранилища для вашей базы данных поддерживает его.Рекомендуется подключение с
AutoCommit => 1
помощью.
Я подозреваю, что вы используете AutoCommit => 0
, когда вам нужно дополнительное txn_commit
.
Комментарии:
1. Вы правы. Проблема заключалась в том, что устаревший код манипулировал состоянием автоматической фиксации с помощью чистой команды SQL, поэтому значение dbh-> {AutoCommit} стало непоследовательным.
Ответ №2:
Короткий ответ: вы совершаете транзакцию дважды. txn_do
автоматически фиксируется при выходе из блока, когда не генерируется исключение. Пожалуйста, опубликуйте пример кода, который загружает Moose и журнал из DBIC_TRACE=1, который показывает, что фиксация не запускается.