2009-08-15 42 views
17

Tôi có ứng dụng python mở kết nối cơ sở dữ liệu có thể treo trực tuyến trong một giờ, nhưng đôi khi máy chủ cơ sở dữ liệu khởi động lại và trong khi python vẫn có kết nối, nó sẽ không hoạt động với ngoại lệ OperationalError.Đảm bảo rằng kết nối cơ sở dữ liệu psycopg2 còn sống

Vì vậy, tôi đang tìm bất kỳ phương pháp đáng tin cậy nào để "ping" cơ sở dữ liệu và biết rằng kết nối vẫn còn hoạt động. Tôi đã kiểm tra một tài liệu psycopg2 nhưng không thể tìm thấy bất cứ điều gì như thế. Chắc chắn tôi có thể phát hành một số câu lệnh SQL đơn giản như SELECT 1 và bắt ngoại lệ, nhưng tôi hy vọng có một phương thức gốc, giống như PHP pg_connection_status

Cảm ơn.

Trả lời

8

pg_connection_status được triển khai bằng PQstatus. psycopg không hiển thị API đó, vì vậy kiểm tra không có sẵn. Chỉ có hai nơi psycopg gọi PQstatus chính nó là khi một kết nối mới được thực hiện, và vào lúc bắt đầu thực hiện. Vì vậy, có, bạn sẽ cần phải phát hành một câu lệnh SQL đơn giản để tìm hiểu xem kết nối vẫn còn đó.

+0

Tôi đã đi đến kết luận tương tự khi đọc nguồn psycopg2. Cảm ơn. – HardQuestions

+0

Sẽ gửi yêu cầu tới tác giả psycopg để thêm chức năng như vậy. – HardQuestions

+0

Xem câu trả lời của Jaymon bên dưới. – sage88

30

Câu hỏi này thực sự cũ, nhưng vẫn bật lên trên các tìm kiếm của Google nên tôi cho rằng phiên bản psycopg2.connection hiện có closed attribute sẽ là 0 khi kết nối mở và lớn hơn 0 khi kết nối là đã đóng cửa. Ví dụ sau đây cần chứng minh:

import psycopg2 
import subprocess 

connection = psycopg2.connect(
    database=database, 
    user=username, 
    password=password, 
    host=host, 
    port=port 
) 

print connection.closed # 0 

# restart the db externally 
subprocess.check_call("sudo /etc/init.d/postgresql restart", shell=True) 

# this query will fail because the db is no longer connected 
try: 
    cur = connection.cursor() 
    cur.execute('SELECT 1') 
except psycopg2.OperationalError: 
    pass 

print connection.closed # 2 
+3

Bạn đã thử giết các kết nối cơ sở dữ liệu TCP xử lý (trên Windows). 'connection.closed' tiếc là sẽ không thay đổi giá trị. – Vyktor

+0

@Vyktor Bạn nói đúng! Vấn đề là kết nối của Python không biết nó đã bị cắt đứt cho đến khi nó cố gắng liên lạc với db. Tôi đã cập nhật ví dụ. Tin tốt là bạn có thể quấn mã thực thi truy vấn để kiểm tra kết nối bị lỗi và kết nối lại khi thích hợp. – Jaymon

+0

Kết nối của tôi bị đóng trong khi truy vấn vì cơ sở dữ liệu đã khởi động lại, 'cur.execute ('SELECT 1')' đã ném 'InterfaceError' trong trường hợp của tôi với thông báo' cursor has closed' – raphael

6

connection.closed không phản ánh kết nối bị đóng/cắt bởi máy chủ. Nó chỉ cho biết kết nối mà khách hàng đã đóng bằng cách sử dụng connection.close()

Để đảm bảo kết nối vẫn hợp lệ, hãy đọc thuộc tính connection.isolation_level. Điều này sẽ tăng một OperationalError với pgcode == "57P01" trong trường hợp kết nối bị chết.

Điều này cho biết thêm một chút thời gian chờ cho một chuyến đi đến cơ sở dữ liệu nhưng nên thích hợp hơn với một số SELECT 1 hoặc tương tự.

import psycopg2 
dsn = "dbname=postgres" 
conn = psycopg2.connect(dsn) 

# ... some time elapses, e.g. connection within a connection pool 

try: 
    connection.isolation_level 
except OperationalError as oe: 
    conn = psycopg2.connect(dsn) 

c = conn.cursor() 
c.execute("SELECT 1") 
+1

Thử nghiệm với psycopg2 2.5.2 và psql 8.4 - cách ly mức luôn luôn bằng không cho dù thế nào đi chăng nữa. –

Các vấn đề liên quan