bestsource

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

bestsource 2023. 10. 26. 21:17
반응형

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

저는 어떤 종류의 프레임워크에서도 실행되지 않는 서버측 프로세스인 프로젝트에 대한 매우 전문화된 요구사항을 충족시키기 위해 맞춤형 DAO와 같은 클래스를 개발했습니다.

새로운 요청이 있을 때마다 MySQLdb.connect를 통해 새로운 연결을 여는 것을 제외하고는 솔루션이 잘 작동합니다.

파이썬에서 연결 풀링을 사용하는 것으로 전환하기 위한 가장 좋은 "드롭인" 솔루션은 무엇입니까?저는 자바용 커먼즈 DBCP 솔루션과 같은 것을 상상하고 있습니다.

프로세스가 오래 실행되고 요청해야 하는 많은 스레드가 있지만 동시에 모든 스레드가 실행되는 것은 아닙니다.특히 그들은 짧은 시간 동안 결과의 일부를 쓰기 전에 꽤 많은 일을 합니다.

추가하기 위해 편집: 검색을 좀 더 한 후에 itpool을 찾았습니다.py는 괜찮은 것 같지만, python을 비교적 처음 접하기 때문에 더 명백한/더 관용적인/더 나은 해결책을 놓치지 않고 싶은 것 같습니다.

MySQL에?

연결 풀링에 신경쓰지 말라고 말씀드리고 싶습니다.MySQL을 사용하면 문제의 원인이 되는 경우가 많기 때문에 원하는 성능의 이점을 얻을 수 없습니다.이 길은 정치적으로 많은 노력이 필요할 수도 있습니다. 왜냐하면 이 공간에는 연결 풀링의 장점에 대해 손을 흔드는 것과 교과서적인 표현이 너무 많기 때문입니다.

연결 풀은 상태 비저장 응용프로그램(예: HTTP 프로토콜)의 웹 이후 시대와 상태 비저장(stateful) 장수명 일괄 처리 응용프로그램의 웹 이전 시대 사이의 다리일 뿐입니다.사전 웹 데이터베이스에서는 접속 비용이 매우 높았기 때문에(접속을 설정하는 데 걸리는 시간에 대해 아무도 크게 신경 쓰지 않았기 때문에), 사후 웹 응용 프로그램은 이러한 접속 풀 체계를 고안하여 모든 히트가 RDBMS에서 이렇게 큰 처리 오버헤드를 발생시키지 않도록 했습니다.

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

이것은 정치적 장애물이 극복되지 않는 한, 여러분이 이를 극복하는 것으로부터 이익을 얻을 수 있는 문제입니다.

연결 클래스를 마칩니다.

연결 횟수에 대한 제한을 설정합니다.사용하지 않는 연결을 반환합니다.가까이에서 가로채서 연결을 해제합니다.

업데이트 : 이런 것을 dbpool에 넣었습니다.py:

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

IMO, "더 명백한/더 관용적인/더 나은 해결책"은 DAO와 같은 수업을 발명하는 것보다 기존의 ORM을 사용하는 것입니다.

ORM은 "원시" SQL 연결보다 더 인기가 많은 것 같습니다. 왜죠?Python은 OO이기 때문에 SQL 행에서 객체로의 매핑이 절대적으로 중요합니다.Python 개체에 매핑되지 않는 SQL 행을 다루는 사용 사례는 많지 않습니다.

저는 SQLAlchemy 또는 SQObject(및 관련 연결 풀링)가 더 관용적인 Pythonic 솔루션이라고 생각합니다.

별도의 기능으로 풀링하는 것은 일반적이지 않은데, 이는 (객체 매핑이 없는) 순수 SQL이 연결 풀링을 통해 이익을 얻는 복잡한 장기 프로세스에서는 그다지 대중적이지 않기 때문입니다.예, 순수 SQL이 사용되지만 풀링이 도움이 되지 않는 단순하거나 더 통제된 애플리케이션에서는 항상 사용됩니다.

두 가지 대안이 있을 수 있다고 생각합니다.

  1. SQLLchemy 또는 SQLObject를 사용하도록 수업을 수정합니다.이것이 처음에는 고통스러워 보이지만(모든 작업이 낭비됨), 모든 디자인과 생각을 활용할 수 있어야 합니다.그것은 널리 사용되는 ORM과 풀링 솔루션을 채택하는 연습일 뿐입니다.
  2. 개요를 설명한 알고리즘을 사용하여 간단한 연결 풀을 롤아웃합니다. 즉, 순환하는 연결 목록 또는 간단한 세트를 사용합니다.

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

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()

이것은 개체를 생성하는 모든 개체가 필요한 경우 적절한 소멸자를 가지고 있다고 가정합니다(일부 서버는 연결 개체가 명확하게 닫히지 않는 한 삭제되지 않음).

그냥 똑같은 걸 찾고 있었어요.

pysqlpoolsqalchemy pool 모듈을 찾았습니다.

당신의 앱이 멀티스레딩을 사용하기 시작한다면 당신만의 연결 풀을 만드는 것은 나쁜 생각입니다.다중 스레드 응용 프로그램에 대한 연결 풀을 만드는 것은 단일 스레드 응용 프로그램에 대한 연결 풀보다 훨씬 복잡합니다.PySQ 같은 것을 사용할 수 있습니다.그럴 땐 L풀.

성능을 찾고 있다면 ORM을 사용하는 것도 좋지 않습니다.

수많은 선택, 삽입, 업데이트 및 삭제를 동시에 처리해야 하는 대용량/무거운 데이터베이스를 다루려면 성능이 필요합니다. 즉, 조회 및 잠금 시간을 최적화하기 위해 맞춤형 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

참고하실 수 있도록 오픈 서치로 했습니다.

    from opensearchpy import OpenSearch

    def get_connection():
                    connection = None
                    try:
                        connection = OpenSearch(
                            hosts=[{'host': settings.OPEN_SEARCH_HOST, 'port': settings.OPEN_SEARCH_PORT}],
                            http_compress=True,
                            http_auth=(settings.OPEN_SEARCH_USER, settings.OPEN_SEARCH_PASSWORD),
                            use_ssl=True,
                            verify_certs=True,
                            ssl_assert_hostname=False,
                            ssl_show_warn=False,
                        )
                    except Exception as error:
                        print("Error: Connection not established {}".format(error))
                    else:
                        print("Connection established")
                    return connection

    class OpenSearchClient(object):
        connection_pool = []
        connection_in_use = []

        def __init__(self):
            if OpenSearchClient.connection_pool:
                pass
            else:

                OpenSearchClient.connection_pool = [get_connection() for i in range(0, settings.CONNECTION_POOL_SIZE)]

        def search_data(self, query="", index_name=settings.OPEN_SEARCH_INDEX):
            available_cursor = OpenSearchClient.connection_pool.pop(0)
            OpenSearchClient.connection_in_use.append(available_cursor)
            response = available_cursor.search(body=query, index=index_name)
            available_cursor.close()
            OpenSearchClient.connection_pool.append(available_cursor)
            OpenSearchClient.connection_in_use.pop(-1)
            return response

언급URL : https://stackoverflow.com/questions/98687/what-is-the-best-solution-for-database-connection-pooling-in-python

반응형