Oracle: ¿alguna forma de ver los cambios no confirmados en una tabla en particular?

24

Actualmente estoy depurando a través de un proceso por lotes que hace muchas declaraciones DML, pero no hace una confirmación de inmediato. Sería bueno poder ver los cambios "pendientes" de otra sesión mientras no se confirma la transacción. es posible?

Ejemplo:

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

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

...other DML statements....

commit;
contactmatt
fuente
Hay más de una forma de hacerlo. Por ejemplo, las declaraciones SQL aquí pueden resolver: ducquoc.wordpress.com/2012/07/14/oracle-uncommited-changes buena suerte,

Respuestas:

18

Existen algunos enfoques diferentes según los detalles de su proceso por lotes y por qué está tratando de ver los cambios no confirmados.

1) Oracle Workspace Manager es una herramienta que fue diseñada originalmente para permitir que las personas que desarrollan aplicaciones espaciales tengan el equivalente de transacciones de muy larga duración (es decir, transacciones que pueden requerir varios días o semanas para que los humanos descubran dónde ejecutar una tubería en una transacción ) Su proceso por lotes podría crear un nuevo espacio de trabajo (que es lógicamente como crear una nueva transacción), realizar los cambios que desee en ese espacio de trabajo mientras se compromete cuando lo desee. En una sesión separada, no vería ninguno de los cambios confirmados hasta que ingrese al espacio de trabajo del proceso por lotes. Cuando finaliza el proceso por lotes, podría fusionar su espacio de trabajo nuevamente en el espacio de trabajo en vivo, que es el equivalente de confirmar una transacción.

2) El paquete DBMS_XA se puede utilizar para permitirle " transferir " una transacción de una sesión a otra y permitir que una sesión se conecte a una transacción iniciada por otra sesión. Este es un paquete bastante oscuro para usar, pero recientemente hubo un buen ejemplo de su uso en el Desafío PL / SQL (es posible que necesite una cuenta gratuita para acceder a él).

3) Si solo está tratando de ver el estado del proceso por lotes en lugar de ver los datos reales, el proceso por lotes puede escribir información de registro utilizando transacciones autónomas que luego puede consultar desde otra sesión. O puede usar el paquete DBMS_APPLICATION_INFO para que su aplicación actualice varios atributos en V $ SESSION y / o V $ SESSION_LONGOPS para que pueda monitorear el estado de la carga desde otra sesión.

Justin Cave
fuente
10

editar: esto fue escrito antes de aclarar la pregunta

Se podría utilizar consultas de flashback para ver la tabla sin su propia datos no 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 la diferencia entre la tabla con mi transacción y la tabla vista por otros, podría emitir:

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

        ID
----------
         6
Vincent Malgrat
fuente
2
@jack: no está claro si el OP quiere ver datos no confirmados fuera de su sesión (el pseudo script podría estar en una sola sesión). Mi respuesta solo funcionaría para ver las modificaciones pendientes de una tabla.
Vincent Malgrat
Tienes razón, lo siento. Gran respuesta.
Jack Douglas
8

Sí, LogMiner puede hacer esto. De hecho, si solo desea transacciones comprometidas, ¡debe filtrar específicamente la salida! Y hay TABLE_NAMEen V$LOGMINER_CONTENTS, eso es cómo se vería en una sola mesa.

Gayo
fuente
5

No hay método directo; tendrá que analizar los registros (como se menciona en otra respuesta) o usar métodos alternativos para ver qué sucede en un proceso de larga duración.

Personalmente, sugiero usar transacciones autónomas para habilitar esta función, no en la transacción en sí, sino como un mecanismo de registro que le permite saber lo que está sucediendo. Por ejemplo, podría hacer que PROCEDURE LONG_ACTION llame a PROCEDURE WRITE_LOG_ENTRY (definido como una transacción autónoma) que escribiría un VARCHAR2 en otra tabla. Las transacciones autónomas NO interfieren con su transacción actual (desde una perspectiva LÓGICA; tenga cuidado con los posibles impactos en el rendimiento) y así puede ver lo que sucede a través de sus entradas de registro independientemente de un COMPROMISO o ROLLBACK en su transacción actual. Dicho esto, puedes hacerlo con una declaración DML masiva; tendrías que usar un bucle.

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 lo anterior, obtendrá una entrada de registro por cada 500 filas procesadas independientemente del éxito de la acción larga. Si necesita un duplicado exacto de los datos para ver cómo funciona, sugiero hacer una tabla duplicada y llamar a un procedimiento que duplicará los datos (el procedimiento es una transacción autónoma). Luego bombardea los datos después del hecho. (No es necesario duplicarlo).

Además, si esto es para un propósito de depuración, sugiero eliminar o reducir drásticamente la necesidad de tal registro cuando las cosas han sido probadas. Y, como siempre, pruebe, pruebe, pruebe en su propio sistema para verificar cómo funcionarán las cosas. (Vea el comentario de Niall para un buen ejemplo de cómo el registro puede afectar drásticamente el rendimiento).

(Finalmente, porque me olvidé de mencionarlo antes: tenga cuidado con las transacciones autónomas. Comprendalas completamente antes de implementarlas, y no las use "solo porque". Se pueden usar de un millón de formas incorrectas (por ejemplo, INTENTAR evitar un error de mutación en un disparador), por lo que siempre es mejor encontrar alternativas, si es posible. Si no puede, proceda con precaución. El registro durante operaciones de larga duración siempre ha sido un caso en el que es bastante seguro (ignorar problemas de rendimiento), pero no se apresure a aplicarlo a otros usos sin conocer las consecuencias).

Kerri Shotts
fuente
1
Las advertencias al final de esta sugerencia se exploran más a fondo en mi larga respuesta (con código) en orawin.info/blog/2011/09/06/advice-from-the-internet . En resumen, la adopción de este enfoque puede afectar seria y negativamente el código que ya es lento.
Niall Litchfield
1
@Niall Litchfield, como siempre, al recibir consejos de Internet, uno siempre debe probar, probar, probar. Cuando mencioné que la transacción autónoma no afecta la transacción, me refería al hecho de que ni se COMPROMETE ni ROLLsBACK su transacción actual; por lo tanto, en un sentido LÓGICO, no hace nada a su transacción actual. Sí, por supuesto, Oracle ha hecho cosas detrás de escena para que las cosas funcionen, lo que puede significar problemas de rendimiento, desde el punto de vista de solo transacciones, la transacción autónoma no se interpone en el estado de mi transacción actual.
Kerri Shotts
@Niall Litchfield, todo lo dicho, las transacciones autónomas tienen sus propios problemas (uno de los cuales es que la gente trata de usarlos para moverse alrededor de una mesa de mutaciones), por lo que los recomiendo con moderación y precaución, y SOLO con entender lo que está pasando.
Kerri Shotts
3

No está disponible en 10 g, pero DBMS_XA puede permitir que una transacción cruce varias sesiones. Usando eso, la segunda sesión puede ver qué sucede en la transacción

Gary
fuente
3

Además de la otra información aquí, algunas formas adicionales de enviar información sobre una transacción no confirmada serían enviar un correo electrónico o escribir en un archivo de texto.

Leigh Riffel
fuente