问题:

接到需求,告知项目的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.gz

tar -zxf DBUtils-1.1.tar.gz

cd DBUtils-1.1
python setup.py install

使用:

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

  导入:import DBUtils.PersistentDB

  • dbapi :数据库接口
  • mincached :启动时开启的空连接数量
  • maxcached :连接池最大可用连接数量
  • maxshared :连接池最大可共享连接数量
  • maxconnections :最大允许连接数量
  • blocking :达到最大数量时是否阻塞
  • maxusage :单个连接最大复用次数
#不用连接池的MySQL连接方法
import MySQLdb
conn= 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 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()

自用:

生成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.ora
DIAG_ADR_ENABLED=OFF
DIAG_SIGHANDLER_ENABLED=FALSE
DIAG_DDE_ENABLED=FALSE

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

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

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

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

python - DBUtils 连接池减少oracle数据库的连接数的更多相关文章

  1. Python DBUtils 连接池对象 (PooledDB)

    数据处理框架用到 mysql, 需要在多进程中的多线程中使用 mysql 的连接 使用到的模块: DBUtils 实现: 使用 DBUtils 中的 PooledDB 类来实现. 自己写一个类, 继承 ...

  2. python使用dbutils的PooledDB连接池,操作数据库

    1.使用dbutils的PooledDB连接池,操作数据库. 这样就不需要每次执行sql后都关闭数据库连接,频繁的创建连接,消耗时间 2.如果是使用一个连接一直不关闭,多线程下,插入超长字符串到数据库 ...

  3. DBUtils连接池,websocket

    1.mysql数据库连接池 概念:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放. 这样 ...

  4. Python 使用Python远程连接并操作InfluxDB数据库

    使用Python远程连接并操作InfluxDB数据库 by:授客 QQ:1033553122 实践环境 Python 3.4.0 CentOS 6 64位(内核版本2.6.32-642.el6.x86 ...

  5. Java java jdbc thin远程连接并操作Oracle数据库

    JAVA jdbc thin远程连接并操作Oracle数据库 by:授客 QQ:1033553122 测试环境 数据库:linux 下Oracle_11g_R2 编码工具:Eclipse 编码平台:W ...

  6. jdbc连接rac的oracle数据库

    jdbc连接rac的oracle数据库需要配置所有racIP,如下: DB1 =(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(H ...

  7. 孤荷凌寒自学python第五十八天成功使用python来连接上远端MongoDb数据库

    孤荷凌寒自学python第五十八天成功使用python来连接上远端MongoDb数据库 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第四天.今天的感觉是,mongoDB数据 ...

  8. Python使用cx_Oracle模块操作Oracle数据库--通过sql语句和存储操作

    https://www.jb51.net/article/125160.htm?utm_medium=referral  Python使用cx_Oracle调用Oracle存储过程的方法示例 http ...

  9. 查看oracle数据库的连接数以及用户

    查看oracle数据库的连接数以及用户 11.查询oracle的连接数2select count(*) from v$session;32.查询oracle的并发连接数4select count(*) ...

随机推荐

  1. CDH部署StreamSets

    StreamSets是一个大数据采集工具,数据源支持包括结构化和半/非结构化,目标源支持HDFS,HBase,Hive,Kudu,Cloudera Search, ElasticSearch等.它包括 ...

  2. React中用EChart写面积图

    UED出的设计图如下:  实际展示效果如下: 调取的数据如下: "staffCountList":[ { "time":"2019-12-24 17: ...

  3. juniper 命令

    show chassis hardware 查看系统硬件配置,fpc表示板卡,pic表示板卡中的槽位,xcvr表示板卡中的槽位的端口位置 show chassis envirmonent 查看系统运行 ...

  4. python中reload(sys)作用

    python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报错UnicodeDecodeError: 'ascii' codec can't decode ...

  5. 清北学堂提高突破营游记day1

    上午7点半到的国防宾馆,8点开始的培训. 讲课人林永迪. 没错就是这个人: 他推荐的教辅:刘汝佳紫书,算法导论(也就看看..),刘汝佳白书 先讲模拟.(貌似就是看题论题. 然后贪心. 贪心没有固定的模 ...

  6. 清华集训2014 sum

    清华集训2014sum 求\[∑_{i=1}^{n}(-1)^{⌊i√r⌋}\] 多组询问,\(n\leq 10^9,t\leq 10^4, r\leq 10^4\). 吼题解啊 具体已经讲得很详细了 ...

  7. 【HDU5289】Assignment

    题目大意:给定一个长度为 N 的序列,求序列中最大值和最小值相差小于 K 的连续段的个数. 题解: 最大值和最小值相差不超过 K 是一个在值域角度的限制,应考虑采用平衡树或权值...数据结构进行维护. ...

  8. VirtualBox导入VmWare生成的.vmdk格式虚拟机镜像

    VmWare默认的镜像格式是.vmdk格式的,VirtualBox则默认是.vdi格式的.其实这在VirtualBox新建虚拟机的过程中是可选的. 导入.vmdk格式的镜像到VirtualBox只需要 ...

  9. jQuery、JS读取xml文件里的内容(JS先通过document.implementation.createDocument方法将xml转换成document对象,jQuery将读取到的xml转成table)

    xml文件:test.xml <?xml version="1.0"?> <note> <to>George</to> <fr ...

  10. jvm——CodeCache

    https://juejin.im/post/5c890f21f265da2d993dc692 CodeCache是热点代码的暂存区,经过即时编译器编译的代码会放在这里,它存在于堆外内存.除了JIT编 ...