我有一段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();
答案 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)。