Oracle隊列實現


Oracle隊列實現

-- 核心技術點:for update

創建測試表

create table t

  ( id       number primary key,

    processed_flag varchar2(1),

    payload  varchar2(20)

);

創建函數索引

create index

  t_idx on

  t( decode( processed_flag, 'N', 'N' ) );

插入幾條測試數據

insert into t

  select r,

         case when mod(r,2) = 0 then 'N' else 'Y' end,

         'payload ' || r

    from (select level r

            from dual

         connect by level <= 5)

/

方式一,通過函數返回未鎖定行

創建隊列獲取一行數據的函數

支持Oracle8.0及以后的版本

create or replace

  function get_first_unlocked_row

  return t%rowtype

  as

      resource_busy exception;

      pragma exception_init( resource_busy, -54 );

      l_rec t%rowtype;

  begin

      for x in ( select rowid rid

                   from t

                   where decode(processed_flag,'N','N') = 'N')

      loop

      begin

          select * into l_rec

            from t

           where rowid = x.rid and processed_flag='N'

             for update nowait;

          return l_rec;

      exception

          when resource_busy then null;

          when no_data_found then null;

      end;

      end loop;

      return null;

end;

/

獲取未加鎖的第一行數據

declare

      l_rec  t%rowtype;

  begin

      l_rec := get_first_unlocked_row;

      dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );

  end;

/

eoda/muphy> I got row 2, payload 2

獲取未加鎖的第二行數據

declare

      pragma autonomous_transaction;

      l_rec  t%rowtype;

  begin

      l_rec := get_first_unlocked_row;

      dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );

      commit;

  end;

/

eoda/muphy> I got row 4, payload 4

方式二,直接通過skip locked實現

獲取未加鎖的第一行數據

declare

      l_rec t%rowtype;

      cursor c

      is

      select *

        from t

       where decode(processed_flag,'N','N') = 'N'

         FOR UPDATE

        SKIP LOCKED;

  begin

      open c;

      fetch c into l_rec;

      if ( c%found )

      then

          dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );

      end if;

      close c;

  end;

/

eoda/muphy> I got row 2, payload 2

獲取未加鎖的第二行數據

declare

      pragma autonomous_transaction;

      l_rec t%rowtype;

      cursor c

      is

      select *

       from t

       where decode(processed_flag,'N','N') = 'N'

         FOR UPDATE

        SKIP LOCKED;

  begin

      open c;

      fetch c into l_rec;

      if ( c%found )

      then

          dbms_output.put_line( 'I got row ' || l_rec.id || ', ' || l_rec.payload );

      end if;

      close c;

      commit;

  end;

/

eoda/muphy> I got row 4, payload 4

--參考自Oracle編程藝術 深入理解數據庫體系結構第三版


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM