【问题标题】:Generating unique id for customer without using sequence while using multiple sessions in oracle在oracle中使用多个会话时为客户生成唯一ID而不使用序列
【发布时间】:2020-04-06 04:42:47
【问题描述】:

我正在使用 select nvl(max(customerid),0)+1 生成客户 ID。它正在工作,但每小时有近 700 到 1000 名客户加入。因此,在几毫秒内使用上述代码时,会话会获得相同的最大客户 ID。所以它引发了唯一的约束违规。我不想使用序列,因为如果交易失败。我会失去顺序。

下面是示例代码。

Create or replace procedure ADM_customerregisration
P_firstname varchar2,
P_lastname varchar2
As
V_customerid number;
Begin
Insert into mas_customerdetails
(
Customerid,
Firstname,
Lastname
)
Values
(
(Select nvl(max(customerid),0)+1 from mas_customerdetails),
P_firstname,
P_lastname
) returning customerid into v_customerid;

Commit;

Exception

When others then

Return;
End;

【问题讨论】:

  • 请使用标签下方的edit 按钮编辑您的问题,并包含将实际编译的代码。谢谢。

标签: oracle auto-increment unique-constraint


【解决方案1】:

您真的不想在高交易量系统中执行此操作。它将大大降低您的并发性和吞吐量,并且会产生阻塞的持续支持问题。但是,如果您想生成顺序值并确保没有间隙,则必须

  • 锁定共享资源,使其他会话无法插入新客户
  • 生成值
  • 提交您的事务并释放锁定

这样做的一种方法是

create table my_slow_sequence (
  table_name varchar2(30),
  next_value integer
);

insert into my_slow_sequence( 'CUSTOMER', 1 );

create or replace procedure insert_customer( 
  p_firstname in varchar2,
  p_lastname  in varchar2
)
as
  l_customer_id integer;
begin
  select next_value + 1
    into l_customer_id
    from my_slow_sequence
   where table_name = 'CUSTOMER'
     for update; -- Lock the row so no one else can use it

  insert into customer( customer_id, first_name, last_name )
    values( l_customer_id, p_firstname, p_lastname );

  update my_slow_sequence
     set next_value = next_value + 1
   where table_name = 'CUSTOMER';
end;

您将遇到的问题将包括

  • 通过锁定共享资源,您可以明确且有意地阻止其他会话同时插入客户。在交易量较低的情况下,这并不是什么大问题。然而,随着系统的增长,并且当您为其他表复制此逻辑时,您将等待很多。如果您想保证没有间隙,则需要 - 在您确保之前的每笔交易都已完成之前,您无法获得下一个值。
  • 当您想要更大的交易(例如,创建客户本身可能不是交易,它可能是其他交易的一部分)或您开始进行实际数量的验证(即您想要检查客户针对列入黑名单的客户的 Web 服务或在您的系统中查找重复的客户),您创建了会话将获取锁然后挂起并且永远不会释放锁的可能性。当然,在 DBA 收到紧急页面之前,整个系统都会停止,直到她可以终止会话。到时候她会诅咒写这种东西的开发者。
  • 如果您的事务涉及多个表,则需要确保以相同的顺序获取锁以防止死锁。

我强烈建议您推迟“无间隙”要求。这实际上从来都不是真正需要的东西,它对商业用户来说听起来很容易。如果您想知道这是创建的第 n 个客户,您可以计算出来。如果您想知道客户没有被删除,您可以对其进行审核。如果您向业务用户展示此类需求的成本(即我们需要购买更强大的服务器,我们需要花费更多时间监控和解决问题,我们将创造整个系统必须努力解决的情况当任何地方出现问题时停止,我们会让用户的速度明显变慢),他们几乎肯定愿意重新考虑。

【讨论】:

    【解决方案2】:

    实际 ID 在您的用例中真的很重要,还是您只关心唯一性?

    如果是后者,使用SYS_GUID() 可能会更容易,而不是尝试生成唯一的数字

    【讨论】:

    • 是的。它的 。我需要那些客户ID。独一无二的和。任何地方都没有间隙。它应该是连续的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多