Python에서 데이터베이스 연결 풀링을 위한 가장 좋은 솔루션은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/98687

문제

나는 어떤 종류의 프레임워크에서도 실행되지 않는 서버 측 프로세스인 내 프로젝트에 대한 매우 특수한 요구 사항을 충족하기 위해 일부 사용자 정의 DAO 유사 클래스를 개발했습니다.

새로운 요청이 있을 때마다 MySQLdb.connect를 통해 새로운 연결을 연다는 점을 제외하면 솔루션은 훌륭하게 작동합니다.

Python에서 연결 풀링을 사용하도록 전환하는 가장 좋은 "드롭인" 솔루션은 무엇입니까?저는 Java용 Commons DBCP 솔루션과 같은 것을 상상하고 있습니다.

프로세스가 오래 실행되고 요청을 해야 하는 스레드가 많지만 동시에 모두 요청하지는 않습니다.특히 그들은 결과 덩어리를 잠깐 작성하기 전에 꽤 많은 작업을 수행합니다.

다음을 추가하도록 편집되었습니다.좀 더 검색한 끝에 발견한 anitpool.py 괜찮아 보이지만 Python을 처음 접했기 때문에 더 명확하고 관용적이며 더 나은 솔루션을 놓치지 않았는지 확인하고 싶습니다.

도움이 되었습니까?

해결책

IMO, "더 명확하고 더 관용적이며 더 나은 솔루션"은 DAO와 유사한 클래스를 만드는 대신 기존 ORM을 사용하는 것입니다.

제가 보기에는 ORM이 "원시" SQL 연결보다 더 인기가 있는 것 같습니다.왜?왜냐하면 파이썬 ~이다 OO 및 SQL 행에서 객체로의 매핑 ~이다 절대적으로 필수적입니다.Python 객체에 매핑되지 않는 SQL 행을 처리하는 경우는 많지 않습니다.

내 생각에는 SQLAlchemy 또는 SQL객체 (및 관련 연결 풀링) 더 관용적인 Python 솔루션입니다.

개체 매핑이 없는 순수 SQL은 연결 풀링의 이점을 누릴 수 있는 복잡하고 오래 실행되는 프로세스에 그다지 인기가 없기 때문에 별도의 기능으로 풀링하는 것은 그리 일반적이지 않습니다.예, 순수 SQL입니다. ~이다 사용되지만 풀링이 도움이 되지 않는 더 간단하거나 더 제어된 애플리케이션에서는 항상 사용됩니다.

내 생각에는 두 가지 대안이 있을 수 있습니다.

  1. SQLAlchemy 또는 SQLObject를 사용하도록 클래스를 수정하세요.처음에는 이것이 고통스러워 보이지만(모든 작업이 낭비됨) 모든 디자인과 생각을 활용할 수 있어야 하며 이는 널리 사용되는 ORM 및 풀링 솔루션을 채택하는 연습일 뿐입니다.
  2. 간략하게 설명한 알고리즘(순환하는 연결의 간단한 세트 또는 목록)을 사용하여 자신만의 간단한 연결 풀을 굴립니다.

다른 팁

MySQL에서?

연결 풀링에 신경 쓰지 마세요.이는 종종 문제의 원인이 되며 MySQL을 사용하면 원하는 성능 이점을 얻을 수 없습니다.이 길은 정치적으로 따라야 할 많은 노력이 필요할 수 있습니다. 왜냐하면 이 공간에는 연결 풀링의 장점에 대해 손을 흔드는 모범 사례와 교과서적인 설명이 너무 많기 때문입니다.

연결 풀은 단순히 상태 비저장 애플리케이션(예:HTTP 프로토콜) 및 상태가 유지되고 수명이 긴 배치 처리 애플리케이션이 존재하는 웹 이전 시대입니다.웹 이전 데이터베이스에서는 연결이 매우 비쌌기 때문에(아무도 연결이 설정되는 데 걸리는 시간에 대해 너무 신경 쓰지 않았기 때문에) 웹 이후 애플리케이션은 모든 적중이 엄청난 처리 오버헤드를 발생시키지 않도록 이 연결 풀 체계를 고안했습니다. RDBMS에서.

MySQL은 웹 시대의 RDBMS에 가깝기 때문에 연결이 매우 가볍고 빠릅니다.나는 MySQL에 대한 연결 풀을 전혀 사용하지 않는 많은 대용량 웹 애플리케이션을 작성했습니다.

이는 극복해야 할 정치적 장애물이 없는 한, 없이도 도움이 될 수 있는 합병증입니다.

연결 클래스를 래핑하십시오.

연결 수에 대한 제한을 설정하십시오.사용되지 않은 연결을 반환합니다.연결을 해제하려면 가까운 곳을 가로채세요.

업데이트:dbpool.py에 다음과 같은 내용을 넣었습니다.

import sqlalchemy.pool as pool
import MySQLdb as mysql
mysql = pool.manage(mysql)

오래된 스레드이지만 범용 풀링(연결 또는 비용이 많이 드는 개체)의 경우 다음과 같은 것을 사용합니다.

def pool(ctor, limit=None):
    local_pool = multiprocessing.Queue()
    n = multiprocesing.Value('i', 0)
    @contextlib.contextmanager
    def pooled(ctor=ctor, lpool=local_pool, n=n):
        # block iff at limit
        try: i = lpool.get(limit and n.value >= limit)
        except multiprocessing.queues.Empty:
            n.value += 1
            i = ctor()
        yield i
        lpool.put(i)
    return pooled

느리게 구성되고 선택적 제한이 있으며 내가 생각할 수 있는 모든 사용 사례에 일반화해야 합니다.물론 이는 모든 리소스의 풀링이 실제로 필요하다고 가정하지만 많은 최신 SQL과 유사한 경우에는 그렇지 않을 수도 있습니다.용법:

# in main:
my_pool = pool(lambda: do_something())
# in thread:
with my_pool() as my_obj:
    my_obj.do_something()

이는 ctor가 생성하는 모든 객체에 필요한 경우 적절한 소멸자가 있다고 가정합니다(일부 서버는 명시적으로 닫히지 않는 한 연결 객체를 종료하지 않습니다).

나는 단지 같은 종류의 것을 찾고 있었습니다.

내가 발견했다 pysqlpool 그리고 sqlalchemy 풀 모듈

앱이 멀티스레딩을 사용하기로 결정한 경우 자체 연결 풀을 만드는 것은 나쁜 생각입니다.다중 스레드 응용 프로그램에 대한 연결 풀을 만드는 것은 단일 스레드 응용 프로그램에 대한 것보다 훨씬 더 복잡합니다.이 경우 PySQLPool과 같은 것을 사용할 수 있습니다.

성능을 찾고 있다면 ORM을 사용하는 것도 나쁜 생각입니다.

많은 SELECTS, Inserts, Update 및 Deletes를 동시에 처리 해야하는 거대한/무거운 데이터베이스를 처리하려면 성능이 필요합니다. 이는 조회를 최적화하기 위해 사용자 정의 SQL이 필요합니다. 그리고 잠금 시간.ORM을 사용하면 일반적으로 유연성이 없습니다.

따라서 기본적으로 자신만의 연결 풀을 만들고 ORM을 사용할 수 있지만 방금 설명한 내용이 전혀 필요하지 않다고 확신하는 경우에만 가능합니다.

이전 스레드에 응답했지만 마지막으로 확인했을 때 MySQL은 드라이버의 일부로 연결 풀링을 제공합니다.

다음에서 확인할 수 있습니다.

https://dev.mysql.com/doc/connector-python/en/connector-python-connection-pooling.html

TFA에서 명시적으로 연결 풀을 열고 싶다고 가정합니다(OP가 명시한 대로).

dbconfig = {  "database": "test", "user":"joe" }
cnxpool = mysql.connector.pooling.MySQLConnectionPool(pool_name = "mypool",pool_size = 3, **dbconfig)

그런 다음 get_connection() 함수를 통해 풀에 요청하여 이 풀에 액세스합니다.

cnx1 = cnxpool.get_connection()
cnx2 = cnxpool.get_connection()

사용 DBUtils, 간단하고 신뢰할 수 있습니다.

pip install DBUtils
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top