2010-12-20 14 views
6

Si ejecuto una instrucción de selección simple en el desarrollador pl/sql en una tabla de base de datos, obtengo un conjunto de resultados estándar como era de esperar.¿Por qué obtengo una transacción abierta cuando solo selecciono desde una base de datos Vista?

Recientemente, pegué una consulta de un procedimiento almacenado que pasó a seleccionar de una vista, y noté que una transacción aparentemente se dejaba abierta. Esto fue evaluado por la reversión y las opciones de confirmación estuvieron disponibles en el desarrollador de PL/SQL.

Una encuesta de otros desarrolladores reveló que esto parece afectar a algunos pero no a otros, lo que me lleva a sospechar de la configuración del Desarrollador PL/SQL.

¿Por qué demonios sería este el caso? La vista tiene un DBLink a otra base de datos, pero no esperaría que esto tenga ningún efecto.

¿Alguna idea?

Respuesta

1

Cualquier instrucción SQL inicia una transacción en Oracle.

From the manual:

Una transacción comienza con la primera sentencia de SQL ejecutable. Una transacción finaliza cuando se confirma o revierte, ya sea explícitamente con una instrucción COMMIT o ROLLBACK o implícitamente cuando se emite una instrucción DDL. [...] Una sentencia SQL ejecutable es una instrucción SQL que genera llamadas a una instancia, incluyendo DML y DDL

más probable es que los que no lo esta viendo este se ejecutan en modo auto-commit, donde la transacción iniciada por una declaración se compromete inmediatamente después de que la declaración haya finalizado.

Otros han afirmado que un SELECT no es LMD, pero de nuevo the manual clearly states:

lenguaje de manipulación de datos (DML) de consulta o manipular los datos en objetos de esquema existentes. Que le permiten:

      * Recuperar o ir a buscar datos de una o más tablas o vistas (SELECCIONAR)
      * Añadir nuevas filas de datos en una tabla o vista (INSERT)
[. ..]
+0

Gracias. ¿Cómo se alterna el modo Auto-Commit? –

+0

No uso PL/SQL Developer, así que no sé –

+5

@a_horse_with_no_name: no todas las sentencias SQL inician una transacción. Ver la demostración en mi respuesta (actualizada). –

15

Al contrario de lo que esperaba, parece que el enlace de la base de datos es el origen de la transacción abierta. Me he dado cuenta de este comportamiento antes al ejecutar consultas SELECT en tablas remotas en PL/SQL Developer.

Para citar Tom Kyte (source):

material distribuido inicia una transacción "por si acaso".

EDIT: 'Cualquier instrucción SQL inicia una transacción en Oracle'? No, no es así, y aquí hay una demostración de ello.Esta demostración usa la vista del diccionario de datos V$TRANSACTION, que enumera las transacciones activas. Todo esto se está ejecutando en mi base de datos Oracle XE local, que no tiene más usuarios conectados que yo.

Usaremos la siguiente tabla durante esta demostración. Contiene una sola columna:

 
SQL> desc test; 
Name          Null? Type 
----------------------------------------- -------- ---------------------------- 
A             NUMBER(38) 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

No hay transacciones activas en este momento. Vamos a ejecutar una consulta SQL en esta tabla:

 
SQL> select * from test; 

     A 
---------- 
     2 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

Todavía no hay transacciones activas. Ahora hagamos algo que inicie una transacción:

 
SQL> insert into test values (1); 

1 row created. 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     1 

Como era de esperar, ahora tenemos una transacción activa.

 
SQL> commit; 

Commit complete. 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

Después de realizar la transacción, ya no está activo.

Ahora, creemos un enlace de base de datos. Estoy usando Oracle XE, y el siguiente, se crea un vínculo de base de datos de mi instancia de Oracle XE nuevo a sí mismo:

 
SQL> create database link loopback_xe connect to user identified by password using 'XE'; 

Database link created. 

Ahora vamos a ver lo que sucede cuando seleccionamos de la mesa sobre el enlace de base de datos:

 
SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

SQL> select * from [email protected]_xe; 

     A 
---------- 
     2 
     1 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     1 

Como puede ver, simplemente seleccionando desde una tabla remota se abre una transacción.

No estoy seguro de lo que hay que comprometer o revertir aquí, pero tengo que admitir que no conozco los pormenores de las transacciones distribuidas, dentro de las cuales probablemente resida la respuesta.

+0

del manual de conceptos de Oracle: "Una transacción comienza con la primera instrucción SQL ejecutable. la transacción finaliza cuando se confirma o se retrotrae ". http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/transact.htm#i1666 –

+0

Tienes razón, pero solo para tu información, debes tener cuidado con las consultas de v $ transaction, al menos en XE. Algunas transacciones no aparecen en esa vista. Por ejemplo, "actualizar una prueba de conjunto = 0 donde 1 = 2" no siempre crea filas en v $ transacción, pero se muestra en dbms_transaction.local_transaction_id(). –

+0

@Luke_Woodward Una consulta a través de un enlace de base de datos en Oracle abre una transacción para admitir confirmaciones de 2 fases. Puede consultar la tabla DBA_2PC_PENDING para ver las entradas en el db remoto. Al consultar sobre el enlace de db, no creo que el iniciador pueda saber cuáles son los efectos secundarios en el db remoto. Puede estar consultando desde una función y esa función puede tener efectos secundarios que modifiquen los datos. Mi experiencia (8i timeframe): una falla en el inicio de la base de datos después de la consulta, pero antes de una confirmación o reversión, dejaba la transacción abierta en la base de datos remota, bloqueaba la fila y fallaba en otros trabajos. Doloroso de encontrar – Glenn

1

No se puede abrir una transacción estrictamente con una consulta normal. Puede abrir uno en un enlace de base de datos. El tipo que publicó un enlace a los médicos ya sea de forma deliberada o completamente descuidada dejó fuera la segunda oración.

"Una transacción en la base de datos Oracle comienza cuando se encuentra la primera instrucción SQL ejecutable . Una sentencia de SQL ejecutable es un instrucción SQL que genera llamadas a una instancia, incluyendo DML y DDL declaraciones."

SELECT no es ni un DML ni un DDL. También es TRIVIAL probar realmente esto. No quiero parecer un troll aquí, pero es realmente molesto cuando la gente simplemente arroja respuestas en un foro para tratar de obtener puntos y las respuestas son basura completa.

Lea el resto del documento y PRUEBE PRIMERO.

  • de inicio de sesión a una sesión
  • ejecutar un selecto
  • ver si tiene una transacción abierta al unirse v$Session (para la sesión) para v$transaction.

Si vuelve un registro, tiene una transacción. Si no, no lo haces.

+2

"* SELECT no es ni DML ni DDL *". El manual debe diferir: http://docs.oracle.com/cd/B28359_01/server.111/b28318/sqlplsql.htm#autoId2 'SELECT' está claramente categorizado como una declaración DML allí. –

+0

Lo sentimos, @a_horse_with_no_name pero la documentación 11g establece explícitamente en [SET TRANSACTION] (http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10005.htm) que solo ejecuta un SELECT normal (sin PARA ACTUALIZAR) no inicia una transacción. Y como la gente se está manifestando, y acabo de aprender de la manera difícil hoy, eso parece ser el comportamiento real. –

1

Tenga en cuenta que, de acuerdo con el Oracle 11g Admin Guide, si hace un simple viejo SELECCIONAR a través de un enlace de base de datos, comenzará una transacción, que debe confirmarse (o retrotraerse).

Cuestiones relacionadas