【问题标题】:How to handle when connection pool gets exhausted using snowflake with pythonpython - 使用雪花和python连接池耗尽时如何处理
【发布时间】:2022-10-19 21:52:39
【问题描述】:

有人可以解释一下当任何数据库达到最大连接数限制时我们如何处理这种情况。我们可以在等待状态下建立连接,直到任何现有连接自动释放。

import snowflake.connector as sf
import sqlalchemy.pool as pool
def get_conn():
    conn = sf.connect(
        user='username',
        password='password',
        account='snowflake-account-name',
        warehouse='compute_wh',
        database='customer_data'
    )

    return conn

mypool = pool.QueuePool(get_conn, max_overflow=10, pool_size=5)
a = mypool.connect()
a1 = mypool.connect()
a2 = mypool.connect()
a3 = mypool.connect()
a4 = mypool.connect()
a5 = mypool.connect()
a6 = mypool.connect()
a7 = mypool.connect()
a8 = mypool.connect()
a9 = mypool.connect() 
a11 = mypool.connect()
a12 = mypool.connect()
a13 = mypool.connect()
a14 = mypool.connect()
a15 = mypool.connect()

直到 a14 我们将成功获得 10 个连接对象,但是 当我们取消注释并运行这个 a15.当池用尽时,我们会收到一个错误。如何处理这种情况??

如果我们需要以这样一种方式编写逻辑,我们甚至必须授予访问权限
尽管实例不断增加。帮助我如何发回连接
去游泳池??

【问题讨论】:

    标签: python sqlalchemy snowflake-cloud-data-platform connection-pooling


    【解决方案1】:

    您的池配置为容纳五个与数据库的打开连接,并在负载较重时创建多达十个“溢出”连接。

    执行mypool.connect() 将检查连接,因此当您超过池大小加上溢出时会出现错误。

    如果您不需要它们做更多的工作,您应该将连接返回到池中。

    这可以通过调用例如明确地完成。 a1.close()(顺便说一句,最好给出描述性名称 - 这些是 Connection 对象)。

    但是,更好的方法是使用上下文管理器,因为如果在您签出连接并使用conn.close() 返回它之间抛出异常,您最终将拥有一个永久签出的连接并最终遇到同样的问题。

    例如

    with mypool.connect() as conn:
        do_some_work(conn)
    
    more_code()
    

    当您完成 with 块(上下文管理器)并继续执行更多代码时,或者如果您因异常退出它,连接将返回到池以供将来使用。

    【讨论】:

    • @padding Atlon 感谢您给我的提示......我尝试通过使用 with 语句来实现......并成功地做到了。请检查我的代码,如果我错了,请帮助我...
    【解决方案2】:

    我认为即使在池中达到最大限制,此代码也会起作用。如果我做错了什么,请纠正我。

    import snowflake.connector as sf
    import sqlalchemy.pool as pool
        
    class Database:
        connection_pool = None
        
        @classmethod
        def initialise(cls):
            def get_conn():
                conn = sf.connect(
                    user='username',
                    password='password',
                    account='accountname',
                    warehouse='compute_wh',
                    database='customer_data'
                )
        
                return conn
        
            cls.connection_pool = pool.QueuePool(get_conn, max_overflow=1, pool_size=1)
        
    class ConnectionFromPool:
        def __init__(self):
            self.connection  = None
            
        def __enter__(self):
            self.connection = Database.connection_pool.connect()
            return self.connection
            
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.connection.commit()
            Database.connection_pool.dispose()
        
        
    class User:
        def __init__(self, cust_key, name, address):
            self.cust_key = cust_key
            self.name = name
            self.address = address
        
        def save_to_db(self):
            with ConnectionFromPool() as connection:
                with connection.cursor() as cursor:
                    cursor.execute("insert into data(cust_key,name,address) values (%s, %s, %s)", (self.cust_key, self.name, self.address))
        
        
        
    Database.initialise()
    user_to_db = User(1,'padma', 'ramnagar')
    user_to_db.save_to_db()
    user_to_db.save_to_db()
    print("success")
    

    【讨论】:

    • 看起来很……错综复杂。但也许我不明白你的用例。正如我在回答中所说,SQLAlchemy 连接可以自动在上下文管理器中使用,所以不确定为什么需要自己创建。我也不确定 pool.dispose 是否是您想要的(为什么要丢弃池连接?),如果您不想绑定到数据库硬限制以外的多个连接,我不是确定你为什么想要一个游泳池?
    • @PaddyAlton,首先。感谢您对这个问题的关注。让我们假设我已经提到 pool_size 为 5 和 max_overflow 限制为 10 用于连接,并假设我们部署了我们的项目。用户尝试登录我们的应用程序。它只允许第 16 个尝试登录失败的人最多 15 个连接,以处理这种情况。我的代码现在可以正常工作了。
    • 正确 - 拥有一个池的目的是限制您的应用程序可以使用多少数据库资源。如果您在实践中需要更多的同时连接,您可以增加池的大小。如果您不想要这些限制,则可以完全避免使用池。无论如何,如果你想要一个游泳池,那么我认为你应该将Database.connection_pool.dispose() 更改为self.connection.close()。这会将连接返回到池,而不是丢弃池。
    • @PaddyAlton 感谢您的帮助,但我正在使用 sqlalchemy 中的 Queuepool 用于连接池目的,但 queepool 类没有 close() 方法。它只有一个 dispose() 方法来关闭连接
    • 没错,但是您从池中签出的连接确实有一个close() 方法。请注意,我的建议是将Database.connection_pool.dispose 切换为self.connection.close(其中selfConnectionFromPool 的一个实例)。尽管有名称,这实际上不会关闭连接 - 它会将连接检查回池中,以备重用。如果你不想要那个,那么在我看来你根本不想要一个游泳池。
    猜你喜欢
    • 2019-06-18
    • 2017-07-10
    • 2020-05-14
    • 2023-03-19
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 2022-07-24
    相关资源
    最近更新 更多