sql >> Base de Datos >  >> RDS >> Mysql

¿Debe SELECCIONAR... PARA ACTUALIZAR siempre contener ORDEN POR?

Su ejemplo en su pregunta muestra que el orden de bloqueo depende del método de acceso. Esta ruta de acceso no la decide directamente la cláusula ORDER BY de la consulta, hay muchos factores que pueden influir en esta ruta de acceso. Por lo tanto, no puede evitar un interbloqueo simplemente agregando ORDER BY porque aún podría tener dos rutas de acceso distintas. De hecho, al ejecutar su caso de prueba con el orden y cambiando los parámetros de la sesión, pude hacer que dos sesiones se ejecutaran en un ORA-60 con la misma consulta.

Si las sesiones involucradas no tienen otro bloqueo pendiente, bloquear las filas en el mismo orden en todas las sesiones evitará interbloqueos, pero ¿cómo puede forzar este orden de manera confiable? Tenga en cuenta que esto solo evitaría este caso muy especial de interbloqueo de todos modos. Todavía podría tener interbloqueos con múltiples consultas en cada sesión o diferentes planes.

En la práctica, este caso es realmente especial y, de todos modos, no debería ocurrir con frecuencia:si le preocupan los interbloqueos, sigo pensando que existen métodos más sencillos para evitarlos.

La forma más sencilla de evitar un interbloqueo es usar FOR UPDATE NOWAIT o FOR UPDATE WAIT X (aunque WAIT X aún puede desencadenar un interbloqueo con valores de X superiores al mecanismo de detección de interbloqueo, actualmente creo que 3 segundos a partir de 11 g, gracias @APC para la corrección).

En otras palabras, ambas transacciones deberían preguntar:dame esas filas y bloquéalas, pero si otro usuario ya tiene un bloqueo, devolverá un error en lugar de esperar indefinidamente. Es la espera indefinida la que provoca los bloqueos.

En la práctica, diría que la mayoría de las aplicaciones con usuarios reales preferirían recibir un error inmediatamente que tener una transacción esperando indefinidamente a que finalice otra transacción. Yo consideraría FOR UPDATE sin NOWAIT solo para trabajos por lotes no críticos.