问题描述
嗨,汤姆,
我有一张表有大约500万条记录。
表结构:
DESC rpt _ msg _ 更改
我需要为状态 = 'AVAILABLE' 的每个记录调用一个过程,然后在其他表上进行一些压缩/插入/删除,然后将状态标记为 “已处理” 或 “失败”。我正在使用以下脚本调用:
现在,我在plsql块上方运行,该块执行大约20 k条具有可用状态的记录的过程。在mid中 (假设处理5k记录后),如果我想停止执行,我只需将状态更新为 “processed” 的表。现在,我不确定为什么会话仍在运行,并且几乎需要处理每个记录所需的时间。
你能不能让我知道oracle在这种情况下的行为,它是简单地打开一个缓冲区-> 复制其中的所有记录-> 处理缓冲区中的所有记录 (不管主表记录更新) 还是在后台有一些其他的动作?
谢谢
阿米特
我有一张表有大约500万条记录。
表结构:
DESC rpt _ msg _ 更改
Name Null Type ---------- -------- -------------- OID NOT NULL NUMBER PRODUCT NOT NULL VARCHAR2(20) OPERATION NOT NULL CHAR(1) STATUS NOT NULL VARCHAR2(30)
我需要为状态 = 'AVAILABLE' 的每个记录调用一个过程,然后在其他表上进行一些压缩/插入/删除,然后将状态标记为 “已处理” 或 “失败”。我正在使用以下脚本调用:
DECLARE ...... CURSOR c1 IS select distinct PRODUCT, OID from RPT_MSG_CHANGE WHERE STATUS='AVAILABLE' ORDER BY OID; BEGIN FOR v1 IN c1 LOOP BEGIN pkg_rpt_asr_orders.proc_process_oid(v1.OID, l_data_ord_tbl); --- calling procedure .......... .......... .......... ----Rest Code here END; END LOOP; COMMIT; END;
现在,我在plsql块上方运行,该块执行大约20 k条具有可用状态的记录的过程。在mid中 (假设处理5k记录后),如果我想停止执行,我只需将状态更新为 “processed” 的表。现在,我不确定为什么会话仍在运行,并且几乎需要处理每个记录所需的时间。
你能不能让我知道oracle在这种情况下的行为,它是简单地打开一个缓冲区-> 复制其中的所有记录-> 处理缓冲区中的所有记录 (不管主表记录更新) 还是在后台有一些其他的动作?
谢谢
阿米特
专家解答
所以在第二个会话中,你运行:
希望您的流程将没有更多的行要处理,因此停止?
不会那样做的...
记住:
光标的结果在您打开时是固定的。其他事务保存的任何更改对它来说都是不可见的!
当所有行的y = 1时,下面的示例打开游标。然后,它使用单独的事务将所有y值设置为零。
完成此操作后,它将显示光标的内容。但是结果与时间一致before然后更新。所以你看到了所有的表的行!
只有在关闭并重新打开光标后,您才能看到更新的效果:
所以你的代码仍然在处理所有20k个可用行。如果你想阻止它,你需要要么:
-杀了它
-更改代码以具有 “停止处理” 标志,您可以在循环期间从另一个表中查找值。
更改代码是更好的选择;) 在执行此操作时,请切换到批量处理。这应该有助于它运行得更快:
http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28plsql-095155.html
update RPT_MSG_CHANGE set status = 'PROCESSED' where status = 'AVAILABLE'; commit;
希望您的流程将没有更多的行要处理,因此停止?
不会那样做的...
记住:
光标的结果在您打开时是固定的。其他事务保存的任何更改对它来说都是不可见的!
当所有行的y = 1时,下面的示例打开游标。然后,它使用单独的事务将所有y值设置为零。
完成此操作后,它将显示光标的内容。但是结果与时间一致before然后更新。所以你看到了所有的表的行!
只有在关闭并重新打开光标后,您才能看到更新的效果:
create table t ( x int, y int ); insert into t select level, 1 from dual connect by level <= 5; commit; declare type cur_tp is ref cursor return t%rowtype; cur cur_tp; rw t%rowtype; procedure upd_t as pragma autonomous_transaction; begin update t set y = 0; commit; end upd_t; procedure display_rows ( c sys_refcursor ) as rw cur%rowtype; begin loop fetch c into rw; exit when c%notfound; dbms_output.put_line ( rw.x ); end loop; end display_rows; begin open cur for select * from t where y = 1; upd_t; dbms_output.put_line ( '*** 1st try ***' ); display_rows ( cur ); close cur; open cur for select * from t where y = 1; dbms_output.put_line ( '*** 2nd try ***' ); display_rows ( cur ); close cur; end; / *** 1st try *** 1 2 3 4 5 *** 2nd try ***
所以你的代码仍然在处理所有20k个可用行。如果你想阻止它,你需要要么:
-杀了它
-更改代码以具有 “停止处理” 标志,您可以在循环期间从另一个表中查找值。
更改代码是更好的选择;) 在执行此操作时,请切换到批量处理。这应该有助于它运行得更快:
http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28plsql-095155.html
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。