PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Khi autovacuum không hút chân không

Một vài tuần trước, tôi đã giải thích những điều cơ bản về điều chỉnh autovacuum. Ở cuối bài đăng đó, tôi hứa sẽ sớm xem xét các vấn đề với việc hút bụi. Chà, mất nhiều thời gian hơn tôi dự định, nhưng chúng ta bắt đầu.

Để tóm tắt nhanh, hãy autovacuum là một quy trình nền dọn dẹp các hàng chết, ví dụ:các phiên bản hàng cũ đã bị xóa. Bạn cũng có thể thực hiện dọn dẹp theo cách thủ công bằng cách chạy VACUUM , nhưng autovacuum điều đó tự động tùy thuộc vào số lượng hàng chết trong bảng, vào đúng thời điểm - không quá thường xuyên nhưng đủ thường xuyên để kiểm soát lượng "rác".

Nói chung, autovacuum không thể chạy quá thường xuyên - việc dọn dẹp chỉ được thực hiện sau khi đạt đến một số hàng chết được tích lũy trong bảng. Nhưng nó có thể bị trì hoãn vì nhiều lý do khác nhau, dẫn đến các bảng và chỉ mục trở nên lớn hơn mong muốn. Và đó chính xác là chủ đề của bài đăng này. Vậy thủ phạm phổ biến là gì và làm thế nào để xác định chúng?

Throttling

Như đã giải thích trong phần điều chỉnh cơ bản, autovacuum công nhân được điều chỉnh để chỉ thực hiện một số lượng công việc nhất định trong một khoảng thời gian. Các giới hạn mặc định khá thấp - khoảng 4MB / giây ghi, 8MB / giây đọc. Điều đó phù hợp với các máy nhỏ như Raspberry Pi hoặc các máy chủ nhỏ từ 10 năm trước, nhưng các máy hiện tại mạnh hơn (cả về CPU và I / O) và xử lý nhiều dữ liệu hơn.

Hãy tưởng tượng bạn có một vài cái bàn lớn và một vài cái nhỏ. Nếu cả ba autovacuum công nhân bắt đầu dọn dẹp các bàn lớn, không một bàn nhỏ nào được hút bụi bất kể số lượng hàng chết mà họ tích tụ. Việc xác định điều này không đặc biệt khó, giả sử bạn có đủ khả năng giám sát. Tìm các khoảng thời gian khi tất cả autovacuum công nhân bận rộn trong khi bàn không được hút bụi dù có nhiều hàng chết.

Tất cả thông tin cần thiết có trong pg_stat_activity (số lượng autovacuum quy trình công nhân) và pg_stat_all_tables (last_autovacuumn_dead_tup ).

Tăng số lượng autovacuum công nhân không phải là một giải pháp, vì tổng khối lượng công việc vẫn như cũ. Bạn có thể chỉ định giới hạn điều chỉnh cho mỗi bảng, loại trừ nhân viên đó khỏi tổng giới hạn, nhưng điều đó vẫn không đảm bảo sẽ có nhân công sẵn sàng khi cần thiết.

Giải pháp phù hợp là điều chỉnh điều chỉnh, sử dụng các giới hạn hợp lý đối với cấu hình phần cứng và các mẫu khối lượng công việc. Một số khuyến nghị điều chỉnh cơ bản đã được đề cập trong bài trước. (Rõ ràng, nếu bạn có thể giảm số lượng hàng chết được tạo ra trong cơ sở dữ liệu, đó sẽ là một giải pháp lý tưởng.)

Từ thời điểm này, chúng tôi sẽ giả định rằng việc điều chỉnh không phải là vấn đề, tức là autovacuum công nhân không bị bão hòa trong thời gian dài và quá trình dọn dẹp được thực hiện trên tất cả các bàn mà không có sự chậm trễ bất hợp lý.

Giao dịch dài hạn

Vì vậy, nếu bàn được hút bụi thường xuyên, chắc chắn nó không thể tích tụ nhiều hàng chết, phải không? Tiếc là không có. Các hàng không thực sự "có thể tháo rời" ngay sau khi bị xóa, mà chỉ khi không có giao dịch nào có thể nhìn thấy chúng. Hành vi chính xác phụ thuộc vào những gì các giao dịch khác đang (đã) thực hiện và mức độ tuần tự hóa, nhưng nói chung:

ĐỌC ĐƯỢC CAM KẾT

  • đang chạy chặn truy vấn dọn dẹp
  • các giao dịch nhàn rỗi chỉ chặn việc dọn dẹp nếu chúng thực hiện ghi
  • các giao dịch không hoạt động (không có bất kỳ lần ghi nào) sẽ không chặn việc dọn dẹp (nhưng dù sao cũng không phải là một phương pháp hay để giữ chúng ở lại)

CÓ THỂ XÁC NHẬN

  • đang chạy chặn truy vấn dọn dẹp
  • chặn các giao dịch nhàn rỗi dọn dẹp (ngay cả khi chúng chỉ đọc)

Trong thực tế, tất nhiên, nó có nhiều sắc thái hơn, nhưng việc giải thích tất cả các bit khác nhau sẽ yêu cầu đầu tiên giải thích cách hoạt động của XID và ảnh chụp nhanh và đó không phải là mục tiêu của bài đăng này. Điều bạn thực sự nên bỏ qua là các giao dịch dài là một ý tưởng tồi, đặc biệt nếu các giao dịch đó có thể đã được thực hiện bằng văn bản.

Tất nhiên, có những lý do hoàn toàn hợp lệ tại sao bạn có thể cần phải giữ các giao dịch trong thời gian dài (ví dụ:nếu bạn cần đảm bảo ACID cho tất cả các thay đổi). Nhưng hãy đảm bảo rằng nó không xảy ra một cách không cần thiết, ví dụ:do thiết kế ứng dụng kém.

Một hậu quả hơi bất ngờ của việc này là sử dụng CPU và I / O cao, do autovacuum chạy đi chạy lại mà không làm sạch bất kỳ hàng chết nào (hoặc chỉ một vài trong số chúng). Do đó, các bảng vẫn đủ điều kiện để dọn dẹp vào vòng sau, gây hại nhiều hơn lợi.

Làm thế nào để phát hiện điều này? Đầu tiên, bạn cần theo dõi các giao dịch dài hạn, đặc biệt là các giao dịch nhàn rỗi. Tất cả những gì bạn cần làm là đọc dữ liệu từ pg_stat_activity . Định nghĩa chế độ xem thay đổi một chút với phiên bản PostgreSQL, vì vậy bạn có thể cần chỉnh sửa điều này một chút:

 SELECT xact_start, state FROM pg_stat_activity; - đếm các giao dịch 'không hoạt động' dài hơn 15 phút (kể từ BEGIN) CHỌN COUNT (*) TỪ pg_stat_activity WHERE trạng thái ='không hoạt động trong giao dịch' VÀ (hiện tại () - xact_start)> khoảng thời gian '15 phút' - đếm giao dịch 'không hoạt động' trong hơn 5 phút 

Bạn cũng có thể chỉ cần sử dụng một số plugin giám sát hiện có, ví dụ:check_postgres.pl. Những người đã bao gồm loại kiểm tra sự tỉnh táo. Bạn sẽ phải quyết định đâu là thời lượng giao dịch / truy vấn hợp lý, dành riêng cho ứng dụng.

Kể từ PostgreSQL 9.6, bạn cũng có thể sử dụng idle_in_transaction_session_timeout để các giao dịch không hoạt động quá lâu sẽ tự động bị chấm dứt. Tương tự, đối với các truy vấn dài có statement_timeout .

Một điều hữu ích khác là VACUUM VERBOSE điều này thực sự sẽ cho bạn biết có bao nhiêu hàng chết chưa thể loại bỏ:

 db =# VACUUM verbose z; THÔNG TIN:hút bụi "public.z" THÔNG TIN:"z":tìm thấy 0 phiên bản hàng có thể tháo rời, 66797 phiên bản hàng không thể di chuyển trong 443 trên 443 trang CHI TIẾT:Không thể xóa 12308 phiên bản hàng chết ... . 

Nó sẽ không cho bạn biết chương trình phụ trợ nào đang ngăn cản việc dọn dẹp, nhưng đó là một dấu hiệu khá rõ ràng về những gì đang xảy ra.

Lưu ý: . Bạn không thể dễ dàng nhận được thông tin này từ autovacuum bởi vì nó chỉ được ghi bằng DEBUG2 theo mặc định (và bạn chắc chắn không muốn chạy với mức nhật ký đó trong quá trình sản xuất).

Các truy vấn dài về các standby nóng

Giả sử các bảng đang được hút bụi kịp thời, nhưng không loại bỏ các bộ mã đã chết, dẫn đến bảng và chỉ mục bị phồng lên. Bạn đang theo dõi pg_stat_activity và không có giao dịch kéo dài. Vấn đề có thể là gì?

Nếu bạn có một bản sao phát trực tuyến, rất có thể sự cố có thể nằm ở đó. Nếu bản sao sử dụng hot_standby_feedback=on , các truy vấn trên bản sao hoạt động khá nhiều như các giao dịch trên bản chính, bao gồm cả việc chặn dọn dẹp. Tất nhiên, hot_standby_feedback=on được sử dụng chính xác khi chạy các truy vấn dài (ví dụ:phân tích và khối lượng công việc BI) trên các bản sao, để ngăn chặn việc hủy do xung đột sao chép.

Rất tiếc, bạn sẽ phải chọn - giữ hot_standby_feedback=on và chấp nhận sự chậm trễ trong việc dọn dẹp hoặc giải quyết các truy vấn đã bị hủy. Bạn cũng có thể sử dụng max_standby_streaming_delay để hạn chế tác động, mặc dù điều đó không ngăn chặn hoàn toàn việc hủy (vì vậy bạn vẫn cần thử lại các truy vấn).

Trên thực tế, bây giờ có một lựa chọn thứ ba - sao chép hợp lý. Thay vì sử dụng sao chép trực tuyến vật lý cho bản sao BI, bạn có thể sao chép các thay đổi bằng cách sử dụng bản sao lôgic mới, có sẵn trong PostgreSQL 10. Bản sao lôgic giúp thư giãn khớp nối giữa bản sao chính và bản sao và làm cho các cụm hầu như độc lập (được dọn dẹp độc lập, v.v.).

Điều này giải quyết hai vấn đề liên quan đến sao chép luồng vật lý - quá trình dọn dẹp bị trì hoãn đối với các truy vấn chính hoặc bị hủy trên bản sao BI. Mặc dù vậy, đối với các bản sao phục vụ mục đích DR, sao chép trực tuyến vẫn là sự lựa chọn phù hợp. Nhưng những bản sao đó không (hoặc không nên) chạy các truy vấn dài.

Lưu ý: Trong khi tôi đã đề cập rằng bản sao hợp lý sẽ có sẵn trong PostgreSQL 10, một phần đáng kể của cơ sở hạ tầng đã có trong các bản phát hành trước (đặc biệt là PostgreSQL 9.6). Vì vậy, bạn có thể làm điều này ngay cả trên các bản phát hành cũ hơn (chúng tôi đã làm điều đó cho một số khách hàng của mình), nhưng PostgreSQL 10 sẽ làm cho nó thuận tiện và thoải mái hơn nhiều.

Sự cố với autoanalyze

Một chi tiết bạn có thể bỏ lỡ là autovacuum người lao động thực sự thực hiện hai nhiệm vụ khác nhau. Đầu tiên là dọn dẹp (như thể đang chạy VACUUM ), mà còn thu thập số liệu thống kê (như thể đang chạy ANALYZE ). Và cả hai các bộ phận được điều chỉnh bằng cách sử dụng autovacuum_cost_limit .

Nhưng có một sự khác biệt lớn trong việc xử lý các giao dịch. Bất cứ khi nào VACUUM một phần đạt đến autovacuum_cost_limit , công nhân thả ảnh chụp ra và ngủ một giấc. ANALYZE tuy nhiên phải chạy trong một ảnh chụp nhanh / giao dịch duy nhất, điều này không dọn dẹp khối.

Đây là một cách thú vị để tự bắn vào chân mình, đặc biệt nếu bạn cũng thực hiện một số cách sau:

  • tăng default_statistics_target để xây dựng số liệu thống kê chính xác hơn từ các mẫu lớn hơn
  • thấp hơn autovacuum_analyze_scale_factor để thu thập số liệu thống kê thường xuyên hơn

Tất nhiên, hậu quả không mong muốn là ANALYZE sẽ diễn ra thường xuyên hơn, sẽ lâu hơn và lâu hơn (không giống như VACUUM phần) ngăn chặn việc dọn dẹp. Giải pháp thường khá đơn giản - đừng hạ autovacuum_analyze_scale_factor quá nhiều. Đang chạy ANALYZE mỗi lần 10% bảng thay đổi sẽ là quá đủ trong hầu hết các trường hợp.

n_dead_tup

Một điều cuối cùng tôi muốn đề cập là về những thay đổi trong pg_stat_all_tables.n_dead_tup các giá trị. Bạn có thể nghĩ rằng giá trị là một bộ đếm đơn giản, tăng lên bất cứ khi nào một bộ giá trị chết mới được tạo và giảm đi bất cứ khi nào nó được làm sạch. Nhưng thực tế đó chỉ là ước tính về số lượng bộ giá trị đã chết, được cập nhật bởi ANALYZE . Đối với các bảng nhỏ (dưới 240MB), nó không thực sự là một sự khác biệt lớn, bởi vì ANALYZE đọc toàn bộ bảng và vì vậy nó khá chính xác. Tuy nhiên, đối với các bảng lớn, nó có thể thay đổi một chút tùy thuộc vào tập con của bảng nào được lấy mẫu. Và hạ thấp autovacuum_vacuum_scale_factor làm cho nó ngẫu nhiên hơn.

Vì vậy, hãy cẩn thận khi xem n_dead_tup trong một hệ thống giám sát. Giá trị giảm hoặc tăng đột ngột có thể chỉ do ANALYZE tính toán lại một ước tính khác và không phải do quá trình dọn dẹp thực tế và / hoặc các bộ giá trị mới xuất hiện trong bảng.

Tóm tắt

Để tóm tắt điều này thành một vài điểm đơn giản:

  • autovacuum chỉ có thể hoạt động nếu không có giao dịch nào có thể cần đến các bộ giá đã chết.
  • Các truy vấn chạy dài thực hiện việc dọn dẹp khối. Cân nhắc sử dụng statement_timeout để hạn chế thiệt hại.
  • Giao dịch lâu dài có thể chặn quá trình dọn dẹp. Hành vi chính xác phụ thuộc vào những thứ như mức độ cô lập hoặc những gì đã xảy ra trong giao dịch. Theo dõi chúng và chấm dứt chúng nếu có thể.
  • Các truy vấn kéo dài trên các bản sao với hot_standby_feedback=on cũng có thể chặn quá trình dọn dẹp.
  • autoanalyze cũng được điều chỉnh, nhưng không giống như VACUUM một phần nó giữ một ảnh chụp nhanh duy nhất (và do đó chặn quá trình dọn dẹp).
  • n_dead_tup chỉ là ước tính được duy trì bởi ANALYZE , vì vậy, hãy mong đợi một số biến động (đặc biệt là trên các bảng lớn).

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle chuyển sang PostgreSQL:Lý do nên di chuyển

  2. Tối ưu hóa truy vấn trong PostgreSQL. GIẢI THÍCH Khái niệm cơ bản - Phần 3

  3. GROUP BY và tổng hợp các giá trị số tuần tự

  4. Lỗi khi cài đặt Psycopg2 trên MacOS 10.9.5

  5. Postgres và chỉ mục trên các khóa ngoại và khóa chính