2009-09-19 28 views
5

Tôi cần xóa một loạt dữ liệu và không có không gian đĩa để nhật ký tiếp tục phát triển. Khi nhìn vào vấn đề xa hơn, có vẻ như không có cách nào xung quanh chuyện này, nhưng tôi nghĩ tôi sẽ hỏi chắc chắn; thật khó cho tôi để tin rằng một cái gì đó rất đơn giản là không thể.Phải có cách xóa dữ liệu trong SQL Server bằng cách quá tải nhật ký

Tôi đã thử lặp lại, xóa theo khối và gọi shrinkfile trên nhật ký sau mỗi lần lặp. SQL Server dường như bỏ qua lệnh shrinkfile. Đã làm tương tự với bản ghi sao lưu (sau đó xóa các tập tin sao lưu sau đó). Cùng một điều - đăng nhập chỉ tiếp tục phát triển. Mô hình phục hồi trên cơ sở dữ liệu Tôi đang cố gắng điều này trên là đơn giản - tôi nghĩ rằng sẽ làm cho nó dễ dàng hơn, nhưng nó không.

+0

Làm thế nào mà bạn cố gắng để thu nhỏ các bản ghi trong chiến lược 'xóa trong khối' của bạn ? Các lệnh chính xác là gì? –

+0

dbcc shrinkfile ('log_file_name', 0) - hoạt động tốt bên ngoài tập lệnh – dudeNumber4

+0

Bạn có thực sự xóa thông tin liên tục không? Hoặc có thể một bảng tạm thời phù hợp với nhu cầu lưu trữ của loạt dữ liệu này? – pascal

Trả lời

14

Đừng sự xóa trong khối, nhưng thay vì cố gắng để thu nhỏ log giữa lần, đừng đăng nhập sao lưu giữa các khối (có nghĩa là nếu bạn đang ở hồi phục hoàn toàn)

Vấn đề là các bản ghi đầy và do đó phải phát triển. Nếu nó đầy, cố gắng thu nhỏ nó là vô ích, không có không gian trống trong nhật ký để phát hành cho hệ điều hành. Thay vào đó, những gì bạn cần làm là tạo không gian bên trong tệp có sẵn để sử dụng lại.

Vì DB đang khôi phục đơn giản, hãy chạy lệnh xóa theo khối với lệnh CHECKPOINT ở giữa mỗi đoạn. Bạn không thể thực hiện sao lưu nhật ký trong khôi phục đơn giản

Đây là mã mẫu không xóa được nhật ký (trong khôi phục đơn giản). KHÔNG bọc nó trong một giao dịch tùy chỉnh. Điều đó hoàn toàn đánh bại điểm xóa theo lô vì nhật ký không thể bị xóa cho đến khi toàn bộ giao dịch được thực hiện.

(SQL 2005 trở lên.Đối với SQL 2000, loại bỏ TOP và sử dụng SET ROWCOUNT)

DECLARE @Done BIT 
SET @Done = 0 
WHILE @Done = 0 
    BEGIN 
    DELETE TOP (20000) -- reduce if log still growing 
     FROM SomeTable WHERE SomeColumn = SomeValue 
    IF @@ROWCOUNT = 0 
     SET @Done = 1 
    CHECKPOINT -- marks log space reusable in simple recovery 
    END 

Để hiểu quản lý đăng nhập, hãy nhìn vào bài viết này - http://www.sqlservercentral.com/articles/64582/

+0

Khi tôi đọc các tài liệu trên CHECKPOINT, nó nói điều này xảy ra trên một bản sao lưu đăng nhập với TRUNCATE_ONLY. nhật ký sao lưu 'db_name' với TRUNCATE_ONLY có cùng hiệu ứng - ngồi xổm. Vì vậy, tất cả mọi thứ (bao gồm cả các báo cáo đăng nhập sao lưu) được cuộn lại thành một giao dịch khổng lồ vô ích trong trường hợp của tôi. Tôi cần hiệu quả của việc thực hiện lệnh 'go' mà không làm mất ngữ cảnh của vòng lặp của tôi (không thể có 'đi' ở giữa vòng lặp). – dudeNumber4

+0

Bạn không cần GO ở giữa vòng lặp. GO không có gì liên quan đến giao dịch, đó là một công cụ chấm dứt hàng loạt Chỉ cần không khai báo giao dịch rõ ràng và SQL sẽ thực hiện từng lần xóa trong giao dịch của chính nó và cho phép nhật ký bị cắt bớt sau đó, bằng một trạm kiểm soát – GilaMonster

+0

. mã bạn đang sử dụng cho 'chunking' các xóa, cũng như kết quả của truy vấn sau cho DB trong câu hỏi SELECT tên, log_reuse_wait_desc FROM sys.databases Tôi đã thực hiện loại hàng loạt xóa hàng trăm lần , vì vậy nó có thể hoạt động. – GilaMonster

4

Một mẹo nhỏ tôi đã sử dụng tùy thuộc vào kích thước của dữ liệu tôi đang giữ so với số tiền tôi đang xóa là:

  1. chọn tất cả các "dữ liệu để giữ" vào bảng khác (chỉ tạm lưu trữ)

  2. truncate bảng gốc

  3. chèn tất cả các dữ liệu từ các bảng lưu trữ tạm thời trở lại vào ban

Tính năng này hoạt động tốt nếu số tiền bạn đang giữ nhỏ hơn số tiền bạn đang xóa.

Một lựa chọn tương tự nếu tất cả các tập tin cơ sở dữ liệu đang ở trên cùng một đĩa (dữ liệu và các bản ghi) và các dữ liệu bị xóa là khoảng một nửa của dữ liệu, sẽ được xuất khẩu "dữ liệu để giữ" vào một tập tin trên một ổ đĩa riêng biệt bằng cách sử dụng tiện ích dòng lệnh bcp, sau đó cắt ngắn và chèn tệp dữ liệu với bcp một lần nữa.

Tôi đã nhìn thấy các DBA lấy cơ sở dữ liệu ngoại tuyến, sao lưu nhật ký, tắt ghi nhật ký và thực hiện theo cách đó nhưng có vẻ như rất nhiều rắc rối. :-)

+0

Vâng, tôi nghi ngờ tôi có đủ chỗ cho điều đó vì nó sẽ giống như những gì nhật ký đang phát triển (cần xóa khoảng một nửa dữ liệu). Khi tôi hiểu nó, với oracle bạn chỉ có thể nói "với nolog" và xóa một số dữ liệu. Tôi không thể tin rằng không có cách nào để làm một cái gì đó rất đơn giản trong SQL Server. – dudeNumber4

+0

Bạn chính xác, tất cả các thao tác đều được đăng nhập vào SQL Server. – GilaMonster

0

Nếu cài đặt khôi phục của bạn được đặt thành Đầy đủ, bạn có thể thử thực hiện sao lưu nhật ký giao dịch để xóa nhật ký ngay trước khi xóa.

+0

Có lẽ tôi hiểu sai, nhưng ngay cả khi nhật ký gần trống khi bắt đầu quá trình, nó sẽ trở nên quá lớn trong quá trình xóa. Vấn đề là các máy chủ (cả QA và sản xuất) đang nhận được ít trên không gian. Chúng tôi đã quyết định một chiến lược mới sẽ làm giảm đáng kể lượng dữ liệu chúng tôi cần để lưu trữ, nhưng chúng tôi cần loại bỏ dữ liệu lịch sử trước tiên. – dudeNumber4

+0

Có lý do nào khiến bạn không thể thiết lập mô hình khôi phục cho cơ sở dữ liệu thành BULK LOGGED hoặc SIMPLE trong khi bạn đang xóa, sau đó đặt lại trạng thái bình thường sau đó không? –

+0

Nó đã được đơn giản, nơi tôi đang chạy này – dudeNumber4

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