Oracle-以任何方式查看对特定表的未提交的更改?


24

我目前正在通过批处理过程进行调试,该批处理过程执行许多DML语句,但不会立即进行提交。能够在未提交事务的情况下查看另一个会话中的“待处理”更改将是很好的。这可能吗?

例:

Insert into table myTable (col1, col2) values ("col1", "col2");

--Somehow view the pending transaction maybe by system view?....

...other DML statements....

commit;

有多种方法可以做到这一点。例如,此处的SQL语句可以解决:ducquoc.wordpress.com/2012/07/14/oracle-uncommited-changes祝您好运,

Answers:


18

有几种不同的方法,具体取决于批处理过程的详细信息以及尝试查看未提交的更改的原因。

1)Oracle Workspace Manager是一种工具,其最初旨在使开发Spatial应用程序的人们能够拥有非常长时间运行的事务(即,可能需要数天或数个人的事务才能确定在一个事务中在何处运行管道的事务) )。您的批处理过程可以创建一个新的工作空间(在逻辑上类似于创建新的事务),在需要时进行提交时,在该工作空间中进行所需的任何更改。在单独的会话中,您将不会看到任何已提交的更改,除非您进入批处理过程的工作空间。批处理过程完成后,它可以将其工作空间合并回实时工作空间,这等同于提交事务。

2)DBMS_XA包可用于允许您将事务从一个会话“切换”到另一个会话,并允许一个会话连接到另一个会话启动的事务。这是一个非常晦涩的软件包,但是最近有一个很好的示例在PL / SQL Challenge中使用它(您可能需要一个免费帐户才能访问它)。

3)如果您只是想查看批处理过程的状态而不是查看实际数据,则批处理过程可以使用自主事务写入日志记录信息,然后您可以从另一个会话中查询。或者,您可以使用DBMS_APPLICATION_INFO包使您的应用程序更新V $ SESSION和/或V $ SESSION_LONGOPS中的各种属性,以便可以监视来自另一个会话的负载状态。


10

编辑:这是在澄清问题之前写的

您可以使用闪回查询查看没有您自己的未提交数据的表。

考虑:

SQL> CREATE TABLE my_table
  2  AS SELECT ROWNUM ID FROM dual CONNECT BY LEVEL <= 5;

Table created

SQL> INSERT INTO my_table VALUES (6);

1 row inserted

要查看我的事务处理的表与其他人看到的表之间的区别,我可以发出:

SQL> SELECT * FROM my_table
  2  MINUS
  3  SELECT * FROM my_table AS OF TIMESTAMP (systimestamp);

        ID
----------
         6

2
@jack:尚不清楚OP是否希望在其会话之外查看未提交的数据(伪脚本可能在单个会话中)。我的答案只会在看到一个人自己对表的未决修改时起作用。
Vincent Malgrat

你说得对,对不起。好答案。
杰克·道格拉斯

8

是的-LogMiner可以做到这一点。实际上,如果只需要提交的事务,则必须专门过滤输出!还有就是TABLE_NAMEV$LOGMINER_CONTENTS,这就是你会怎么看待一个表。



5

没有直接的方法。您将不得不解析日志(如另一个答案中所述),或使用其他方法来查看长时间运行的过程中发生的情况。

就个人而言,我建议使用自主事务来启用此功能-不在事务本身上,而是作为一种日志记录机制,让您知道正在发生的事情。例如,您可能具有PROCEDURE LONG_ACTION调用PROCEDURE WRITE_LOG_ENTRY(定义为自主事务),该调用会将VARCHAR2写入另一个表。自主事务不会干扰您的当前事务(从逻辑的角度;要注意对性能的潜在影响),因此无论当前事务中的COMMIT还是ROLLBACK,您都可以通过日志记录条目查看正在发生的情况。就是说,您可以使用一个庞大的DML语句来做到这一点;您必须使用循环。

考虑:

TABLE LOG_ENTRIES defined as
    activity_date  date,
    log_entry varchar2(2000)

TABLE BIG_JOB (definition doesn't really matter)

PROCEDURE WRITE_LOG_ENTRY
                        ( str VARCHAR2 )
IS
    PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    INSERT INTO LOG_ENTRIES VALUES ( SYSDATE, str );
    COMMIT;
END;

PROCEDURE LONG_ACTION IS
    c NUMBER;
BEGIN
    FOR r IN ( SELECT * FROM BIG_JOB )
    LOOP
       c := c + 1;
       UPDATE BIG_JOB z
          SET fld = hairy_calculation
        WHERE z.rowid = r.rowid;
       IF MOD(c,500) = 0 THEN
           WRITE_LOG_ENTRY ( c || ' rows processed.' );
       END IF;
    END LOOP;
    COMMIT;
END;

鉴于以上所述,无论长操作是否成功,您将获得每处理500行的日志条目。如果您需要数据的精确重复才能正常工作,我建议制作一个重复表并调用一个将复制数据的过程(该过程是一个自主事务)。然后事后核对数据。(无需重复。)

此外,如果这是出于调试目的,我建议在测试完毕后删除或大幅减少此类日志记录的需求。而且,与往常一样,在您自己的系统上进行测试,测试和测试,以验证事物的工作方式。(有关日志如何严重影响性能的一个很好的示例,请参阅Niall的评论。)

(最后,因为我之前没有提到它:当心自主事务。在实施之前要充分理解它们,不要“仅仅因为”使用它们。它们有百万种用法不正确(例如,对于ATTEMPT,避免在触发器中发生变异错误),因此,如果可能的话,最好总是找到替代方法。如果不能,则请谨慎行事。长期运行ops期间的日志记录一直是相当安全的一种情况(忽略性能问题),但不要在不知道后果的情况下急于将其应用于其他用途。)


1
我在orawin.info/blog/2011/09/06/advice-from-the-internet上的长期答复(带有代码)中进一步探讨了该建议结尾处的警告。简而言之,采用这种方法可能会对已经很慢的代码产生严重和不利的影响。
尼尔·利奇菲尔德

1
@Niall Litchfield,和往常一样,当从互联网上获得建议时,应该始终进行测试,测试和测试。当提到自主事务不会影响事务时,我指的是它既不会提交也不会回滚您当前的事务。因此,从逻辑上讲,它对您当前的交易没有任何作用。是的,当然,Oracle具有幕后处理功能以使工作正常运行,这可能意味着性能问题,从仅事务的角度来看,自主事务不会妨碍我当前事务的状态。
Kerri Shotts

@Niall Litchfield,总而言之,自主交易有其自身的相当多的问题(其中之一恰好是人们试图使用它们来解决变异表的问题),因此,我建议您谨慎谨慎地使用它们,并且仅了解发生了什么。
Kerri Shotts

3

在10g中不可用,但是DBMS_XA可以允许事务跨多个会话。使用第二个会话可以查看事务中发生了什么


3

除了此处的其他信息外,发送有关未提交的交易的信息的其他一些方法是发送电子邮件或写入文本文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.