38

私は、プロジェクトの非常に特殊な要件を満たすために、カスタムDAOのようなクラスをいくつか開発しました。これは、どのような種類のフレームワーク内でも実行されないサーバー側のプロセスです。

新しいリクエストが行われるたびに、MySQLdb.connectを介して新しい接続を開くことを除いて、このソリューションはうまく機能します。

Pythonで接続プールを使用するようにこれを切り替えるための最良の「ドロップイン」ソリューションは何ですか?私はJava用のコモンズDBCPソリューションのようなものを想像しています。

このプロセスは長時間実行されており、リクエストを行う必要のあるスレッドが多数ありますが、同時にすべてではありません...具体的には、結果のチャンクを短時間で書き出す前に、かなり多くの作業を行います。

追加するために編集:さらに検索した後、まともなように見えるanitpool.pyを見つけましたが、私はPythonに比較的慣れていないので、より明白な/より慣用的な/より良い解決策を見逃していないことを確認したいと思います。

4

8 に答える 8

24

MySQLでは?

接続プーリングを気にしないでください。それらはしばしば問題の原因となり、MySQL では、期待するパフォーマンス上の利点をもたらすことはありません。この道をたどるには、政治的に多大な努力が必要かもしれません。なぜなら、このスペースには、コネクション プーリングの利点について手を振っているベスト プラクティスや教科書的な言い回しがたくさんあるからです。

接続プールは、ステートレス アプリケーション (HTTP プロトコルなど) のポスト Web 時代と、ステートフルで長寿命のバッチ処理アプリケーションのプリ Web 時代との間の架け橋にすぎません。Web 以前のデータベースでは接続に非常にコストがかかるため (接続の確立にかかる時間をあまり気にする人は誰もいなかったので)、Web 以降のアプリケーションでは、すべてのヒットでこの巨大な処理オーバーヘッドが発生しないように、この接続プール スキームを考案しました。 RDBMS で。

MySQL は Web 時代の RDBMS に近いため、接続は非常に軽量で高速です。私は、MySQL 用の接続プールをまったく使用しない大量の Web アプリケーションを多数作成しました。

これは、克服すべき政治的障害がない限り、なくてもよい複雑な問題です。

于 2008-09-19T04:11:38.877 に答える
18

接続クラスをラップします。

接続数に制限を設定します。未使用の接続を返します。接続を解放するために近くで傍受します。

更新:dbpool.pyに次のようなものを入れました:

import sqlalchemy.pool as pool
import MySQLdb as mysql
mysql = pool.manage(mysql)
于 2008-09-19T01:38:19.027 に答える
18

IMO、「より明白/より慣用的/より良い解決策」は、DAOのようなクラスを発明するのではなく、既存のORMを使用することです。

ORM は「生の」SQL 接続よりも人気があるようです。なんで?Pythonオブジェクト指向であるため、SQL 行からオブジェクトへのマッピング絶対に不可欠です。Python オブジェクトにマップされない SQL 行を処理するユース ケースはあまりありません。

SQLAlchemyまたはSQLObject (および関連する接続プール) は、より慣用的な Pythonic ソリューションだと思います。

独立した機能としてのプーリングはあまり一般的ではありません。これは、純粋な SQL (オブジェクト マッピングを使用しない) は、接続プーリングの恩恵を受ける複雑で長時間実行されるプロセスではあまり一般的ではないためです。はい、純粋な SQL使用されますが、プーリングが役に立たない、より単純な、またはより制御されたアプリケーションで常に使用されます。

2つの選択肢があると思います:

  1. SQLAlchemy または SQLObject を使用するようにクラスを修正します。これは最初は面倒に思えますが (すべての作業が無駄になります)、すべての設計と考えを活用できるはずです。これは、広く使用されている ORM とプーリング ソリューションを採用するための演習にすぎません。
  2. 概説したアルゴリズムを使用して、独自の単純な接続プールを展開します。これは、循環する接続の単純なセットまたはリストです。
于 2008-09-19T02:13:07.260 に答える
9

古いスレッドですが、汎用プーリング (接続または高価なオブジェクト) には、次のようなものを使用します。

def pool(ctor, limit=None):
    local_pool = multiprocessing.Queue()
    n = multiprocesing.Value('i', 0)
    @contextlib.contextmanager
    def pooled(ctor=ctor, lpool=local_pool, n=n):
        # block iff at limit
        try: i = lpool.get(limit and n.value >= limit)
        except multiprocessing.queues.Empty:
            n.value += 1
            i = ctor()
        yield i
        lpool.put(i)
    return pooled

これは遅延して構築され、オプションの制限があり、私が考えることができるあらゆるユースケースに一般化する必要があります. もちろん、これは、リソースのプールが本当に必要であることを前提としていますが、最新の SQL ライクの多くではそうではないかもしれません。使用法:

# in main:
my_pool = pool(lambda: do_something())
# in thread:
with my_pool() as my_obj:
    my_obj.do_something()

これは、ctor が作成するオブジェクトが必要に応じて適切なデストラクタを持っていることを前提としています (一部のサーバーは、接続オブジェクトが明示的に閉じられない限り、接続オブジェクトを強制終了しません)。

于 2014-07-14T16:53:14.827 に答える
3

私はちょうど同じ種類のものを探していました。

pysqlpoolsqlalchemyプールモジュールを見つけました

于 2009-05-14T17:41:51.780 に答える
1

アプリがマルチスレッドの使用を開始することを決定した場合、独自の接続プールを作成することは悪い考えです。マルチスレッド アプリケーション用の接続プールの作成は、シングルスレッド アプリケーション用の接続プールよりもはるかに複雑です。その場合、PySQLPool のようなものを使用できます。

パフォーマンスを求めている場合、ORM を使用するのも悪い考えです。

大量の選択、挿入、更新、および削除を同時に処理する必要がある巨大で重いデータベースを扱う場合は、パフォーマンスが必要になります。つまり、ルックアップを最適化するためにカスタム SQL を作成する必要があります。そしてロック時間。ORM では、通常、そのような柔軟性はありません。

つまり、基本的には、独自の接続プールを作成して ORM を使用できますが、これは、今説明したものが何も必要ないことが確実な場合に限られます。

于 2011-08-22T22:05:55.430 に答える