Redshift并行调用不同存储过程被中止,如何查询报错及排查原因?
报错查询方法
可以通过Redshift内置系统表定位中止原因,优先执行以下查询:
-- 筛选近24小时内被中止的存储过程调用记录,关联错误信息 SELECT q.query, q.querytxt, q.starttime, e.error_code, e.errormessage FROM STL_QUERY q LEFT JOIN STL_ERROR e ON q.query = e.query WHERE q.aborted = 1 AND q.querytxt ILIKE '%CALL SP_%' AND q.starttime >= GETDATE() - INTERVAL '1 day' ORDER BY q.starttime DESC;
如果错误信息包含deadlock detected相关提示,可进一步查询STL_DEADLOCK表查看死锁涉及的具体资源。
根因分析
该现象90%以上概率是公共LOG表导致的死锁:
- 两个存储过程都运行在Redshift默认的隐式大事务中,事务提交前所有持有锁不会释放,包括写
LOG表时加的锁 - 两个存储过程执行逻辑高度一致,都会多次申请
LOG表的写入权限,并发场景下极易满足死锁的四个必要条件,Redshift检测到死锁后会随机中止其中一个事务释放资源,符合观察到的“其中一个被中止”的现象。
解决方案
- 最高优先级方案:将
LOG存储过程改造为自治事务,写入日志后立刻单独提交,释放LOG表相关锁,避免锁持有贯穿整个存储过程生命周期。Redshift存储过程中可通过单独的COMMIT语句实现日志写入的独立提交。 - 无需改存储过程的临时方案:调整Lambda触发逻辑,增加简单的并发控制,比如用DynamoDB实现分布式锁,同一时间仅允许一个存储过程执行;或者检测到两个文件都上传完成后串行调用两个存储过程,从根源避免并发冲突。
- 低成本缓解方案:在Lambda调用存储过程前增加随机1-2秒的延迟,错开两个存储过程的锁申请时间,可大幅降低死锁触发概率。
内容的提问来源于stack exchange,提问作者baronnoraz
相关产品推荐
相关产品推荐

