6

我想知道如果我在使用 oracle 数据库时替换触发器是否会丢失任何数据。我创建了一个玩具示例,似乎我不会,但我的一位同事声称并非如此。

create table test_trigger (id number);
create table test_trigger_h (id number);
create sequence test_trigger_seq;

--/
create or replace trigger test_trigger_t after insert on test_trigger for each row
begin
  insert into test_trigger_h (id) values (:new.id);
end;    
/

--/
begin
  for i in 1..100000 loop
    insert into test_trigger (id) values (test_trigger_seq.nextval);
  end loop;
end;
/

--/
begin
  for i in 1..10000 loop
    execute immediate 'create or replace trigger test_trigger_t after insert on test_trigger for each row begin insert into test_trigger_h (id) values (:new.id); end;';
  end loop;
end;
/

ran the two loops at the same time

select count(1) from test_trigger;

COUNT(1)
100000

select count(1) from test_trigger_h;

COUNT(1)
100000
4

3 回答 3

1

create or replace正在锁定桌子。所以所有的插入都会等到它完成。不用担心错过插入。

于 2013-10-30T13:38:39.550 回答
0

以下 URL 答案可以在应用程序运行时修改触发器。它将是“库缓存”锁而不是“数据”锁。Oracle 在内部处理它,您无需担心它。

查看 Ben 提出的问题- 可以锁定触发器吗?如何确定它是?

-- 从会话 2 运行:select * from v$access where object = upper('test_trigger_t');

于 2014-01-24T12:34:59.360 回答
0

我认为您可能会以错误的方式进行测试。您的插入语句根本不需要任何时间,因此触发器的替换可以通过插入之间的间隙进行调整。由于以下原因,至少这是我推断的。

如果您更改测试以确保您有一个长时间运行的 SQL 语句,例如

create table test_trigger (id number);
create table test_trigger_h (id number);
create sequence test_trigger_seq;

create or replace trigger test_trigger_t 
 after insert on test_trigger for each row
begin
  insert into test_trigger_h (id) values (:new.id);
end;    
/

insert into test_trigger
 select level
   from dual
connect by level <= 1000000;

如果您随后尝试在单独的会话中替换触发器,则在插入完成之前不会发生。

不幸的是,我在文档中找不到任何支持我的东西;这只是我知道的行为。

于 2013-08-27T07:57:08.857 回答