我在ORacle 10g生产数据库中运行了一个作业,该数据库同步两个数据库表A和B.作业从表A中获取数据并插入到表B中。作业每天运行,在过去的几个月中它开始运行生产失败并出现错误“检索数据错误-54”。在检查存储过程时,我可以看到当其他作业锁定表A中的记录并且我们的作业无法处理时,由于锁定记录问题而导致作业失败。所以我开始寻找下面给出的一些可能的解决方案。
更改作业的运行时间,以便它可以处理记录。但这不会有帮助,因为表A非常关键并且总是被生产工作所使用。它还有来自用户的实时更新。
使用“SKIP LOCKED”代替“No WAIT”,以便作业将跳过锁定的记录并运行正常。但问题在于,如果跳过锁定记录(这与巨大的生产数据相比总是可以忽略不计),那么当天表A和B中的数据将不匹配。第二天运行将清除此问题,因为作业也会选择前几天的未记录的记录。但是,作业失败的天数轻微不匹配可能会导致小问题
让作业等到所有记录都解锁并处理完毕。但是这又引起了问题,因为我们无法预测作业处于等待状态的长度(长时间运行状态)。
截至目前,对我来说,一个可能的解决方案是使用选项2并忽略表A和Bs数据之间的轻微偏差。 Oracle 10g Db中是否有任何其他方式可以在不失败的情况下运行作业并长时间运行并处理所有记录。我希望得到一些技术指导。
由于 PB
答案 0 :(得分:2)
我会处理异常(请注意,您必须初始化自己的EXCEPTION
或处理OTHERS
并检查SQLCODE
)并跟踪行的ID被跳过了。这样,一旦处理完所有可用记录,您就可以重试它们。
这样的事情:
DECLARE
row_is_locked EXCEPTION;
PRAGMA EXCEPTION_INIT(row_is_locked, -54);
TYPE t_id_type IS VARRAY(1) OF INTEGER;
l_locked_ids t_id_type := t_id_type();
l_row test_table_a%ROWTYPE;
BEGIN
FOR i IN (
SELECT a.id
FROM test_table_a a
)
LOOP
BEGIN
-- Simulating your processing that requires locks
SELECT *
INTO l_row
FROM test_table_a a
WHERE a.id = i.id
FOR UPDATE NOWAIT;
INSERT INTO test_table_b
VALUES l_row;
-- This is on the basis that you're commiting
-- to release the lock on each row after you've
-- processed it; may not be necessary in your case
COMMIT;
EXCEPTION
WHEN row_is_locked THEN
l_locked_ids(l_locked_ids.LAST) := i.id;
l_locked_ids.EXTEND();
END;
END LOOP;
IF l_locked_ids.COUNT > 0 THEN
FOR i IN l_locked_ids.FIRST .. l_locked_ids.LAST LOOP
-- Reconcile the remaining ids here
NULL;
END LOOP;
END IF;
END;