2009-10-26 31 views
5

Tôi đang cố xóa 10.000 tệp cùng một lúc, ví dụ: nguyên tử hoặc tất cả cần phải được xóa cùng một lúc, hoặc tất cả cần phải ở lại tại chỗ.Xóa nguyên tử cho một lượng lớn tệp

Tất nhiên, câu trả lời rõ ràng là di chuyển tất cả các tệp vào một thư mục tạm thời và xóa nó một cách đệ quy về thành công, nhưng tăng gấp đôi số lượng I/O yêu cầu.

Nén không hoạt động, vì 1) Tôi không biết tệp nào sẽ cần xóa và 2) các tệp cần được chỉnh sửa thường xuyên.

Có điều gì ngoài đó có thể giúp giảm chi phí I/O không? Mọi nền tảng sẽ làm.

EDIT: giả sử cúp điện có thể xảy ra bất cứ lúc nào.

Trả lời

13

Kibbee là chính xác: bạn đang tìm kiếm một giao dịch. Tuy nhiên, bạn không cần phải phụ thuộc vào cơ sở dữ liệu hoặc các tính năng hệ thống tập tin đặc biệt nếu bạn không muốn. Bản chất của giao dịch là:

  1. Viết bản ghi vào một tệp đặc biệt (thường được gọi là "nhật ký") liệt kê các tệp bạn sắp xóa.
  2. Khi bản ghi này được ghi một cách an toàn, hãy đảm bảo ứng dụng của bạn hoạt động giống như các tệp thực sự đã bị xóa.
  3. Sau đó, bắt đầu xóa các tệp có tên trong bản ghi giao dịch.
  4. Sau khi tất cả các tệp được xóa, hãy xóa bản ghi giao dịch.

Lưu ý rằng, bất kỳ lúc nào sau bước (1), bạn có thể khởi động lại ứng dụng và nó sẽ tiếp tục xóa các tệp đã xóa một cách hợp lý cho đến khi chúng hết.

Xin lưu ý rằng bạn không nên theo đuổi con đường này rất xa: nếu không bạn đang bắt đầu triển khai lại hệ thống giao dịch thực. Tuy nhiên, nếu bạn chỉ cần một vài giao dịch đơn giản, cách tiếp cận cuộn của riêng bạn có thể được chấp nhận.

+1

+1: Đánh dấu để xóa; ngừng sử dụng. Xóa vật lý có thể xảy ra bất cứ lúc nào sau đó. –

+0

Điều gì sẽ xảy ra nếu xảy ra sự cố khiến một trong các tệp không thể xóa được, như một trong số các tệp đang được sử dụng bởi một quy trình khác. Bạn chỉ có thể chờ nó được giải phóng, nhưng có thể mất một lúc. Làm thế nào bạn sẽ quay trở lại trong trường hợp không phải tất cả mọi thứ có thể bị xóa? – Kibbee

+0

Đây chính xác là những gì tôi cần. +1 cho "Tại sao tôi không nghĩ về điều đó?" –

2

Thay vì di chuyển tệp, hãy tạo liên kết tượng trưng vào thư mục tạm thời. Sau đó, nếu mọi thứ là OK, hãy xóa các tập tin. Hoặc, chỉ cần tạo danh sách các tệp ở đâu đó và sau đó xóa chúng.

5

Tôi nghĩ những gì bạn đang thực sự tìm kiếm là khả năng có giao dịch. Bởi vì đĩa chỉ có thể viết một lĩnh vực tại một thời điểm, bạn chỉ có thể xóa từng tệp một. Những gì bạn cần là khả năng cuộn lùi các lần xóa trước đó nếu một trong các lần xóa không xảy ra thành công. Các tác vụ như thế này thường được dành riêng cho cơ sở dữ liệu. Hệ thống tệp của bạn có thể thực hiện giao dịch hay không tùy thuộc vào hệ thống tệp và hệ điều hành bạn đang sử dụng. NTFS trên Windows Vista hỗ trợ Transactional NTFS. Tôi không chắc chắn về cách nó hoạt động, nhưng nó có thể hữu ích.

Ngoài ra, có một cái gì đó gọi là shadow copy cho Windows, trong thế giới Linux được gọi là LVM Snapshot. Về cơ bản nó là một bản chụp của đĩa tại một thời điểm. Bạn có thể chụp nhanh trực tiếp trước khi thực hiện xóa, và nếu cơ hội không thành công, hãy sao chép các tệp đó ra khỏi ảnh chụp nhanh. Tôi đã tạo bản sao bóng bằng cách sử dụng WMI trong VBScript, tôi chắc chắn rằng apis tương tự tồn tại cho C/C++ cũng.

Một điều về Shadow Copy và LVM Snapsots. Công việc trên toàn bộ phân vùng. Vì vậy, bạn không thể chụp nhanh chỉ một thư mục. Tuy nhiên, việc chụp nhanh toàn bộ đĩa chỉ mất vài giây. Vì vậy, bạn sẽ có một bản chụp. Xóa các tệp và sau đó nếu không thành công, hãy sao chép các tệp ra khỏi ảnh chụp nhanh. Điều này sẽ chậm, nhưng tùy thuộc vào tần suất bạn dự định quay trở lại, điều đó có thể chấp nhận được. Ý tưởng khác là khôi phục toàn bộ ảnh chụp nhanh. Điều này có thể hoặc có thể không tốt vì nó sẽ quay trở lại tất cả các thay đổi trên toàn bộ đĩa. Không tốt nếu hệ điều hành của bạn hoặc các tập tin quan trọng khác được đặt ở đó. Nếu phân vùng này chỉ chứa các tệp bạn muốn xóa, việc khôi phục toàn bộ ảnh chụp có thể dễ dàng và nhanh hơn.

6

Trên * nix, việc di chuyển tệp trong một hệ thống tệp đơn là hoạt động chi phí rất thấp, nó hoạt động bằng cách tạo liên kết cứng đến tên mới và sau đó hủy liên kết tệp gốc. Nó thậm chí không thay đổi bất kỳ thời gian tập tin.

Nếu bạn có thể di chuyển tệp vào một thư mục, thì bạn có thể đổi tên thư mục đó để làm cho nó không hoạt động như một op nguyên tử, và sau đó xóa các tệp (và thư mục) sau đó chậm hơn, không thời trang nguyên tử.

Bạn có chắc chắn không chỉ muốn một cơ sở dữ liệu? Tất cả đều có cam kết giao dịch và được xây dựng lại.

+0

Tại sao bạn cho rằng di chuyển rẻ hơn xóa? –

+0

Vì tôi không biết trước, các tệp nào sẽ bị xóa, cách tiếp cận này vẫn còn đắt hơn so với một thư mục đổi tên. Nó sẽ là tốt đẹp mặc dù. –

+2

@ralu: tất cả các hệ thống giao dịch đều ghi lại ý định và xác định và điều phối điểm không trả lại, trước khi thực hiện bất kỳ điều gì không thể đảo ngược. Tôi đã cố gắng gọi ra một cách tiếp cận giao dịch để xóa các tập tin. Nó có nhiều chi phí hơn là chỉ chipping đi với 'unlink (2)' nhưng đó là giá của việc có một giao dịch. Có lẽ tôi đã nói vậy. – DigitalRoss

1

Tôi nghĩ phương pháp sao chép và xóa là khá nhiều cách tiêu chuẩn để thực hiện việc này. Bạn có biết một thực tế là bạn không thể chịu đựng được I/O bổ sung?

Tôi sẽ không tính xuất bản vào hệ thống tệp, nhưng tôi sẽ tưởng tượng rằng bất kỳ triển khai thực hiện giao dịch nào cũng cần phải thực hiện tất cả các hành động mong muốn và sau đó sẽ cần phải quay lại và cam kết những hành động đó. I E. bạn không thể tránh thực hiện nhiều I/O hơn là làm nó không nguyên tử.

1

Bạn có lớp trừu tượng (ví dụ: cơ sở dữ liệu) để truy cập các tệp không? (Nếu phần mềm của bạn đi trực tiếp đến hệ thống tập tin thì đề xuất của tôi không áp dụng).

Nếu điều kiện là "đúng" để xóa các tệp, hãy thay đổi trạng thái thành "đã xóa" trong lớp trừu tượng của bạn và bắt đầu công việc nền để "thực sự" xóa chúng khỏi hệ thống tệp.

Tất nhiên đề xuất này phải gánh chịu một chi phí nhất định khi mở/đóng cửa của các tập tin nhưng giúp bạn tiết kiệm một số I/O trên tạo liên kết tượng trưng vv

2

thể bạn không chỉ cần xây dựng danh sách các tên đường dẫn để xóa, viết này liệt kê ra một tập tin to_be_deleted.log, hãy chắc chắn rằng tập tin đã nhấn đĩa (fsync()), sau đó bắt đầu thực hiện xóa. Sau khi tất cả các xóa đã được thực hiện, hãy xóa nhật ký giao dịch to_be_deleted.log.

Khi bạn khởi động ứng dụng, nó sẽ kiểm tra sự tồn tại của to_be_deleted.log và nếu có ở đó, hãy phát lại các lần xóa trong tệp đó (bỏ qua lỗi "không tồn tại").

1

Trên Windows Vista hoặc mới hơn, Transactional NTFS nên làm những gì bạn cần:

HANDLE txn = CreateTransaction(NULL, 0, 0, 0, 0, NULL /* or timeout */, TEXT("Deleting stuff")); 
if (txn == INVALID_HANDLE_VALUE) { 
    /* explode */ 
} 
if (!DeleteFileTransacted(filename, txn)) { 
    RollbackTransaction(txn); // You saw nothing. 
    CloseHandle(txn); 
    die_horribly(); 
} 
if (!CommitTransaction(txn)) { 
    CloseHandle(txn); 
    die_horribly(); 
} 
CloseHandle(txn); 
1

Câu trả lời cơ bản cho câu hỏi của bạn là "Không". Câu trả lời phức tạp hơn là điều này đòi hỏi sự hỗ trợ từ hệ thống tập tin và rất ít hệ thống tập tin có loại hỗ trợ đó. Dường như NT có FS giao dịch hỗ trợ điều này. Có thể BtrFS cho Linux cũng sẽ hỗ trợ điều này.

Trong trường hợp không hỗ trợ trực tiếp, tôi nghĩ rằng liên kết cứng, di chuyển, loại bỏ tùy chọn là tốt nhất bạn sẽ nhận được.

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