javamysql事务死锁
java mysql transaction deadlock
我有这样一个场景(半伪代码)
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) { }
}
然后我必须同时在另一个程序中做相反的事情才能从第二家银行转账到第一家,所以
在这种情况下如何避免死锁?
考虑如下模式:
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
每个银行都有自己的 table 使得编写查询变得更加困难。考虑带有 bank_id
.
的单个 table
在交易中任何 SELECTs
的末尾添加 FOR UPDATE
。
SELECT cash FROM bank_1 WHERE user = 1 FOR UPDATE;
这会锁定那里提到的行,以便其他连接不会在此事务完成之前弄乱该行。
(有些情况下不需要 FOR UPDATE
,但那是一个较长的讨论。)
我有这样一个场景(半伪代码)
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) { }
}
然后我必须同时在另一个程序中做相反的事情才能从第二家银行转账到第一家,所以 在这种情况下如何避免死锁?
考虑如下模式:
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
每个银行都有自己的 table 使得编写查询变得更加困难。考虑带有 bank_id
.
在交易中任何 SELECTs
的末尾添加 FOR UPDATE
。
SELECT cash FROM bank_1 WHERE user = 1 FOR UPDATE;
这会锁定那里提到的行,以便其他连接不会在此事务完成之前弄乱该行。
(有些情况下不需要 FOR UPDATE
,但那是一个较长的讨论。)