2016-11-10 3 views
0

내 질문은 전체 응용 프로그램에서 단일 데이터베이스 연결을 유지하는 가장 좋은 방법은 무엇입니까?싱글 톤 패턴을 사용 하시겠습니까? 방법? 필요파이썬 응용 프로그램 전체에 단일 데이터베이스 연결 (싱글 톤 패턴 다음)

조건이 처리 촬영하기 : 여러 요청의 경우

  1. 을, 나는 닫힌 경우 연결에서 동일한 연결
  2. 를 이용해야한다, 새로운 연결을 만들
  3. 연결이 시간 초과 된 경우 새 요청에서 내 코드가 새 연결을 만들어야합니다.

내 데이터베이스에 대한 드라이버는 장고 ORM 지원하지 않습니다. 동일한 드라이버 관련 문제로 인해 pyodbc을 사용하여 데이터베이스에 연결합니다. 지금 당장 DB 연결을 만들고 관리하는 데 필요한 클래스가 아래와 같습니다.

class DBConnection(object): 
    def __init__(self, driver, serve, 
       database, user, password): 

     self.driver = driver 
     self.server = server 
     self.database = database 
     self.user = user 
     self.password = password 

    def __enter__(self): 
     self.dbconn = pyodbc.connect("DRIVER={};".format(self.driver) +\ 
            "SERVER={};".format(self.server) +\ 
            "DATABASE={};".format(self.database) +\ 
            "UID={};".format(self.user) +\ 
            "PWD={};".format(self.password) + \ 
            "CHARSET=UTF8", 
            # "", 
            ansi=True) 

     return self.dbconn 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     self.dbconn.close() 

그러나이 방법의 문제점은 각 쿼리에 대해 새 데이터베이스 연결을 만드는 것입니다. 싱글 톤 패턴을 따르는 것이 더 좋은 방법일까요? 내가 생각할 수있는 방법은 연결이 닫힌 경우 연결에 대한 참조를 보유합니다. 예 :

def get_database_connection(): 
    conn = DBConnection.connection 
    if not conn: 
      conn = DBConnection.connection = DBConnection.create_connection() 
    return conn 

이 작업을 수행하는 가장 좋은 방법은 무엇입니까? 어떤 제안/아이디어/예?

추신 : 나는 약한 참조를 만드는 것을 허용하는 weakref을 사용하고 있는지 확인하고있었습니다. 나는 weakref을 연결 변수 저장을위한 싱글 톤 패턴과 함께 사용하는 것이 좋은 생각이라고 생각합니다. 이 방법은 내가 DB를 사용하지 않을 때 alive 연결을 유지할 필요가 없습니다. 너희들이 이것에 대해 뭐라하니?

+0

연결을 관리하기위한 연결

class DBConnector(object): def __init__(self, driver, server, database, user, password): self.driver = driver self.server = server self.database = database self.user = user self.password = password self.dbconn = None # creats new connection def create_connection(self): return pyodbc.connect("DRIVER={};".format(self.driver) + \ "SERVER={};".format(self.server) + \ "DATABASE={};".format(self.database) + \ "UID={};".format(self.user) + \ "PWD={};".format(self.password) + \ "CHARSET=UTF8", ansi=True) # For explicitly opening database connection def __enter__(self): self.dbconn = self.create_connection() return self.dbconn def __exit__(self, exc_type, exc_val, exc_tb): self.dbconn.close() 

DBConnection 클래스을 만들기위한 그들 :

DBConnector 클래스을 언급 느낌 [django-pyocdb] (https://pypi.python.org/pypi/django-pyodbc)와 같은 pyocdb에 대한 몇 가지 타사 백엔드가되어야합니다. 왜 그 중 하나를 사용하지 않습니까? – knbk

+0

django-pyodbc가 지원하지 않는 데이터베이스로 IBM Netezza를 사용하고 있습니다. –

+0

연결 및 커서 생성만을 지원하는 최소한의 데이터베이스 백엔드를 구현할 수 있습니다. 그렇게하면 Django의 연결 관리를 사용하여 연결을 처리 할 수 ​​있습니다. 연결 처리를 구현하는 것보다 쉬울 것이라고 생각합니다. – knbk

답변

0

지금은 싱글 톤 클래스 방식을 사용하겠습니다. 이에 잠재적 인 결함을 보는 사람은 누구나 것 같다

class DBConnection(object): 
    connection = None 

    @classmethod 
    def get_connection(cls, new=False): 
     """Creates return new Singleton database connection""" 
     if new or not cls.connection: 
      cls.connection = DBConnector().create_connection() 
     return cls.connection 

    @classmethod 
    def execute_query(cls, query): 
     """execute query on singleton db connection""" 
     connection = cls.get_connection() 
     try: 
      cursor = connection.cursor() 
     except pyodbc.ProgrammingError: 
      connection = cls.get_connection(new=True) # Create new connection 
      cursor = connection.cursor() 
     cursor.execute(query) 
     result = cursor.fetchall() 
     cursor.close() 
     return result 
+0

연결이 스레드간에 공유되지 않도록하거나, 놀랍고 어려운 디버깅 동작을 수행해야합니다. 'threading.local()'객체에 연결을 저장할 수 있으므로 각 스레드는 자신의 싱글 톤 연결을 갖습니다. – knbk

+0

@knbk : 나는 단지 연결 객체를 공유하고 있지만 execute_query 함수에서 각 쿼리에 대해 새로운 로컬'cursor'를 생성합니다. 그래서 쿼리/결과 관계가 커서에 의해 유지되므로'execute_query'가 비동기 적으로 호출 되더라도 아무런 해가되지 않습니다. 그것은 다시 내 가정이다. 또는 나는 틀린가? –

+1

[pyodbc docs] (https://mkleehammer.github.io/pyodbc/api.html)에서 : "** threadsafety ** 스레드가 모듈을 공유하지만 연결은 할 수 없음을 나타내는 정수 1입니다. 커서는 다른 스레드에서 동시에 사용할 수 있습니다. " - 따라서 데이터베이스에 동시에 액세스하려는 스레드간에 연결을 공유 할 수 없습니다. – knbk