PythonでOracle Databaseに接続するには、cx_Oracleを使う。
マルチスレッド環境下でcx_Oracleを使う場合にハマったのでメモを残す。
Oracleのクライアントライブラリは、マルチスレッドで使う際には、OCI_THREADEDというモードで使わないといけないらしい。
cx_OracleをOCI_THREADEDモードで使うには、connect関数のthreadedオプションにTrueを指定する。
>>> import cx_Oracle >>> connection = cx_Oracle.connect( ... "testuser", ... "testpassword", ... "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oracledb.example.com) (PORT=1521))(CONNECT_DATA=(SID=ORCL)))", ... threaded=True)
cx_Oracleのドキュメントにも説明があった。
The threaded argument is expected to be a boolean expression which indicates whether or not Oracle should use the mode OCI_THREADED to wrap accesses to connections with a mutex.
Module Interface — cx_Oracle 5.2.1 documentation
Doing so in single threaded applications imposes a performance penalty of about 10-15% which is why the default is False.
DjangoでOracleを使っていて、マルチスレッドで動作させる場合だと、settingsのデータベース設定に指定すればよい。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'oracledb.example.com:1521/orcl', 'USER': 'testuser', 'PASSWORD': 'testpassword', 'OPTIONS': { 'threaded': True, } } }
この指定をしない状態で、gunicornのThreadWorkerで動かしていた際に、低頻度でワーカープロセスがログを出力せずに死ぬ、という現象が発生していた。
シングルスレッドの場合は、threaded=Falseのほうがパフォーマンスが良いそうなので、使いどころに気をつけたい。