2

我们使用一个对象来保持与 PostgreSQL 数据库的连接并创建新的游标来服务请求。我观察到奇怪的行为:即使读取响应并关闭游标,请求仍然挂在数据库中,阻止更新表等。

当连接关闭时,它就会消失。

我知道 ORM 框架,也许最终会使用其中之一,但我只想了解这里发生了什么。为什么请求仍然存在?

这是python代码:

import psycopg2

def main():

    conn = psycopg2.connect("dbname=tmpdb password=1 host=localhost")

    cur = conn.cursor()
    cur.execute("SELECT 1;")
    items = cur.fetchall()
    cur.close()
    #uncommenting the following line solves the problem
    #conn.close()

    print items
    while True:
        pass
main()

以下是如何启动代码:

>python test_loop.py
[(1,)]

以下是观察挂起请求的方法:

tmpdb=# SELECT datname,usename,pid,client_addr,waiting,query_start,query FROM pg_stat_activity ;
 datname | usename  |  pid  | client_addr | waiting |          query_start          |                                          query                                           
---------+----------+-------+-------------+---------+-------------------------------+------------------------------------------------------------------------------------------
 tmpdb     | savenkov |   530 | ::1         | f       | 2013-08-12 13:56:32.652996+00 |             SELECT 1;
 tmpdb     | savenkov | 88351 |             | f       | 2013-08-12 13:56:35.331442+00 | SELECT datname,usename,pid,client_addr,waiting,query_start,query FROM pg_stat_activity ;
(2 rows)
4

1 回答 1

1

为什么你认为它是阻塞的?

创建表

create table t (i integer);

现在运行它:

import psycopg2

def main():

    conn = psycopg2.connect("dbname=cpn")
    cur = conn.cursor()

    cur.execute("SELECT i from t;")
    items = cur.fetchall()
    print items

    raw_input('Enter to insert')

    cur.execute("insert into t (i) values (1) returning i;")
    items = cur.fetchall()
    conn.commit()
    cur.execute("SELECT i from t;")
    items = cur.fetchall()
    print items

    raw_input('Enter to update')

    cur.execute("update t set i = 2 returning i")
    items = cur.fetchall()
    conn.commit()
    cur.execute("SELECT i from t;")
    items = cur.fetchall()
    print items

    cur.close()

    while True:
        pass
main()

请注意,您需要提交connection.commit()它。

话虽如此,不要进行连接管理。相反,请使用 Pgbouncer 之类的连接池。它将使您免于许多复杂性和挫败感。

如果应用程序与数据库在同一台机器上运行,那么就不用费心了。只要总是根据需要经常关闭连接。如果两者都在一个快速的 Intranet 中,那么增加连接池的复杂性也不值得,除非有非常大量的查询。

于 2013-08-12T16:18:00.113 回答