есть ли простой способ установить тайм-аут для оператора SQL, чтобы он завершился ошибкой вместо ожидания (например, доставил пустой набор результатов или сообщение об ошибке или что-то еще), чтобы я мог позволить сбой резервирования ресурсов задания и дать шанс другому? Я ищу какой-нибудь вариант DBI, на который я до сих пор не обращал внимания; посылать себе SIGALRM для совершения самоубийства - это скорее не то, что я имел в виду (хотя, возможно, мне пришлось бы прибегнуть к этому, если бы мне пришлось).
Отрезанный код является псевдоизолированным и урезанным до крайности, но я надеюсь, что вы уловите дрейф.
my $sql = "SELECT one, two, three FROM sometable WHERE this = ? AND that = ?";
my $sth = $self->make_handle( $sql );
eval {
foreach my $this ( sort keys %needed_ressources ) {
# vvv This is where the idle time is spent vvv
$sth->execute( $this, $that ) or die( "DB connection gone?!" );
# ^^^ This is where the idle time is spent ^^^
my ( $one, $two, $three ) = $sth->fetchrow_array();
unless( $one ) { # undefined record set == not found
$self->{DB_HANDLE}->rollback();
die( "$this not defined for $that!" );
}
}
# If we haven't died so far, we can move on
foreach... #similar loop here doing the actual update statement
$self->{DB_HANDLE}->commit();
};
return( 1 ) unless $@;
return( undef );
Вот кровавые подробности для интересующихся:
В приложении, которое выполняет массовую параллельную обработку чисел, реализован механизм блокировки ресурсов, использующий таблицу оракула. Каждое задание должно заблокировать ряд ресурсов для чтения и / или ряд ресурсов для записи, и может запускаться только в том случае, если все блокировки были успешно получены. Вместо того, чтобы терпеливо ждать освобождения ресурсов, задания должны просто терпеть неудачу и повторно запускаться позже их мастером (это снижает количество открытых транзакций, одновременно повышая производительность за счет большего количества заданий, связанных с фактическим кризисом).
Конечно, перед фактическим обновлением таблицы каждая строка резервируется с помощью оператора «SELECT ... FOR UPDATE», поэтому Oracle использует блокировку на уровне строк, и в таблице могут происходить параллельные транзакции. Чтобы еще больше уменьшить возможные состояния гонки и взаимоблокировки, все задания сначала выбирают строки с их ресурсами, а затем блокируют их, используя тот же порядок, прежде чем выполнять обновление.
Что касается текущей реализации, это прекрасно работает в большинстве случаев. Но поскольку «Выбрать для обновления» блокируется до тех пор, пока Oracle фактически не предоставит блокировку строки, все еще может случиться так, что задание простаивает в ожидании своих ресурсов, и я стремлюсь к тому, чтобы лучше использовать доступную мощность процессора. Можно подождать секунду или две, но не десять или больше только для блокировки. Для снятия блокировки позже, конечно же, требуется ожидание, поэтому установка всего соединения с БД на прием только немедленных результатов не сработает.
Я всегда благодарен за ответы RTFM, если они указывают на место в M, которое у меня TF должно быть R < / strong> ;-))
Заранее большое спасибо,
Олфан