I have a scenario like this (semi-pseudocode)
con.setAutoCommit(false);
try {
SELECT cash FROM bank_1 WHERE user = 1;
long money = rs.getLong("cash")
... if money >= the amount we want then...
UPDATE bank_1 SET cash=cash-money WHERE user = 1;
UPDATE bank_2 SET cash=cash money WHERE user = 2;
con.commit();
} catch(Exception e1) {
con.rollBack();
} finally {
con.setAutoCommit(true);
try { con.close(); } catch(Exception e) { }
}
then I have to do the opposite in another program concurrently to transfer from the second bank to the first one, so how do I avoid deadlock in this situation?
CodePudding user response:
Add FOR UPDATE
on the end of any SELECTs
in the transaction.
SELECT cash FROM bank_1 WHERE user = 1 FOR UPDATE;
This locks the row(s) mentioned there so that other connections will not mess with the row before this transaction is finished.
(There are cases where FOR UPDATE
is not needed, but that's a longer discussion.)
CodePudding user response:
Consider a pattern like:
BEGIN
UPDATE bank_1 SET cash=cash - $money WHERE user = 1 AND cash >= $money
if rows affected > 0
UPDATE bank_2 SET cash=cash $money WHERE user = 2
COMMIT
else
ROLLBACK
Also having each bank in its own table make it harder to write queries. Consider a single table with a bank_id
.