`

怎样消除多事务并发问题?

阅读更多

多事务并发,大家在实际的项目或者产品开发过程中会常常遇到。

 

在开发过程中,如果业务中有必须唯一性的业务单元,例如:消息ID,订单ID等,这时开发人员就需要考虑:多事务并发时,会不会产生错误的执行结果,对具体问题具体分析,进而得到合理的解决方案。

 

我在项目中遇到过多个多用户并发的问题,顺便对Oracle中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 允许普通select查询,不允许做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的值有可能是错误的。

 

这说明仅在sql中添加for update是无法消除多用户并发问题的。

暂且这么说,因为如果整个系统对于特定的数据,都采取统一的锁机制,是可以避免这个问题的,例如:一个大系统的所有子系统,对于表A的操作都统一的采用悲观锁或者乐观锁的机制。


多事务并发问题多出现在一个系统中没有明确的事务操作规则,而且开发人员的编码水平参差不齐,有的人没有想到需要做这样的处理,就容易造成并发问题。

 

锁机制的指定:

数据库的锁机制有多种管理方式,数据库本身提供自动管理机制;另外,也允许用户在事务中指定具体应用哪种锁,例如:在sql中添加for update,在具备锁机制的DB中的意思就是指定对当前查询的数据记录应用独占锁。

 

其实解决多事务并发的问题方法有多种,这里只提下version处理机制,它不仅适用于单个系统,而且即便是分布式系统也没问题。有经验的用户都比较了解这种方式,就不再多说了,可参考hibernate采用版本控制实现乐观锁的处理。

4
0
分享到:
评论
5 楼 charles751 2008-11-13  
teclogid:
如果是查询后发update,那发这个update之前事务1没完成,你这个update失败,如果完成了,那就是先后两个事务了,当然后面的修改覆盖前面的。

1.查询当然不能更新。
2.事务2的update不一定失败,有可能事务2暂时让出CPU时间,处于暂停状态。
3.这种场景下不是先后两个事务,因为这两个事务是同时开始的。
4 楼 charles751 2008-11-11  
谢谢你,wangxuliangboy
你说的没错。

下面的是我没有说清楚,已经改正了,呵呵。

select * from sometable where id = 1 for update;
1.1允许对表中的其他记录做普通查询,但不允许做for update查询。

改为:
1.1不允许对该记录做for update查询,允许对其他记录做for update查询。
3 楼 wangxuliangboy 2008-11-11  
是的..我没提交事务...
select * from product where id ='10006924' for update

select * from product where id='10001407' for update
我觉的是行级锁..只会锁得当前行..而不会影响其它的FOR UPDATE
2 楼 charles751 2008-11-11  
能说说你是怎么测试的吗?

下面这条查询,你是怎么执行的,确认该事务尚未提交吗?
select * from sometable where id = 1 for update
1 楼 wangxuliangboy 2008-11-11  
允许对表中的其他记录做普通查询,但不允许做for update查询。

为什么我在PL/SQL中可以做呢...

相关推荐

Global site tag (gtag.js) - Google Analytics