Loops Teradata中的捕获插入错误

Loops Teradata中的捕获插入错误,loops,error-handling,insert,teradata,Loops,Error Handling,Insert,Teradata,我有一个存储过程,它使用以下语句将记录插入到Teradata数据仓库中的表中: INSERT INTO UAT_AUDIT_VIEWS.AUDIT_BATCH( BATCH_KEY ,AUDIT_STATUS_KEY ,BATCH_START_DATETIME ,BATCH_END_DATETIME ,BATCH_OWNER ,BATCH_EXECUTION_START_DATETIME ,BATCH_EXECUTION_END_DATETIME ) VALUES( (SELECT COALES

我有一个存储过程,它使用以下语句将记录插入到Teradata数据仓库中的表中:

INSERT INTO UAT_AUDIT_VIEWS.AUDIT_BATCH(
BATCH_KEY
,AUDIT_STATUS_KEY
,BATCH_START_DATETIME
,BATCH_END_DATETIME
,BATCH_OWNER
,BATCH_EXECUTION_START_DATETIME
,BATCH_EXECUTION_END_DATETIME
)
VALUES(
(SELECT COALESCE(MAX(BATCH_KEY),0)+1 FROM UAT_AUDIT_VIEWS.AUDIT_BATCH)
,5 --PENDING
,'1900-01-01 00:00:00'
,'2999-12-31 00:00:00'
,:P_BATCH_OWNER
,CURRENT_TIMESTAMP
,'2999-12-31 00:00:00'
);
注意,我对主键BATCH_键有一个唯一性约束。在某些情况下,我的insert语句失败,因为表中已存在主键。发生这种情况时,我希望存储过程循环并重试插入,直到插入成功

我已尝试使用以下多种解决方案,但未成功:

  • 为SQLEXCEPTION声明CONTINUE处理程序
    ,以避免在插入失败时存储的过程失败
  • 执行
    WHILE DO
    循环以重试插入
你能描述一下你将如何处理这种情况吗? 下面是我为测试该过程而构建的测试存储过程的简化版本(该过程不起作用):


这个评论太长了

您当前的方法必须执行完整的表扫描以获得最大值(默认为表级别的读锁),但Insert默认为行哈希级别的写锁。当您请求在表级别写入时,它应该可以防止死锁

定义一种序列表时,每个访问都是UPI访问,例如

CREATE SET TABLE Sequences
 (
   SequenceName VARCHAR(128) CHARACTER SET Unicode NOT CaseSpecific NOT NULL,
   nextVal BIGINT NOT NULL DEFAULT 1
 )
UNIQUE PRIMARY INDEX ( SequenceName )
;

REPLACE PROCEDURE NextVal (IN SequenceName VARCHAR(128) CHARACTER SET Unicode, OUT NextVal BIGINT)
BEGIN
   BEGIN REQUEST
      LOCK ROW WRITE
      SELECT nextVal INTO :nextVal FROM Sequences 
      WHERE SequenceName = :SequenceName;

      UPDATE Sequences SET nextVal = nextVal + 1 
      WHERE SequenceName = :SequenceName;
   END REQUEST; 
END;
初始化新序列:

INSERT INTO sequences ('mytable', 1);
获取下一个值:

CALL nextVal('mytable', nextval);`
编辑:

您可以在多个会话上并行使用BTEQ日志轻松测试它,例如,在10个会话中运行1000个调用:

.set session 10; 
.logon ...; 
select * from sequences where SequenceName = 'mytable';

.repeat 1000
CALL nextVal('mytable', nextval); 

select * from sequences where SequenceName = 'mytable';

观察按顺序返回的值,无死锁:-)

该键仅在并行运行SP时存在。与处理并发问题不同,您只需切换到写锁:
lock TABLE UAT\u AUDIT\u VIEWS.AUDIT\u BATCH FOR WRITE INSERT…
我有多个团队并行调用存储过程。我们实现了写锁作为第一个解决方案,但当存在并发访问时,它最终导致死锁问题。这就是为什么我要删除它,捕获插入错误并重试。如果您还有其他我感兴趣的选项,那么您发布的插入不会像在表级与写锁并行运行时那样导致死锁。另一个解决方案(可扩展性更好)是基于序列表,该表只有一行存储最大值,您的SP读取当前值,将其增加1,然后将其写回。感谢您的评论。我仍然认为写锁是死锁问题的原因,因为我们能够重现该问题,并将其删除。我们注意到该问题不再发生(但我们出现了BATCH_KEY unicity constraint错误)。我不明白为什么将Max(批处理密钥)存储在专用表中可以解决这两个问题中的任何一个?谢谢,我想我已经达到了我的技术极限。。。您知道如果两个进程同时调用SP NextVal会发生什么情况吗?这个实现是否保证它不会为这两个进程返回相同的nextVal,并且它们都不会面临死锁?我将尝试一下……。@Alexis.Rolland:编辑了我的答案,演示了如何测试它
.set session 10; 
.logon ...; 
select * from sequences where SequenceName = 'mytable';

.repeat 1000
CALL nextVal('mytable', nextval); 

select * from sequences where SequenceName = 'mytable';