现在有一个用户参与活动的表,字段包含用户号码,是否中奖两个字段。select count(1) into v_temp_count from table where gift =1;
if v_temp_count > 1 then--当一等奖已被抽掉,用户不能再中一等奖
    insert into table(phone_number,gift)values(phone,0);--插入用户未中奖记录
end if;
因为服务器是集群的,所以需要在数据库端进行锁操作。但是oracle中查询是不能锁的。
那么如何保证查询count和insert在同一原子操作中呢?!

解决方案 »

  1.   

    你的这个问题应该是这样的吧,把抽中的结果移动到另外一个表,然后删除原表抽中的用户,这两个放在一个事务中。也可以不需要按这个方式来处理,下一轮抽奖的时候,过滤条件gift字段等于0的即参加一下轮抽奖。
      

  2.   


    --如果中奖,修改中奖记录表
      if v_gift = 1 then
        select t.one into v_temp_count from t_rbt_gift9_result t for update;
        if v_temp_count < v_gift_one then
          update t_rbt_gift9_result t set t.one = (t.one + 1) where t.id = 1;
        else
          v_gift := 0;
        end if;
        insert into t_rbt_gift9_info (ID,phone_number,gift,create_time,random_num)
                 values(seq_rbt_gift9_info.nextval,v_phone_number,v_gift,sysdate,v_random);
      elsif v_gift = 2 then
        select t.two into v_temp_count from t_rbt_gift9_result t for update;
        if v_temp_count < v_gift_two then
          update t_rbt_gift9_result t set t.two = (t.two + 1) where t.id = 1;
        else
          v_gift := 0;
        end if;
        insert into t_rbt_gift9_info (ID,phone_number,gift,create_time,random_num)
                 values(seq_rbt_gift9_info.nextval,v_phone_number,v_gift,sysdate,v_random);
      elsif v_gift = 3 then
        select t.three into v_temp_count from t_rbt_gift9_result t for update;
        if v_temp_count < v_gift_three then
          update t_rbt_gift9_result t set t.three = (t.three + 1) where t.id = 1;
        else
          v_gift := 0;
        end if;
        insert into t_rbt_gift9_info (ID,phone_number,gift,create_time,random_num)
                 values(seq_rbt_gift9_info.nextval,v_phone_number,v_gift,sysdate,v_random);
      else--插入未中奖信息
        insert into t_rbt_gift9_info (ID,phone_number,gift,create_time,random_num)
                 values(seq_rbt_gift9_info.nextval,v_phone_number,v_gift,sysdate,v_random);
      end if;现在的处理方式是这样。
      

  3.   

    我不明白一个事情,你的代码明明是PL/SQL..为什么存在不是一个原子操作的问题呢?本身一个BEGIN END就可以是一个事务,不管你是集群还是单机.
      

  4.   


    是这样的,原来只有一个表的情况下,如果两个线程通过count查询当前中奖数都是0,当第一个线程执入中奖信息的时候,第二个线程还会再插入中奖信息,因为count不会锁表。两个线程查询出来都是没有超出中奖上限的。所以都会插入表。
      

  5.   


    你是不是说begin end中,一次只能有一个线程访问吗?