如有一个Balance字段,用来保存用户余额,程序中发现如果有2条语句同时更新这个字段的话,就会出现问题
update XXXX set Balance=Balance+'1000'
update XXXX set Balance=Balance+'500' ,当然这2条更新语句都是在程序的不同地方
如果Balance的最初值是1000,第一条语句得到Balance的值,正要更新但是还没有更新,马上就该第2条语句执行了,它首先得到的值也是1000,而不是第一条语句更新后的2000,这个时候第一条语句执行更新了Balance的值是2000,然后第2条语句再执行更新,Balance的值就变成了1500了,而不是想要的2500,想请教各位大侠一下,有办法解决这一的问题吗?在执行第一条语句的时候,第2条检查到字段Balance正在被更新,就会阻塞,等到第一条被更新完毕以后再执行,不知道这样行不行!!!请教各位了!!!!!!
update XXXX set Balance=Balance+'1000'
update XXXX set Balance=Balance+'500' ,当然这2条更新语句都是在程序的不同地方
如果Balance的最初值是1000,第一条语句得到Balance的值,正要更新但是还没有更新,马上就该第2条语句执行了,它首先得到的值也是1000,而不是第一条语句更新后的2000,这个时候第一条语句执行更新了Balance的值是2000,然后第2条语句再执行更新,Balance的值就变成了1500了,而不是想要的2500,想请教各位大侠一下,有办法解决这一的问题吗?在执行第一条语句的时候,第2条检查到字段Balance正在被更新,就会阻塞,等到第一条被更新完毕以后再执行,不知道这样行不行!!!请教各位了!!!!!!
我在这2个SQL语句前面都加了事物
conn.setAutoCommit(false);
update XXXX set Balance=Balance+'1000'
conn.setAutoCommit(true);
conn.commit();
conn.setAutoCommit(false);
update XXXX set Balance=Balance+'500'
conn.setAutoCommit(true);
conn.commit();
第2条语句执行的时候,正好第一条还没有被提交,所以得到的值才会是1500
pstmt.executeUpdate();
更新SQL语句的方法是绑定变量,executeUpdate执行
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE EMPLOYEE SET SALARY = SALARY + 1000 WHERE EMP_ID = 'XXX';
-- ... some other scripts
COMMIT;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
1.更新数据,等待提交
2.另个一session,更新数据,发现记录被锁,等待
3.commit第一个session,查询数据被更新
4.commit第二个session,查询数据是根据3.提交之后的数据再次更新
结果和楼主说的不一样,我的操作和楼主的操作过程不一样么?
不考虑效率的话
可以在update XXXX set Balance=Balance+'1000之前运行
select * from XXXX for update 打开锁则第二个语句
update XXXX set Balance=Balance+'500' 在第一个语句commit前运行就会报错
然后update XXXX set Balance=Balance+'1000,这时候如果执行update XXXX set Balance=Balance+'500'
的话,update XXXX set Balance=Balance+'500' 会出现等待现象。
等到update XXXX set Balance=Balance+'1000执行完成,执行commit之后,
update XXXX set Balance=Balance+'500'才会执行。
解决楼主问题
在执行第一条语句的时候,第2条检查到字段Balance正在被更新,就会阻塞,等到第一条被更新完毕以后再执行;使用Select…For Update语句的语法 FOR UPDATE [NOWAIT]子句。
该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。