【SQLAlchemy】第二篇——连接失效及连接池

2023-11-12

一、背景

为了节约资源,MySQL会对建立的连接进行监控,当某些连接处于不活跃状态的时间超过一个阈值时,则关闭它们。

用户可以执行show variables like '%wait_timeout%';来查看这个阈值:

请添加图片描述

可以看到,在默认的情况下,这个阈值是28800秒,即,如果一个连接处于不活跃的时间超过8小时,则该连接不再可用。

下面给出一个具体的例子。

1、为了能够快速验证,首先使用set global wait_timeout=10;语句将该阈值设置为10。

设置成功后需要通过show global variables like '%wait_timeout%';进行查看。为什么要加global?可以参考这里

2、执行以下验证代码:

from sqlalchemy import create_engine, text
engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/platform')
sql = "select 1+1;"
with engine.connect() as conn:
    res = conn.execute(text(sql))
    print(res.fetchone()[0])

打印结果2

3、等待超过10秒钟后,再次执行上述代码中的with:部分,则会得到如下错误:

sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query')

即无法连接到MySQL服务器。

二、问题

设想这样一个场景:通过flask启动了一个REST服务,该服务需要访问数据库,且每天被定时请求一次(除此之外无请求)。

按照上一节的讨论,由于两次请求间隔(24小时)超过了关闭阈值(8小时),因此在下一次发送请求时,会报出Lost connection的错误。

三、解决方案

一个可选的解决方案是,增加wait_timeout的值,使之超过24小时。但这样很可能导致数据库中存在大量的处于sleep状态的进程,从而造成资源的浪费。这里不考虑此种方案。

既然是连接失效,那么一种比较直观的解决方案就是在每次使用连接进行数据库操作前,先检验一下连接是否有效。有效就直接使用;无效则重新连接

SQLAlchemy提供了基于上述思路的解决方案——指定pool_pre_ping参数:

engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/platform', pool_pre_ping=True)

这样定义engine之后,再执行上面的验证例子可以发现,即使两次执行with:的间隔超过了阈值,仍可以执行成功。

四、更深入的分析

4.1 Engine与连接池

本系列的第一篇中说“可以将Engine对象视为连接池”,但严格来讲这是不正确的。要正确理解它们之间的关系,需要借助下面这张结构图:

请添加图片描述

最右侧是数据库,SQLAlchemy通过第三方的DBAPI与之进行连接——在上面的例子中,这个DBPAI是PyMySQL。而上述Engine对象则是通过PoolDialect来与DBPAI进行交互。

先说Dialect,这个单词的字面意思是“方言”,在这里可以引申为不同的数据库类型。在上面定义engine的url中的mysql实际上就告诉SQLAlchemy要初始化一个支持连接MySQLDialect类。

当使用create_engine函数创建Engine对象时,默认使用QueuePool来创建连接池,用户可以指定poolclass参数来选择不同的Pool。当调用Engineconnect()方法时,就会从连接池中获取一个连接对象来执行操作。

4.2 pool_pre_ping的限制

仔细分析不难看出,第三部分提供的方案是有弊端的。在使用从连接池获取的连接进行实际工作前,都需要向数据库服务器发送ping命令,这无疑会增加开销。

所谓的“发送ping命令”是一个概括的说法,有可能是通过连接向服务器发送了select 1;等简单的命令。

另外,如果服务器出现了性能瓶颈,可能导致ping命令迟迟得不到有效的相应,从而影响程序性能。

因为上述原因,pool_pre_ping方法被称为是“悲观的”。

4.3 乐观方法

上述悲观方法是被动式的——要等到连接不可用了之后,才能通过ping命令检测到。而乐观方法则是主动式的:通过在调用create_engine时设置pool_recycle参数来指定连接持续时间。这个参数的作用是,在达到pool_recycle的时间限制后,连接池将所有的连接回收,并重新进行连接。这样就保证了连接的有效性。

与悲观方法相比,乐观方法减轻了服务器的负担。

4.4 连接池

直观地查看一下连接池的作用:

# 代码由chatGPT生成
from sqlalchemy import create_engine, text
import concurrent.futures
import threading

# 创建连接池引擎
# 这里限制了池中连接的数量为3,且不允许自动增加连接的数量
engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/test', pool_size=3, max_overflow=0)


# 定义并发函数
# 为了能从数据库服务器查看连接的执行情况,执行了一个休眠命令
def run_query(query_num):
    print('线程:', threading.current_thread().native_id, '正在执行...')
    with engine.connect() as conn:
        ret = conn.execute(text(f'select sleep({query_num})'))
    print('线程:', threading.current_thread().native_id, '执行完成')
    return ret.one()[0]


# 使用多线程并发执行查询
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    # 线程池中共有10个线程
    futures = []
    for i in range(10):
        futures.append(executor.submit(run_query, 5))
    for future in concurrent.futures.as_completed(futures):
        print(future.result())

执行上述代码,首先在控制台上打印出类似如下的内容:

线程: 517317 正在执行...
线程: 517318 正在执行...
线程: 517319 正在执行...
线程: 517321 正在执行...
线程: 517322 正在执行...
线程: 517320 正在执行...
线程: 517323 正在执行...
线程: 517325 正在执行...
线程: 517326 正在执行...
线程: 517324 正在执行...

这说明,10个线程已经开始执行。但由于连接池中只有3个连接,此时通过show processlist可以看到有三个连接在执行操作:

请添加图片描述

结合控制台打印的输出,当有线程执行完成时,数据库中对应连接的Time字段又从0开始计时,这说明改连接被复用了。

当所有的线程执行完成后,上述三个连接消失。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【SQLAlchemy】第二篇——连接失效及连接池 的相关文章

  • 无法在 Jupyter Notebook 中安装 arcpy

    我安装了 ArcGIS Pro 其中包括已安装的 Python 包 我正在尝试学习 Python 并且想使用 ArcPy 函数 我以前从未使用过 Jupyter Notebook 但为了开始使用 我创建了一个新的 Python 3 文件 我
  • Python正则表达式替换除特定单词之外的所有内容

    我正在尝试执行以下操作用正则表达式 import re x re compile going you words to replace s I am going home now thank you string to modify pri
  • Python argparse 作为函数

    以这种方式获取命令行参数有什么本质上的错误吗 我的意思是把参数解析放入它自己的函数中 它会被认为是非 Pythonic 或更严重吗 usr bin python import argparse def getArgs argv None p
  • 扭曲多种协议

    我希望为我正在从事的项目学习扭曲 该项目需要服务器响应 HTTP 请求以及通过 TCP 连接的其他协议 Twisted能够同时处理多种协议吗 我想使用 Twisted Web 来帮助处理 HTTP 但同时需要响应其他端口上的 TCP 连接
  • Python 正则表达式从文本中提取域

    我有以下正则表达式 r a zA Z0 9 a zA Z0 9 61 a zA Z0 9 a zA Z 2 6 当我将其应用于文本字符串时 比方说 这是 www website1 com 这是 website2 com 我得到 www we
  • 绘制对数轴

    我想使用 matplotlib 绘制一张带有一个对数轴的图 我一直在阅读文档 但无法弄清楚语法 我知道这可能很简单 scale linear 在情节争论中 但我似乎无法正确理解 示例程序 import pylab import matplo
  • 如何将数据从 JavaScript 发送到 Python

    我正在 jinja2 和 python2 7 上使用 GAE 进行 Web 开发 我可以从Python获取数据 但我无法将数据从 JavaScript 发送到 Python 这是 JavaScript 代码 function toSave
  • 打开文件路径在 python 中不起作用[重复]

    这个问题在这里已经有答案了 我正在编写一个数据库程序 personica 是我的测试主题 我通常在文件路径的位置有一个变量 但出于测试和演示的目的 我只有一个字符串 在我的计算机上的这个确切位置有一个文本文件 顺便说一句 因为我很偏执 所以
  • NLTK:包错误?朋克和泡菜?

    基本上 我不知道为什么会收到此错误 只是为了获得更多图像 这里有一个代码格式的类似消息 由于是最新的 该帖子的答案已经在消息中提到 Preprocessing raw texts LookupError Traceback most rec
  • “DATETIME_INPUT_FORMATS”在 Django Admin 中不起作用,而“DATE_INPUT_FORMATS”和“TIME_INPUT_FORMATS”则可以

    I use 日期时间字段 https docs djangoproject com en 4 2 ref models fields datetimefield 日期字段 https docs djangoproject com en 4
  • 将具有多个时区的 pandas 列转换为单个时区

    Problem 我在 pandas DataFrame 中有一个列 其中包含带有时区的时间戳 此列中有两个不同的时区 我需要确保只有一个 这是该列末尾的输出 260003 2019 05 21 12 00 00 06 00 260004 2
  • django-allauth:电子邮件确认

    我已经设置了 django allauth 并在新用户注册时使用电子邮件确认 效果很好 但在确认电子邮件中 我得到 Hello from example com You re receiving this e mail because us
  • 如何在solidpython中设置特殊变量$fa、$fs、$fn

    in 上一个线程 https stackoverflow com questions 54040390 how to save data in stl file after python solid processing显示了如何通过 So
  • Python 中的 Firebase 身份验证时出现 KeyError:“databaseURL”

    相信你做得很好 我是 firebase 的新手 正在尝试进行用户身份验证 我已经安装了pyrebase4并在firebase控制台上创建了一个项目 我还启用了使用 电子邮件和密码 登录并尝试连接我的应用程序 下面是我正在尝试的代码 impo
  • Python-使用元组作为列表索引[重复]

    这个问题在这里已经有答案了 我有一个元组列表 tuples list 1 0 2 3 3 2 2 0 我想访问二维数组的元素a例如 使用其中一些元组 for i in range 3 print a tuples list i 应该输出的值
  • 使用 Celery 通过 Gevent 进行实时、同步的外部 API 查询

    我正在开发一个 Web 应用程序 该应用程序将接收用户的请求 并且必须调用许多外部 API 来编写对该请求的答案 这可以直接从主 Web 线程使用 gevent 之类的东西来扇出请求来完成 或者 我在想 我可以将传入的请求放入队列中 并使用
  • 启动客户端时,代码要求提供电话/机器人令牌

    使用 Telethon 库运行我的第一个代码时 它要求提供机器人令牌 这是实际的代码 from telethon import TelegramClient events sync api id 1234567 api hash xxxxx
  • Django - 渲染到字符串无法加载 CSS

    我正在尝试使用 Django 1 8 render to string 通过管理命令将 html 转换为 pdf 而不是使用 View request 以下代码可以将模板转换为 pdf 但它无法将 CSS 加载到模板中 def html t
  • 如何将 Django 数据库中的模板标签解释/渲染为 HTML

    我正在尝试添加带有来自 Django 管理站点的图像的帖子 但安全 自动转义关闭过滤器无法解释 Django 的模板标签 My input and page look like 复制图像地址 给出http 127 0 0 1 8000 7B
  • `numpy.diff` 和 `scipy.fftpack.diff` 在微分时给出不同的结果

    我正在尝试计算一些数据的导数 并且正在尝试比较有限差分的输出和谱方法的输出 但结果却截然不同 我无法弄清楚到底为什么 考虑下面的示例代码 import numpy as np from scipy import fftpack as sp

随机推荐

  • Hyper-V:无法打开虚拟机,因为虚拟机监控程序未运行

    管理员权打开 cmd 窗口 输入 bcdedit set hypervisorlaunchtype Auto 前提是机器已经开启了 虚拟化和开启了虚拟机监控程序
  • kafka 应用实战

    一 Java 中使用 kafka 进行通信 依赖
  • 孟岩谈通证(11):通证所代表的多维价值观

    通证Token都有那些多维价值观呢 我还是你举一个特别具体的例子来说明 我有一个朋友他开了一个社区 是专门做中小学教育课外辅导老师之间交流的 社区里大家互相交换教学资料 试题等等材料 你说这个东西有没有价值 教书育人 然后帮助孩子们成长 这
  • ssh远程连接Ubuntu(局域网和非局域网)

    文章目录 前言 1 局域网 远程连接 2 非局域网 远程连接 3 Zerotier常用命令 4 远程桌面控制 总结 前言 我们通常使用ssh连接虚拟机中的Ubuntu 方便学习 但是当在项目中遇到远程控制主机的时候 发现ssh连接不到外网主
  • Vue中实现电子围栏/围栏(高德地图)功能:

    1 思路 大部分与车辆轨迹相同 1 先获取key gt 官网 https lbs amap com ref https console amap com 2 下载并导入依赖 npm install vue amap S 3 使用 2 官网
  • 加速乐-AAencode-ob混淆

    加速乐 AAencode ob混淆 多层响应 Cookie 逆向 前言 本次案例是对加速乐 AAEncode OB 混淆方式的破解 破解出多层响应 Cookie 逆向 声明 本文章中所有内容仅供学习交流 相关链接做了脱敏处理 若有侵权 请联
  • Eclipse安装LomBok插件

    1 使用LomBok的好处在于实体类不用手动去生成set get方法了 类会在编译时自动生成 是代码简洁节省工作量 2 maven项目的pom文件添加坐标下载
  • 程序员进阶架构师的必备——思维导图

    架构师是什么 要做什么 架构师 是一个既需要掌控整体又需要洞悉局部瓶颈并依据具体的业务场景给出解决方案的团队领导型人物 架构师不是一个人 他需要建立高效的体系 带领团队去攻城略地 在规定的时间内完成项目 1 确认需求 架构师要懂得用户需求
  • 什么是面向对象思想

    面向对象是一种思想 是基于面向过程而言的 就是说面向对象是将功能等通过对象来实现 将功能封装进对象之中 让对象去实现具体的细节 这种思想是将数据作为第一位 而方法或者说是算法作为其次 这是对数据一种优化 操作起来更加的方便 简化了过程 面向
  • 人工智能作业homework2--------A*算法解决八数码

    1 启发式搜索算法A 启发式搜索算法A 一般简称为A算法 是一种典型的启发式搜索算法 其基本思想是 定义一个评价函数f 对当前的搜索状态进行评估 找出一个最有希望的节点来扩展 评价函数的形式如下 f n g n h n 其中n是被评价的节点
  • 全网最详细中英文ChatGPT接口文档(五)30分钟快速入门ChatGPT——手把手示例教程:如何建立一个人工智能回答关于您的网站问题,小白也可学

    30分钟开始使用ChatGPT Models模型 How to build an AI that can answer questions about your website 如何建立一个人工智能 回答有关您的网站的问题 Getting
  • 整理了27个Python人工智能库,建议收藏

    为了大家能够对人工智能常用的 Python 库有一个初步的了解 以选择能够满足自己需求的库进行学习 对目前较为常见的人工智能库进行简要全面的介绍 1 Numpy NumPy Numerical Python 是 Python的一个扩展程序库
  • ssd m.2接口详解

    ssd有两种接口 一种是sata 一种是m 2 这里主要深入讲解一下m 2接口的ssd 1 ssd 尺寸与规格 我们在买ssd的时候 商家都会说什么ssd是2280还是2242规格的 这里的规格实际上就是代表的ssd的大小 M 2模组的尺寸
  • pytrch手写数字识别

    使用Pytorch实现手写数字识别 目标 知道如何使用Pytorch完成神经网络的构建 知道Pytorch中激活函数的使用方法 知道Pytorch中torchvision transforms中常见图形处理函数的使用 知道如何训练模型和如何
  • Unity:利用 射线Ray 检测物体

    利用 射线Ray 检测物体 Unity射线 Ray 是通过发射一条射线来检测碰撞体或触发器 不带碰撞器组件的物体时无法检测的 可以在物理设置里取消检测触发器 Edit Project Setting Physics Physics2D Ph
  • Spring Boot中的Dozer和MapStruct比较

    Spring Boot中的Dozer和MapStruct比较 在Java开发中 数据对象之间的转换是一个常见的任务 Spring Boot作为一个流行的Java框架 提供了多种方式来处理对象之间的转换 两个常用的工具是Dozer和MapSt
  • call、apply、bind方法详解

    1 每个函数都包含两个非继承而来的方法 call 方法和apply 方法 2 相同点 这两个方法的作用是一样的 只是传参方式不一样而已 call 方法使用 window msg 1 document msg 2 var log msg 3
  • springboot 如何修改控制台输出的图案

    如图 操作步骤 1 在项目的resource文件夹下 新建一个文件命名为banner txt 2 进入网站 http patorjk com software taag p display h 0 v 0 f Big t SpringBoo
  • Spring WebSocket通信应用

    文章目录 前言 一 客户端 服务端双向通信交互图 二 项目说明 1 引入包 2 项目各模块说明 问题 参考 前言 本文章主要记录项目客户端 服务端双向通信解决方案 基于Spring WebSocket架构实现双向数据通信 以及项目实际应用中
  • 【SQLAlchemy】第二篇——连接失效及连接池

    一 背景 为了节约资源 MySQL会对建立的连接进行监控 当某些连接处于不活跃状态的时间超过一个阈值时 则关闭它们 用户可以执行show variables like wait timeout 来查看这个阈值 可以看到 在默认的情况下 这个