【问题标题】:how to fix cx_Oracle.DatabaseError: ORA-12170: TNS:Connect timeout occurred如何修复 cx_Oracle.DatabaseError:ORA-12170:TNS:发生连接超时
【发布时间】:2020-10-10 16:06:36
【问题描述】:

我正在尝试运行 Python 脚本以将一些数据从 docker 映像插入到 Oracle 表中。

我得到了以下连接字符串:

jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=3)(RETRY_COUNT=2)(FAILOVER=ON)(LOAD_BALANCE=NO) (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=host_1)(PORT=1521))) (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=host_2)(PORT=1521))) (CONNECT_DATA=(SERVICE_NAME=service_name)))   

我正在尝试使用cx_Oracle 包进行连接:

try:
    # establish a new connection
    with cx_Oracle.connect(self.oracle_user,
                            self.oracle_pwd,
                            self.oracle_dsn) as connection:
        logger.info('ElasticsearchFinder.oracle_write : connexion established with DB')

oracle_dsn 是连接字符串(减去 jdbc:oracle:thin:@ 部分)

我也尝试过

cx_Oracle.connect(self.oracle_user+'/'+self.oracle_pwd+'@'+self.oracle_dsn)

如在某些示例中所见,但我总是收到以下超时错误:

cx_Oracle.DatabaseError: ORA-12170: TNS:Connect timeout occurred

telnet host 1521 工作正常,我也尝试更改 CONNECT_TIMEOUT 值。

我也试过

dsn_tns = cx_Oracle.makedsn(self.oracle_host, self.oracle_port, service_name = self.oracle_service_name)
cx_Oracle.connect(self.oracle_user,self.oracle_pwd,dsn_tns) 

按照here 的建议,但我得到了

cx_Oracle.DatabaseError: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor

我正在使用 Dockerfile 从 Docker 映像构建运行我的脚本:

FROM oraclelinux:7.8
RUN  yum -y install oracle-release-el7 && \
     yum-config-manager --enable ol7_oracle_instantclient && \
     yum -y install oracle-instantclient18.3-basic && \
     rm -rf /var/cache/yum
COPY ./fetch_session_iptv.py /opt/
COPY ./conf/fetch_session_iptv.conf /opt/conf/
#COPY ./conf/certs/* /opt/conf/certs/
COPY ./logs /opt/logs
RUN yum install -y \
    #https://yum.oracle.com/repo/OracleLinux/OL7/developer/x86_64/getPackage/oracle-instantclient18.3-basic-18.3.0.0.0-2.x86_64.rpm \
    https://yum.oracle.com/repo/OracleLinux/OL7/developer/x86_64/getPackage/python-cx_Oracle-7.3-1.el7.x86_64.rpm \
    https://yum.oracle.com/repo/OracleLinux/OL7/developer/x86_64/getPackage/python36-pytz-2016.10-2.0.1.el7.noarch.rpm
COPY ./python_requirements/elasticsearch-7.8.0-py2.py3-none-any.whl .
COPY ./python_requirements/certifi-2020.4.5.2-py2.py3-none-any.whl .
COPY ./python_requirements/urllib3-1.25.9-py2.py3-none-any.whl .
RUN pip3 install --user \
    certifi-2020.4.5.2-py2.py3-none-any.whl \
    urllib3-1.25.9-py2.py3-none-any.whl \
    elasticsearch-7.8.0-py2.py3-none-any.whl \
    cx_Oracle
RUN sh -c "echo /usr/lib/oracle/18.3/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf"
RUN ldconfig
RUN export ORACLE_HOME=/usr/lib/oracle/18.3/client64/
RUN yum -y install telnet
#CMD ["/bin/bash"]
CMD [ "python3", "/opt/fetch_session_iptv.py" ]

我不明白出了什么问题?

[更新]我已经设置了

  • ORACLE_HOME=/usr/lib/oracle/18.3/client64/bin
  • TNS_ADMIN=$ORACLE_HOME/admin
  • LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib
  • PATH=$PATH:$ORACLE_HOME

我在 TNS_ADMIN 目录中添加了一个tnsnames.ora 文件,其中

CNX=(DESCRIPTION=(CONNECT_TIMEOUT=3)(RETRY_COUNT=2)(FAILOVER=ON)(LOAD_BALANCE=NO) (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=host_1)(PORT=1521))) (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=host_2)(PORT=1521))) (CONNECT_DATA=(SERVICE_NAME=service_name)))

现在,当我尝试sqlplus MY_USER@CNX 时,我得到了同样的结果:

ORA-12170: TNS:Connect timeout occured

但至少它似乎接受了连接字符串和用户。在正确设置所有环境变量之前,我只收到了关于TNS: listener does not currently know of service requested in connect descriptor 或网络服务名称不正确的不同 TNS 错误消息。

[更新 2] 我已经与给我所有连接信息的人核对了:用户、密码和连接字符串是否正确。他们正在运行 Oracle Database 12c (12.1.0.2.0),根据this page,它与我正在使用的 18c 客户端兼容。

我不知道这个超时错误还有什么可能的原因?

【问题讨论】:

  • 你是否定义了一个名为TNS_ADMIN的环境变量,并设置指向TNSNAMES.ORA文件的目录?
  • 我没有使用TNSNAMES.ORA文件来获取连接信息,Oracle是否默认只检查该文件?
  • 另外,当我尝试将任何环境变量设置到我的 Dockerfile (RUN export my_env_variable = /usr/....) 中,然后 docker exec echo $my_env_variable 中,它总是返回一个空字符串,我不明白为什么它似乎没有上班
  • 首先,永远不要使用 Instant Client 设置 ORACLE_HOME。它会导致诸如命中 ORA-1804 之类的问题。 Instant Client 不是基于 Oracle Home 的安装。其次,网络文件的默认目录是/usr/lib/oracle/18.3/client64/lib/network/admin。将文件放在那里并取消设置 TNS_ADMIN。

标签: python oracle sqlplus cx-oracle oracleclient


【解决方案1】:

首先使用 cx_Oracle 中的等效连接字符串:

self.oracle_dsn = "(DESCRIPTION=(CONNECT_TIMEOUT=3)(RETRY_COUNT=2)(FAILOVER=ON)(LOAD_BALANCE=NO) (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=host_1)(PORT=1521))) (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=host_2)(PORT=1521))) (CONNECT_DATA=(SERVICE_NAME=service_name)))"

try:
    # establish a new connection
    with cx_Oracle.connect(self.oracle_user,
                            self.oracle_pwd,
                            self.oracle_dsn) as connection:
        logger.info('ElasticsearchFinder.oracle_write : connexion established with DB')

关于连接和连接字符串的 cx_Oracle 手册是here

我个人会使用 19c Instant Client,它将连接到与 18c 相同的数据库版本 - 并且不需要运行 ldconfig。见Docker for Oracle Database Applications in Node.js and Python

用信息更新你的问题,我同样可以更新这个答案。

【讨论】:

  • 这已经是我正在使用的连接字符串,我将尝试使用 19c Instant Client
猜你喜欢
  • 2019-01-21
  • 2019-11-13
  • 2014-07-21
  • 2016-12-04
  • 1970-01-01
  • 2015-11-03
  • 2012-02-03
  • 2016-07-29
  • 2015-05-23
相关资源
最近更新 更多