Connections

使用 psycopg2 時如何查看未關閉的 PostgreSQL 連接?

  • March 22, 2020

我執行python程式碼:

con = psycopg2.connect(some_dsn)
cur = con.cursor()
cur.execute(some_sql)
res = cur.fetchone()
#con.close() <-- connection is not closed

然後我嘗試:

ps auxf | grep postgres

或者

SELECT * FROM pg_stat_activity

兩者都不顯示對應的資訊。如何查看未關閉的連接?

蟒蛇答案

給定一個psycopg2名為 的連接對象conn,通過以下方式初始化,例如:

import psycopg2

conn = psycopg2.connect(database="my_database", 
                       user="username", 
                       password=password, 
                       host="localhost", 
                       port="5432")

如果我想看看是否conn關閉,我通常在python 3中做的是;

conn.closed

如果.closed方法返回 1,則連接關閉。

如果該.closed方法返回 0,則連接仍處於打開狀態。

如文件中所述:

關閉

只讀整數屬性:如果連接打開,則為 0,如果連接關閉或斷開,則為非零。

https://www.psycopg.org/docs/connection.html

您還可以通過在 python 控制台中輸入連接名稱並查看最後的closed鍵來看到這一點;

conn
Out[4]: <connection object at 0x7fe3d042e2b8; dsn: 'user=postgres 
       password=xxx dbname=my_database host=localhost port=5432', closed: 0>

conn.close()

conn
Out[6]: <connection object at 0x7fe3d042e2b8; dsn: 'user=postgres 
       password=xxx dbname=my_database host=localhost port=5432', closed: 1>

您可以使用以下方法獲得有關連接器方法的更多幫助:

help(conn)

注意

完成更改後關閉連接非常重要。當然,不要忘記commit()他們,否則您的更改將會失去,就好像您執行了 psycopg2 文件中所述的回滾一樣:

關閉()

立即關閉連接(而不是在執行 del 時)。從現在開始,連接將無法使用;如果嘗試對連接進行任何操作,將引發 InterfaceError。這同樣適用於所有試圖使用連接的游標對象。請注意,關閉連接而不首先送出更改將導致任何掛起的更改被丟棄,就像執行了 ROLLBACK 一樣(除非選擇了不同的隔離級別:請參閱 set_isolation_level())。

資料來源:https ://www.psycopg.org/docs/connection.html

psql 和系統工具回答

psql,您還可以列出連接。

例如,通過使用以下命令:

select pid as process_id, 
      usename as username, 
      datname as database_name, 
      client_addr as client_address, 
      client_hostname,
      client_port,
      application_name,
      backend_start,
      state,
      state_change
from pg_stat_activity;

或者正如你所說的那樣select * from pg_stat_activity;

這裡要注意的有趣的事情是 的值client_port

修改後的前一條命令:https ://dataedo.com/kb/query/postgresql/list-database-sessions

無論如何,這裡給出的問題和答案: Psycopg2到底是什麼? 可能有助於理解使用;psycopg2將連接與來自 Python 外部的標準連接區分開來幾乎是不可能的。psql打開的連接psycopg2看起來像任何其他打開的連接。

但…

現在,如果您打開一個psycopg2連接並仔細觀察上述psql命令的輸出,您當然會在打開連接時看到額外的一行(與關閉的psycopg2連接相比)。

在我係統上的一個範例中,對應於打開的連接的行psycogp2如下所示:

process_id | username | database_name | client_address | client_hostname | client_port |     application_name     |         backend_start         | state  |         state_change          
------------+----------+---------------+----------------+-----------------+-------------+--------------------------+-------------------------------+--------+-------------------------------
     12693 | postgres | my_database   | 127.0.0.1      |                 |       59218 |                          | 2020-03-22 10:58:12.143291+01 | idle   | 2020-03-22 10:58:12.149866+01

它在 上打開了一個連接client_port 59218

正如我所說,從這裡開始,您無法區分任何其他連接。

然後,如果我查看ps -ef | grep "PID\|59218"(59218client_port前一個psql輸出的) 的輸出,我有:

$ ps -ef | grep "PID\|59218"

UID PID PPID C STIME TTY TIME CMD postgres 14663 31224 0 10:59 ? 00:00:00 postgres: 10/main: postgres my_database 127.0.0.1(59218) 空閒

同樣,這看起來與任何其他連接完全相同,所以我不知道哪個應用程序打開了這個連接。

但是您可以進一步探索以下輸出netstat

$ sudo netstat -ap | grep -i "Proto\|59218"
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 localhost:59218         localhost:postgresql    ESTABLISHED 859/python3         
tcp        0      0 localhost:postgresql    localhost:59218         ESTABLISHED 14663/postgres: 10/ 
(...)

localhost:postgresql對應的localhost:5432位置(這可以通過啟動/停用 的-P標誌來查看。)在這裡lsof您還可以看到與上面輸出postgres PID中的相同。 所以準備好在打開的客戶端埠上接受 IO 操作。此埠在連接關閉時關閉。ps
postgresql``python3``59218``psycopg2

因此,您可以嘗試找出和client_port之間的連接,例如: python3``postgresql

sudo netstat -ap | grep -i "python3" | grep "postgres"

然後在和grep的輸出中獲取其值。psql``ps

注意

我也嘗試使用該sockstat工具:

$ sudo sockstat | grep -i "PID\|5432\|59218"
USER     PROCESS              PID      PROTO  SOURCE ADDRESS            FOREIGN ADDRESS           STATE
username python3              859      tcp4   127.0.0.1:59136           127.0.0.1:5432            ESTABLISHED
postgres postgres             14663    tcp4   127.0.0.1:5376            127.0.0.1:59218           ESTABLISHED

在這裡,不幸的是,我不知道59136Python 本身在源地址中使用的埠是什麼,也不知道5376postgres 使用的埠,因為兩者都不匹配我的pscopg2連接指定的預設埠,即5432. 套接字連接中可能使用了底層協議/連接,我不是網路專家來解釋這些。

我還發現了這個執行緒:https ://serverfault.com/questions/128284/how-to-see-active-connections-and-current-activity-in-postgresql-8-4

它還提到了一個名為pg_top的有趣工具,但它並不能完全回答您的問題。

引用自:https://dba.stackexchange.com/questions/262144