博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python - DBUtils 连接池减少oracle数据库的连接数
阅读量:6969 次
发布时间:2019-06-27

本文共 3855 字,大约阅读时间需要 12 分钟。

问题:

接到需求,告知项目的oracle连接次数过多,对系统造成太过大的负担,要求减少oracle数据库的连接次数

分析:

仔细分析代码以后,发现产生问题的原因,在于之前要求提升oracle监控的监控速度时,将oracle监控的脚本代码,拆分成了多个子进程。导致每次循环服务器都会产生子进程次数的数据库连接,产生了过多的不必要连接

解决方案:

讨论分析过后,决定更改代码的架构,用DBUtils的连接池功能+多线程(http://www.cnblogs.com/fnng/p/3670789.html)的组合,替代现有的 多进程+子进程对数据库的单次连接

DBUtils:

DBUtils 是一套允许线程化 Python 程序可以安全和有效的访问数据库的模块。

下载并安装:

$ wget https://pypi.python.org/packages/65/65/89afee016aca7fbb5c1642e6ef3864d80af808dc5efa7367b328093eece9/DBUtils-1.1.tar.gztar -zxf DBUtils-1.1.tar.gzcd DBUtils-1.1python setup.py install

使用:

  参考:http://blog.163.com/power_mr/blog/static/138744007201391823253744/

  导入:import DBUtils.PersistentDB

  • dbapi :数据库接口
  • mincached :启动时开启的空连接数量
  • maxcached :连接池最大可用连接数量
  • maxshared :连接池最大可共享连接数量
  • maxconnections :最大允许连接数量
  • blocking :达到最大数量时是否阻塞
  • maxusage :单个连接最大复用次数
#不用连接池的MySQL连接方法import MySQLdbconn= MySQLdb.connect(host='localhost',user='root',passwd='pwd',db='myDB',port=3306)  cur=conn.cursor()SQL="select * from table1"r=cur.execute(SQL)r=cur.fetchall()cur.close()conn.close()
#用连接池后的连接方法import MySQLdbfrom DBUtils.PooledDB import PooledDBpool = 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()

 

 

自用:

生成mysql池

# get mysql PooledDB    logger.info("get MySQL connect.")    host = get_config('monitor_server','host')    port = get_config('monitor_server','port')    user = get_config('monitor_server','user')    passwd = get_config('monitor_server','passwd')    dbname = get_config('monitor_server','dbname')    try:        # mincached 最少的空闲连接数,如果空闲连接数小于这个数,pool会创建一个新的连接        mysql_pool = PooledDB(MySQLdb,mincached=20,blocking=True,host=host,user=user,passwd=passwd,port=int(port),db=dbname,connect_timeout=5,charset='utf8')        glob.set_value('mysql_conn',mysql_pool)    except Exception,e:        print "start mysql(pooledDB) error:" + str(e)

生成oracle池:

#get oracle servers list    logger.info("get Oracle connect.")    servers=func.mysql_query("select id,host,port,dsn,username,password,tags from db_servers_oracle where is_delete=0 and monitor=1;")    if servers:        for row in servers:            server_id=row[0]            host=row[1]            port=row[2]            dsn=row[3]            username=row[4]            password=row[5]            tags=row[6]            ora_dsn = host + ":" + port + "/" + dsn            try:                oracle_pool = PooledDB(cx_Oracle,mincached=20,blocking=True,user=username,password=password,dsn=ora_dsn)                conn_name = "server_"+str(server_id)+"_pool"                glob.set_value(conn_name,oracle_pool)            except Exception, e:                logger_msg="check oracle server connect %s : %s" %(ora_dsn,str(e).strip('\n'))                logger.warning(logger_msg)

 

问题:

改动过程中,碰到了比较难以解决的“疑难杂症”:脚本在执行过程中,会出现异常导致无限执行的死循环中断现象,同时出现中断时,不产生异常报错,导致bug的解决比较困难

为了找出异常的部分,对代码进行了更详细的测试:

  1. 搭建代码框架,进行框架测试
  2. 向框架中填充基本内容,进行基本内容测试
  3. 对代码的各个部分,进行实验性测试:
连接池 + 单index线程循环 + 服务器循环外join + 执行oracle操作 -> 异常退出单连接 + 单index线程循环 + 服务器循环外join + 执行oracle操作 -> 异常退出单连接 + 单index线程循环 + 服务器循环外join + 不执行oracle操作 -> 正常连接池 + 单index线程循环 + 服务器循环外join + 不执行oracle操作 -> 正常连接池 + 单index线程循环 + 服务器循环外join + 执行单条oracle操作 -> 异常

确认了问题产生于oracle数据库

确认了问题所在后,经过多次试验,发现在使用多线程连接数据库的过程中,打印出了两次异常:

  KPEDBG_HDL_POP_FCPTRKPEDBG_HDL_POP_FCPTRKPEDBG_HDL_POP_FCPTRORA-24550: signal received: [si_signo=11] [si_errno=0] [si_code=1] [si_int=16] [si_ptr=0x10] [si_addr=(nil)]

百度后修改oracle客户端的配置文件(sqlnet.ora)

#路径:/usr/lib/oracle/12.2/client64/network/admin/sqlnet.oraDIAG_ADR_ENABLED=OFFDIAG_SIGHANDLER_ENABLED=FALSEDIAG_DDE_ENABLED=FALSE

同时,改动oracle数据库的使用方式:

      从之前获取连接以后,使用连接作为oralce监控方法的传输参数,

      改为,传递oracle连接池的池连接(oralce_pool)作为参数,在方法内,生成新的oracle连接

1.     搭建代码框架,进行框架测试

转载于:https://www.cnblogs.com/blitheG/p/7772389.html

你可能感兴趣的文章
堆排序python理解_python堆排序如何使用呢?
查看>>
5道java面试题_5道常见的Java面试题!值得一看
查看>>
mysql数据类型支持比较运_MySQL整理5—数据类型和运算符
查看>>
java反序列化成object_java常用知识:ObjectInputStream反序列化流
查看>>
Java程序编译后的扩展名_一个Java源程序经过编译后,得到的文件扩展名一定是.class。...
查看>>
java 菱形 乱码_(04)Spring MVC之Get方式传参访问Controller,从Controller返回json串出现菱形问号(?????)乱码,解决方法。...
查看>>
php怎么连kafka,php连接kafka
查看>>
php动态生成html,通用PHP动态生成静态HTML网页的代码
查看>>
dede个人中心php在哪,dedecms织梦如何自定义会员中心目录名称的方法
查看>>
linux 运维高级脚本生成器,Linux运维实例 高效运维的工具--shell脚本
查看>>
linux配置redis服务,Linux下安装Redis并设置相关服务
查看>>
poj1106
查看>>
个人知识管理工具 PinPKM
查看>>
Jobs in Codility they're hiring
查看>>
linux下VNC的配置及使用
查看>>
为什么.NET Framework就没有个专门的P/Invoke Library?
查看>>
Silverlight动态设置WCF服务Endpoint
查看>>
lucene对日期(date)和整形(int)处理
查看>>
hdu 4081 次小生成树
查看>>
HtmlNodeType枚举
查看>>