web-dev-qa-db-ja.com

PythonのMySQL接続プール?

Pythonを使用して大量のデータを処理し、MySQLで処理ステータスを維持しようとしています。しかし、python-mysqlの標準接続プールがない(JavaのHikariCPなど)がないことに驚いています) 。

私は最初はPyMySQLから始めましたが、プログラムが最初の数時間実行されるまでは素晴らしいことでした。数時間後、物事は失敗し始めました。次のような多くのエラーが発生しました:

pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 99] Cannot assign requested address)")

さらに、接続プールがないために接続を頻繁に開いたり閉じたりしているため、多くのポートがTIME_WAIT状態でスタックしていました。

/d/p/950 ❯❯❯ netstat -nt | wc -l
84752

this および this に従って、tcp_fin_timeoutとip_local_port_rangeを設定しようとしましたが、ほとんど改善されませんでした。

echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 15000 65000 > /proc/sys/net/ipv4/ip_local_port_range

次に、MySQLが pooling 機能を備えたmysql.connectorを提供していることを知りました。すべてを行った後、実際にパフォーマンスが低下しました。より多くのプロセスが失敗し始めました。 Pythonのマルチプロセッシングモジュールを使用して、24コアマシンで29プロセス(multiprocessing.Poolはデフォルトではこれを選択していません)を同時に実行しています。以下はコードですが、もちろん.my.cnfを使用してすべての資格情報を渡し、それらがgitにコミットされないようにしました。

    import mysql.connector
    from mysql.connector import pooling
    conn_pool = pooling.MySQLConnectionPool(pool_name="mypool1",
                                              pool_size=pooling.CNX_POOL_MAXSIZE,
                                              option_files=MYSQL_CONFIG,
                                              option_groups=MYSQL_GROUP_NODE1,
                                              allow_local_infile=True)
conn = conn_pool.get_connection()

最後に、古いコードに戻しました。まだPyMySQLを使用していて、エラーはそれほど頻繁ではありませんが、それでも大きな問題を引き起こしています。私はSQLAlchemyを調べましたが、プールに関するドキュメントの多くは実際には見つかりませんでした。

他の誰もがmysql-python接続プーリングの問題にどのように対処しているのでしょうか?車輪を再発明する必要がないように、そこに何かがあるはずだと本当に信じています。

どんなポインタでも大歓迎です。

8
Geek

DBUtils MySQLを実装します(通常、DB-API 2準拠のデータベースインターフェイスをサポートすると主張しています)ユーザーサイズの接続プールPooledDB、ad-mappedプールPersistentDBおよびSteadyDB機能セクション を参照)。後者はmultiprocessing.Poolは、管理された永続的なデータベース接続をそれぞれ持つワーカープロセスを作成します。次のように記述されます。

DBUtils.SteadyDBは、DB-API 2データベースモジュールによって作成された通常の接続に基づいて、データベースへの「強化された」接続を実装するモジュールです。 「強化された」接続は、閉じられたとき、またはデータベース接続が失われたとき、またはオプションの使用制限よりも頻繁に使用されたときに、アクセス時に透過的に再開されます。

次のようにPyMySQLで使用できます。

import pymysql
from DBUtils.SteadyDB import connect

db = connect(
  creator = pymysql, # the rest keyword arguments belong to pymysql
  user = 'guest', password = '', database = 'name', 
  autocommit = True, charset = 'utf8mb4', 
  cursorclass = pymysql.cursors.DictCursor)

他の例については この関連する質問 も参照してください。

3
saaj