2009-01-21 10 views
14

Me gustaría poder eliminar la consulta de un usuario en Oracle 10.2.0.4 sin matar toda la sesión. Esto permitiría que la consulta finalice, pero no desconecte a ese usuario de su sesión, para que pueda continuar haciendo otras consultas. ¿Es esto posible? ¿O el martillo contundente de matar a la sesión es la única manera de terminar con la ejecución de una consulta?¿Es posible matar una sola consulta en el oráculo sin matar la sesión?

Respuesta

15

He encontrado un truco. No tengo idea de cuán seguro es jugar con esto, pero funciona. Hay un evento de Oracle, 10237, que se describe como "simular^C (para fines de prueba)".

Debe tener el SID y el NÚMERO DE SERIE de la sesión que desea interrumpir.

llamada SYS.DBMS_SYSTEM.SET_EV ( sid, serial # , 10237, 1 '') para activar el evento en la sesión de destino. Cualquier declaración que se esté ejecutando actualmente debe interrumpirse (recibiendo "ORA-01013: cancelación solicitada por el usuario de la operación actual"). Mientras el evento esté configurado, cualquier declaración adicional que la sesión intente ejecutar terminará inmediatamente con el mismo error.

Para desactivar el evento, realice la misma llamada con el cuarto parámetro establecido en "0". La sesión podrá entonces ejecutar declaraciones nuevamente.

Tenga en cuenta que la sesión de destino debe detectar que el evento está configurado, lo que puede llevar tiempo o puede que nunca suceda, dependiendo de lo que esté haciendo. Por lo tanto, no puede activar y desactivar el evento rápidamente. Debería activarlo, verificar que la afirmación en cuestión se haya detenido y luego desactivarla.

Aquí hay un código de muestra. Esto se debe ejecutar como un bloque anónimo en SQLPlus, con las variables de sustitución "sid" y "serial" definidas de forma adecuada. Podría convertirlo en un procedimiento almacenado con esos como sus parámetros.

DECLARE 
    l_status v$session.status%TYPE; 
BEGIN 

    dbms_system.set_ev(&sid, &serial, 10237, 1, ''); 

    LOOP 
    SELECT status INTO l_status FROM v$session 
     WHERE sid = &sid and serial# = &serial; 
    EXIT WHEN l_status='INACTIVE'; 
    END LOOP; 

    dbms_system.set_ev(&sid, &serial, 10237, 0, ''); 
END; 
+1

Agradable. Sin embargo, tal vez una condición de salida más robusta de ese bucle - por ejemplo, si el estado de la sesión se convierte en "KILLED" o "SNIPED", y tal vez un tiempo de espera automático también. –

+0

¿No saldrías cuando el estado no es ACTIVO en lugar de @Jeffrey? – Ben

+0

@Ben, si quieres, seis y media docenas realmente –

1

Se podría buscar en los límites de recursos:

"Si un usuario supera un límite de recursos de nivel de llamada, a continuación, Oracle detiene el proceso de la sentencia, deshace la declaración, y devuelve un error Sin embargo, todos los anteriores. las declaraciones de la transacción actual permanecen intactas, y la sesión del usuario permanece conectada ".

Suponiendo que la razón para cancelar el SQL es un límite de recursos, en lugar de actualizar el conjunto incorrecto de filas (por ejemplo). Sospecho que no podría afectar el SQL actualmente en ejecución agregando un límite de recursos.

http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/security.htm#i13767 
http://download.oracle.com/docs/cd/B19306_01/server.102/b14231/dbrm.htm#i1010776 
2

Sospecho que es posible ya que puede hacerlo en TOAD. Mientras se ejecuta una consulta, aparece un cuadro de diálogo Cancelar que puede pulsar para detener la consulta.

Cómo se implementa No lo sé, pero estaría muy interesado en saberlo también.

Si está utilizando java, existe el método java.sql.Statement cancel() que se supone que debe hacer esto. Vea aquí algunas notas y limitaciones ...

http://download.oracle.com/docs/cd/B14117_01/java.101/b10979/tips.htm#BACDAICJ

+1

SAPO hace esto mediante la ejecución de la consulta en un segundo período de sesiones; si el operador cancela la consulta, TOAD elimina la segunda sesión. –

1

Lo ideal sería que la aplicación del usuario debe tener la capacidad de cancelar una consulta (a través de OCICancel o equivalente).

De lo contrario, lo mejor sería utilizar Resource Manager (si en Oracle EE), puede utilizar DBMS_RESOURCE_MANAGER.SWITCH_CONSUMER_GROUP_FOR_SESS para establecer la sesión de destino para el grupo de consumidores CANCEL_SQL.

Otro truco para cancelar otras sesiones de consulta, que no funciona con las sesiones de cliente de Windows sqlplus embargo, sería enviar la señal de urgencia al proceso de Oracle mediante -URG kill (que es un corte, no para el uso diario)

he escrito sobre por qué funciona aquí:

http://blog.tanelpoder.com/2010/02/17/how-to-cancel-a-query-running-in-another-session/