sql >> Base de Datos >  >> RDS >> Oracle

¿Cómo puedo desbloquear automáticamente tablas en Oracle después de un tiempo determinado?

En primer lugar, bloquear una tabla no evitará que otra sesión emita SELECT declaraciones contra los datos.

En la Sesión 1, si bloqueo la mesa

SQL> lock table foo in exclusive mode;

Table(s) Locked.

Luego puedo iniciar la Sesión 2 y consultar los datos todo lo que quiera

SQL> select * from foo;

      COL1
----------
         1
         1

En Oracle, los escritores no bloquean a los lectores, por lo que nunca puede evitar que otra sesión consulte los datos de una tabla.

Parece que lo que está tratando de implementar es un bloqueo pesimista. En ese caso, en lugar de bloquear la tabla, haga un SELECT FOR UPDATE que bloquea la entrada particular que pretende procesar. Siempre que todas las demás sesiones también intenten hacer SELECT FOR UPDATE (según la versión de Oracle, es posible que se agregue SKIP LOCKED calificador y/o WAIT Calificatorio). Eso bloquea la fila específica que está procesando y permite que la segunda sesión seleccione una fila diferente o agote el tiempo de espera o descubra que no hay filas para procesar según los detalles de la implementación. Eso no implica cerrar la mesa.

La única forma de liberar un bloqueo es que la sesión que lo adquirió lo libere (generalmente finalizando la transacción) o que la sesión que lo adquirió finalice. Si la aplicación cliente aún se está ejecutando pero no hace nada para liberar el bloqueo o finalizar la sesión, el bloqueo se mantendrá indefinidamente. Un DBA necesitaría eliminar explícitamente la sesión, permitir que la transacción retroceda y liberar el bloqueo para que el sistema vuelva a moverse. Si la aplicación cliente deja de ejecutarse o, al menos, deja de responder (todavía no tengo claro exactamente qué escenario de falla está discutiendo), es posible que habilite la detección de conexión inactiva (DCD) a través de Parámetro 'SQLNET.EXPIRE_TIME' en el nivel de la base de datos, la base de datos determinaría que el cliente no responde y eliminaría automáticamente la sesión, revirtiendo la transacción y liberando el bloqueo.

Sin embargo, si hay múltiples sesiones procesando datos, generalmente es mucho más preferible usar alguna forma de bloqueo optimista. De lo contrario, está diseñando un sistema que inevitablemente necesitará que el DBA encuentre y elimine sesiones con urgencia para que los usuarios comerciales vuelvan a trabajar y eso requerirá más y más intervención cuanto más ocupado esté. Eso no es algo que a los DBA les guste hacer y no es algo de lo que los usuarios comerciales disfruten quejándose. Un esquema de bloqueo optimista simple sería algo así como

  • Seleccione una clave para procesar y algún tipo de fecha que indique la última vez que se actualizó la fila.
  • Actualice una columna de estado a "procesando" para que otras sesiones no intenten procesar esa misma fila.
  • Procesar la entrada en su solicitud
  • Cuando haya terminado de procesar, actualice los datos con la clave y la hora que seleccionó en el primer paso. Si actualiza 1 fila, sabe que ninguna otra sesión ha modificado los datos en cuestión desde que la seleccionó. Si actualiza 0 filas, sabe que alguna otra sesión ha modificado los datos desde que la seleccionó.

Con este tipo de arquitectura, es relativamente fácil consultar la base de datos para ver qué filas se están procesando y, por ejemplo, tener un trabajo que vuelva a establecer la columna de estado en "sin procesar" después de un período de tiempo si el cliente no lo ha hecho. acabado. Es relativamente fácil para otras sesiones elegir una fila diferente para procesar. Y es relativamente seguro si, por ejemplo, la aplicación se congela durante un par de horas y luego se recupera, ya que, una vez que termina de procesar, descubre que otra sesión ya volvió a procesar la fila.