Apache Airflow 和 Oracle 连接

问题描述 投票:0回答:1

我正在尝试从本地 Oracle 数据库(Oracle Database 11g 版本 11.2.0.4.0 - 64 位生产)读取数据。

我创建了自己的 docker 镜像:

# Use the base Apache Airflow image
FROM apache/airflow:2.8.3
# Set environment variables for the Oracle Instant Client
ENV ORACLE_HOME=/opt/oracle
ENV LD_LIBRARY_PATH=$ORACLE_HOME/lib
# Switch to the root user temporarily
USER root
# Install required packages
RUN apt-get update && apt-get install -y \
    unzip \
    libaio1 \
    && rm -rf /var/lib/apt/lists/*
# Create the Oracle directory with proper permissions
RUN mkdir -p $ORACLE_HOME && chown -R airflow: $ORACLE_HOME
# Create the tmp directory with proper permissions
RUN mkdir -p /tmp && chown -R airflow: /tmp
# Switch back to a non-root user (e.g., "airflow")
USER airflow
# Install Python packages required for Oracle client and Airflow Oracle provider
RUN pip install oracledb apache-airflow-providers-oracle pandas sqlalchemy
# Download and install the Oracle Instant Client
# https://www.oracle.com/de/database/technologies/instant-client/linux-x86-64-downloads.html
COPY instantclient-basic-linux.x64-19.22.0.0.0dbru.zip /tmp/
COPY instantclient-sdk-linux.x64-19.22.0.0.0dbru.zip /tmp/
RUN unzip /tmp/instantclient-basic-linux.x64-19.22.0.0.0dbru.zip -d $ORACLE_HOME && \
    unzip -o /tmp/instantclient-sdk-linux.x64-19.22.0.0.0dbru.zip -d $ORACLE_HOME 
# Delete ZIP Files
RUN rm -rf /tmp/instantclient-basic-linux.x64-19.22.0.0.0dbru.zip /tmp/instantclient-sdk-linux.x64-19.22.0.0.0dbru.zip
# Set environment variables for Oracle Instant Client
ENV PATH=$PATH:$ORACLE_HOME
ENV ORACLE_VERSION=19.22

简而言之:oracledb apache-airflow-providers-oracle pandas sqlalchemy 以及来自 oracle.com 的 instantclient-basic-linux.x64-19.22.0.0.0dbru.zip 已添加到标准映像中。

docker compose build 可以工作,docker compose init 可以工作,docker compose up 可以正常工作,没有错误。

Oracle 显示为连接类型,我已经创建了一个连接:

我的测试 DAG 如下所示:

from datetime import datetime
from airflow import DAG
from airflow.decorators import task
from airflow.providers.oracle.hooks.oracle import OracleHook

table_name = "DB.TABLE"
@task
def get_data_from_oracle():
    oracle_hook=OracleHook(oracle_conn_id='Oracle_***')
    data = oracle_hook.get_pandas_df(sql=f"SELECT COUNT(1) FROM {table_name}")
    return data.to_dict()

with DAG('oracle_test', start_date=datetime(2022, 1, 1), schedule_interval='@once') as dag:
    data = get_data_from_oracle()

如果我运行所述 DAG,我会收到无法解决的错误。它运行大约一分钟,并因以下错误而终止:(我假设超时)

[2024-03-21T10:27:31.754+0000] {standard_task_runner.py:107} 错误 - 无法执行任务 get_data_from_oracle 的作业 8(DPY-6005:无法连接到数据库(CONNECTION_ID=P26GiMCTIFWWPDhkB4vZQ==)。 DPY-4011:数据库或网络关闭了连接 [Errno 104] 连接被对等方重置 帮助:https://python-oracledb.readthedocs.io/en/latest/user_guide/troubleshooting.html#dpy-4011; 534)

或者,取决于配置:(无超时)

[2024-03-21, 16:57:08 CET] {standard_task_runner.py:107} 错误 - 无法为任务 get_data_from_oracle 执行作业 16(DPY-6005:无法连接到数据库(CONNECTION_ID=Ma2uz0YYUUhkdOMBsNNS0w==)。 DPY-6003:SID“**”未在主机“10...”端口 1524 处向侦听器注册。(类似于 ORA-12505);第5827章)

我仔细检查了 ip、ping、SID(通过查询)等。

我想我在这两方面都做了一些严重错误的事情

  1. 容器的设置
  2. DAG
  3. 与 Oracle 的联系(这在 文档)

无论哪种方式,互联网研究都没有解决方案。如果有人可以向我提供连接到 Oracle DB 的提示或工作方法,我将不胜感激。请不要让我回到 SSIS。

更新: 使用 Oracle Database 12c 版本 12.1.0.1.0 - 64 位生产 对数据库执行相同的查询,没有任何问题。这似乎是版本/驱动程序的问题。

oracle airflow
1个回答
0
投票

我终于弄清楚了:使用正确参数的连接(我在那里犯了一个错误,因为从 tnsping 复制粘贴似乎默认给出了 2 个主机)会给你这个错误:

DPY-3010:精简模式下的 python-oracledb 不支持与此数据库服务器版本的连接

从那里(在将 python-oracledb 连接到 Oracle DB 11.2 时出现错误 DPY-3010 的帮助下),您可以访问 https://airflow.apache.org/docs/apache-airflow-providers-oracle/stable/connections /oracle.html 解释了如何通过 DAG 中的“厚模式”访问 Oracle 数据库:

def get_data_from_oracle(): oracle_hook=OracleHook(oracle_conn_id='Oracle_SWILX1_2', thick_mode=True) data = oracle_hook.get_pandas_df(sql=f"SELECT COUNT(1) FROM {table_name}") return data.to_dict()
接下来您需要确保正确设置 oracle 即时客户端。 oracle Zip (instantclient-basic-linux.x64-19.22.0.0.0dbru.zip) 包含一个带有版本名称的子文件夹。如果将其内容复制到 $ORACLE_HOME airflow/python/oracle 将无法在预期文件夹中找到文件。

DPI-1047:无法找到 64 位 Oracle 客户端库:“/opt/oracle/lib/libclntsh.so:无法打开共享对象文件:没有这样的文件或目录”。

我在我的 dockerfile 中用 -j(压平 ZIP 中的文件夹)永久修复了这个问题:

# Use the base Apache Airflow image FROM apache/airflow:2.8.3 # Set environment variables for the Oracle Instant Client ENV ORACLE_HOME=/opt/oracle ENV LD_LIBRARY_PATH=$ORACLE_HOME # Switch to the root user temporarily USER root # Install required packages RUN apt-get update && apt-get install -y \ unzip \ libaio1 \ && rm -rf /var/lib/apt/lists/* # Create the Oracle directory with proper permissions RUN mkdir -p $ORACLE_HOME && chown -R airflow: $ORACLE_HOME # Create the tmp directory with proper permissions RUN mkdir -p /tmp && chown -R airflow: /tmp # Switch back to a non-root user (e.g., "airflow") USER airflow # Install Python packages required for Oracle client and Airflow Oracle provider RUN pip install cx_Oracle oracledb apache-airflow-providers-oracle pandas sqlalchemy # Download and install the Oracle Instant Client # https://www.oracle.com/de/database/technologies/instant-client/linux-x86-64-downloads.html COPY instantclient-basic-linux.x64-19.22.0.0.0dbru.zip /tmp/ RUN unzip -j /tmp/instantclient-basic-linux.x64-19.22.0.0.0dbru.zip -d $ORACLE_HOME # Delete ZIP Files RUN rm -rf /tmp/instantclient-basic-linux.x64-19.22.0.0.0dbru.zip # Set environment variables for Oracle Instant Client ENV PATH=$PATH:$ORACLE_HOME ENV ORACLE_VERSION=19.22
只要启用厚模式,就可以从那里连接到“旧”(12.1 之前)系统。

后续步骤:

    我相信有人可以想出更好的解决方案
  • unzip -j
  • 也许有一种方法可以在气流连接级别注入
  • thick_mode=true,这样你就不必记住为每个 dag 插入它。
P.s.谢谢您

https://stackoverflow.com/users/610979/frank-schmitt的评论!

© www.soinside.com 2019 - 2024. All rights reserved.