You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何抑制Glue作业中Redshift临时表不存在的异常通知?

问题解决:Glue写入Redshift时临时表不存在的异常消除

核心原因

你的推测完全正确:Glue的write_dynamic_frame.from_jdbc_conf在执行preactions之前,会先校验dbtable指定的表是否存在,第一次运行时表尚未创建,底层JDBC驱动会抛出表不存在的异常。虽然后续preactions会创建表并完成数据写入,但该异常会留在日志中,且Python的try-except无法捕获(因为异常来自Glue底层JDBC操作,而非Python代码层面)。

解决方案

1. 提前独立创建临时表

在调用from_jdbc_conf之前,先通过Redshift Data API执行表创建语句,确保写入时表已存在。

示例代码:

import boto3
import time

# 初始化Redshift Data客户端
redshift_data = boto3.client('redshift-data')

# 构建创建临时表的SQL
create_table_sql = f"CREATE TABLE IF NOT EXISTS staging_table (LIKE {_redshift_db_info['TargetTable']})"

# 执行SQL语句
execute_response = redshift_data.execute_statement(
    ClusterIdentifier="你的Redshift集群ID",
    Database="some_db",
    IamRoleArn=REDSHIFT_JDBC_IAM,
    Sql=create_table_sql
)

# 等待SQL执行完成
statement_id = execute_response['Id']
while True:
    status = redshift_data.describe_statement(Id=statement_id)['Status']
    if status in ["FINISHED", "FAILED", "ABORTED"]:
        if status == "FAILED":
            raise Exception(f"创建临时表失败:{redshift_data.describe_statement(Id=statement_id)['Error']}")
        break
    time.sleep(2)

# 执行Glue写入操作
from_jdbc_conf(
    frame=df,
    catalog_connection=CATALOG_CONNECTION,
    connection_options=jdbc_options,
    transformation_ctx="write_dynamic_frame",
    redshift_tmp_dir=S3_BUCKET_REDSHIFT_TEMP_DIR
)

2. 调整日志过滤规则

如果不想修改代码逻辑,可以通过CloudWatch日志过滤掉该异常:

  • 进入Glue作业对应的CloudWatch日志组
  • 添加过滤模式,精准匹配表不存在的异常文本(例如"Table does not exist"),将其设置为忽略
  • 注意:过滤规则要精准,避免误屏蔽其他重要错误日志

替代流程方案

方案A:使用Spark原生JDBC写入

将Glue DynamicFrame转换为Spark DataFrame,直接调用Spark的JDBC写入API,部分场景下Spark会优先执行preActions再校验表存在:

# 转换为Spark DataFrame
spark_df = df.toDF()

# 构建JDBC参数
jdbc_url = "jdbc:redshift://你的Redshift集群端点:5439/some_db"
spark_jdbc_options = {
    "dbtable": "staging_table",
    "preActions": f"CREATE TABLE IF NOT EXISTS staging_table (LIKE {_redshift_db_info['TargetTable']})",
    "postActions": query_to_insert_from_stageing_table_to_target_table,
    "aws_iam_role": REDSHIFT_JDBC_IAM,
    "tempdir": S3_BUCKET_REDSHIFT_TEMP_DIR,
    "driver": "com.amazon.redshift.jdbc42.Driver"
}

# 执行写入
spark_df.write \
    .format("jdbc") \
    .options(**spark_jdbc_options) \
    .mode("append") \
    .save()

方案B:改用固定临时表+截断逻辑

提前在Redshift中创建好staging_table结构,每次写入前用preactions截断表,而非动态创建:

jdbc_options = {
    "database": "some_db",
    "dbtable": "staging_table",
    "preactions": "TRUNCATE TABLE staging_table;",
    "postactions": query_to_insert_from_stageing_table_to_target_table,
    "aws_iam_role": REDSHIFT_JDBC_IAM
}

这种方式彻底避免了表不存在的校验问题,适合重复使用同一临时表的场景。

内容的提问来源于stack exchange,提问作者Nick Clayne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 13:52:41