使用AWS Glue从S3向Redshift执行Upsert时临时表引用失败的问题排查
解决AWS Glue向Redshift Upsert时临时表不存在的问题
问题根源
你遇到的relation "public.#table_stg" does not exist错误,核心原因是AWS Glue会自动给未指定schema的dbtable参数添加public前缀,但Redshift的会话级临时表(以#开头)不允许携带任何schema前缀——临时表不属于任何用户定义的schema,而是存储在会话专属的临时空间中。Glue生成的COPY语句变成了COPY public.#my_table_stg ...,自然找不到对应的临时表。
解决方案
要让Glue正确处理Redshift临时表,只需修改一个关键配置,同时保持原有查询逻辑不变:
阻止Glue自动添加schema前缀
在connection_options中添加"schema": ""(空字符串),这样Glue就不会给dbtable指定的临时表名自动追加public前缀,确保COPY语句直接使用不带schema的临时表名。保持pre/post查询的正确性
你原有的pre/post查询逻辑(创建空临时表、Upsert后删除)是正确的,因为这些查询里已经直接使用不带schema的临时表名,完全符合Redshift对临时表的使用要求。
修改后的完整代码
table_wo_schema = "my_table" stg_table_name = f"#{table_wo_schema}_stg" table_name = f"myschema.{table_wo_schema}" # 保持原有的pre/post查询逻辑,临时表无schema前缀 pre_query = f"drop table if exists {stg_table_name};create table {stg_table_name} as select * from {table_name} where 1=2;" post_query= f"delete from {table_name} using {stg_table_name} where {stg_table_name}.id = {table_name}.id ; insert into {table_name} select * from {stg_table_name}; drop table {stg_table_name};" # 添加schema: "" 阻止Glue自动追加public前缀 glueContext.write_dynamic_frame.from_jdbc_conf( frame = dynamic_frame_to_write, catalog_connection = "my-redshift-connection", connection_options = { "preactions": pre_query, "dbtable": stg_table_name, "database": "my-redshift-database", "postactions": post_query, "schema": "" # 关键配置:禁用自动schema前缀 }, redshift_tmp_dir = "s3://some/dir" )
额外验证点
- 确认Glue连接使用的Redshift用户拥有创建临时表的权限(默认情况下,只要用户有数据库的USAGE权限就能创建临时表)。
- 临时表是会话级别的,只会在当前Glue任务的会话中存在,其他会话无法访问,完全符合你不想让staging表被外部访问的需求。
内容的提问来源于stack exchange,提问作者Gamaliel Ronzón
相关产品推荐
相关产品推荐

