首页 > 解决方案 > 查找序列在删除之前生成的最后一个数字

问题描述

我们发现我们客户的一个 UAT 实例中不存在序列“_SEQUENCE”。我们不知道它是如何被删除的以及何时被删除的。这是一个非常关键的序列,因为此序列生成的数字在 DB 中的许多表中用作唯一列值。换句话说,数据库中任何两个表中的任何两个列(特定列类型)都不会与 value 具有相同的数字。在其中一些列上,我们也有唯一索引。

我们可以再次创建序列,但我们不知道序列的初始值应该是什么,因为我们不知道旧序列生成的最后一个数字是什么。如果我们将错误的数字设置为初始值并且偶然地为已经存在的表的同一列生成相同的数字,我们最终可能会得到唯一键违规异常。

我们可以将初始值设置为一个非常大的数字,但这是最后一个选项。现在;

  1. 是否可以找到序列“_SEQUENCE”在删除之前生成的最后一个数字?
  2. 是否可以找到哪个进程删除了序列“_SEQUENCE”以及何时删除?

标签: oraclesequenceoracle12cdatabase-administration

解决方案


闪回操作不适用于序列,但可用于表。机制可能由DDL主要在数据库用户SYSSYSTEM数据库用户中创建的触发器的贡献产生。作为一个例子,考虑这个过程:

create or replace procedure pr_ddl_oper as
  v_oty          varchar2(75) := ora_dict_obj_type;
  v_don          varchar2(75) := ora_dict_obj_name;
  v_evt          varchar2(75) := ora_sysevent;
  v_olu          varchar2(75) := nvl(ora_login_user,'Unknown Schema');
  v_sql          ora_name_list_t;
  v_stm          clob;
  v_sct          owa.vc_arr;
  n              pls_integer;
  n_max          pls_integer := 10000; -- max number of rows for CLOB object 
                                       -- to hold object's source.
begin
      v_sct(1) := 'SESSIONID';
      v_sct(2) := 'IP_ADDRESS';
      v_sct(3) := 'TERMINAL';
      v_sct(4) := 'OS_USER';
      v_sct(5) := 'AUTHENTICATION_TYPE';
      v_sct(6) := 'CLIENT_INFO';
      v_sct(7) := 'MODULE';
      for i in 1..7
      loop
       v_sct(i) := sys_context('USERENV',v_sct(i));
      end loop;
      select decode(v_sct(1),0,null,v_sct(1)),decode(upper(v_sct(3)),
            'UNKNOWN',null,v_sct(3)) 
        into v_sct(1),v_sct(3) 
        from dual;

       n := ora_sql_txt( v_sql );
      if n > n_max then
       n := n_max;
      end if;
      for i in 1..n
      loop
       v_stm := v_stm || v_sql(i);
      end loop;

       insert into log_ddl_oper(event_time,usr,evnt,stmt,sessionid,ip,terminal,os_user,
         auth_type,object_type,object_name,client_info,module_info)
       values(sysdate,v_olu,v_evt,v_stm,v_sct(1),v_sct(2),v_sct(3),v_sct(4),v_sct(5),
         v_oty,v_don,v_sct(6),v_sct(7));
end;

此触发器可以调用它作为将来的参考:

--| Compiling this trigger, especially for Production Systems, should be handled with care |

create or replace trigger system.trg_admin_ddl before ddl on database
declare
begin
 pr_ddl_oper;
end;

通过连接 SYS 用户,您可以查询last_number删除的序列的列:

select last_number
  from dba_sequences 
  as of timestamp to_timestamp('2018-11-27 23:50:17', 'YYYY-MM-DD HH24:MI:SS') s 
 where s.sequence_name = 'MYSEQ';

时间戳值可以通过以下方式检测到

select l.event_time 
--> returns to_timestamp('2018-11-27 23:50:17', 'YYYY-MM-DD HH24:MI:SS')
--> to use for the above SQL Select statement
  from log_ddl_oper l
 where l.object_name = 'MYSEQ'
   and l.evnt = 'DROP'

推荐阅读