Amazon Redshift 支持 Iceberg 表多语句事务
有效阅读仅保存在当前浏览器,用于「为你」推荐;暂停或清除记录。
DataHot 速览
Amazon Redshift 现在支持对 Apache Iceberg 表执行多语句事务,多条 DML 可在单个 BEGIN…COMMIT 内执行,并作为单一 Iceberg 快照提交。其他会话和引擎的读取者只能看到提交前或提交后的表状态,失败或回滚的事务无需清理残留。该功能随 Patch 206 及以后版本提供,解决了此前每条写入语句单独提交导致的多步管道脆弱问题。
为什么值得关注:湖仓开放表格式的事务语义是数据平台架构的关键能力,直接影响数据管道的一致性与下游可读性,对数据工程与平台选型有参考价值。
译文
AI 逐段翻译数据管道通常会在多个步骤中更改表,例如先更新插入当天的销售数据,然后移除已取消的订单。Amazon Redshift 现在支持 Apache Iceberg 表的多语句事务,因此你可以在单个 BEGIN … COMMIT 内,针对同一个 Iceberg 表运行多条数据操作语言(DML)语句。Amazon Redshift 会将它们发布为一个 Iceberg 快照。其他会话和引擎中的读取者看到的要么是批次提交之前的表,要么是提交之后的表。失败或回滚的事务不会留下任何需要撤销的内容。Amazon Redshift 在 Patch 206 及更高版本中提供多语句事务。
多语句事务扩展了 Amazon Redshift 现有的 Iceberg 支持,你可以使用该支持来 创建 Iceberg 表并使用 INSERT 写入其中、使用 DELETE、UPDATE 和 MERGE 修改行、将物化视图存储为 Iceberg 表,以及 提交互不重叠的并发写入。不过在此之前,每次写入都是各自提交的,一次一条语句。
在本文中,我们解释为什么每条语句提交一次会让多步骤管道变得脆弱,以及 Amazon Redshift 如何将多条语句作为一个快照提交。我们还会介绍可以在事务中运行什么、并发读取者和写入者会看到什么,以及多语句事务的性能表现。
每条语句提交一次的挑战
设想一家零售商,其财务团队跟踪每日收入。在白天,一些销售点(POS)值会被更正,例如价格修正,另一些则会被作废,例如已取消的订单。仪表板和下游作业从外部模式 sales(sale_id、store_id、sale_date、amount)中的一个 Iceberg 表读取收入,该外部模式为 iceberg_schema。每晚,POS 系统将当天的批次作为两个暂存 Iceberg 表交付。pos_sales 保存新增和更正的销售数据,每个 sale_id 一行,而 pos_voids 列出已作废的销售。一个作业用两条语句应用该批次:
-- 1. Upsert new and corrected sales
MERGE INTO iceberg_schema.sales USING iceberg_schema.pos_sales p
ON sales.sale_id = p.sale_id
WHEN MATCHED THEN UPDATE SET amount = p.amount
WHEN NOT MATCHED THEN INSERT VALUES (p.sale_id, p.store_id, p.sale_date, p.amount);
-- auto-commits: revenue includes voided sales
-- 2. Remove voided sales
DELETE FROM iceberg_schema.sales
WHERE sale_id IN (SELECT sale_id FROM iceberg_schema.pos_voids);
-- auto-commits: revenue is correct由于每条语句各自提交,它们之间的状态是公开的。在 DELETE 提交之前,每个读取者看到的收入都包含已作废的销售。如果 DELETE 失败,例如因为查询被取消,表就会保持该状态。如果作业后的检查发现批次有误,两项更改都已公开,因此你必须弄清楚哪些语句已生效,并编写 SQL 来撤销它们。每次提交也会耗费时间,因为它要将新的表元数据写入 Amazon Simple Storage Service(Amazon S3)并更新目录。一个包含 N 条语句的作业要支付 N 次目录更新。
Amazon Redshift 如何将多条语句作为一个快照提交
要使批次具有原子性,请将同样的语句包裹在 BEGIN 和 COMMIT 中。无需新的语法,作业可以在提交前审核结果:
BEGIN;
-- 1. Upsert new and corrected sales (full statement above)
MERGE INTO iceberg_schema.sales USING iceberg_schema.pos_sales p ON ...;
-- 2. Remove voided sales
DELETE FROM iceberg_schema.sales
WHERE sale_id IN (SELECT sale_id FROM iceberg_schema.pos_voids);
-- 3. Audit: data quality checks see the uncommitted changes
SELECT sum(amount) AS day_total,
sum(CASE WHEN amount < 0 THEN 1 ELSE 0 END) AS negative_rows
FROM iceberg_schema.sales
WHERE sale_date = '2026-10-06';
-- 4. COMMIT if the checks pass; otherwise ROLLBACK
COMMIT;此事务中发生的情况如下:
- 每条语句都基于前一条语句未提交的元数据构建,因此事务会累积一个待处理快照。
- 在事务内以相同名称读取
sales会看到该待处理快照。审核SELECT会在其他任何会话或引擎都看不到该批次的情况下对其进行检查。 - 在
COMMIT时,Amazon Redshift 将整个批次作为一个快照发布,只需一次目录更新,而不是每条语句一次。其他会话和引擎中的读取者看到的要么是批次之前的表,要么是批次之后的表,绝不会看到中间状态。 - 如果某条语句失败,或作业发出
ROLLBACK,则不会发布任何内容。表保持BEGIN之前的状态,无需撤销任何内容。
此事务是纯 SQL 中会话作用域的写入-审核-发布模式。作业的编排器,例如你的应用程序或 Apache Airflow 任务,仅在 day_total 与 POS 系统的控制总计匹配且 negative_rows 为零时才提交。否则它会发出 ROLLBACK,读取者继续看到 sales 最后验证过的版本,同时团队调查该批次。
图 1:其他读取者在自动提交和多语句事务下看到的内容
在事务内可以运行什么
Iceberg DML 可在显式事务块、多语句命令字符串和预备语句中接受,包括通过 Amazon Redshift JDBC 驱动程序发送的预备语句。
事务中的所有写入都必须指向同一个 Iceberg 表。该表可以位于 AWS Glue Data Catalog 或 Amazon S3 Tables 中,你可以通过外部模式或自动挂载的 awsdatacatalog 目录来引用它。在整个事务中,请使用相同的名称引用该表。Amazon Redshift 通过你引用表的方式来标识表。如果你通过两个外部模式引用同一个物理表,或者通过一个外部模式和 awsdatacatalog 引用同一个物理表,它会被视为两个表。通过第二个名称进行的写入会被拒绝。
| 事务内的语句 | 行为 |
| 跨数据库读取 Iceberg、Redshift 托管存储(RMS)和外部表 | 允许 |
针对一个 Iceberg 表的 INSERT、UPDATE、DELETE、MERGE | 允许。在 COMMIT |
时作为一个快照发布对一个 Iceberg 物化视图执行 REFRESH MATERIALIZED VIEW | 允许。该视图是事务的写入目标 |
| 以相同名称读取你正在写入的 Iceberg 表 | 允许。可看到你未提交的更改 |
| 写入第二个 Iceberg 表 | 拒绝 |
在 Iceberg 写入之前或之后的任何其他写入:RMS 或临时表 DML、COPY、UNLOAD、GRANT、REVOKE、ANALYZE 或其他数据定义语言(DDL) | 拒绝 |
对 Iceberg 表执行 DDL:CREATE TABLE、CREATE TABLE AS、ALTER TABLE、CREATE MATERIALIZED VIEW、DROP TABLE、DROP MATERIALIZED VIEW | 拒绝 |
| 在存储过程中进行 Iceberg 写入 | 拒绝 |
被拒绝的语句会失败并中止事务,因此它之前执行的任何内容都不会被发布。
夜间作业符合这些规则:它读取 Iceberg 表 pos_sales 和 pos_voids,并且只写入 sales。如果该作业还要从暂存表中清除已处理的行,请在 COMMIT 之后执行。在事务内部执行则会成为对第二个 Iceberg 表的写入。
注意:这会改变现有工作负载的行为。以前在 BEGIN … COMMIT 中执行单个 Iceberg DDL 语句会成功,现在则会被拒绝。请将 Iceberg DDL 作为独立语句运行。
清理孤立文件
事务写入但未提交的中间文件不会被任何快照引用,会成为孤立文件。对于 Amazon S3 Tables,表存储桶默认启用了 未引用文件移除。对于 AWS Glue Data Catalog 中的表,请启用 孤立文件删除表优化器。它只删除在启用后创建的文件,因此请在开始使用多语句事务之前启用它。
并发读取方和写入方
多语句事务提供三项保证:
- 原子发布:在你执行
COMMIT之前,其他会话和引擎看不到你的任何更改;提交后,它们会在一个快照中看到全部更改。 - 读取自己的写入:只要你使用相同的名称,对你正在写入的 Iceberg 表的读取会包含你未提交的更改。
- 对每个表的可重复读取:对某个 Iceberg 表的首次读取会为该表的版本在事务的剩余部分内固定下来。之后对该表的读取会返回相同的数据,即使其他会话在此期间向该表提交了更改。
每个表的版本在首次读取时固定,而不是在事务开始时固定。你在事务中稍后首次读取的 Iceberg 表可以包含其他会话在事务开始后提交的更改。例如,假设夜间作业读取 sales,然后在 Iceberg stores 表中查找门店详情。该查找会包含另一个会话在此期间提交到 stores 的更改:
-- Session 1 -- Session 2
BEGIN;
SELECT * FROM iceberg_schema.sales;
-- fixes the version of sales
INSERT INTO iceberg_schema.stores ...;
-- auto-commit
SELECT * FROM iceberg_schema.stores;
-- first read of stores:
-- includes Session 2's insert
COMMIT;RMS 表遵循其自己的快照,该快照取自事务的第一条语句,且不与 Iceberg 目录协调。
性能
为了衡量性能影响,我们将逐条提交每条语句与将相同的语句批量放入多语句事务进行了比较。我们报告的是相对于单语句提交的结果。
设置:在 US East (N. Virginia) 区域(us-east-1)的 AWS Glue Data Catalog 中注册的一个 Iceberg 表,由单个 Amazon Redshift 预置集群写入。吞吐量测试在固定时间窗口内为每个写入方运行一个会话。每个写入方背靠背地运行其事务。提交失败的事务会回滚,且不计入统计。结果因语句大小、分区和争用情况而异。
延迟
我们首先测量了批处理旨在帮助的场景:大量小语句,其中提交而非数据移动主导运行时间。每种配置针对一个表运行相同的 500 条小语句,只有每次提交的语句数量发生变化。
图 2:500 条小语句总运行时间的减少幅度,相对于逐条提交每条语句
如图 2 所示,与逐条提交每条语句相比,每次提交批量处理 25 条语句使 INSERT 的总运行时间减少了 14.77%,使 DELETE 的总运行时间减少了 11.29%。其中超过一半的收益在每次提交 4 条语句时已经实现(9.20% 和 6.21%)。收益来自每个事务只需支付一次目录提交,而不是每条语句支付一次,并且减少了每条语句的事务开销。
然而,当每条语句本身已经执行繁重的数据工作时,合并提交节省的时间太小,难以察觉。将语句批量放入一个事务并不会使作业显著更快。
吞吐量
使用多语句事务时,一次目录提交可以承载多条语句的更改,从而提高写入吞吐量。为了衡量这一点,我们针对一个表运行了数量递增的并发写入方,比较了自动提交的单语句 INSERT 与包含四条 INSERT 的事务。图 3 显示了每秒提交的语句数,并归一化到单个自动提交写入方。
这些结果是在启用冲突解决的情况下测得的,该机制适用于每个多语句事务。在你的事务打开期间,另一个写入方可能向同一个表提交。如果两组更改不重叠,Amazon Redshift 会将你的事务变基到最新的表版本,并将其作为一个快照提交,而不会重新运行其中的任何语句。只有真正的冲突(即两个写入更改了相同的数据)才会导致 COMMIT 失败。在这种情况下,请从应用程序中重试该事务。
图 3:随着并发写入方增加,每秒提交的语句数,归一化到单个自动提交写入方
优势随着并发度提高而增长。在只有一个写入方时,事务提交的语句数是自动提交的 1.18 倍。随着写入方增加,两种配置的每秒目录提交数都趋于平稳,但每个事务提交承载四条语句而不是一条。在 32 个并发写入方时,自动提交达到单写入方速率的 2.89 倍,事务达到 10.37 倍。也就是在同一时间窗口内提交的语句数是 3.59 倍。
结论
多步骤写入是数据管道的常规形态。在此之前,针对 Iceberg 表的每个步骤都各自可见,只能手动撤销。借助多语句事务,Amazon Redshift 将针对同一张 Iceberg 表的一组 DML 语句作为单个原子快照发布。读取方永远不会看到半途应用的变化,失败后也无需撤销任何内容。该管道还只需支付一次目录提交,而不是每条语句一次。要开始使用,请升级到 补丁 206 或更高版本。
要了解有关 Amazon Redshift 中 Iceberg 支持的更多信息,请参阅以下资源:
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏