python编程中可以使用pymysql进行数据库连接及增删改查操作,但每次连接mysql请求时,都是独立的去请求访问,比较浪费资源,而且访问数量达到一定数量时,对mysql的性能会产生较大的影响。因此实际使用中,通常会使用数据库的连接池技术,来访问数据库达到资源复用。

python的数据库连接池包:DBUtils --仅提供给了连接池管理,实际的数据库操作依然是由符合 DB-API 2 标准的目标数据库模块完成的。

DBUtils提供两种外部接口:

  • PersistentDB:提供线程专用的数据库连接,并自动管理连接。
  • PooledDB:提供进程内所有线程共享的数据库连接池,并自动管理连接。

DBUtils包安装: pip3 install DBUtils

或者下载 DBUtils 安装包,解压后,使用python setup.py install 命令进行安装

实测证明 PersistentDB 的速度是最高的,但是在某些特殊情况下,数据库的连接过程可能异常缓慢,而此时的PooledDB则可以提供相对来说平均连接时间比较短的管理方式。

另外,实际使用的数据库驱动也有所依赖,比如SQLite数据库只能使用PersistentDB作连接池。 下载地址:http://www.webwareforpython.org/downloads/DBUtils/

使用方法

连接池对象只初始化一次,一般可以作为模块级代码来确保。 PersistentDB的连接例子:

import DBUtils.PersistentDB
persist=DBUtils.PersistentDB.PersistentDB(dbpai=MySQLdb,maxusage=1000,**kwargs)

这里的参数dbpai指使用的底层数据库模块,兼容DB-API的。maxusage则为一个连接最大使用次数,参考了官方例子。后面的**kwargs则为实际传递给MySQLdb的参数。

获取连接: conn=persist.connection() 实际编程中用过的连接直接关闭 conn.close() 即可将连接交还给连接池。

PooledDB使用方法同PersistentDB,只是参数有所不同。

  • dbapi :数据库接口
  • mincached :启动时开启的空连接数量
  • maxcached :连接池最大可用连接数量
  • maxshared :连接池最大可共享连接数量
  • maxconnections :最大允许连接数量
  • blocking :达到最大数量时是否阻塞
  • maxusage :单个连接最大复用次数
  • setsession :用于传递到数据库的准备会话,如 [”set name UTF-8″] 。

未使用连接池的数据库方法:


 import MySQLdb
 conn= MySQLdb.connect(host='localhost',user='root',passwd='pwd',db='myDB',port=3306)
 #import pymysql
 #conn = pymysql.connect(host='localhost', port='3306', db='game', user='root', password='123456', charset='utf8')
 cur=conn.cursor()
 SQL="select * from table1"
 r=cur.execute(SQL)
 r=cur.fetchall()
 cur.close()
 conn.close()

def getconn(host, user, passwd, db, sql, port=3306,charset='utf8'):
conn = pymysql.connect(host=host, user=user, passwd=passwd, port=port, db=db, charset=charset) #建立连接
cur = conn.cursor(cursor=pymysql.cursors.DictCursor) #建立游标并指定游标类型
cur.execute(sql) #执行sql
if sql.startswith('select'): #判断sql是否是select
res = cur.fetchone()
else:
conn.commit() #insert\delete\update语句执行完毕后需要进行commit
res = 88
cur.close() #关闭游标
conn.close() #关闭连接
return res

用数据库连接池后的方法:

import MySQLdb
from DBUtils.PooledDB import PooledDB
pool = PooledDB(MySQLdb,5,host='localhost',user='root',passwd='pwd',db='myDB',port=3306) #5为连接池里的最少连接数 conn = pool.connection() #以后每次需要数据库连接就是用connection()函数获取连接就好了
cur=conn.cursor()
SQL="select * from table1"
r=cur.execute(SQL)
r=cur.fetchall()
cur.close()
conn.close()

测试代码:

 
import sys
import threading
import MySQLdb
import DBUtils.PooledDB connargs = { "host":"localhost", "user":"user1", "passwd":"123456", "db":"test" }
def test(conn):
try:
cursor = conn.cursor()
count = cursor.execute("select * from users")
rows = cursor.fetchall()
for r in rows: pass
finally:
conn.close() def testloop():
print ("testloop")
for i in range(1000):
conn = MySQLdb.connect(**connargs)
test(conn) def testpool():
print ("testpool")
pooled = DBUtils.PooledDB.PooledDB(MySQLdb, **connargs)
for i in range(1000):
conn = pooled.connection()
test(conn) def main():
t = testloop if len(sys.argv) == 1 else testpool
for i in range(10):
threading.Thread(target = t).start() if __name__ == "__main__":
main()
 

看看 10 线程的测试结果。

 
$ time ./main.py
testloop
testloop
testloop
testloop
testloop
testloop
testloop
testloop
testloop
testloop
real 0m4.471s
user 0m0.570s
sys 0m4.670s
$ time ./main.py -l
testpool
testpool
testpool
testpool
testpool
testpool
testpool
testpool
testpool
testpool
real 0m2.637s
user 0m0.320s
sys 0m2.750s
 

虽然测试方式不是很严谨,但从测试结果还是能感受到 DBUtils 带来的性能提升。当然,我们我们也可以在 testloop() 中一直重复使用一个不关闭的 Connection,但这却不适合实际开发时的情形。

DBUtils 提供了几个参数,便于我们更好地调整资源利用。

 
DBUtils.PooledDB.PooledDB(self, creator,
mincached=0, maxcached=0, maxshared=0, maxconnections=0, blocking=False, maxusage=None,
setsession=None, failures=None, *args, **kwargs)
Docstring:
Set up the DB-API 2 connection pool.
creator: either an arbitrary function returning new DB-API 2
connection objects or a DB-API 2 compliant database module
mincached: initial number of idle connections in the pool
(0 means no connections are made at startup)
maxcached: maximum number of idle connections in the pool
(0 or None means unlimited pool size)
maxshared: maximum number of shared connections
(0 or None means all connections are dedicated)
When this maximum number is reached, connections are
shared if they have been requested as shareable.
maxconnections: maximum number of connections generally allowed
(0 or None means an arbitrary number of connections)
blocking: determines behavior when exceeding the maximum
(if this is set to true, block and wait until the number of
connections decreases, otherwise an error will be reported)
maxusage: maximum number of reuses of a single connection
(0 or None means unlimited reuse)
When this maximum usage number of the connection is reached,
the connection is automatically reset (closed and reopened).
setsession: optional list of SQL commands that may serve to prepare
the session, e.g. ["set datestyle to ...", "set time zone ..."]
failures: an optional exception class or a tuple of exception classes
for which the connection failover mechanism shall be applied,
if the default (OperationalError, InternalError) is not adequate
args, kwargs: the parameters that shall be passed to the creator
function or the connection constructor of the DB-API 2 module
 

DBUtils 仅提供给了连接池管理,实际的数据库操作依然是由符合 DB-API 2 标准的目标数据库模块完成的。

下面利用pymysql 和 DBUtils 建立自己的mysql 数据库连接工具包

class OPMysql(object):

    _pool = None

    def __init__(self):
# 构造函数,创建数据库连接、游标
self.coon = OPMysql.getmysqlconn()
self.cur = self.coon.cursor(cursor=pymysql.cursors.DictCursor) # 数据库连接池连接
@staticmethod
def getmysqlconn():
if OPMysql._pool is None:
OPMysql._pool = PooledDB(creator=pymysql, mincached=1, maxcached=20, host=mysqlInfo['host'], user=mysqlInfo['user'], passwd=mysqlInfo['passwd'], db=mysqlInfo['db'], port=mysqlInfo['port'], charset=mysqlInfo['charset'])
print(OPMysql._pool)
return OPMysql._pool.connection() # 插入\更新\删除sql
def op_insert(self, sql):
try:
# print('op_insert', sql)
insert_num = self.cur.execute(sql)
# print('mysql sucess ', insert_num)
self.coon.commit()
return insert_num
except Exception, e:
print "错误信息", e #仅仅输出错误的愿因,下面的print_exc函数内部会把堆栈信息打印出来
traceback.print_exc() #打印出错误堆栈信息 # 查询
def op_select(self, sql):
print('op_select', sql)
self.cur.execute(sql) # 执行sql
select_res = self.cur.fetchone() # 返回结果为字典
print('op_select', select_res)
return select_res #释放资源
def dispose(self):
self.coon.close()
self.cur.close()

配置文件mysqlinfo,包含数据库的连接信息、用户名密码等:

mysqlInfo = {
"host": '192.168.1.112',
"user": 'root',
"passwd": '',
"db": 'apitest',
"port": 3306,
"charset": 'utf8'
}

创建test,测试数据库连接

if __name__ == '__main__':
#申请资源
opm = OPMysql() sql = "select * from demo where name ='a' and pwd='e10adc3949ba59abbe56e057f20f883e' "
res = opm.op_select(sql) #释放资源
opm.dispose()

PooledDB参数解释:

  1. mincached,最少的空闲连接数,如果空闲连接数小于这个数,pool会创建一个新的连接。
  2. maxcached,最大的空闲连接数,如果空闲连接数大于这个数,pool会关闭空闲连接。
  3. maxconnections,最大的连接数,进程中最大可创建的线程数。
  4. blocking, 当连接数达到最大连接数时,再次请求时,如果这个值是True,请求连接的程序会一直等待,直到当前连接数小于最大连接数;如果这个值为False,会报错。
  5. masxshared,当连接数达到这个数时,新请求的连接会分享已经分配出去的连接。

在uwsgi中,每个http请求都会有一个进程,连接池中配置的连接数都是一个进程为单位的(即上面的最大连接数,都是在一个进程中创建的线程数),如果业务中,一个http请求中需要的sql连接数不是很多的话(其实大多数都只需要创建一个连接),配置的连接数配置都不需要太大。

连接池对性能的提升:

  • 在程序创建连接的时候,可以从一个空闲的连接中获取,不需要重新初始化连接,提升获取连接的速度。
  • 关闭连接的时候,把连接放回连接池,而不是真正的关闭,所以可以减少频繁的打开和关闭连接。

如何选择

PooledDB和PersistentDB都通过回收数据库连接,且即使数据库连接中断也能保持稳定性的方式从而达到提升数据库访问性能的目的。在现实场景中应该如何选择呢?对于保持常量线程数且频繁使用数据库的应用,使用PersistentDB;对于频繁开启、结束线程的应用,使用PooledDB。

其他

如果程序中使用了ORM框架,如SQLObjectSQLAlchemy,不需要使用DBUtils,因为这些框架自身维护了连接池。

数据库线程安全级别:

比如pymysql就是可以共享模块但不能共享连接,查看方式pymysql.threadsafety

https://www.cnblogs.com/KKSoft/p/8040374.html

https://blog.csdn.net/xc_zhou/article/details/80893289

http://aiuxian.com/article/p-34172.html

CheckBox和richTextBox的更多相关文章

  1. WPF基础学习第二天(高级控件)

    1.Menu菜单控件 Exp1: Code: <Window x:Class="菜单Menu.MainWindow" xmlns="http://schemas.m ...

  2. GroupBox、TextBox、CheckBox、ToolStrip、RichTextBox、Timer控件

    GroupBox:划分窗体区域,内部可以拖放组件 TextBox:可编辑文本框,也可设置为只读 属性:ReadOnly(只读).PasswordChar(密码显示的符号,如*).Multiline(多 ...

  3. WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展

    一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本 ...

  4. WPF RichTextBox 做内容展示框 滚动条控制判定是否阅读完成

    一.项目背景: 最近,做项目,因为是金融项目,客户登录交易的时候,有一个提示框,就是告知客户要“入市需谨慎”等等,想必大家都遇到这样的场景,当然,这种提示是没人会看的,不过作为交易所,这样的提示又必不 ...

  5. WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Che ...

  6. 【转】WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展

    一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要是对文本输入控件进行样式开发,及相关扩展功能开发,主要内容包括: 基本文 ...

  7. WPF CheckBox 样式

    <Style x:Key="FocusVisual"> <Setter Property="Control.Template"> < ...

  8. 计算Div标签内Checkbox个数或已被disabled的个数

    先看下面的html: 计算div内的checkbox个数:$('#divmod input[type="checkbox"]').length 计算div内checkbox被dis ...

  9. 前端开发:css技巧,如何设置select、radio 、 checkbox 、file这些不可直接设置的样式 。

    前言: 都说程序员有三宝:人傻,钱多,死得早.博主身边的程序“猿”一大半应了这三宝,这从侧面说明了一个问题,只有理性是过不好日子的.朋友们应该把工作与生活分开,让生活变得感性,让工作变得理性,两者相提 ...

随机推荐

  1. SSIS实践入门3:把SSIS程序包从A电脑到B电脑的转移

    接触SSIS已经有几天了,之前一直是在A电脑做一些demo和修改一些之前的SSIS程序.这次在包中拖入了一个脚本任务,但是在A电脑打开编辑一直打不开,如下图所示 在B电脑就可以打开SSIS脚本编辑器 ...

  2. 关于使用jquery时,ie8下提示对象不支持的属性或方法的解决办法

    转自:http://wapapp.baidu.com/auoong/item/538790fcbe87c834d7ff8cde 首先这个问题的前提是已经排除了常见的这个问题.下面说一种今天我碰到的一种 ...

  3. 极客Web开发资源大荟萃

    前端开发已经成为当前炙手可热的技术之一.此次我们总结的前端开发包含了相关技术和流行趋势,希望从中大家可以挖掘你们所需要的,并带给你们最有价值的帮助!原文来自:极客标签 使用代码回放来愉快地学习前端知识 ...

  4. mysql基础知识之-数据库的创建、查看等常用操作

    命令创建mysql数据库: 先启动mysql数据库,连接数据库: mysql -uroot -p123456         (语法:mysql -u登录名 -p密码) 创建表: create dat ...

  5. KineticJS教程(9)

    KineticJS教程(9) 作者: ysm  9.选择器 Kinetic在舞台.层和组对象上都提供了get方法,用于返回这三者中包含的对象. 9.1.根据ID获取对象 要用id获取对象,首先要给对象 ...

  6. (转)android适配各种分辨率的问题

    Android设备屏幕的尺寸是各式各样的,如小米是4英寸的,Xoom平板是10英寸:分辨率也千奇百怪,800×480,960×540等:Android版本的碎片化问题更是萦绕于心,不过在设计应用时可以 ...

  7. Android中对Handle机制的理解

    一.重要參考资料  [參考资料]     眼下来看,以下的几个网址中的内容质量比較不错.基本不须要再读别的网址了. 1.android消息机制一     http://xtfncel.javaeye. ...

  8. 15-spring学习-集合表达式

    spring认为,数组和List集合是等价的. 要想操作list集合,利用“{内容,内容...}”的形式就可以完成了(类似数组). package com.Spring.ELDemo; import ...

  9. 铁通网络没有一个真实的公网IP,NAT转换能不能解决?

    铁通网络没有一个真实的公网IP,NAT转换能不能解决?     我的是铁通宽带,现在想用自己的机子做一个动态主机,可是因为铁通垃圾网络的NAT转发问题,使用cn99qdns手动更新动态域名IP后公网能 ...

  10. 【LeetCode】103. Binary Tree Zigzag Level Order Traversal

    Binary Tree Zigzag Level Order Traversal Given a binary tree, return the zigzag level order traversa ...