Python2.7中使用pool.apply_async无法向MySQL表插入值的问题
聊聊并行填充MySQL表的
dbWriter函数优化 嘿,看了你这段用来并行填充MySQL表的dbWriter函数,我发现几个关键细节需要调整,尤其是在并行场景下,这些点直接影响程序的稳定性和效率:
1. 别每次调用都新建数据库连接!
你现在的写法是每次执行dbWriter都重新创建数据库连接,要是用多线程/多进程并行跑,很快就会把MySQL的连接数占满,触发Too many connections错误。
建议换成连接池的方式,提前初始化好连接池,每次用的时候从池里拿连接,用完归还。比如用DBUtils的PooledDB实现:
import os import MySQLdb from DBUtils.PooledDB import PooledDB # 全局初始化连接池,整个程序只执行一次 MYSQL_CNF = os.path.abspath('.') + '/mysql.cnf' db_pool = PooledDB( creator=MySQLdb, read_default_file=MYSQL_CNF, db='dedupe', charset='utf8', maxconnections=10, # 数值根据你的并行任务数调整 blocking=True # 无可用连接时等待,而非直接报错 ) def dbWriter(sql, rows): conn = None cursor = None try: # 从连接池获取连接 conn = db_pool.connection() cursor = conn.cursor() cursor.executemany(sql, rows) conn.commit() except Exception as e: # 出错必须回滚,避免数据不一致 if conn: conn.rollback() # 可根据需求添加日志记录或自定义异常处理 raise e finally: # 无论成功失败,都要释放资源 if cursor: cursor.close() if conn: conn.close() # 此处是归还连接到池,而非真正关闭
2. 必须加上异常处理!
原函数完全没有异常捕获,要是插入时遇到主键冲突、数据格式错误这类问题,程序直接崩溃不说,还会导致部分数据插入成功、部分失败,造成数据混乱。上面的代码加了try-except-finally块,确保出错时回滚事务,且一定会释放游标和连接。
3. 并行场景的额外提醒
- 若使用多进程,注意连接池不能在主进程初始化后直接传给子进程,建议每个子进程单独初始化连接池,或使用进程安全的连接池实现。
- 批量插入的
rows别太大,否则会触发MySQL的max_allowed_packet限制,太小又没效率,一般每次插1000-5000条比较合适(具体看单条数据的大小)。 - 确保你的表使用支持事务的引擎(比如InnoDB),如果是MyISAM,
commit毫无意义,且并行插入会有锁的问题,效率极低。
4. 别忘了收尾原函数!
你原代码里cursor.clos...没写完,不管用不用连接池,游标和连接都一定要手动关闭,不然会造成连接泄漏,时间长了照样会占满连接数。
内容的提问来源于stack exchange,提问作者mersa
相关产品推荐
相关产品推荐

