10

我正在尝试使用 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

根据thisthis,我尝试设置 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 提供了带有功能的 mysql.connector。在做了所有这些之后,性能实际上恶化了。更多进程开始失败。我正在使用 Python 的 multiprocessing 模块在 24 核机器上同时运行 29 个进程(multiprocessing.Pool 默认选择这个 no)。以下是代码,当然我使用 .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 连接池问题?我真的相信应该有一些东西,这样我就不必重新发明轮子。

任何指针都非常感谢。

4

1 回答 1

4

DBUtils实现了 MySQL(并且通常声称支持任意 DB-API 2 兼容的数据库接口)用户大小的连接池PooledDB、ad-mapped 池PersistentDBSteadyDB(参见功能部分)。后者应该适合您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)

另请参阅此相关问题以获取更多示例。

于 2018-03-31T19:28:08.843 回答