查询了菜鸟教程以及博客园等各种文章,有修改完善
转载自https://www.cnblogs.com/yuhou/p/10893056.html
自己完善部分:
python连接mysql使用连接池:
一、为什么要用连接池?
1、数据库 本身有压力,并不能创建太多的并发数访问数据库,如果是大表那更加会有压力,因此限制一定的连接是更加科学的方法。
2、创建和释放数据库连接是一个很耗时的操作,频繁地进行这样的操作将占用大量的性能开销,进而响应速度下降,严重的时候可能导致服务器崩溃,数据库连接池可以节省系统许多开销。
综上所述,可以使用连接池当然最好是使用连接池了。
二、使用DBUtils包
DBUtils是一套Python数据库连接池包,并允许对非线程安全的数据库接口进行线程安全包装。DBUtils来自Webware for Python。
DBUtils提供两种外部接口:
- PersistentDB :提供线程专用的数据库连接,并自动管理连接。
- PooledDB :提供线程间可共享的数据库连接,并自动管理连接。
需要库
1、DBUtils pip install DBUtils
2、pymysql pip install pymysql/MySQLdb
此处用的是DBUtils 2.0,详细的请看官方文档
with语句的工作原理:此处使用with语句进行操作,自动调用with后边类的返回值,最后调用类的exit方法清理
紧跟with后面的语句会被求值,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as关键字后面的变量,当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。
with语句最关键的地方在于被求值对象必须有__enter__()和__exit__()这两个方法,那我们就可以通过自己实现这两方法来自定义with语句处理异常。
import pymysql
from dbutils.pooled_db import PooledDB
#配置文件,连接数据库使用,配置连接池相关参数
config = {
'host':'127.0.0.1',
'port':3306,
'user':'root',
'password':"",
'db':'test',
'creator':pymysql,#使用连接数据库的模块,这里是mysql,还可以是pgsql,oracle等等
'mincached':1,#启动时开启的闲置连接数量(缺省值 0 表示开始时不创建连接)
'maxcached':5,#连接池中允许的闲置的最多连接数量(缺省值 0 代表不闲置连接池大小)
'maxshared':5,#共享连接数允许的最大数量(缺省值 0 代表所有连接都是专用的)如果达到了最大数量,被请求为共享的连接将会被共享使用
'maxconnections':10,#创建连接池的最大数量(缺省值 0 代表不限制)
'blocking':True,#设置在连接池达到最大数量时的行为(缺省值 0 或 False 代表返回一个错误<toMany......> 其他代表阻塞直到连接数减少,连接被分配)
'maxusage':0,# 单个连接的最大允许复用次数(缺省值 0 或 False 代表不限制的复用).当达到最大数时,连接会自动重新连接(关闭和重新打开)
'setsession':None,#一个可选的SQL命令列表用于准备每个会话,如["set datestyle to german", ...]
'charset':'utf8'
}
"""
通过DBUtils,实例化一个PooledDB对象作为MyConnectionPool类的类属性,
通过重写__enter__和__exit__方法让我们在进入with语句时从连接池中获取到数据库连接,
通过with语句调用,在with语句结束后,自动释放连接池,归还给连接池。
"""
class MyConnectionPool(object):
def __init__(self,**kwargs):
self.pool = PooledDB(**config)
# 创建数据库连接,以及获取游标
def __enter__(self):
print("进入enter")
self.conn = self.pool.connection()
self.cursor = self.conn.cursor()
return self
# 释放连接池资源
def __exit__(self, exc_type, exc_val, exc_tb):
self.cursor.close()
self.conn.close()
print("执行了exit")
#以上就完成了整个流程,建立连接,获取游标等
#以上整体可以作为一个工具,作为数据库连接池
#####################===================================================================================##################
#下边,具体如何使用数据库连接池示例
if __name__ == '__main__':
with MyConnectionPool() as db:
db.cursor.execute("select * from review")
db.conn.commit()
for row in db.cursor.fetchall():
print("nid:%d created_at:%s content:%s source:%s" % row)
输出打印:
进入enter
nid:1 created_at:2020-12-22 content:中文支持吗 source:啊啊啊啊啊
nid:1 created_at:2020-12-22 content:修改内容 source:啦啦啦
nid:2 created_at:2020-12-22 content:修改内容 source:牛牪犇
nid:3 created_at:2020-12-22 content:修改内容 source:啦啦啦
nid:4 created_at:2020-12-22 content:修改内容 source:中国
nid:5 created_at:2020-12-22 content:修改内容 source:啦啦啦
nid:6 created_at:2022-1-1 content:修改内容 source:啦啦啦
nid:6 created_at:2022-1-1 content:修改内容 source:啦啦啦
nid:7 created_at:2020-12-22 content:修改内容 source:啦啦啦
执行了exit
来源:https://www.cnblogs.com/woider/p/5926744.html
==================pymysql===================
由于 MySQLdb 模块还不支持 Python3.x,所以 Python3.x 如果想连接MySQL需要安装 pymysql 模块。
pymysql 模块可以通过 pip 安装。但如果你使用的是 pycharm IDE,则可以使用 project python 安装第三方模块。
[File] >> [settings] >> [Project: python] >> [Project Interpreter] >> [Install按钮]
由于Python统一了数据库连接的接口,所以 pymysql 和 MySQLdb 在使用方式上是类似的:
#创建数据库连接
pymysql.Connect()参数说明 host(str): MySQL服务器地址 port(int): MySQL服务器端口号 user(str): 用户名 passwd(str): 密码 db(str): 数据库名称 charset(str): 连接编码,存在中文的时候,连接需要添加charset='utf8',否则中文显示乱码。 connection对象支持的方法 cursor() 使用该连接创建并返回游标 commit() 提交当前事务,不然无法保存新建或者修改的数据 rollback() 回滚当前事务 close() 关闭连接 cursor对象支持的方法 execute(op) 执行SQL,并返回受影响行数 fetchone() 取得结果集的下一行 fetchmany(size) 获取结果集的下几行 fetchall() 获取结果集中的所有行 rowcount() 返回数据条数或影响行数 close() 关闭游标对象
==================MySQL===================
首先在连接数据库之前,先创建一个交易表,方便测试 pymysql 的功能:
DROP TABLE IF EXISTS trade; CREATE TABLE trade ( id int(4) unsigned NOT NULL AUTO_INCREMENT, name varchar(6) NOT NULL COMMENT '用户真实姓名', account varchar(15) NOT NULL COMMENT '银行储蓄账号', saving decimal(8,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '账户储蓄金额', expend decimal(8,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '账户支出总计', income decimal(8,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '账户收入总计', PRIMARY KEY (id), UNIQUE KEY name_UNIQUE (name) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO trade VALUES (1,'乔布斯','18012345678',0.00,0.00,0.00);
==================Python===================
使用Python脚本实现增删改查和事务处理,源码如下:
import pymysql.cursors # 连接数据库 connect = pymysql.Connect( host='localhost', port=3310, user='woider', passwd='3243', db='python', charset='utf8' ) # 获取游标 cursor = connect.cursor() # 插入数据 sql = "INSERT INTO trade (name, account, saving) VALUES ( '%s', '%s', %.2f )" data = ('雷军', '13512345678', 10000) cursor.execute(sql % data) connect.commit() print('成功插入', cursor.rowcount, '条数据') # 修改数据 sql = "UPDATE trade SET saving = %.2f WHERE account = '%s' " data = (8888, '13512345678') cursor.execute(sql % data) connect.commit() print('成功修改', cursor.rowcount, '条数据') # 查询数据 sql = "SELECT name,saving FROM trade WHERE account = '%s' " data = ('13512345678',) cursor.execute(sql % data) for row in cursor.fetchall(): print("Name:%s Saving:%.2f" % row) print('共查找出', cursor.rowcount, '条数据') # 删除数据 sql = "DELETE FROM trade WHERE account = '%s' LIMIT %d" data = ('13512345678', 1) cursor.execute(sql % data) connect.commit() print('成功删除', cursor.rowcount, '条数据') # 事务处理 sql_1 = "UPDATE trade SET saving = saving + 1000 WHERE account = '18012345678' " sql_2 = "UPDATE trade SET expend = expend + 1000 WHERE account = '18012345678' " sql_3 = "UPDATE trade SET income = income + 2000 WHERE account = '18012345678' " try: cursor.execute(sql_1) # 储蓄增加1000 cursor.execute(sql_2) # 支出增加1000 cursor.execute(sql_3) # 收入增加2000 except Exception as e: connect.rollback() # 事务回滚 print('事务处理失败', e) else: connect.commit() # 事务提交 print('事务处理成功', cursor.rowcount) # 关闭连接 cursor.close() connect.close()
==================测试结果===================