Pregunta

Un miembro del equipo ha tenido un problema con un sistema interno antiguo en el que un usuario que hace doble clic en un enlace de una página web puede hacer que se envíen dos solicitudes desde el navegador, lo que genera dos inserciones en la base de datos del mismo registro en condiciones de carrera; el último en ejecutarse falla con una violación de clave primaria. Se han propuesto y discutido varias soluciones y hacks:

  1. Use Javascript en la página web para mitigar el segundo clic deshabilitando el enlace en el primer clic. Esta es una forma rápida y fácil de reducir la aparición del problema, pero no eliminarlo por completo.

  2. Ajustar la ejecución de la solicitud en el lado del servidor en una transacción. Esto se ha considerado una operación demasiado costosa debido a la carga del servidor y los niveles de bloqueo en la tabla en cuestión.

  3. Capture la excepción de la clave principal generada por la inserción fallida, identifíquela como tal y cómela. Esto tiene las desventajas de (a) el bloqueo del proveedor, tener que conocer los matices de las excepciones específicas de la base de datos y (b) potencialmente no iniciar sesión / tratar con fallas legítimas de la base de datos.

  4. Una extensión de # 3 al intentar actualizar el registro si la inserción falla y verificar el resultado de la actualización para asegurar que devuelve 1 registro afectado.

¿Las otras opciones no se han considerado? ¿Hay ventajas y desventajas de las opciones presentadas que se pasaron por alto? ¿Cuál es el menor de todos los males?

¿Fue útil?

Solución

Debe implementar el patrón de token de sincronizador.

Cómo funciona es: se genera un valor (el token) en el servidor para cada solicitud. Este mismo token se debe incluir en el envío del formulario. Al recibir la solicitud, se comparan el token del servidor y el token del cliente y, si son iguales, puede continuar agregando su registro. El token del lado del servidor se regenera, por lo que las solicitudes posteriores que contengan el token anterior fallarán.

Hay una explicación más detallada sobre la mitad de la página esta página .

No estoy seguro de qué tecnología está utilizando, pero Struts proporciona soporte de nivel de marco para este patrón. Vea el ejemplo aquí

Otros consejos

Coloque un identificador único en la página en un campo oculto. Solo acepte una respuesta con un identificador único dado.

Parece que podría estar haciendo mal uso de una solicitud GET para modificar el estado del servidor (aunque este no es necesariamente el caso). Si bien puede que no sea apropiado para su situación, se debe indicar que debe considerar convertir el enlace en un formulario POST.

Parece que ya respondiste a tu propia pregunta allí; # 1 parece ser la única opción viable.

De lo contrario, realmente debe hacer los tres pasos: la integridad de los datos debe manejarse a nivel de la base de datos, pero las comprobaciones adicionales (como la transacción explícita) en el código para evitar viajes de ida y vuelta a la base de datos podrían ser buenos para el rendimiento.

REF Debe implementar el patrón de token de sincronizador.

Esto es para Javascript / HTML, no JAVA

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top