Поиск последнего номера, сгенерированного последовательностью, перед тем, как она будет удалена - PullRequest
0 голосов
/ 27 ноября 2018

Мы обнаружили, что в одном из экземпляров UAT нашего клиента отсутствует последовательность "_SEQUENCE".Мы не знаем, как это было удалено и когда.Это очень важная последовательность, потому что числа, сгенерированные этой последовательностью, используются как уникальные значения столбцов во многих таблицах в БД.Другими словами, никакие два столбца (определенных типов столбцов) в любых двух таблицах в БД не будут иметь такое же число, как и значение.В некоторых из этих столбцов у нас также есть уникальный индекс.

Мы можем снова создать последовательность, но мы не знаем, каким должно быть начальное значение последовательности, потому что мы не знаем, какое число было последним.старая последовательность генерируется.Если мы установим неправильное число в качестве начального значения и случайно, если оно сгенерирует то же число для того же столбца таблицы, которая уже присутствует, мы можем получить исключение нарушения уникального ключа.

Мы можемустановите начальное значение на очень большое число, но это последний вариант.Now;

  1. Можно ли найти последнее число, которое сгенерировала последовательность "_SEQUENCE" до того, как оно было удалено?
  2. Можно ли найти, какой процесс удалил последовательность "_SEQUENCE" икогда?

1 Ответ

0 голосов
/ 28 ноября 2018

Операция возврата в памяти недоступна для последовательности, в то время как она доступна для таблиц.Механизм может быть создан с помощью триггера DDL, созданного в основном пользователями баз данных SYS или SYSTEM.В качестве примера рассмотрим следующую процедуру:

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'
...