Python大数据处理中MySQL连接池缺失及PyMySQL运行报错求助
嘿,这个问题我之前帮不少人排查过,本质上是连接没管好导致的端口耗尽,咱们一步步来解决:
首先得搞懂报错的原因:你每次处理数据时如果都新建一个MySQL连接,用完又没正确关闭(或者关闭后TCP连接进入TIME_WAIT状态没及时释放),系统的本地端口很快就会被耗尽,这就出现了pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 99] Cannot assign requested address)")这个错误。
Python确实没有像Java HikariCP那样官方标准的连接池,但有几个非常成熟的替代方案,完全能解决你的问题:
方案一:用SQLAlchemy(最推荐)
SQLAlchemy是Python生态里最常用的ORM框架,它内置的连接池非常稳定,自动帮你处理连接的复用、回收、重连,不用你手动操心。示例代码如下:
from sqlalchemy import create_engine # 创建带连接池的引擎,可根据你的并发量调整pool_size和max_overflow engine = create_engine( 'mysql+pymysql://your_user:your_password@127.0.0.1/your_db?charset=utf8mb4', pool_size=20, # 连接池保持的最小连接数 max_overflow=10 # 超出pool_size的临时连接数,用完会回收 ) # 处理数据时直接用上下文管理器获取连接 with engine.connect() as conn: # 执行SQL result = conn.execute("INSERT INTO status_table (status, data_id) VALUES (%s, %s)", ("processed", 123)) conn.commit()
用这种方式,你再也不用手动管理连接的创建和关闭,SQLAlchemy会帮你把连接池维护得妥妥的。
方案二:用DBUtils(专注连接池的库)
如果你不想用ORM,只想单纯用连接池,DBUtils是个不错的选择,它专门为Python的DB API 2.0实现了连接池,有两种模式可选:
from dbutils.pooled_db import PooledDB import pymysql # 初始化连接池 pool = PooledDB( creator=pymysql, # 指定用PyMySQL作为连接创建器 maxconnections=20, # 连接池最大连接数 mincached=5, # 初始化时在连接池创建的空闲连接数 maxcached=10, # 连接池最多空闲的连接数 host='127.0.0.1', user='your_user', password='your_password', database='your_db', charset='utf8mb4' ) # 获取连接(注意:这里的close不是真的关闭,而是放回连接池) conn = pool.connection() try: cursor = conn.cursor() cursor.execute("UPDATE status_table SET status = 'done' WHERE id = %s", (456,)) conn.commit() finally: cursor.close() conn.close()
临时应急方案(不推荐长期用)
如果暂时不想引入新库,那你必须确保复用连接,而不是每次处理数据都新建,并且用完后正确关闭资源:
import pymysql # 程序启动时只创建一次连接 conn = pymysql.connect( host='127.0.0.1', user='your_user', password='your_password', database='your_db', charset='utf8mb4' ) def process_single_data(data): cursor = None try: cursor = conn.cursor() cursor.execute("INSERT INTO status_table ...", data) conn.commit() except pymysql.err.OperationalError as e: # 如果连接断开,重新建立连接 global conn conn = pymysql.connect(host='127.0.0.1', user='your_user', password='your_password', database='your_db') # 重新执行操作 cursor = conn.cursor() cursor.execute("INSERT INTO status_table ...", data) conn.commit() except Exception as e: conn.rollback() # 处理其他异常 finally: if cursor: cursor.close() # 批量处理数据 for data in your_large_data_set: process_single_data(data) # 程序结束时关闭连接 conn.close()
不过这个方案有局限性,比如多线程场景下单连接会有线程安全问题,而且重连逻辑需要自己维护,不如用成熟的连接池库省心。
总结一下:Python虽然没有像HikariCP那样的「标准」连接池,但SQLAlchemy和DBUtils都是工业级的解决方案,完全能满足你处理大量数据时的连接管理需求,赶紧换掉原来的裸连方式吧!
内容的提问来源于stack exchange,提问作者Geek

