oracle for update实现线程同步取数据

        背景:在电信软件领域,一个软件常常有多个portal,对于话单的处理常常用多个定时任务来处理,那么问题来了,如何保证每个portal的每个定时任务取得话单都是各不相同的呢? 有人会问,为什么不在取数据的Java侧进行同步控制呢,但是问题是多个portal,很明显这不是Java侧的同步能控制的。

        基础:oracle的for update关键字是一个行级排它锁,也就是说for update只会排他锁定相关的行,并不会锁定整个表,在锁定期间,其他线程可以读取,但不能再加其他排它锁了,任何尝试加排它锁的线程都将阻塞等待该锁的释放(注:for update nowait不会等待,直接返回错误)。oracle遇到for update的语句就会自动进入事务(和 update操作是一个效果),我们可以做一个简单的实验,在pl/sql dev中写“select * from TICKET t where t.id = 1 for update;”,执行它会发现左上角出现了事务提交和事务回滚的按钮。

       实现:那么我们同步获取话单数据就可以利用for update加排它锁的特性,来实现同步取数据,实现如下:

create or replace procedure p_sycn_getoneticket
(
       dt_in_createtime in date,                --createtime
       cur_tickets out sys_refcursor         --return cursor
) as      --定义数组实体,用于后边接受数据
       nstb_ids nstb_numbers_type := new nstb_numbers_type();
begin
       --取数据
       select t.id
        bulk collect into nstb_ids
         from ticket t
       where t.createtime < dt_in_createtime
           and  t.status = 1
           for update; 
                   
      --更新数据状态,避免被其他线程获取到
      update ticket t
             set t.status = 2
       where t.createtime < dt_in_createtime
           and  t.status = 1;
       
       --提交,释放update锁
       commit;
       
       --将数组数据放入游标,用于返回
       open cur_tickets for
                  select t1.id, t1.price, t1.des, t1.status, t1.createtime
                    from ticket t1, table(cast (nstb_ids as nstb_numbers_type))  t2
                 where t1.id = t2.column_value;
                 
exception
         when others then
                  rollback;
         --返回空游标
         open cur_tickets for
                   select 'X'
                     from dual 
                   where 1=1;
end;
       实现说明:在多线程同时执行该段代码的时候

①线程1先获取到该条记录的行级排它锁,其他线程进入等待状态;

②线程1更新数据状态,并提交,释放锁;

③线程2获取到数据的排它锁,但发现检索发现并不是符合条件的数据,重新检索数据,进而锁定另一部分数据。

如此往复,形成了该段代码对于同一数据行的同步取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值