【问题标题】:How to safe connect to postgres with mulitple scripts如何使用多个脚本安全地连接到 postgres
【发布时间】:2020-11-26 21:24:54
【问题描述】:

我已经开始学习如何使用 Python 编写 psycopg2 代码。我所做的是我的脚本很少。让我们举个例子,它最多可以有 150 个连接,我们知道,我们不能同时连接超过 100 个连接。我发现每当我想进行数据库查询/执行时,我都会连接到数据库,执行执行然后关闭数据库。但是我确实认为打开和关闭新连接非常昂贵并且应该更长寿。

我做过这样的事情:

DATABASE_CONNECTION = {
    "host": "TEST",
    "database": "TEST",
    "user": "TEST",
    "password": "TEST"
}


def get_all_links(store):
    """
    Get all links from given store
    :param store:
    :return:
    """

    conn = psycopg2.connect(**DATABASE_CONNECTION)

    sql_update_query = "SELECT id, link FROM public.store_items WHERE store = %s AND visible = %s;"

    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

    try:

        data_tuple = (store, "yes")
        cursor.execute(sql_update_query, data_tuple)

        test_data = [{"id": links["id"], "link": links["link"]} for links in cursor]
        cursor.close()
        conn.close()
        return test_data

    except (Exception, psycopg2.DatabaseError) as error:
        print("Error: %s" % error)
        cursor.close()
        conn.rollback()
        return 1



def get_all_stores():
    """
    Get all stores in database
    :return:
    """

    conn = psycopg2.connect(**DATABASE_CONNECTION)

    sql_update_query = "SELECT store FROM public.store_config;"

    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

    try:

        cursor.execute(sql_update_query)

        test_data = [stores["store"] for stores in cursor]

        cursor.close()
        conn.close()
        return test_data

    except (Exception, psycopg2.DatabaseError) as error:
        print("Error: %s" % error)
        cursor.close()
        conn.rollback()
        return 1

我想知道如何使它尽可能有效,因为我可以将大量脚本连接到数据库但仍然没有遇到 max_connection 问题?

我忘了补充说我连接的方式是我有多个脚本等:

test1.py
test2.py
test3.py
....
....

每个脚本都为自己运行

他们都有一个导入database.py,其中包含我之前展示过的以下代码。

更新:

from psycopg2 import pool

threaded_postgreSQL_pool = psycopg2.pool.ThreadedConnectionPool(1, 2,
                                                                user="test",
                                                                password="test",
                                                                host="test",
                                                                database="test")

if (threaded_postgreSQL_pool):
    print("Connection pool created successfully using ThreadedConnectionPool")
    

def get_all_stores():
    """
    Get all stores in database
    :return:
    """

    # Use getconn() method to Get Connection from connection pool
    ps_connection = threaded_postgreSQL_pool.getconn()

    sql_update_query = "SELECT store FROM public.store_config;"

    ps_cursor = ps_connection.cursor(cursor_factory=psycopg2.extras.DictCursor)

    try:

        ps_cursor.execute(sql_update_query)

        test_data = [stores["store"] for stores in ps_cursor]

        ps_cursor.close()

        threaded_postgreSQL_pool.putconn(ps_connection)
        print("Put away a PostgreSQL connection")

        return test_data

    except (Exception, psycopg2.DatabaseError) as error:
        print("Error: %s" % error)
        ps_cursor.close()
        ps_connection.rollback()
        return 1

【问题讨论】:

  • @clamp 我不确定如果每个脚本都会导入 database.py 文件是否有好处,我可能是错误的并且显然被误解了,但如果我错了请纠正我
  • 处理连接有不同的选择。一般来说,游泳池使连接更便宜。请参阅 (pgbouncer.org/usage.html)。
  • @clamp 哦,我明白了,我认为在这种情况下,我需要在连接到数据库的同一服务器/主机中安装它?这是否意味着我的代码很好?还是我在两者之间缺少什么?

标签: python sql postgresql


【解决方案1】:

虽然打开和关闭数据库连接不是免费的,但与启动和停止 python 解释器相比,它也不是那么昂贵。如果您的所有脚本都独立且短暂地运行,那可能是您应该修复的第一件事。在知道如何(以及是否)使用连接池之前,您必须决定并描述如何安排和调用您的脚本。

众所周知,我们不能同时连接超过 100 个连接。

100 是 max_connections 的默认设置,但它是完全可配置的。如果你愿意,你可以增加它。如果您为性能进行重构,您可能应该以一种自然意味着您不需要提高 max_connections 的方式这样做。但是仅仅因为你不想提高 max_connections 就进行重构是让尾巴摇摆不定。

【讨论】:

    【解决方案2】:

    你是对的,建立数据库连接很昂贵;因此,您应该使用连接池。但是没有必要重新发明轮子,因为psycopg2 has built-in connection pooling

    使用psycopg2.pool.SimpleConnectionPoolpsycopg2.pool.ThreadedConnectionPool(取决于您是否使用线程)并使用getconn()putconn() 方法来获取或返回连接。

    【讨论】:

    • 劳伦兹您好!如果您可以查看它,我现在已经在线程中进行了更新。你的意思是这样的吗?但是,我在使用它时可能会想到的问题仍然存在。如果我有几个自己运行的脚本(我的意思是我启动 py test1.py、py test2.py、py test3.py ... 最多 150 个),实际会发生什么。这是否仍会被视为 150 个已连接,或者此方法将如何工作?
    • 乍一看还可以,但我对 Python 不是很了解。如果你启动了许多不同的 Python 解释器实例,你最终会得到许多连接池,目的就会失败。但是,如果您的应用程序有多个线程,它们将共享一个连接池,那就这样做吧。
    猜你喜欢
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多