用python自定义实现db2的连接池

手动迁移原创博客,原文发表在http://www.cnblogs.com/paololiu/p/5070749.html


想要模仿zabbix的oracle插件orabix来实现对db2的监控,但是Java能力有限,就用python来实现了。但是python常用的连接池PooledDB似乎并不支持db2,一直报这样的错误:"Database module is not thread-safe."所幸我只是用来做监控的,要求并不是很高,只要实现连接池的两个基本功能即可:
1.连接复用
2.连接检查,重连


#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import threading,ibm_db,time,Queue

class db2pool(object):
    def __init__(self,host,port,user,password,db,conn_num):
        self.host=host
        self.port=port
        self.user=user
        self.password=password
        self.db=db
        self.conn_num=conn_num
        
        self.conn_queue=Queue.Queue(0)
                        
        for i in range (0,self.conn_num):
            try:
                conn=(ibm_db.connect("DATABASE="+self.db+";HOSTNAME="+self.host+";PORT="+self.port+";PROTOCOL=TCPIP;UID="+self.user+";PWD="+self.password+";", "", ""))
                self.conn_queue.put(conn)
            except Exception as e:    
                print e
    
    def getconnect(self):
            
        for i in range (0,5):

            if self.conn_queue.qsize()>0:
                conn=self.conn_queue.get()
                
                try:
                    stmt=ibm_db.prepare(conn,"select 1 from sysibm.sysdummy1")
                    ibm_db.execute(stmt)
                    return conn
                except Exception as e:
                    print e
                    try:
                        conn=(ibm_db.connect("DATABASE="+self.db+";HOSTNAME="+self.host+";PORT="+self.port+";PROTOCOL=TCPIP;UID="+self.user+";PWD="+self.password+";", "", ""))
                        self.conn_queue.put(conn)
                    except Exception as e:
                        print e
                
            time.sleep(0.5)
                
        self.logger.echo("warning","get connection error")
            
    def getclose(self,conn):        
        self.conn_queue.put(conn)

#example
def work(pool,i):
    # while True:
    conn=pool.getconnect()
    if conn:
        try:
            pass
            stmt=ibm_db.prepare(conn,"select "+str(i)+" from sysibm.sysdummy1")
            ibm_db.execute(stmt)
            result=ibm_db.fetch_both(stmt)
            while (result):
                print "\nresult[0]="+str(result[0])+"++++"+str(conn)
                result=ibm_db.fetch_both(stmt)
        except Exception as e:
            print e
        finally:
            pass
            pool.getclose(conn)
    time.sleep(5)

if __name__=="__main__":
    pool=db2pool("172.16.2.9","60000","db2inst1","db2inst1","secs",5)
    for i in range (0,50):
        t=threading.Thread(target=work,args=(pool,i,))
        t.start()

因为我自己对python也不熟,这里有个地方我采用了妥协的办法:
我是在调用连接的时候去检查连接是否还存活着,而一般的情况下都是用一个后台的线程每隔一段时间去检查线程的。

我也尝试着这样去做了,但发现一个问题:获取连接队列conn=self.conn_queue.get()这一过程对各方都是平等的,谁抢到就是谁的。如果要做个检查连接的方法,则我希望它获得队列的优先级要高与正常调用的的方法,这样就不会出现连接队列一直被正常调用的方法霸占着,而检查连接的方法却因为抢不到连接而不工作。看来这部分要在实现了可控优先级的队列后才能实现了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个 Python 3.x 实现数据库连接池类单例模式的例子,使用了线程安全的单例模式: ```python import sqlite3 from queue import Queue from threading import Lock class ConnectionPool: __instance = None __lock = Lock() @staticmethod def get_instance(): if ConnectionPool.__instance is None: with ConnectionPool.__lock: if ConnectionPool.__instance is None: ConnectionPool.__instance = ConnectionPool() return ConnectionPool.__instance def __init__(self, max_size=10, db_file=':memory:'): self.max_size = max_size self.db_file = db_file self.pool = Queue(maxsize=max_size) for _ in range(max_size): connection = sqlite3.connect(db_file) self.pool.put(connection) def get_connection(self): return self.pool.get() def release_connection(self, connection): self.pool.put(connection) ``` 在上面的例子中,`ConnectionPool` 是一个单例类,它维护了一个 SQLite 数据库连接池。通过 `get_instance` 方法获取单例对象,通过 `get_connection` 方法从连接池中获取一个数据库连接,通过 `release_connection` 方法将连接释放回连接池。 在构造函数中,我们创建了一个指定大小的连接池,并将连接放入队列中。在 `get_connection` 方法中,我们从队列中获取连接,如果队列为空,则会阻塞,直到有可用连接为止。在 `release_connection` 方法中,我们将连接放回队列中。 使用单例模式,可以保证我们只有一个数据库连接池实例,避免了在多个地方同时创建数据库连接池实例的问题。同时,使用线程安全的单例模式,可以保证在多线程环境下,单例对象的创建过程是线程安全的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值