pythonのdatasetでcloseできない!コネクションが切れない!更新が反映されないときの対処法

PythonのDBライブラリであるdatasetは、ORMライブラリのためSQL文を書かずにmysqlを操作が可能です。

ものすごく便利なライブラリーなのですが、クセが少なからずあるようです。

筆者は、以下の2つの問題で大変苦労しました。

  1. 任意のタイミングでコネクションを切断できなくてコネクションがたまり続ける
  2. 別コネクションの更新が、反映されない

やっと解消方法がわかったので記事にしたいと思います!

closeができず、任意のタイミングでコネクションを切断できない

データベースとのやり取りするライブラリーは、closeなどの処理を呼び出せば、だいたい接続を切断できます。

しかし、datasetだとなぜかcloseを呼び出しても、コネクションが切断されませんでした。

その結果、WEBサーバーとしてリクエスト受ける度にdataset.connectを呼び出すものだと、

コネクションが増産されてしまいます。

「show processlist」で確認すると、ひたすらコネクションが増え続けることが確認取れます。

解消方法は次の2点です。

解消方法1・datasetを呼び出しているPythonのプロセスを終了させる

datasetを呼び出しているPythonのプロセスを終了させることで、コネクションを切断できます。

その結果、コネクションの異常な増殖を回避できます。

プロセスを終了させるわけだから、コネクションも自動的に消えるのも納得できます。

しかし、WEBプロセスのように常に待受が必要なものは、プロセスを終了させることができません。

そんなときは、次の方法が役立ちます。

解消方法2・closeの前に「あるコード」を呼び出す

closeの前に以下のコードを実行します。

db.executable.invalidate()
db.executable.engine.dispose()
db.close()

その結果、コネクションを切断することができ、

「show processlist」にてコネクションが増殖しないことを確認できました。

この方法は、私がお世話になっているスーパーエンジニアに当たる方から教えていただきました。

datasetについての情報があまりなかったため、大変助かりました。

全体的なコードは以下のとおりです。

import dataset
user_id = "root"
password = "mysql_pass"
host = "127.0.0.1"
db_name = "dj_test"

db = dataset.connect(
            'mysql://%s:%s@%s/%s?charset=utf8mb4' % (user_id, password, host, db_name))

#適当にselectする
table = db['auth_user']
result = table.find_one()
print(result)

##以下追加
db.executable.invalidate()
db.executable.engine.dispose()

#closeする
db.close()

尚、closeの詳細な挙動については、以下のサイトで詳しく検証されているので参考になります!

Pythonのdataset(SQLAlchemyのラッパー)のclose系処理を調べる

別コネクションの更新が反映されない

別コネクションの更新が、queryに反映されないという問題が発生しました。

現象は以下のような状況で発生しました。

  1. dataset.connectを呼び出してDBと接続する
  2. 任意のタイミングでテーブルAをfind(query)してデータを読み込む
  3. MySQLWorkBenchなどで、別コネクションでテーブルAのデータを変更する
  4. 変更したテーブルAにたいして再びfind(query)する

その結果、2回目のfindの結果は、MySQLWorkBenchで変更した内容が反映されていませんでした。

解決策1・_streamedを有効にする

find処理をするとき、以下のように_streamedを有効にします。

table.find_one(_streamed = True)

その結果、別コネクションの変更が反映されるようになります。

しかし、この欠点は、findの内部処理で新たにコネクションを作ってしまうこと。

コネクションを切断しないとコネクションが増え続けることを意識する必要があります。

解決策2・コネクションを切断する

どうやら、datasetはfindの実行結果をキャッシュしてしまうようです(詳しく見ていないので確認とれていませんが)。

よって、任意のタイミングでコネクションを切断します。

コネクションを切断し、再度、つなぐことにより別コネクションの内容を反映させることができます。

まとめ

datasetは、mysql文を書く機会を減らしてくれるので大変便利なライブラリです。

しかし、今回挙げたようなクセもあるので、うまく回避して使うことができれば良いですね。

スポンサーリンク
PR




PR




シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
PR