数据库连接池,主要用于多线程,为了防止多线程同时对数据库进行操作出现混乱。创建数据库线程池,维护n个数据库连接供程序使用
import threading
import pymysql
from DBUtils.PooledDB import PooledDB
class SqlHelper(object):
def __init__(self):
self.pool = PooledDB(
# 数据库驱动模块
creator=pymysql,
# 线程池最大连接数
maxconnections=6,
# 初始化连接池时创建的连接数
mincached=2,
# 池中空闲连接的最大数量
maxcached=5,
# 池中共享连接的最大数量
maxshared=3,
#默认False,即达到最大连接数时,再取新连接将会报错,True,达到最大连接数时,新连接阻塞,等待连接数减少再连接
blocking=True,
# 连接的最大使用次数
maxusage=None,
# 确定何时使用ping()检查连接。默认1,即当连接被取走,做一次ping操作。0是从不ping,1是默认,2是当该连接创建游标时ping,4是执行sql语句时ping,7是总是ping
ping=0,
host='127.0.0.1',
port=3306,
user='blogadmin',
password='blogpwd',
database='flask_blog',
charset='utf8',
)
self.local = threading.local()
# 打开连接
def open(self):
conn = self.pool.connection()
cursor = conn.cursor()
return conn, cursor
# 关闭连接
def close(self, cursor, conn):
cursor.close()
conn.close()
# 查询全部
def fetchall(self, sql, *args):
conn, cursor = self.open()
cursor.execute(sql, *args)
result = cursor.fetchall()
self.close(cursor, conn)
return result
# 查询一条
def fetchone(self, sql, *args):
conn, cursor = self.open()
cursor.execute(sql, *args)
result = cursor.fetchone()
self.close(cursor, conn)
return result
# 插入一条
def insert(self, sql, *args):
conn, cursor = self.open()
try:
cursor.execute(sql, *args)
# 食物提交
conn.commit()
self.close(cursor, conn)
return True
except:
# 事务回滚
conn.rollback()
return False
def __enter__(self):
conn, cursor = self.open()
rv = getattr(self.local,'stack',None)
if not rv:
self.local.stack = [(conn, cursor)]
else:
rv.append((conn, cursor))
self.local.stack = rv
return cursor
def __exit__(self):
rv = getattr(self.local,'stack',None)
if not rv:
del self.local.stack
return
else:
conn, cursor = self.local.stack.pop()
self.close(conn, cursor)
def __new__(cls, *args, **kwargs):
if not hasattr(SqlHelper, '_instance'):
SqlHelper._instance = super().__new__(cls)
return SqlHelper._instance
db = SqlHelper()
# with db as c1:
# c1.execute('select sleep(1)')