论坛首页 Java企业应用论坛

遇到一个多事务并发的问题

浏览 12474 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-11-11  
今天遇到一个多用户并发的问题,顺便对for update做下测试。以下是在oracle10下的测试结果:

1.在查询某一条记录的sql上,加上for update。
例如:select * from sometable where id = 1 for update;

1.1 允许对该记录做普通查询;不允许对该记录做for update查询,允许对其他记录做for update查询。
1.2 允许对其他记录做普通sql的update;不允许update锁定的该条记录。
1.3 允许insert操作。
1.4 允许delete操作,不允许对锁定记录做delete操作。


2.在查询表的所有记录的sql上,加上for update。
例如:select * from sometable for update;

2.1 允许普通search查询,不允许做for update查询。
2.2 不允许对表中任何记录做update操作;
2.3 允许insert操作;
2.4 不允许delete操作。

另外,update和insert语句加上for update报语法错误。


扩展开来:
由1.1可以设想如下一个场景:

现在有两个事务,操作同一条记录Ar,执行过程如下:
事务1:执行for update查询,然后更新字段Ac,最后提交;
事务2:执行普通查询,然后更新字段A,最后提交。

两个事务执行完毕,得到的记录Ar的字段Ac的值肯定是错误的。

面对这种情况,大家都是怎么处理的呢?

   发表时间:2008-11-11  
如果要保持事务一致,在进行事务2的时候,在查询之前获取那条记录的锁,即通过
select row from tablename for update where id = ...
这样可以保证在事务1提交之后,事务2才会开始查询
0 请登录后投票
   发表时间:2008-11-11  
如果事务2在另一个系统中,执行的是普通的查询,并且没有for update,
除了给它加上for update,还有其他办法吗?
0 请登录后投票
   发表时间:2008-11-11  
charles qi 写道
如果事务2在另一个系统中,执行的是普通的查询,并且没有for update,
除了给它加上for update,还有其他办法吗?

可以试试将事务2的隔离级别设为repeatable read,不过好像oracle把这个级别看成是serializable级别,比较慢
0 请登录后投票
   发表时间:2008-11-12  
引用

现在有两个事务,操作同一条记录Ar,执行过程如下:
事务1:执行for update查询,然后更新字段Ac,最后提交;
事务2:执行普通查询,然后更新字段A,最后提交。

两个事务执行完毕,得到的记录Ar的字段Ac的值肯定是错误的。

事务1已经提交完成以后,事务2当然可以做update操作了。如果事务1没有提交,由于其在记录Ar上加了行级锁,事务2更新不了记录Ar,可以避免脏读现象,有什么问题吗?
0 请登录后投票
   发表时间:2008-11-12   最后修改:2008-11-12
javaboy2006

你想的太简单了。如果两个事务同时执行,事务2可能会覆盖掉事务1的更新,造成最终的字段值是错误的。
0 请登录后投票
   发表时间:2008-11-12   最后修改:2008-11-12
javaeyebird 写道
charles qi 写道
如果事务2在另一个系统中,执行的是普通的查询,并且没有for update,
除了给它加上for update,还有其他办法吗?

可以试试将事务2的隔离级别设为repeatable read,不过好像oracle把这个级别看成是serializable级别,比较慢



这样设置的话,是不是所有的DB操作事务都采用串行话的事务,还是每个事务都可以自定义?
一个系统中,只是操作某些表的数据时需要做事务的串行化处理,另外一些并不需要。相信大多数系统都是这种情况,在这种系统中将所有的事务都设置为serializable,性能上是比较差的了。有没有更好的方式?

对于采用连接池的方式,一般都该怎么处理呢?
0 请登录后投票
   发表时间:2008-11-12  
charles qi 写道
javaeyebird 写道
charles qi 写道
如果事务2在另一个系统中,执行的是普通的查询,并且没有for update,
除了给它加上for update,还有其他办法吗?

可以试试将事务2的隔离级别设为repeatable read,不过好像oracle把这个级别看成是serializable级别,比较慢



这样设置的话,是不是所有的DB操作事务都采用串行话的事务,还是每个事务都可以自定义?
一个系统中,只是操作某些表的数据时需要做事务的串行化处理,另外一些并不需要。相信大多数系统都是这种情况,在这种系统中将所有的事务都设置为serializable,性能上是比较差的了。有没有更好的方式?

对于采用连接池的方式,一般都该怎么处理呢?


该事物设置一下就可以了。
0 请登录后投票
   发表时间:2008-11-12  
charles qi 写道
javaboy2006

你想的太简单了。如果两个事务同时执行,事务2可能会覆盖掉事务1的更新,造成最终的字段值是错误的。


这个感觉是程序设计上的问题。 本来就是应该如此的。 事务一提交之后事务二当然可以继续操作。 你难道要让事务二无法操作?
0 请登录后投票
   发表时间:2008-11-12  
问题已经解决,可参见。
http://qify.iteye.com/admin/blogs/265040
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics