この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
いわさです。
Lambda(Python)から RDS for Oracle へアクセスする必要があり、今回実装にOracle公式の python-oracledb というモジュールを試してみたのでご紹介します。
python-oracledb とは
Oracle公式
python-oracledb とは、Pythonプログラムが Oracle データベースへアクセスできるようにするためのオープンソースモジュールです。
Python DB-API v2.0 に準拠しており、Oracle によって開発・提供されています。
cx_Oracleの後継
以前は、PythonプログラムからOracleデータベースへアクセスする際には、Python cx_Oracleというモジュールを使っていました。
python-oracledbはcx_oracleの後継です。
Oracle Client ライブラリなしでも接続可能(!!)
ドキュメントを読んでいて、これはすごいなぁと思ったのが、このモジュールのみで Oracle Client ライブラリなしで直接接続出来ます。(Thin Mode)
cx_Oracleでは別途Oracle Clientライブラリをインストールする必要があり、Lambdaの場合であればデプロイパッケージに同梱するかLambdaレイヤーを用意する必要がありました。
ただし、Oracle Client ライブラリを使って接続するモード(Thick Mode)も用意されており、高度なOracleクライアントの機能を使う場合はこちらのモードを利用する必要があります。
デフォルトはThinモードで動作しており、ThickモードでOracle Clientライブラリを使いたい場合は別途有効化が必要です。
3.1. Enabling python-oracledb Thick mode¶
ライセンスは Apache License 2.0
あと、cx_OracleはライセンスがBSDでしたが、python-oracledbではApache License 2.0に変わっています。
特に、cx_Oracleから移行される方は認識しておきましょう。
パブリックアクセス可能なRDS と SAM を使って試してみる
今回はThinモードを使って、Oracle Client ライブラリなしで RDS for Oracleへ接続してみたいと思います。
事前にパブリックアクセス可能なRDS for Oracleを作成し、適当なテーブルとレコードを作成しておきます。
認証情報や接続文字列はサンプル用に適当なものを使っています。
$ sqlplus admin/password@database-1.cpnu9ipu74g4.ap-northeast-1.rds.amazonaws.com:1521/orcl
SQL*Plus: Release 19.0.0.0.0 - Production on Thu Jun 16 18:51:19 2022
Version 19.8.0.0.0
Copyright (c) 1982, 2020, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.14.0.0.0
SQL> CREATE TABLE test
(
hoge_id VARCHAR2( 2 3 8) NOT NULL,
hoge_name VARCHAR2(50)
);
Table created.
SQL> INSERT INTO test (hoge_id, hoge_name) VALUES ('1', 'aaa');
1 row created.
SQL> INSERT INTO test (hoge_id, hoge_name) VALUES ('2', 'bbb');
1 row created.
SQL> INSERT INTO test (hoge_id, hoge_name) VALUES ('3', 'ccc');
1 row created.
SQL> select * from test;
HOGE_ID HOGE_NAME
-------- --------------------------------------------------
1 aaa
2 bbb
3 ccc
検証用のテーブルとレコードを作成しました。
Lambda から利用してみる
次に、Lambdaから先程作成したデータを取得してみます。
今回は、SAM CLI の HelloWolrd テンプレートにデータアクセスロジックを追加してみたいと思います。
流れとしてはrequirements.txt
にoracledb
を追加し、データアクセスロジックを追加します。
あとはsam build
してsam deploy
すればうまいことレイヤー作ってうまいことデプロイしてくれます。
デプロイパッケージ作成する時どうするとか、普通にRDBMSにアクセスしちゃってるのでコネクションまわり大丈夫なのかとかあると思うのですが、今回はとりあえずモジュール使ってOracleデータベースへアクセスするってところを目的にしているので、細かいことは無視したいと思います。
$ sam init
You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.
:
HelloWorld配下のrequirements.txt
に追加し、pip install
します。
requirements.txt
requests
oracledb
$ pip install -r requirements.txt
Collecting oracledb
Downloading oracledb-1.0.1-cp39-cp39-macosx_10_9_universal2.whl (2.4 MB)
|████████████████████████████████| 2.4 MB 639 kB/s
Collecting cryptography>=3.4
Downloading cryptography-37.0.2-cp36-abi3-macosx_10_10_x86_64.whl (2.8 MB)
|████████████████████████████████| 2.8 MB 325 kB/s
Collecting cffi>=1.12
Downloading cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl (178 kB)
|████████████████████████████████| 178 kB 529 kB/s
Collecting pycparser
Downloading pycparser-2.21-py2.py3-none-any.whl (118 kB)
|████████████████████████████████| 118 kB 692 kB/s
Installing collected packages: pycparser, cffi, cryptography, oracledb
Successfully installed cffi-1.15.0 cryptography-37.0.2 oracledb-1.0.1 pycparser-2.21
:
データアクセスロジックを追加します。
コネクションを作成し、クエリを実行します。
以下の実装は公式サンプルを参考に実装していますが、カーソルオブジェクトからフェッチする動きはcx_Oracleと同じですね。
移行簡単に出来るかもしれないです。
app.py
import json
import oracledb
import os
un = os.environ.get('PYTHON_USERNAME')
pw = os.environ.get('PYTHON_PASSWORD')
cs = os.environ.get('PYTHON_CONNECTSTRING')
def lambda_handler(event, context):
with oracledb.connect(user=un, password=pw, dsn=cs) as connection:
with connection.cursor() as cursor:
sql = """select * from test"""
for r in cursor.execute(sql):
print(r)
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
# "location": ip.text.replace("\n", "")
}),
}
あとはビルドして、クラウド上へデプロイします。
$ sam build
Your template contains a resource with logical ID "ServerlessRestApi", which is a reserved logical ID in AWS SAM. It could result in unexpected behaviors and is not recommended.
Building codeuri: /Users/iwasa.takahito/work/hoge0616oracle/hoge0616oracle/hello_world runtime: python3.9 metadata: {} architecture: x86_64 functions: ['HelloWorldFunction']
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Build Succeeded
:
$ sam deploy --stack-name hoge0616oracle --guided
動作確認
サンプルではデータベースへ接続する際の情報を環境変数から取得しているので、環境変数を設定します。
私はsamのテンプレートでFunctionsに環境変数を追加しました。サンプルなので再デプロイで上書きされることを無視するのであれば以下のように直接Lambda上で環境変数を設定してもOKです。
実運用の際はLambdaのベストプラクティスに従って、Secret Managerなど秘匿情報の取り扱い方法を考える必要があります。
HelloWorldはAPI GatewayもデプロイされるのでHTTPアクセスしても良いですが、今回はLambdaコンソールからテスト実行までで。
実行ログを確認してみます。
START RequestId: 355656f0-29ad-40c0-af52-939d427bcd38 Version: $LATEST
('1', 'aaa')
('2', 'bbb')
('3', 'ccc')
END RequestId: 355656f0-29ad-40c0-af52-939d427bcd38
REPORT RequestId: 355656f0-29ad-40c0-af52-939d427bcd38
おー、取得出来ています。
さいごに
本日は、python-oracledb を使って Lambda(Python) から RDS for Oracle へアクセスしてみました。
Oracle公式から提供されているモジュールということもあり安心して使えますね。
Oracle Client ライブラリ不要で使えるのかなり良いですね、Lambda以外でも、ライトにOracleデータベースへアクセス出来そうです。