pymysql连接以及连接池的理解

mysql连接

1. 不使用连接池

我们知道使用pymysql连接数据库一般需要下面的步骤:

    1. 创建连接对象(一般使用connect或者是连接池)
    1. 创建游标对象
    1. 使用游标执行代码
    1. 使用游标获取结果并返回 # 返回的是元组(每个实例一个元组)!
    1. 关闭游标和连接
conn = pymysql.connect(host, port, ...)
cursor = conn.cursor()
sql = "select * from goods;"
cursor.execute(sql)
res = cursor.fetchall()  # 查看所有,可以查看一部分
print(res)
cursor.close()
conn.close()

2. 使用连接池

2.1 为什么需要连接池

连接池是connection对象的缓冲区,他里面会存放一些connection,当程序需要使用connection时,如果连接池中有,则直接从连接池获取,不需要再重新创建connection。连接池让程序能够复用连接。资源复用.
可以尽量避免连接三次握手四次挥手等非业务流程带来的损耗。池化技术,本质上说就是资源复用。

2.2 连接池管理

1、连接池维护着两个容器空闲池和活动池

2、空闲池用于存放未使用的连接,活动池存放正在使用的连接,活动池中的连接使用完之后要归还回空闲池

3、当需要连接时,先判断空闲池是否有连接,如果有则取出一个放置到活动池供程序使用

4、如果没有,则判断活动池中连接是否达到最大连接数,如果没有,则创建一个连接放到活动池供程序使用。

5、如果空闲池中没有连接,活动池中连接也达到上限,则不能创建新连接,此时会判断是否等待超时,如果没有等待超时则需等待活动池中的连接归还回空闲池

6、如果等待超时,可以采取多种处理方式,例如:直接抛出异常,或将活动池中使用最久的连接移除掉归还回空闲池以供程序使用

2.3 连接池数量确定

参考

首先解决一个问题,为什么需要多个连接?对于数据库而言,每个连接都是独占的,如果一个业务占用连接,而又进入了IO等待,那么这个业务就会一直占用这个连接,其他业务也只能等待。如果开多条连接,不同的业务就可以利用不同的连接通道来处理。
一般情况下,线程池线程数量尽量与连接池中的连接数量一致。这样做可以避免不同线程之间抢资源或是资源过多线程处理不过来导致浪费的情况。注意这里说的一般情况,是业务服务器与数据库服务器性能差不多的情况。其实,数据库服务器也是使用多线程来处理业务,如果连接数过多,数据库会处理不过来。
另外,如果不使用连接池,就需要不同的线程去绑定不同的连接,使得整个系统的耦合度变高。还要注意一点的是,在一个数据库服务器中可能有多个连接池。比如,一个连接池对应写业务,与一个只处理写业务的线程池,共同处理写数据库,而再用另一套连接池只处理读业务,与只读数据库连接,这样做就实现了读写分离。

2. 步骤

    1. 获取锁
    1. 获取池子(可以定义最大连接数,常规的mysql连接参数等)
    1. 使用池子连接
    1. 定义游标
    1. 使用游标执行代码
    1. 使用游标获取结果并返回
    1. 关闭连接
import threading
from typing import Listimport pymysql
from dbutils.pooled_db import PooledDBfrom MovieRecSystem.config import redis_config, mysql_config
from MovieRecSystem.utils.logger_util import loggerdef _encode(v, encoding='UTF-8') -> str:return str(v, encoding=encoding)'''
单例是redis, 然后提供静态方法
可以使用其它的
'''class DB(object):# 单例模式# 必须要有一个静态的属性, 或者说类上的属性__lock = threading.Lock()  # 锁__pool = None  # 只要是单例就会有一个静态的属性, mysql就是我们的线程池def __init__(self):self.pool = DB.__get_conn_pool() # 链接时是需要时间的,所以创建连接池! 保证整个运行只有一个线程@staticmethoddef __get_conn_pool():'''就是获取一个连接池(因为是单例), 获取锁之后再添加实例(和redis一样)但是不代表已经连接成功了,还需要connection:return:'''if DB.__pool is None:DB.__lock.acquire()try:if DB.__pool is None:# 获取配置信息_cfg = mysql_config.cfg.copy()if 'creator' not in _cfg:raise ValueError("必须给定creator参数")if _cfg['creator'] != 'pymysql':raise ValueError("creator参数必须给定为pymysql")del _cfg['creator']DB.__pool = PooledDB(pymysql, **_cfg)# DB.__pool = PooledDB(#     creator=pymysql,  # 使用链接数据库的模块#     maxconnections=500,  # 连接池允许的最大连接数,0和None表示不限制连接数#     mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建#     maxcached=50,  # 链接池中最多闲置的链接,0和None不限制#     blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错#     maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制#     setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]#     ping=1,#     host="121.40.96.93",#     port=3306,#     user="gerry",#     password="123456",#     database="rec_system",#     charset="utf8"# )except Exception as e:raise ValueError("创建Mysql数据库连接池异常!") from efinally:DB.__lock.release()return DB.__pooldef _get_connection(self):conn = self.pool.connection()cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)return conn, cursor@staticmethoddef _close_connection(conn, cursor):if cursor:try:cursor.close()except Exception as e:logger.error("关闭Mysql连接cursor异常。", exc_info=e)if conn:try:conn.close()except Exception as e:logger.error("关闭Mysql连接conn异常。", exc_info=e)# 执行查询结果(这个可以放到缓存里)def query_sql(self, sql, **params):conn, cursor = self._get_connection()try:cursor.execute(sql, params)result = cursor.fetchall()except Exception as e:raise ValueError(f"Query查询异常,当前sql语句为:{sql}, 参数类别为:{params}.") from efinally:self._close_connection(conn, cursor)return result# 执行def execute_sql(self, sql, **params):conn, cursor = self._get_connection()try:cursor.execute(sql, params)result = cursor.lastrowidconn.commit()except Exception as e:conn.rollback()raise ValueError(f"Execute执行异常,当前sql语句为:{sql}, 参数类别为:{params}.") from efinally:self._close_connection(conn, cursor)return result

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/476036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1025. 除数博弈(动态规划)

1. 题目 爱丽丝和鲍勃一起玩游戏&#xff0c;他们轮流行动。爱丽丝先手开局。 最初&#xff0c;黑板上有一个数字 N 。在每个玩家的回合&#xff0c;玩家需要执行以下操作&#xff1a; 选出任一 x&#xff0c;满足 0 < x < N 且 N % x 0 。用 N - x 替换黑板上的数字…

python iterator iterable_Python中Iterator和Iterable的区别

python中list, str&#xff0c;truple, dict都是可以被迭代的&#xff0c;但他们不是迭代器。why?list/truple/map/dict这些数据的大小是确定的&#xff0c;我们可以准确知道他们的size。迭代器不知道要执行多少次&#xff0c;所以可以理解为不知道有多少个元素&#xff0c;每…

javascript之嵌套函数

在javascript中允许使用嵌套函数: <head><meta http-equiv"Content-Type" content"text/html; charsetgb2312" /><title>嵌套函数</title><script type"text/javascript"> function fun1(){ function fun…

BN / LN / IN / GN /

链接 但是代码不敢苟同! 所以自己写了两种代码! 由于这只是测试, 并不是用来训练, 所以α和β参数就没有加! def BN(inputs):c inputs.shape[1]for i in range(c):channel inputs[:,i,:,:]mu np.mean(channel)var np.var(channel)channel_new ((channel - mu)/(np.sqrt(…

LeetCode 672. 灯泡开关 Ⅱ(枚举)

1. 题目 现有一个房间&#xff0c;墙上挂有 n 只已经打开的灯泡和 4 个按钮。 在进行了 m 次未知操作后&#xff0c;你需要返回这 n 只灯泡可能有多少种不同的状态。 假设这 n 只灯泡被编号为 [1, 2, 3 …, n]&#xff0c;这 4 个按钮的功能如下&#xff1a; 1将所有灯泡的状…

安卓手机绘制uml图_Android Studio中绘制simpleUML类图详细说明及使用

一、Android Studio中安装simpleUML1、下载simpleUML jar包2、 添加simpleUMLCEjar包File--->Settings--->Plugins--->Install Plugin from disk,如下图&#xff1a;3、安装完成后重启AndroidStudio二、使用在某个类或module上右击&#xff0c;选择Add to simpleUML D…

ExtJs非Iframe框架加载页面实现

在用Ext开发App应用时&#xff0c;一般的框架都是左边为菜单栏&#xff0c;中间为tab页方式的显示区域。而tab页面大多采用的嵌入一个iframe来显示内容。但是采用iframe方式有一个很大的弊端就是每次在加载一个新的iframe时都要将Ext的核心js&#xff0c;css文件重新加载。由于…

LeetCode 873. 最长的斐波那契子序列的长度(动态规划)

文章目录1. 题目2. 解题2.1 暴力解2.2 动态规划1. 题目 如果序列 X_1, X_2, ..., X_n 满足下列条件&#xff0c;就说它是 斐波那契式 的&#xff1a; n>3n > 3n>3对于所有 i2<ni 2 < ni2<n&#xff0c;都有 XiXi1Xi2X_i X_{i1} X_{i2}Xi​Xi1​Xi2​ 给…

中文验证码 php_还在苦恼验证码怎么实现?看看这个验证码组件合集,你想要的都有...

随着安全性的要求越来越高&#xff0c;如今的验证码已经不再是简单的四个数字或者字母了&#xff0c;更复杂的图形验证码和行为验证码已经成为了更流行的趋势&#xff0c;但更难的实现也让很多开发者头秃&#xff0c;Gitee 已经替你们想到了这一点。不多说了&#xff0c;下面这…

SessionState详解

<sessionState> 元素 配置当前应用程序的会话状态设置。 配置结构的示例&#xff1a; <configuration> <system.web> <sessionState> <sessionState mode"Off|InProc|StateServer|SQLServer" cookieless"true…

reload端口 tomcat_tomcat上部署网站的三种方式

一、利用webapps文件夹自动部署这是最简单的方式&#xff0c;只要将网站直接拷贝到&#xff1a;tomcat根目录下的webapps文件夹里举例&#xff1a;helloworld文件夹下创建里index.html文件&#xff0c;然后把helloworld文件夹移动到tomcat根目录下webapps文件夹里&#xff0c;重…

LeetCode 1095. 山脉数组中查找目标值(二分查找)

1. 题目 给你一个 山脉数组 mountainArr&#xff0c;请你返回能够使得 mountainArr.get(index) 等于 target 最小 的下标 index 值。 如果不存在这样的下标 index&#xff0c;就请返回 -1。 何为山脉数组&#xff1f;如果数组 A 是一个山脉数组的话&#xff0c;那它满足如下…

不能用蛮力法解决的问题_溆浦事蒙汉:脱贫攻坚绝不能心浮气躁骄傲自满疲倦厌战...

脱贫攻坚绝不能心浮气躁骄傲自满疲倦厌战——蒙汉到卢峰镇检查“四支队伍”集村部工作情况检查南华山村“四支队伍”集村部工作情况与大潭村贫困户舒采米座谈红网溆浦讯(记者 伍交才)8月28日&#xff0c;市人大常委会副主任、县委书记蒙汉到卢峰镇南华山村、大潭村检查“四支队…

Oracle 性能调优 概述

在过去的十年中&#xff0c; Oracle 已经成为世界上最专业的数据库之一。对于 IT 专家来说&#xff0c;就是要确保利用 Oracle 的强大特性来提高他们公司的生产力。最有效的方法之一是通过 Oracle 调优。它有大量的调整参数和技术来改进你的 Oracle 数据库的性能。 Oracle 调优…

LeetCode 801. 使序列递增的最小交换次数(动态规划)

1. 题目 我们有两个长度相等且不为空的整型数组 A 和 B 。 我们可以交换 A[i] 和 B[i] 的元素。注意这两个元素在各自的序列中应该处于相同的位置。 在交换过一些元素之后&#xff0c;数组 A 和 B 都应该是严格递增的&#xff08;数组严格递增的条件仅为A[0] < A[1] <…

mock模拟接口测试 vue_vue+mock.js实现前后端分离

之前都是介绍在普通项目中使用mock.js&#xff0c;那么本次就来介绍一下在vue中使用mock.js实现前后端分离。安装&#xff1a;npm install mockjs这里先写个小案例介绍一下具体使用&#xff0c;写法不规范&#xff0c;仅供参考。然后案例讲完后我们讲具体的规范使用那么一起来看…

进一步的去了解正则[一]

1 正则是什么. 请先看 http://www.phpchina.com/html/11/n-34811.html 几k 的解释后. 原地址已被更改&#xff0c;重新找了一个教程&#xff0c;请点击。 http://deerchao.net/tutorials/regex/regex.htm2 实例剖析.1. $str <FORM NAME"ADFA" ACTION"AS…

LeetCode 123. 买卖股票的最佳时机 III(动态规划)

1. 题目 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意: 你不能同时参与多笔交易&#xff08;你必须在再次购买前出售掉之前的股票&#xff09;。 示例 1: 输入: […

mysql异步复制参数_MySQL Replication(异步复制)基本原理

1、复制进程Mysql的复制(replication)是一个异步的复制&#xff0c;从一个Mysqlinstace(称之为Master)复制到另一个Mysqlinstance(称之Slave)。实现整个复制操作主要由三个进程完成的&#xff0c;其中两个进程在Slave(Sql进程和IO进程)&#xff0c;另外一个进程在Master(IO进程…

SQL Server 2005之PIVOT/UNPIVOT行列转换(转)

SQL Server2005引入了很多迎合开发者口味的新特性&#xff0c;虽然改动不大&#xff0c;却大大了减少了开发者的工作量&#xff0c;这种替用户考虑的开发思路&#xff0c;值得称赞。 在SQL Server2000中&#xff0c;要实现行列转换&#xff0c;需要综合利用聚合函数和动态SQL&a…