DBD ERROR: ошибка, возможно, рядом с индикатором <*> на 15-ом символе в 'TRUNCATE TABLE <*> MONTHLY_DATA') - PullRequest
0 голосов
/ 09 июня 2018

У меня есть фрагмент кода на Perl, в котором я пытаюсь обрезать таблицу, урезая таблицу, иногда я получаю сообщение об ошибке, как показано ниже. Она тратит столько времени на мою помощь, что мы оценили

Ошибка: -

DBD::Oracle::st execute failed: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired (DBD ERROR: error possibly near <*> indicator at char 15 in 'TRUNCATE TABLE <*>MONTHLY_DATA') [for Statement "TRUNCATE TABLE MONTHLY_DATA"] at data_arrival.pl line 3.

Код

$dbh = DBI->connect("dbi:Oracle:xxx","xxx","xxx", {RaiseError => 1});
$sth=$dbh->prepare("TRUNCATE TABLE MONTHLY_DATA");
$sth->execute();
$dbh->disconnect();

1 Ответ

0 голосов
/ 09 июня 2018

У вас есть таблица, которая уже заблокирована.Это было объяснено по этой ссылке: https://community.oracle.com/thread/634676. Не одобряется указание только ссылки, поэтому я и здесь выложу ответ.


Поскольку какой-то другой сеанс имеет блокировку для этой таблицы, вы можете удалить ее, потому что фактически удаляете свое согласованное по чтению представление таблицы.См. Этот тестовый пример:

В сеансе 1:

YAS@10G>create table t as select * from dual;

Table created.

YAS@10G>insert into t values(2);

1 row created.

В сеансе 2:

YAS@10G>truncate table t;
truncate table t
               *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified


YAS@10G>delete from t;

1 row deleted.

YAS@10G>commit;

Commit complete.

YAS@10G>select * from t;

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

TRUNCATE - это DDL, и для него требуется эксклюзивная блокировка на столе.Сеанс 1 удерживает общую блокировку таблицы, которая не позволяет другому сеансу получить эксклюзивную блокировку.


Чтобы решить вашу проблему, вы можете просто повторить усечение при ошибке.

#!/usr/bin/perl
# your code goes here
use strict;
use warnings;
my $dbh = DBI->connect("dbi:Oracle:xxx","xxx","xxx", {RaiseError => 1});
my $sth=$dbh->prepare("TRUNCATE TABLE MONTHLY_DATA");
my $retryLimit = 5;
my $retrySleep = 5;
my $retryCount = 0;

$sth->execute()
    || &retry();
$dbh->disconnect();

sub retry {
    sleep($retrySleep);
    $retryCount++;
    if ($retryCount le $retryLimit) {
        print qq{Retrying the TRUNCATE of MONTHLY_DATA\n};
        $sth=$dbh->prepare("TRUNCATE TABLE MONTHLY_DATA");
        $sth->execute() || &retry();
        return;
    } else {
        print qq{Retried TRUNCATING TABLE MONTHLY_DATA $retryLimit times. Quiting now\n};
        exit; 
    }
}

Как правило, это будет работать вокруг вашей проблемы.Играя в игру ожидания.Если ваша таблица также всегда пишется, возможно, вам не удастся использовать ее с успехом.Затем я бы предложил заблокировать ваш стол и затем усечь.Другим предложением является создание таблицы, подобной этой таблице, затем замена их и удаление старой таблицы (я знаю, что вы можете сделать это в MySQL, не уверенный в Oracle).

...