2010-02-02 22 views
10

Tenemos una base de datos Oracle, y la tabla de la cuenta del cliente tiene aproximadamente un millón de filas. A lo largo de los años, hemos construido cuatro IU diferentes (dos en Oracle Forms, dos en .Net), todas las cuales permanecen en uso. Tenemos una serie de tareas en segundo plano (tanto persistentes como programadas) también.Cómo encontrar filas bloqueadas en Oracle

Algo ocasionalmente mantiene un bloqueo prolongado (por ejemplo, más de 30 segundos) en una fila en la tabla de cuentas, lo que hace que falle una de las tareas de fondo persistentes. La tarea en segundo plano en cuestión se reinicia una vez que la actualización expira. Nos enteramos unos minutos después de que sucede, pero para entonces la cerradura ya salió.

Tenemos motivos para creer que podría ser una IU que funciona mal, pero no hemos podido encontrar una "pistola humeante".

He encontrado algunas consultas que enumeran bloques, pero eso es para cuando tienes dos trabajos compitiendo por una fila. Quiero saber qué filas tienen bloqueos cuando no necesariamente hay un segundo trabajo tratando de obtener un bloqueo.

Estamos en 11g, pero hemos tenido el problema desde 8i.

Respuesta

10

Oracle 's concepto de bloqueo es bastante diferente de la de los otros sistemas.

Cuando se bloquea una fila en Oracle, el registro se actualiza con el nuevo valor (si existe) y, además, se coloca un bloqueo (que es esencialmente un puntero al bloqueo de transacción que reside en el segmento de retrotracción) justo en el registro.

Esto significa que bloquear un registro en Oracle significa actualizar los metadatos del registro y emitir una escritura de página lógica. Por ejemplo, no puede hacer SELECT FOR UPDATE en un espacio de tabla de solo lectura.

Más que eso, los registros en sí mismos no se actualizan después de la confirmación: en su lugar, se actualiza el segmento de retrotracción.

Esto significa que cada registro contiene información sobre la transacción que la actualizó por última vez, incluso si la transacción en sí misma ha muerto hace mucho tiempo. Para saber si la transacción está activa o no (y, por lo tanto, si el registro está vivo o no), se requiere visitar el segmento de reversión.

Oracle no tiene un administrador de bloqueos tradicional, y esto significa que la obtención de una lista de todos los bloqueos requiere el escaneo de todos los registros en todos los objetos. Esto tomaría demasiado tiempo.

Puede obtener algunos bloqueos especiales, como objetos de metadatos bloqueados (usando v$locked_object), espera de bloqueo (usando v$session) etc., pero no la lista de todos los bloqueos en todos los objetos en la base de datos.

+0

no puede utiliza V $ LOCK para obtener todas las cerraduras? Incluso si no puede determinar las filas específicas que se están bloqueando, al menos usted sabe qué tablas. –

4

En lugar de cerraduras, le sugiero que consulte transacciones de larga duración, utilizando v$transaction. Desde allí, puede unirse al v$session, lo que le dará una idea acerca de la interfaz de usuario (pruebe las columnas del programa y de la máquina) y del usuario.

4

Mire en dba_blockers, dba_waiters y dba_locks para bloquear. Los nombres deben ser auto explicativos.

Puede crear un trabajo que se ejecute, por ejemplo, una vez por minuto y registre los valores en dba_blockers y el sql_id activo actual para esa sesión. (a través de v $ session y v $ sqlstats).

Es posible que también desee buscar en v $ sql_monitor.Este será el registro predeterminado de todos los SQL que tome más de 5 segundos. También es visible en la página de supervisión de SQL en Enterprise Manager.

+0

'dba_blockers' y otras vistas que mencionó solo listarán los bloqueos que se esperan. @op especificó que quiere todos los bloqueos, no solo aquellos en los registros que se disputan. – Quassnoi

+0

Pero si no se bloquea nada, una sesión puede bloquearse durante el tiempo que quiera, ya que no afectará el rendimiento. Solo los bloqueos de bloqueo afectan el rendimiento. – PenFold

1

se pueden encontrar las tablas bloqueadas en Oralce mediante la consulta con el siguiente consulta

select 
    c.owner, 
    c.object_name, 
    c.object_type, 
    b.sid, 
    b.serial#, 
    b.status, 
    b.osuser, 
    b.machine 
from 
    v$locked_object a , 
    v$session b, 
    dba_objects c 
where 
    b.sid = a.session_id 
and 
    a.object_id = c.object_id; 
Cuestiones relacionadas