2014-10-21 14 views
11

Tôi muốn theo dõi khóa liên tục trong các bưu cục liên tục.Làm cách nào để phát hiện truy vấn chứa khóa trong Postgres?

Tôi đã xem qua bài viết Locks Monitoring và cố gắng để chạy các truy vấn sau đây:

SELECT bl.pid  AS blocked_pid, 
    a.usename AS blocked_user, 
    kl.pid  AS blocking_pid, 
    ka.usename AS blocking_user, 
    a.query AS blocked_statement 
FROM pg_catalog.pg_locks   bl 
JOIN pg_catalog.pg_stat_activity a ON a.pid = bl.pid 
JOIN pg_catalog.pg_locks   kl ON kl.transactionid = bl.transactionid AND kl.pid != bl.pid 
JOIN pg_catalog.pg_stat_activity ka ON ka.pid = kl.pid 
WHERE NOT bl.granted; 

Thật không may, nó không bao giờ trở lại không có sản phẩm nào tập kết quả. Nếu tôi đơn giản hóa truy vấn được cung cấp cho biểu mẫu sau:

SELECT bl.pid  AS blocked_pid, 
    a.usename AS blocked_user, 
    a.query AS blocked_statement 
FROM pg_catalog.pg_locks   bl 
JOIN pg_catalog.pg_stat_activity a ON a.pid = bl.pid 
WHERE NOT bl.granted; 

thì nó sẽ trả về các truy vấn đang chờ khóa. Nhưng tôi không thể quản lý để thay đổi nó để nó có thể trả về cả hai truy vấn bị chặn và chặn.

Bất kỳ ý tưởng nào?

+0

một truy vấn chặn là gì? Đó là một giao dịch nắm giữ một khóa, truy vấn cụ thể đã lấy nó có thể được hoàn thành và đi trong giao dịch đó, trong khi khóa vẫn được giữ. –

+0

Nghe có vẻ hợp lý, nhưng các tác giả bài viết về Khóa Giám sát có ý nghĩa gì trong trường hợp này? – Roman

+1

Điều đó chỉ hiển thị các khóa cấp hàng. Tôi thấy cái này hữu ích hơn (mặc dù phức tạp hơn) vì nó cũng hiển thị các khóa mức đối tượng: http://wiki.postgresql.org/wiki/Lock_dependency_information – jjanes

Trả lời

0

Một điều tôi thấy thường thiếu trong số này là khả năng tra cứu khóa hàng. Ít nhất là trên các cơ sở dữ liệu lớn hơn tôi đã làm việc, các khóa hàng không được hiển thị trong pg_locks (nếu chúng có, pg_locks sẽ lớn hơn nhiều và không có loại dữ liệu thực để hiển thị hàng bị khóa trong chế độ xem đó một cách chính xác).

Tôi không biết rằng có một giải pháp đơn giản cho điều này nhưng thường những gì tôi làm là nhìn vào bảng nơi khóa đang chờ và tìm kiếm các hàng có xmax nhỏ hơn id giao dịch hiện diện ở đó. Điều đó thường cho tôi một nơi để bắt đầu, nhưng nó là một chút thực hành và không thân thiện với tự động.

Lưu ý rằng hiển thị cho bạn các ghi không được cam kết trên các hàng trên các bảng đó. Sau khi đã cam kết, các hàng sẽ không hiển thị trong ảnh chụp nhanh hiện tại. Nhưng đối với các bảng lớn, đó là một nỗi đau.

+1

Phần mở rộng pgrowlocks sẽ cung cấp cho bạn các khóa mức hàng: https: // www.postgresql.org/docs/9.6/static/pgrowlocks.html –

4

Từ số excellent article on query locks in Postgres này, người ta có thể nhận truy vấn bị chặn và truy vấn chặn và thông tin của họ từ truy vấn sau.

CREATE VIEW lock_monitor AS(
SELECT 
    COALESCE(blockingl.relation::regclass::text,blockingl.locktype) as locked_item, 
    now() - blockeda.query_start AS waiting_duration, blockeda.pid AS blocked_pid, 
    blockeda.query as blocked_query, blockedl.mode as blocked_mode, 
    blockinga.pid AS blocking_pid, blockinga.query as blocking_query, 
    blockingl.mode as blocking_mode 
FROM pg_catalog.pg_locks blockedl 
JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid 
JOIN pg_catalog.pg_locks blockingl ON(
    ((blockingl.transactionid=blockedl.transactionid) OR 
    (blockingl.relation=blockedl.relation AND blockingl.locktype=blockedl.locktype) 
) AND blockedl.pid != blockingl.pid) 
JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid 
    AND blockinga.datid = blockeda.datid 
WHERE NOT blockedl.granted 
AND blockinga.datname = current_database() 
); 

SELECT * from lock_monitor; 

Vì truy vấn dài nhưng hữu ích, tác giả bài viết đã tạo chế độ xem để đơn giản hóa việc sử dụng nó.

5

Vì 9.6 điều này dễ dàng hơn nhiều khi giới thiệu hàm pg_blocking_pids() để tìm các phiên đang chặn một phiên khác.

Vì vậy, bạn có thể sử dụng một cái gì đó như thế này:

select pid, 
     usename, 
     pg_blocking_pids(pid) as blocked_by, 
     query as blocked_query 
from pg_stat_activity 
where cardinality(pg_blocking_pids(pid)) > 0; 
Các vấn đề liên quan