ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 并发容易出现的问题与并发控制

并发容易出现的问题与并发控制

原创 Linux操作系统 作者:perry_shi 时间:2008-06-04 14:29:44 0 删除 编辑

  作者:PINNER(转载)

 

在多进程连接的数据库,并发操作是一个很平常的现象,加上Oracle特有的锁机制(不阻塞读),所以理解与控制并发是一个非常重要的事情。

下面用一个简单的例子说明并发处理中的一个问题,如用户表中存放好评的统计数据,假定两个用户同时操作,看如下一个过程。

one session                                 other session
-----------------------------------------------------------------------------------------
T1> SQL>insert into auction_feedbacks values(?)
        1 row inserted                 

T2> SQL>insert into auction_feedbacks values(?)
        1 row inserted  

T3> SQL> update bmw_users set rated_sum =
          (select count(*) from auction_feedbacks
             where username=?)
         where id=?;
         1 row updated                             

T4> SQL> update bmw_users set rated_sum =
           (select count(*) from auction_feedbacks
            where username=?)
         where id=?;
         1 row updated 

T5>SQL> commit;
        Commit complete  

T6> SQL> commit;
     Commit complete

其中时间T1

两个会话,同样的执行语句与同样的执行顺序,都想把增加到好评表中的好评统计放到用户表中去,但是,问题出来了,假定原来该用户的好评是20个,经过两个人的评价后,好评表中最后是22条记录了,而用户表的统计数据是21。

错在哪里?谁都没有错,是并发引发的问题。

要控制好并发,就要深刻理解Oracle的锁机制,Oracle如果一个进程发生数据改变,另外一个进程读该数据的时候,将发生一致性读(以SCN为基准),所以在上面的例子中,进程2读到了进程1 commit之前的统计数,这样就漏掉了会话1发生的好评。

我们要怎么避免并发呢,其实Oracle除了支持一致性读,也支持当前读,也就是说,操作之前检查最新的状态,对于select 可以用序列事务,对于DML本来就是当前读,所以,我们可以利用update的条件中增加需要更新值的原始值来避免并发。

我们利用用户表复制中的防止并发操作来说明,同样的两个会话

会话一

  1. update rep_users_flag f set f.run_flag='runing'
  2.       where f.run_flag='stop' and f.sp_type='users1';

会话二

  1. update rep_users_flag f set f.run_flag='runing'
  2.       where f.run_flag='stop' and f.sp_type='users1';

执行同样的语句,如果会话1先执行但是还没有提交的时候,会话2处于等待状态,但是会话1一旦提交,会话2的条件“where f.run_flag=’stop’”的检查将失效(当前读已经是runing,是会话1提交后的数据),所以会话2能更新到的记录数将是0。通过判断sql%rowcount返回的处理行数就可以决定是否继续,如上面的例子,如更新到的行数返回0,将退出或者是等待。

如果在业务频繁的表上面,也可以与实际业务结合起来,如要把表的字段a增加10,可以这样操作

  1. update table_name set a=a+10
  2.      where  id=? and a=10

在以上例子中,假定原表a的值是10,该语句就可以保证只能有一个进程能更新成功。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/127656/viewspace-331193/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-04-11

  • 博文量
    11
  • 访问量
    67407