Oracle - Alguma maneira de visualizar alterações não confirmadas em uma tabela específica?

24

No momento, estou depurando um processo em lote que executa muitas instruções DML, mas não faz uma confirmação imediatamente. Seria bom poder visualizar as alterações "pendentes" de outra sessão enquanto a transação não foi confirmada. Isso é possível?

Exemplo:

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

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

...other DML statements....

commit;
contactmatt
fonte
Há mais de uma maneira de fazer isso. Por exemplo, as instruções SQL aqui podem resolver: ducquoc.wordpress.com/2012/07/14/oracle-uncommited-changes good luck,

Respostas:

18

Existem algumas abordagens diferentes, dependendo dos detalhes do seu processo em lote e por que você está tentando visualizar as alterações não confirmadas.

1) O Oracle Workspace Manager é uma ferramenta que foi originalmente projetada para permitir que as pessoas que desenvolvem aplicativos espaciais tenham o equivalente a transações de execução extremamente demorada (ou seja, transações que podem exigir vários dias ou semanas de uso humano) para descobrir onde executar um pipeline em uma transação ) Seu processo em lote pode criar um novo espaço de trabalho (que é logicamente como criar uma nova transação), fazer as alterações desejadas nesse espaço de trabalho e confirmar quando quiser. Em uma sessão separada, você não veria nenhuma alteração confirmada até entrar na área de trabalho do processo em lote. Quando o processo em lote é concluído, ele pode mesclar sua área de trabalho de volta à área de trabalho ativa, o que equivale a confirmar uma transação.

2) O pacote DBMS_XA pode ser usado para permitir que você "entregue" uma transação de uma sessão para outra e para permitir que uma sessão se conecte a uma transação iniciada por outra sessão. Este é um pacote bastante obscuro para ser usado, mas houve um bom exemplo de uso no PL / SQL Challenge (você pode precisar de uma conta gratuita para acessá-lo) recentemente.

3) Se você está apenas tentando ver o status do processo em lote, em vez de ver os dados reais, o processo em lote pode gravar informações de log usando transações autônomas que você poderá consultar em outra sessão. Ou você pode usar o pacote DBMS_APPLICATION_INFO para que seu aplicativo atualize vários atributos em V $ SESSION e / ou V $ SESSION_LONGOPS para poder monitorar o status do carregamento de outra sessão.

Justin Cave
fonte
10

edit: isto foi escrito antes que a pergunta fosse esclarecida

Você pode usar consultas de flashback para ver a tabela sem seus próprios dados não confirmados.

Considerar:

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

Para ver a diferença entre a tabela com minha transação e a tabela como vista por outras pessoas, eu poderia emitir:

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

        ID
----------
         6
Vincent Malgrat
fonte
2
@jack: não está claro se o OP quer ver dados não comunicados fora de sua sessão (o pseudo-script pode estar em uma única sessão). Minha resposta funcionaria apenas para ver as próprias modificações pendentes em uma tabela.
Vincent Malgrat
Você está certo, desculpe. Ótima resposta.
Jack Douglas
8

Sim - o LogMiner pode fazer isso. De fato, se você deseja apenas transações confirmadas, precisa filtrar especificamente a saída! E há TABLE_NAMEem V$LOGMINER_CONTENTS, é assim que você iria olhar para uma única tabela.

Gaius
fonte
5

Não há método direto; você precisará analisar os logs (conforme mencionado em outra resposta) ou usar métodos alternativos para ver o que está acontecendo em um processo de longa execução.

Pessoalmente, sugiro o uso de transações autônomas para ativar esse recurso - não na transação em si, mas como um mecanismo de registro, permitindo que você saiba o que está acontecendo. Por exemplo, você poderia ter chamado PROCEDURE LONG_ACTION PROCEDURE WRITE_LOG_ENTRY (definido como uma transação autônoma) que gravaria um VARCHAR2 em outra tabela. As transações autônomas NÃO interferem com sua transação atual (de uma perspectiva LÓGICA; cuidado com os possíveis impactos no desempenho) e, assim, você pode ver o que está acontecendo através de suas entradas de log, independentemente de um COMMIT ou ROLLBACK em sua transação atual. Dito isto, você pode fazer isso com uma declaração DML massiva; você teria que usar um loop.

Considerar:

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;

Dado o exposto, você receberá uma entrada de log para cada 500 linhas processadas, independentemente do sucesso da ação longa. Se você precisar de uma duplicata exata dos dados para ver como está funcionando, sugiro criar uma tabela duplicada e chamar um procedimento que duplicará os dados (o procedimento é uma transação autônoma). Em seguida, adicione os dados após o fato. (Não há necessidade de duplicação.)

Além disso, se isso for para fins de depuração, sugiro remover ou reduzir drasticamente a necessidade desse registro quando as coisas tiverem sido testadas. E, como sempre, teste, teste, teste em seu próprio sistema para verificar como as coisas vão funcionar. (Veja o comentário de Niall para um bom exemplo de como o log pode afetar drasticamente o desempenho.)

(Finalmente, porque eu esqueci de mencioná-lo antes: cuidado com as transações autônomas. Compreenda-as completamente antes da implementação e não as use "apenas porque". Elas podem ser usadas de milhões de maneiras incorretamente (por exemplo, para tentar evitar um erro de modificação em um gatilho), por isso é sempre melhor encontrar alternativas, se possível.Se não puder, continue com cuidado.O registro durante operações de longa duração sempre foi um caso em que é razoavelmente seguro (ignorando problemas de desempenho), mas não se apresse em aplicá-lo a outros usos sem conhecer as consequências.)

Kerri Shotts
fonte
11
As advertências no final desta sugestão são exploradas ainda mais em minha longa resposta (com código) em orawin.info/blog/2011/09/06/advice-from-the-internet . Em suma, a adoção dessa abordagem pode afetar seriamente e adversamente o código que já é lento.
Niall Litchfield
11
@ Niall Litchfield, Como sempre, ao receber conselhos da Internet, é preciso sempre testar, testar, testar. Quando mencionado que a transação autônoma não afeta a transação, eu estava me referindo ao fato de que nem COMMITs nem ROLLsBACK sua transação atual; portanto, no sentido LÓGICO, isso não faz nada na sua transação atual. Sim, é claro, a Oracle faz as coisas nos bastidores para fazer as coisas funcionarem, o que pode significar problemas de desempenho. Do ponto de vista apenas da transação, a transação autônoma não atrapalha o estado da minha transação atual.
11898 Kerri Shotts
@Niall Litchfield, tudo o que foi dito, transações autônomas têm seu próprio quinhão de problemas (um dos quais acontece é que as pessoas tentam usá-los para contornar uma tabela mutante), então eu as recomendo com moderação e cautela, e SOMENTE com a compreensão do que está acontecendo.
11898 Kerri Shotts
3

Não disponível em 10g, mas o DBMS_XA pode permitir que uma transação cruze várias sessões. Usando isso, a segunda sessão pode ver o que está acontecendo na transação

Gary
fonte
3

Além das outras informações aqui, algumas maneiras adicionais de enviar informações sobre uma transação não confirmada seriam enviar um email ou gravar em um arquivo de texto.

Leigh Riffel
fonte