Redshift 存储过程被中止

Posted

技术标签:

【中文标题】Redshift 存储过程被中止【英文标题】:Redshift Stored Procedure being Aborted 【发布时间】:2021-09-27 14:57:38 【问题描述】:

我有一个 S3 存储桶,它几乎在一天中的同一时间接收文件(FILE_AFILE_B)。

我有一个 lambda 函数,当这些文件上传到 S3 时会触发该函数。 lambda 函数将根据文件类型调用两个存储过程之一。

lambda 函数只需使用 Redshift Data API 调用适当的存储过程,然后退出。

IF (FILE_A) 
  CALL SP_A(FILE_A.name)

ELSE IF (FILE_B) 
  CALL SP_B(FILE_B.name)

这两个存储过程几乎相同,它们只是对一组不同的表进行操作。随着每个存储过程的进行,它们通过存储过程将状态信息记录到 Redshift 中的共享 LOG 表中。

每个存储过程的结构基本上是……

LOG('sp_a started')
LOG('sp_a truncate table_a_1')

TRUNCATE TABLE TABLE_A_1

LOG('sp_a copy started')
COPY INTO TABLE_A_1 FROM S3 FILE_A

LOG('sp_a insert table_a_2')
INSERT INTO TABLE_A_2 FROM TABLE_A_1

LOG('sp_a delete dupes')
DELETE FROM TABLE_A_3 WHERE SELECT TABLE_A_2

LOG('sp_a insert table_a_3')
INSERT INTO TABLE_A_3 FROM TABLE_A_2

LOG('sp_a finished')

SP_B 的逻辑完全相同。我可以毫无问题地从 lambda 或 Redshift 控制台调用存储过程。每当我单独运行存储过程时,它们都可以正常工作。

当存储过程基本上同时启动时,当 FILE_A 和 FILE_B 在毫秒内上传到 S3 时,就会出现问题。

两个存储过程之一将被 Redshift 中止。另一个将运行到完成。我还没有 100% 验证这一点,但似乎首先启动的存储过程最终被 Redshift 中止。

我没有在存储过程中定义任何事务边界。我依赖于包装调用 CALL SP_A(FILE_A.name) 的隐式事务。

我可以解释为什么同时调用同一个存储过程可能会导致问题,但我不明白为什么调用不同的存储过程会导致一个失败而另一个失败。如果它们不并行运行,我看不到这个问题。

我已经上下搜索,试图找到 Redshift 在哪里记录存储过程中止的原因,但我找不到任何东西。

有谁知道我在哪里可以找到 Redshift 错误,或者知道为什么其中一个存储过程会中止?感谢您的帮助!!!!!!

【问题讨论】:

您正在执行删除和插入操作。您最终将在表中删除大量记录,并且所有新记录都将未排序 - 这使得使用 Redshift 完全没有意义;在这种情况下,它的行为会退化为 Postgres 的行为。你在做什么真空,对表进行排序并删除已删除的记录? 是的,我明白了。删除是处理一些不良数据的临时解决方法。事实上,其中大部分可能会发生很大变化。但是在继续之前,我想了解发生了什么,以防以我的方式同时运行存储过程存在一些基本缺陷。 一个存储过程就是一个事务;程序没有什么特别之处,只是它们作为事务运行。但是,不正确地使用事务肯定有可能遇到问题。 【参考方案1】:

我对正在发生的事情有一个猜测,但首先要检查的是 stl_error 用于中止的操作。这将为您提供有关正在发生的事情的信息。

现在我的猜测 - 我希望您有一个可序列化的隔离违规,其中 2 个存储过程创建的锁会创建一个依赖循环。在这种情况下,Redshift 必须终止其中一个事务才能清除锁定循环。见https://docs.aws.amazon.com/redshift/latest/dg/c_Concurrent_writes.html

这只是一个猜测,所以请检查 stl_error 并查看遇到了什么错误。

【讨论】:

我查看了STL_ERROR 表,但没有找到与PID 相关的任何内容。我也查看了许多其他表格,但均未成功。在“查询和加载”选项卡上,我可以看到状态为 ABORTED 的父存储过程调用,但没有任何子查询具有 COMPLETED 以外的状态。这两个存储过程在不同的表上运行,所以我不希望它们之间有任何 READ / WRITE 争用。它们共享 LOG 表,但只对 LOG 表执行 INSERTS。 可能是您运行 SP_A 两次,因为两个文件在同时运行时都存在?这可能会导致锁定和争用问题。由于这些问题,第二次调用没有取得进展,但 Lambda 超时并中止了函数。

以上是关于Redshift 存储过程被中止的主要内容,如果未能解决你的问题,请参考以下文章

我们应该在 Redshift 的存储过程中使用 udf

我可以在redshift的存储过程中有表变量吗?

如何在 Redshift 中的 select 语句中使用存储过程

在 redshift 中创建存储过程

在Redshift返回错误的存储过程中传递变量

无法使用 refcursor 调用 Redshift 存储过程