使用 psycopg2 時如何查看未關閉的 PostgreSQL 連接?
我執行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"
(59218
是client_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
在這裡,不幸的是,我不知道
59136
Python 本身在源地址中使用的埠是什麼,也不知道5376
postgres 使用的埠,因為兩者都不匹配我的pscopg2
連接指定的預設埠,即5432
. 套接字連接中可能使用了底層協議/連接,我不是網路專家來解釋這些。它還提到了一個名為pg_top的有趣工具,但它並不能完全回答您的問題。