web-dev-qa-db-fra.com

Pool de connexions MySQL en python?

J'essaie de traiter une grande quantité de données à l'aide de Python et de conserver le statut de traitement dans MySQL. Cependant, je suis surpris qu'il n'y ait pas de pool de connexion standard pour python-mysql (comme HikariCP en Java).

À l’origine, j’ai commencé avec PyMySQL, les choses se sont bien passées jusqu’à ce que le programme fonctionne pendant les premières heures. Après quelques heures, les choses ont commencé à échouer. J'ai eu beaucoup d'erreurs comme:

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

De plus, beaucoup de ports étaient bloqués dans l'état TIME_WAIT car j'ouvre et ferme des connexions trop souvent à cause du manque de pool de connexions.

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

Per this and this , j’ai essayé de définir tcp_fin_timeout et ip_local_port_range, mais pratiquement rien n’a été amélioré.

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

Ensuite, j'ai découvert que MySQL fournit mysql.connector avec la fonctionnalité pooling . Après avoir fait toute cette performance effectivement détériorée. Plus de processus ont commencé à échouer. J'utilise le module de multitraitement de Python pour exécuter simultanément 29 processus (multitraitement.Pool choisi ce numéro par défaut) sur une machine à 24 cœurs. Après le code, bien sûr, j’utilisais le fichier .my.cnf pour transmettre toutes les informations d’identification afin d’éviter de les envoyer à 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()

Enfin, revenons à l'ancien code. Toujours en utilisant PyMySQL et bien que les erreurs soient moins fréquentes, cela pose toujours un problème majeur. J'ai examiné SQLAlchemy et je n'ai pas trouvé beaucoup de documentation sur le pooling. 

Je me demande comment tous les autres traitent le problème du pooling de connexions mysql-python? Je crois vraiment qu'il devrait y avoir quelque chose pour que je ne réinvente pas la roue. 

Tous les indicateurs sont très appréciés.

8
Geek

DBUtils implémente MySQL (et prétend généralement prendre en charge des interfaces de base de données conformes à DB-API 2). Pool de connexions de la taille d'un utilisateur PooledDB, thool pool mappé PersistentDB et SteadyDB (voir la section fonctionnalité ). Ce dernier devrait convenir à votre cas où multiprocessing.Pool crée des processus de travail avec une connexion de base de données persistante gérée chacune. Il est décrit comme:

DBUtils.SteadyDB est un module implémentant des connexions "renforcées" à une base de données, basé sur des connexions ordinaires établies par tout module de base de données DB-API 2. Une connexion "renforcée" se rouvrira de manière transparente lors de l'accès si elle a été fermée ou si la connexion à la base de données a été perdue ou lorsqu'elle est utilisée plus souvent qu'une limite d'utilisation optionnelle.

Vous pouvez l'utiliser avec PyMySQL comme:

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)

Voir aussi cette question connexe pour plus d'exemples. 

2
saaj