Làm cách nào để lấy lại dung lượng đĩa trên PostgreSQL?


25

Tôi đã cài đặt cục bộ cơ sở dữ liệu 9.1 với một vài bảng có cca. Bản ghi 300 mio và cơ sở dữ liệu đã tăng lên khoảng 20 GB. Sau đó tôi đã ban hành delete fromlệnh xóa tất cả các bản ghi khỏi nó (đáng lẽ tôi nên sử dụng truncate, nhưng tôi không biết điều đó). Vì vậy, tôi đã thực hiện đầy đủ chân không trên db của mình để lấy lại dung lượng đĩa, nhưng nó không giúp được gì. Vấn đề của tôi trông giống hệt vấn đề này , nhưng không có giải pháp nào được cung cấp. Tôi đã kiểm tra chủ đề và tài liệu này về "phục hồi dung lượng đĩa" , nhưng vẫn không thể tìm ra giải pháp. Tôi sử dụng mã này để có được kích thước của tất cả các bảng

 SELECT nspname || '.' || relname AS "relation",
 pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
 FROM pg_class C
 LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
 WHERE nspname NOT IN ('pg_catalog', 'information_schema')
 AND C.relkind <> 'i'
 AND nspname !~ '^pg_toast'
 ORDER BY pg_total_relation_size(C.oid) DESC
 LIMIT 15;

Tổng cộng có ít hơn 1GB, tuy nhiên

SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database 

vẫn hiển thị khoảng 20 GB. Lời khuyên nào cũng đánh giá cao.


Vâng, truy vấn kích thước của bạn loại trừ: chỉ mục, bảng trong pg_catalogvà bảng trong information_schema. Vì vậy, hãy thử xem nếu đó là bất kỳ trong số đó bằng cách loại bỏ những hạn chế trong WHEREđiều khoản. Vui lòng hiển thị phiên bản PostgreQuery chính xác của bạn ( SELECT version()) và chính xác những gì bạn đang làm để "hút sạch cơ sở dữ liệu đầy đủ", tức là lệnh chính xác. Nếu có thể, hãy chạy VACUUM FULL VERBOSE;(không có đối số) và dán đầu ra ở đâu đó sau đó liên kết với nó ở đây.
Craig Ringer

Hãy thử bỏ cơ sở dữ liệu. Bạn cũng có thể thử đổ cơ sở dữ liệu, và sau đó khôi phục nó sẽ bỏ rác.
jb.

1
@jb Điều đó sẽ làm việc, nhưng không cần thiết. Tốt hơn để tìm hiểu vấn đề là gì.
Craig Ringer

Câu trả lời:


22

Mặc dù bạn không nói rõ, tôi giả sử từ các tài liệu tham khảo của bạn đến các tài liệu mà bạn đã theo dõi rằng bạn đã thực hiện VACUUM FULL trên cơ sở dữ liệu và / hoặc các bảng bị ảnh hưởng. Bạn cũng không chỉ định phiên bản postgresql nào bạn đang sử dụng - Tôi sẽ cho rằng đó là> 9.0 (VACUUM FULL hoạt động khác trước khi này).

VACUUM FULL sẽ viết lại các bảng bị ảnh hưởng thành các tệp mới, sau đó xóa các tệp cũ. Tuy nhiên, nếu bất kỳ quy trình nào vẫn mở tệp cũ, hệ điều hành sẽ không thực sự xóa tệp - cho đến khi quy trình cuối cùng đã đóng tệp.

Nếu thực tế, khởi động lại cơ sở dữ liệu sẽ đảm bảo rằng tất cả các tệp đang mở được đóng lại.

Nếu điều đó không thực tế, thì bạn có thể xác minh xem đây có phải là sự cố của bạn không và tìm hiểu quy trình nào có các tệp được mở.

Nếu sử dụng Linux (hoặc hầu hết các hệ thống giống Unix khác), bạn có thể sử dụng lệnh 'lsof' để nhận danh sách tất cả các tệp được mở trong tất cả các quy trình. Các tệp đang mở nhưng đã bị xóa sẽ có '(đã xóa)' được thêm vào tên tệp. Vì vậy, bạn có thể grep đầu ra của lsof, tìm kiếm các tệp đã bị xóa, như thế này:

sudo lsof -u postgres | grep 'deleted'

Nếu xác định các quy trình vẫn mở các tệp cũ, bạn có thể sử dụng pg_terminate_backend để chấm dứt quá trình đó:

SELECT pg_terminate_backend(xxx);

Trong đó xxx là PID của quá trình, được tìm thấy trong đầu ra lsof.

Nếu sử dụng Windows, nguyên tắc tương tự có thể được áp dụng, vì postgres mở tệp bằng cờ FILE_SHARE_DELETE, cho phép nó xóa các tệp đang mở trong một quy trình khác. Lệnh ' xử lý ' là tương đương thô của lsof, mặc dù tôi không chắc liệu bạn có thể biết liệu các tệp có bị xóa hay không vì vậy một số công việc bổ sung có thể được yêu cầu.

Đó là một câu hỏi khác là tại sao bất kỳ quá trình như vậy sẽ được treo vào xử lý tập tin cũ. Tuy nhiên, trong chủ đề bạn trích dẫn trong câu hỏi của bạn, Tom Lane dường như ngụ ý rằng nó có thể xảy ra.


Tôi đã phải khẩn trương lấy lại không gian đĩa để tôi bỏ cơ sở dữ liệu và khôi phục nó từ bản sao lưu. Tuy nhiên, "làm thế nào" để giải quyết vấn đề này vẫn còn nhiều giá trị cho các trường hợp trong tương lai. Cơ sở dữ liệu của tôi là 9.1, giành được 8 64 bit, việc đặt tên tệp (trường hợp tệp đang mở) có áp dụng giống như trong linux không?

@arcull OK, tôi không nhận ra bạn đang sử dụng Windows. Tôi đã thêm một số thông tin vào câu trả lời về cách áp dụng cho Windows. Nếu bạn nghĩ rằng nó có thể là một câu trả lời hữu ích, vui lòng xem xét nâng cấp vì nó giúp người khác dễ dàng tìm thấy nó hơn.
hại
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.