DBD错误:错误可能接近< *> 'TRUNCATE TABLE< *> MONTHLY_DATA'中char 15的指示符)

时间:2018-06-09 02:51:59

标签: oracle perl dbi

我有一段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 :(得分:2)

你有一张已经锁定的桌子。这已在此链接中解释: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)。