python下cx_oracle短连接oracle,报ORA-12520

来源:互联网 发布:中兴 知乎 编辑:程序博客网 时间:2024/06/07 16:55

最近在用python下一个数据库操作的小程序,采用短连接方式。

在单线程下,程序跑得比较稳定;在2个线程下就很容易core 下来,gdb查看信息都是如下:

#14 0xfddf46e6 in OCIServerAttach () from /sw/oracle/products/10.2/lib32/libclntsh.so.10.1
#15 0xfe8f2106 in Connection_Init (self=0x830c920, args=0x83964cc, keywordArgs=0x0) at Connection.c:612

 

并有时伴有oracle异常:

DatabaseError: ORA-12520: TNS:listener could not find available handler for requested type of server

(概率比较高,不是一定回先异常后core;有时就直接core了)

 

在网上搜寻一番后,归结原因和session,process等关系密切,监控这2个数据后发现:

当session接近设置的阀值时,程序就core下来;在session为远远低于阀值就没问题。

 

分析:

1, 短连接频繁和数据库交互的时候,对listener造成的压力非常大
2, oracle在MTS配置下问题更容易发生。(我就是配置为MTS的,修改这个配置没有测试过)
 
供参考解决办法:
 
改为长连接。(长连接不能根本解决该问题,只是发生概率会低到可接受的程度)
 
我的测试python代码如下:

#!/usr/bin/env python
#coding=gbk

from socket import *
import sys
import threading
import cx_Oracle
from time import sleep, ctime
from string import *

def getdata(connstr,tablename):
      con = cx_Oracle.connect(connstr)
      cur = con.cursor()
      sqlStr = "select count(*) from %s" % tablename

      cur.execute(sqlStr)
      recList = cur.fetchall()
      num = 0
      if len(recList) > 0:
          num = recList[0][0]

      cur.close()
      con.close()
      return num

class AgentWorker(threading.Thread):
      def __init__(self,seq):
          threading.Thread.__init__(self)
           self.seq = seq
          self.count = 0

            
      def readdb(self):
          sess = getdata(self.connstr,'v$session')
          pros = getdata(self.connstr,'v$process')
          print '%s:(%s,%s,%s)' % (self.seq,self.count,sess,pros)
          self.count += 1
          return 'success'                    


      def __call__(self):
          while True:
              retCode = self.readdb() 
              sleep(1)
           
def main():
    i = 0
    while i < 2:
        t = threading.Thread(target = AgentWorker(i)

        t.start()
        i += 1
    
if __name__ == '__main__':
      main()