当前位置:首页 > 问答 > 正文

Python里用的MySQL连接池那个东西,怎么搞起来更方便点吧

(主要参考了PyMySQL官方文档、DBUtils文档以及一些常见的博客实践,Python中MySQL连接池的简单实现”这类文章)

行,那咱们就直接说怎么把Python里用的MySQL连接池给搞起来,让它用着更方便,别整那些复杂的概念,就说怎么上手干活。

核心思想

连接池就是个“池子”,里面提前放了好几个已经连上数据库的连接,你用的时候,从池子里借一个出来,用完再还回去,而不是每次都重新连一次数据库,这样做的最大好处就是快,省去了反复建立连接、关闭连接的开销,尤其是在需要频繁操作数据库的程序里,效果特别明显。

选个顺手的工具

Python里用的MySQL连接池那个东西,怎么搞起来更方便点吧

Python里自己不带现成的MySQL连接池,你得用第三方库,最常见、最省事的组合是:

  1. PyMySQL:这是一个纯Python写的MySQL客户端库,用起来很简单,和Python自带的sqlite3模块风格有点像,很多人爱用。
  2. DBUtils:这是一个专门提供数据库连接池功能的库,它不关心你具体用PyMySQL还是mysqlclient(另一个更快的C扩展库),它只管给你管理池子。

我们的策略就是用 DBUtils 来管理 PyMySQL 的连接,先安装它们:

pip install PyMySQL DBUtils

开搞:最简单的连接池

下面是一个最直接、最能看出效果的用法,你把这个代码块保存成一个.py文件,比如叫 my_db_pool.py,以后在其他地方就能直接用了。

Python里用的MySQL连接池那个东西,怎么搞起来更方便点吧

import pymysql
from dbutils.pooled_db import PooledDB
# 第一步:在程序一开始,创建这个连接池(通常全局有一个就够了)
POOL = PooledDB(
    creator=pymysql,  # 告诉池子你用哪个库来创建连接
    host='localhost', # 数据库地址
    user='你的用户名',
    password='你的密码',
    database='你的数据库名',
    port=3306,        # 端口,默认是3306
    charset='utf8mb4', # 编码,很重要,用utf8mb4才能存表情符号
    # 下面就是连接池的核心参数了,按你的需求调整
    maxconnections=10,  # 池子里最多能同时存在的连接数
    mincached=2,       # 一开始池子里就创建好的空闲连接数,省得临时要用了再建
    maxcached=5,       # 池子里最多空闲的连接数,多了就关掉
    blocking=True,     # 如果池子满了,新的请求是否等待,True就是等,False就直接报错
)
# 第二步:定义一个函数,用来从池子里取连接用
def get_db_connection():
    # 从池子里借一个连接
    conn = POOL.connection()
    return conn
# 第三步:怎么用?看例子
if __name__ == '__main__':
    # 借连接
    conn = get_db_connection()
    # 从连接上拿一个游标(cursor),用来执行SQL语句
    cursor = conn.cursor()
    try:
        # 执行你的SQL,比如查点东西
        cursor.execute("SELECT * FROM your_table LIMIT 5")
        # 拿到所有结果
        results = cursor.fetchall()
        for row in results:
            print(row)
    except Exception as e:
        # 万一出错了,回滚一下
        conn.rollback()
        print(f"出错了: {e}")
    finally:
        # 最关键的一步:用完了一定要关闭!但这里关闭不是真关,是还给池子。
        cursor.close()
        conn.close()

重点解读一下怎么用着“更方便”

  1. 全局一个池子:你把创建 POOL 的代码放在一个地方(比如一个专门的配置文件或模块里),整个程序就共用这一个池子,不用每次操作数据库都去配一遍参数。
  2. 用的时候“借”,用完“还”conn = POOL.connection() 就是借。conn.close() 就是还,你不用担心真的关闭了连接,DBUtils在背后帮你处理,这个 close() 方法被它改写过,意思变成了“放回池子”。
  3. 异常处理很重要:一定要把 cursor.close()conn.close() 放在 finally 块里,这样即使上面执行SQL出错了,也能保证连接被还回去,不会一直占着茅坑不拉屎,导致连接泄露,最后池子满了程序卡死。

更进一步:让它用起来像喝水一样简单

上面那个例子已经能用,但每次都要写 try...except...finally 也挺烦的,我们可以写一个“上下文管理器”的助手函数,用Python的 with 语句,这样代码更干净。

把下面这个函数也加到你的 my_db_pool.py 文件里:

Python里用的MySQL连接池那个东西,怎么搞起来更方便点吧

from contextlib import contextmanager
@contextmanager
def get_db_cursor():
    """
    一个上下文管理器,用with语句自动处理借连接、还连接的事情。
    你只需要关心执行SQL就行了。
    """
    conn = None
    cursor = None
    try:
        conn = get_db_connection() # 调用我们之前写的函数借连接
        cursor = conn.cursor()
        yield cursor  # 把游标给你用
        conn.commit() # 如果没有出错,就提交事务
    except Exception as e:
        if conn:
            conn.rollback() # 出错了就回滚
        raise e  # 把错误再抛出去,让外面知道
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close() # 这里就是“还”回池子
# 现在用法变得超级简单:
if __name__ == '__main__':
    with get_db_cursor() as cursor:
        cursor.execute("SELECT * FROM your_table LIMIT 5")
        results = cursor.fetchall()
        for row in results:
            print(row)
    # 看,出了with这个块,连接自动就还了,不用你操心关闭的事。

这样搞的好处

  • 代码短:你不用再写一堆 try...finally 了。
  • 不会忘:用 with 语句是Python的推荐做法,能确保资源肯定被释放。
  • 自动事务:这个写法还帮你自动处理了提交和回滚,如果with块里的代码顺利执行完,自动 commit;如果中途抛出异常,自动 rollback

调参小贴士

创建 POOL 时那几个参数,你可以根据程序情况微调:

  • maxconnections:别设太大,比如你程序并发不高,设个10-20足够了,设太大了数据库压力大。
  • mincached:如果你的程序一启动就要疯狂查数据库,可以设大点,比如5,这样启动时就建好5个连接等着用。
  • blocking=True:建议设为True,这样池子满的时候程序会等着有连接空出来,而不是直接报错导致你的请求失败。

总结一下

更方便的做法就是:

  1. :用 DBUtils + PyMySQL 这个组合。
  2. :在程序入口附近,全局创建一个 PooledDB 对象。
  3. :写一个类似 get_db_cursor 的上下文管理器函数,把借连接、还连接、事务处理这些杂活都包起来。
  4. :在需要操作数据库的地方,直接 with get_db_cursor() as cursor:,然后在里面写你的SQL代码。

这么一套下来,你基本就感觉不到连接池的存在了,用起来和直接连数据库一样简单,但性能却好得多,以后你的Python项目里需要搞MySQL,照这个模板套就行。