Oracle重置序列发生器(非重建)

1、背景

1.1 背景

项目中有5个序列发生器(分别为:seq1、seq2、seq3、seq4、seq5),各序列发生的作用是产生[10000,19999)、[20000,29999)、[30000,39999)、[40000,49999)、[50000,59999)的数值。创建序列的DDL如下:

 

CREATE SEQUENCE seq1
  START WITH 10001
  MAXVALUE 19999
  MINVALUE 10001
  increment by 1
  NOCYCLE
  NOCACHE
  ORDER;

其他的同样,区别只是开始值不同

 

1.2 问题

目前每天晚上00:00有定时任务,作用是删掉序列发生器,然后重建,保证每天的序列发生器是从起始值开始的。

最近一段时间偶尔出问题,经查询,重置序列发生器的定时任务在运行时,有其他定时任务正在使用这些序列发生器,从而导致定时任务失败。

因此,现场要求:既要重置序列发生器,又避免发生异常。

所以,采用非重建的方式重置序列发生器

2、解决方案

创建procedure,如下:

 

/*
  创建人:郑林 2017-8-30
  方法说明:重置序列发生器
  参数说明:v_seqname序列发生器名称;v_max_value序列的最大值
  其他说明:cache按默认值处理
*/
create or replace procedure seq_reset(v_seqname varchar2,v_max_value number) as
  n    number(10);
  tsql varchar2(100);
  begin
		
	   --1、设置为nocahe(防止出现ora-04013错误)
	   execute immediate 'alter sequence '|| v_seqname ||' NOCACHE';
		
       --2、获取序列的当前值
       execute immediate 'select '|| v_seqname ||'.nextval from dual' into n;
       n :=v_max_value-n;
       --3、更改步长
       tsql := 'alter sequence '|| v_seqname ||' increment by ' || n;
       execute immediate tsql;
       
       --4、获取当前值
       begin
               execute immediate 'select '|| v_seqname ||'.nextval from dual' into n;
       exception                
               when others then
                 if sqlcode='-8004' then
                    tsql:='alter sequence '||v_seqname||' increment by 1';
                    execute immediate tsql;
                 end if;
       end; 
       
       --5、恢复步长
       tsql := 'alter sequence ' || v_seqname ||' increment by 1';
       execute immediate tsql;
	   
	   --6、恢复cache
	   execute immediate 'alter sequence '|| v_seqname ||' CACHE 20';
  
end seq_reset;

参数中:v_seqname 为序列发生器的名称;v_max_value 为序列发生器的最大值

 

这样,重写定时任务,便可解决当前问题

 

SQL> set serveroutput on;
SQL> exec seq_reset('SRXS001',19999);
PL/SQL procedure successfully completed
 

 

3、参考资料

1、动态SQL,参考:动态SQL资料链接

2、非重建方式,参考:非重建的链接

4、C#调用procedure

        //获取设定的数据
        private int executeProcedure()
        {
            int result = 1;
            //获取数据库连接
            OracleConnection conn = DataBaseContext.GetSequenceOracleConnection();
            OracleCommand command = new OracleCommand();

            try
            {
                command.Connection = conn;
                command.CommandType = CommandType.StoredProcedure;

                List<SeqModel> seqList = getSeqList();
                //完成执行procedure的方法
                seqList.ForEach(t =>
                {
                    result = result * executeProcedure(t.SeqName, t.MaxValue, command);
                });

                conn.Close();

                return result;
            }
            catch (System.Exception ex)
            {
                SysLog.LogWrite("pharmacy.log", ex);
                return -1;
            }
            finally
            {
                if (conn != null) conn.Close();
            }
        }

        //执行procedure的方法
        private int executeProcedure(string sequence_name, int max_value,OracleCommand command)
        {
            int execute_result = 0;
            try
            {
                command.CommandText = "seq_reset";
                command.Parameters.Clear();
                command.Parameters.Add("v_seqname", OracleDbType.Varchar2).Direction = ParameterDirection.Input;
                command.Parameters["v_seqname"].Value = sequence_name;
                command.Parameters.Add("v_max_value", OracleDbType.Int32).Direction = ParameterDirection.Input;
                command.Parameters["v_max_value"].Value = max_value;

                execute_result = command.ExecuteNonQuery();

                return execute_result;
            }
            catch (System.Exception ex)
            {
                SysLog.LogWrite("pharmacy.log", ex);
                return -1;
            }
        }

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值