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

¿Cómo utilizar correctamente las transacciones y los bloqueos para garantizar la integridad de la base de datos?

Hasta ahora, todo bien, esto al menos evitará que el usuario realice el pago en varias sesiones (varias veces tratando de pagar la misma tarjeta; es bueno lidiar con los dobles clics).

¿Cómo lo compruebas? Con un SELECT estándar o con SELECT ... FOR UPDATE ? Según el paso 5, supongo que está revisando una columna reservada en el elemento o algo similar.

El problema aquí es que el SELECT ... FOR UPDATE en el paso 2 NO se va a aplicar el FOR UPDATE bloqueo a todo lo demás. Solo se aplica a lo que es SELECT ed:el cart-item mesa. Según el nombre, ese será un registro diferente para cada carrito/usuario. Esto significa que NO se bloqueará el proceso de otras transacciones.

Siguiendo lo anterior, según la información que ha proporcionado, puede terminar con varias personas comprando el mismo artículo, si no está usando SELECT ... FOR UPDATE en el paso 3.

Solución sugerida

  1. Comenzar transacción
  2. SELECT ... FOR UPDATE el cart-item mesa.

Esto bloqueará la ejecución de un doble clic. Lo que seleccione aquí debe ser algún tipo de columna de "carrito ordenado". Si hace esto, una segunda transacción se detendrá aquí y esperará a que termine la primera, y luego leerá el resultado que guardó la primera en la base de datos.

Asegúrese de finalizar el proceso de pago aquí si el cart-item la tabla dice que ya se ha pedido.

  1. SELECT ... FOR UPDATE la tabla donde registras si un artículo ha sido reservado.

Esto impedirá que OTROS carritos/usuarios puedan leer esos elementos.

Según el resultado, si los artículos no están reservados, continúe:

  1. UPDATE ... la tabla en el paso 3, marcando el artículo como reservado. Haz cualquier otro INSERT s y UPDATE s que necesita, también.

  2. Hacer el pago. Emita una reversión si el servicio de pago dice que el pago no funcionó.

  3. Registre el pago, si tiene éxito.

  4. Confirmar transacción

Asegúrese de no hacer nada que pueda fallar entre los pasos 5 y 7 (como enviar correos electrónicos), de lo contrario, puede terminar haciendo un pago sin que se registre, en caso de que la transacción se revierta.

El paso 3 es el paso importante con respecto a asegurarse de que dos (o más) personas no intenten pedir el mismo artículo. Si dos personas lo intentan, la segunda persona terminará con su página web "colgada" mientras procesa la primera. Luego, cuando finalice el primero, el segundo leerá la columna "reservado" y podrá devolver un mensaje al usuario de que alguien ya compró ese artículo.

Pago en transacción o no

Esto es subjetivo. Por lo general, desea cerrar las transacciones lo más rápido posible, para evitar que varias personas no puedan interactuar con la base de datos a la vez.

Sin embargo, en este caso, realmente quieres que esperen. Es sólo una cuestión de cuánto tiempo.

Si elige confirmar la transacción antes del pago, deberá registrar su progreso en alguna tabla intermedia, ejecutar el pago y luego registrar el resultado. Tenga en cuenta que si el pago falla, deberá deshacer manualmente los registros de reserva de artículos que actualizó.

SELECCIONE... PARA ACTUALIZAR en filas inexistentes

Solo una palabra de advertencia, en caso de que el diseño de su tabla implique insertar filas donde necesita SELECT ... FOR UPDATE antes :Si una fila no existe, esa transacción NO hará que otras transacciones esperen, si también SELECT ... FOR UPDATE la misma fila inexistente.

Por lo tanto, asegúrese de serializar siempre sus solicitudes haciendo SELECT ... FOR UPDATE en una fila que sabes que existe primero. Luego puede SELECT ... FOR UPDATE en la fila que puede o no existir todavía. (No intente hacer solo SELECT en la fila que puede existir o no, ya que leerá el estado de la fila en el momento en que comenzó la transacción, no en el momento en que ejecuta SELECT . Entonces, SELECT ... FOR UPDATE en filas inexistentes todavía es algo que debe hacer para obtener la información más actualizada, solo tenga en cuenta que no hará que otras transacciones esperen).