云函数调用Oracle数据库报DPI-1047错误,如何关联云存储桶中的Oracle Client库?
问题描述
构建调用Oracle数据库的云函数时遇到以下问题:
- 已编写Python查询代码并存入代码库,HTTP触发器运行正常
- Oracle Client Library已上传至同区域云存储桶,但云函数运行时抛出找不到Oracle客户端库的错误
- 错误信息:
Error: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory"
相关代码如下:
import cx_Oracle def queryOracleDatabase(request): # Oracle Database Connection username = 'x' password = 'y' connStr = '00.00.00.00:0000/abcd' try: conn = cx_Oracle.connect(username, password, connStr) except cx_Oracle.DatabaseError as e: error = e.args print('Error: ', error.message) return # Execute the query try: cursor = conn.cursor() cursor.execute('select * table') # 注意:此处SQL语法错误,应为select * from table data = cursor.fetchall() except cx_Oracle.DatabaseError as e: error = e.args print('Error: ', error.message) return # Clean up cursor.close() conn.close() return data
解决步骤
1. 配置云函数的存储桶访问权限
为云函数关联的服务账号添加存储对象查看器(或等价的读取权限),确保云函数有权限读取存储桶中的Oracle Client Library文件。
2. 在云函数启动时下载客户端库到临时目录
云函数运行环境仅/tmp目录可写,需在代码执行前将存储桶中的Oracle Client Library(建议打包为zip压缩包)下载到该目录并解压。以GCP云函数为例,示例代码片段如下:
from google.cloud import storage import os import zipfile def download_oracle_client(): bucket_name = "你的存储桶名称" source_blob_name = "oracle_client.zip" # 存储桶中客户端库压缩包的路径 destination_file_name = "/tmp/oracle_client.zip" extract_path = "/tmp/oracle_client" # 初始化存储客户端 storage_client = storage.Client() bucket = storage_client.bucket(bucket_name) blob = bucket.blob(source_blob_name) # 下载压缩包到临时目录 blob.download_to_filename(destination_file_name) # 解压压缩包 with zipfile.ZipFile(destination_file_name, 'r') as zip_ref: zip_ref.extractall(extract_path) # 设置环境变量,让cx_Oracle能找到客户端库文件 os.environ['LD_LIBRARY_PATH'] = f"{extract_path}/lib:{os.environ.get('LD_LIBRARY_PATH', '')}"
3. 修改原函数,整合客户端初始化逻辑
在queryOracleDatabase函数开头调用上述初始化函数,确保连接Oracle前已完成客户端库的配置:
import cx_Oracle from google.cloud import storage import os import zipfile def download_oracle_client(): bucket_name = "你的存储桶名称" source_blob_name = "oracle_client.zip" destination_file_name = "/tmp/oracle_client.zip" extract_path = "/tmp/oracle_client" storage_client = storage.Client() bucket = storage_client.bucket(bucket_name) blob = bucket.blob(source_blob_name) blob.download_to_filename(destination_file_name) with zipfile.ZipFile(destination_file_name, 'r') as zip_ref: zip_ref.extractall(extract_path) os.environ['LD_LIBRARY_PATH'] = f"{extract_path}/lib:{os.environ.get('LD_LIBRARY_PATH', '')}" def queryOracleDatabase(request): # 先初始化Oracle客户端库 try: download_oracle_client() except Exception as e: print('Failed to initialize Oracle client: ', str(e)) return # Oracle Database Connection username = 'x' password = 'y' connStr = '00.00.00.00:0000/abcd' try: conn = cx_Oracle.connect(username, password, connStr) except cx_Oracle.DatabaseError as e: error = e.args[0] if e.args else e print('Connection Error: ', error.message) return # Execute the query try: cursor = conn.cursor() cursor.execute('select * from table') # 修正SQL语法错误 data = cursor.fetchall() except cx_Oracle.DatabaseError as e: error = e.args[0] if e.args else e print('Query Error: ', error.message) return finally: # 确保资源被正确释放 if 'cursor' in locals(): cursor.close() if 'conn' in locals(): conn.close() return data
4. 添加依赖包
在云函数的requirements.txt中添加所需依赖:
cx_Oracle>=8.0 google-cloud-storage>=2.0
内容的提问来源于stack exchange,提问作者Gojoe
相关产品推荐
相关产品推荐

