数据库为oracle 10G,问题也很简单1
表样例:
testtable
col1 col2
a 3
b 2
案例一:
session1:
执行update testtable set col2 = col2+1 where col2 =3;
不commit;
session2:
执行同一条语句update testtable set col2 = col2+1 where col2 = 3;
不commit;
此时将session1进行commit;则会更新一条记录,即col1=a的记录
再将session2进行commit;会发现session2更新记录为0行。
所以判断后提交的记录是等待先提交的执行完成后,才进行的更新操作。
but案例2,我将SQL稍改下
session1:
执行update testtable set col2 = col2+1 where rowid = (select rowid from testtable where col2 =3);
不commit;
session2:
执行同一条语句update testtable set col2 = col2+1 where rowid = (select rowid from testtable where col2 =3);
不commit;
此时将session1进行commit;则会更新一条记录,即col1=a的记录,col2被更新为4
再将session2进行commit;会发现session2更新记录为1行,查询后发现col1=a的记录,col2被更新为5。
这个我就无法更解了,这个SQL到底是有没有等前一个session执行。为何查询到col2为3的记录了,然后更新时将col2加1后变成5了??????????????
事故起因为自己的一个项目出现高并发时,发现两个session更新到了同一条记录,很不能理解啊。
难道真的是数据库出了BUG?
求助各位大神给个方案。
------解决思路----------------------
1. 你的第二个案例中,使用的是 rowid ,你的字段的内容再怎么更新, rowid 也不变动。
2. 你在会话2 中,使用的是标量子查询,因为在会话1中,你没有提交,所以这个标量子查询取到的还是原来的值,这个值被存储到了 undo 表空间,你可以百度一下 undo 表空间的作用。
------解决思路----------------------
session1:
执行update testtable set col2 = col2+1 where rowid = (select rowid from testtable where col2 =3);
不commit;
session2:
执行同一条语句update testtable set col2 = col2+1 where rowid = (select rowid from testtable where col2 =3);
不commit;
Oracle有一个特性,就是在一事务在更新一个值时,会反这个值备份到其它地方,在session2中,虽然但一句并未提交,但实际上 (select rowid from testtable where col2 =3)这句能仍然能找到修改前的值,也就能得到rowid,至于update则会等待,等到第一句提交再更新。