繁体   English   中英

在触发器中处理多线程

[英]Process the multithreading in trigger

我必须在表事务中为每一行生成 number_order(顺序是:1、2、3...)。

我的解决方案是在插入表事务之前创建一个触发器。 触发器的任务是计算表的总行(select count(1) to v_count from Transaction) --> 然后set :new.num_order = v_count + 1

该解决方案在几乎情况下运行正常,但是当系统有很多线程插入到表中时,触发器由多线程执行并且它们返回 SAME ORDER(原因是 select 命令在插入之前和同时被调用)。 你能给我建议一个替代解决方案吗? 提前谢谢你。

PS :我使用的是oracle 12c 数据库。 而且我不能使用序列,因为顺序实际上基于表中的其他一些列(例如: Room_id )。 所以完整的选择命令是:

select count(1) to v_count from transaction where room_id = :new.room_id

通常,这是一种糟糕的方法,会导致显着的性能、扩展和支持问题。 我会重新考虑设计。

如果你想这样做,你需要强制你的交易序列化。 您可以有一个单独的表,主键为room_idroom_count值,或者您可以将该列添加到room 您需要通过select for update锁定room_id的行。 然后您将更新room_count并将其用于您的insert 当您的事务提交时,锁将被释放。

但是,如果您这样做,涉及相同room_id所有其他事务room_id将阻塞。 如果您的交易时间相对较短,假设您没有太多用户在同一个房间工作,这可能并不可怕。 然而,随着用户数量和交易长度的增加,问题变得更加困难。 如果事务可能涉及多个房间,您需要每个事务以相同的顺序(例如,以room_id顺序)处理它们以避免潜在的死锁。 如果您不仅要使用这张表来做类似的事情,事情也会变得更加复杂。

我更愿意使用序列,然后在查询中生成序列值。 例如

SELECT room_id,
       rank() over (partition by room_id order by sequence_column) your_num_order
  FROM your_table

或者,您可以将sequence_column用于初始插入,并有一个后台作业,该作业定期(每天是常见的)并在事务完成后批量分配num_order

我将提出以下解决方案:新表

create table  room_count( room_id NUMBER primary key,  cnt number);

在自治事务中增加计数的函数:

Create or replace function inc_room_cnt( p_room_id NUMBER) return number as 
PRAGMA autonomous_transaction;
  v_cnt NUMBER;
begin
  update room_count set cnt = cnt +1 where room_id = p_room_id returning cnt into v_cnt;

  -- insert new room if not yet exists
  if SQL%ROWCOUNT = 0 then 
    v_cnt := 1;
    insert into room_count values (p_room_id, v_cnt);
  end if;

  commit;
  return v_cnt;
end;
/

before insert触发器中,您可以调用inc_room_cnt来设置顺序:

:new.room_order := int_room_cnt(:new.room_id);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM