为什么在RedShift中,隐式表锁会在事务结束之前被释放?

4
我有一个 ETL 过程,它在 RedShift 中递增地构建维度表。 它按以下顺序执行操作:
  1. 开始事务
  2. 创建像 foo 的表 staging_foo
  3. 将数据从外部源复制到 staging_foo
  4. 对 foo 执行大规模插入/更新/删除,以使其与 staging_foo 匹配
  5. 删除 staging_foo
  6. 提交事务
单独执行此过程有效,但为了实现对 foo 的连续流式刷新和在发生故障时的冗余性,我同时运行了几个过程实例。 当发生这种情况时,偶尔会出现并发串行化错误。 这是因为两个过程都在重放某些来自 foo_staging 的更改到 foo 中,这些更改在重叠的事务中进行。
发生的情况是第一个进程创建了名为staging_foo的表,当第二个进程尝试创建同名表时被阻塞(这正是我想要的)。当第一个进程提交其事务(可能需要几秒钟)时,我发现第二个进程在提交完成之前就被解除了阻塞状态。因此,它似乎在提交完成之前获取了foo表的快照,导致插入/更新/删除操作(其中一些可能是冗余的)失败。
我根据文档http://docs.aws.amazon.com/redshift/latest/dg/c_serial_isolation.html进行推测。
并发事务对彼此是不可见的;它们无法检测到彼此的更改。每个并发事务都会在事务开始时创建数据库快照。数据库快照是在大多数SELECT语句、COPY、DELETE、INSERT、UPDATE和TRUNCATE等DML命令以及以下DDL命令中的第一次出现时在事务中创建的: ALTER TABLE(添加或删除列) CREATE TABLE DROP TABLE TRUNCATE TABLE
上述文档对我来说有些混淆,因为它首先说将在事务开始时创建快照,但随后说只有在某些特定的DML/DDL操作的第一次出现时才会创建快照。
我不想做一个深度复制,而是要逐步更新替换foo。我有其他进程不断查询这个表,所以没有时间可以在不中断的情况下替换它。另一个问题提出了类似的问题,但对我没有用:如何确保正在被替换的表上的同步DDL操作? 有没有方法可以使我的操作避免并发序列化错误?我需要确保foo的读取访问是可用的,因此无法对该表进行LOCK
1个回答

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接