update una try transaction transacción transacciones start qué example ejemplos ejemplo catch mysql transactions

una - transaction update mysql



Transacción MySQL con aplicación de contabilidad (2)

¿Estás usando tablas InnoDB o tablas MyISAM? MySQL no admite transacciones en tablas MyISAM (pero no le dará un error si intenta usarlas). Además, asegúrese de que su nivel de aislamiento de transacción esté configurado adecuadamente, debe ser SERIALIZABLE, que no es el predeterminado para MySQL.

Este artículo tiene un buen ejemplo que explica el impacto de los diferentes niveles de aislamiento usando un ejemplo muy similar al tuyo.

Tengo una mesa como la siguiente:

transaction_id user_id other_user_id trans_type amount

Esta tabla se usa para mantener las transacciones de cuenta para una aplicación de tipo financiero.

Su contabilidad de doble entrada por lo que una transferencia del usuario A a B insertaría dos filas en la tabla pareciendo.

1, A, B, Sent, -100 1, B, A, Received, 100

El saldo en cualquier cuenta se calcula sumando las transacciones para esa cuenta.

Por ejemplo:

select sum(amount) from transactions where user_id=A

¿Cuál es la mejor manera de bloquear la transferencia de fondos? Mi código actual se ve así:

Start Transaction Debit the sender''s account check the balance of the sender''s account if new balance is negative then the sender didn''t have enough money and rollback if the balance is positive then credit the receiver and commit

Esto parece no estar funcionando exactamente como se esperaba. Veo muchos ejemplos en línea sobre transacciones que dicen básicamente: inicio, remitente de débito, receptor de crédito, compromiso. Pero, ¿cuál es la mejor manera de verificar el saldo del emisor en el medio?

Tengo transacciones que pasan que no deberían. Digamos que un usuario tiene un saldo de 3K y dos transacciones ingresan exactamente al mismo tiempo para 3K, ambas están llegando cuando solo debería hacerlo.

Gracias


El problema es que el concepto de "cuenta de usuario" está "disperso" a través de muchas filas en su tabla. Con la representación actual, creo que no puede "bloquear la cuenta de usuario" (por así decirlo), por lo que está abierto a las condiciones de carrera cuando los modifique.

Una posible solución sería tener otra tabla con cuentas de usuario y bloquear una fila en esa tabla, de modo que cualquiera que necesite modificar la cuenta pueda intentar obtener el bloqueo, realizar la operación y liberar el bloqueo.

Por ejemplo:

begin transaction; update db.accounts set lock=1 where account_id=''Bob'' and lock=0; if (update is NOT successful) # lock wasn''t on zero { rollback; return; } if (Bob hasn''t enough funds) { rollback; return; } insert into db.transactions value (?, ''Bob'', ''Alice'', ''Sent'', -3000); insert into db.transactions value (?, ''Alice'', ''Bob'', ''Received'', 3000); update db.accounts set lock=0 where account_id=''Bob'' and lock=1; commit;

... o algo así.