DBA tình cờ: Không chắc chắn tại sao tôi có chuỗi log bị hỏng?


7

Trước hết, cảm ơn vì đã xem xét điều này - Chúng tôi đã có một cơ sở dữ liệu lớn trong môi trường sản xuất của chúng tôi (1,26 TB), nó có vài trăm trang bị hỏng trong đó và đã thực hiện trong nhiều tháng, vì vậy tất cả tham nhũng tương tự của các bản sao lưu có sẵn.

Tôi đã bị kéo vào cuối tuần trước vì dường như các công việc được lên lịch để sắp xếp lại các chỉ mục đã bị thất bại trong một thời gian do tham nhũng và chúng tôi hiện đang ở giai đoạn mà các chỉ mục trên các bảng lớn nhất và được sử dụng phổ biến nhất nằm trong khoảng từ 50% và Phân mảnh 80% đang làm giảm nghiêm trọng hiệu suất ứng dụng.

Tôi đã giải trí một số ý tưởng về cách tôi có thể khắc phục tình trạng này (tin tôi đi, tôi không chỉ cởi mở với các lựa chọn thay thế) và từ những gì tôi đã đọc tôi nghĩ những âm thanh sau đây giống như một ý tưởng hay:

  1. Hãy sao lưu cơ sở dữ liệu bị hỏng từ sản xuất (SQL Server 2008R2), sao chép xuống máy chủ phát triển (cục bộ) của chúng tôi (SQL Server 2016) và chạy sửa chữa (không đủ không gian trên hệ thống sản xuất để có hai bản sao của db tham nhũng được đính kèm đồng thời).
  2. Khôi phục hai bản sao lưu bị hỏng này lên máy chủ phát triển nơi chúng tôi có đủ dung lượng.
  3. Chạy sửa chữa trên máy chủ phát triển với tùy chọn allow_data_loss cho một trong những dbs này, đổi tên thành "DbNameHereRepaired" (hầu hết các trang bị hỏng mà tôi đã xem với DBCC PAGE dù sao cũng đã đặt dữ liệu của chúng thành 0x00).
  4. Đổi tên bản sao khác thành DbNameHereCorrupt, cố gắng chạy khôi phục cấp độ trang bằng mã sau đây:

        alter database DbNameHereCorrupt set single_user with rollback immediate
    
        --set db to FULL recovery mode
        alter database DbNameHereCorrupt set recovery full
    
        --Declare paths for backups
        declare @fullBackupPath nvarchar(max) = N'D:\Restore\DbNameHereCorrupt-FullBackup.bck'
        declare @tranLogBackupPath nvarchar(max) = N'D:\Restore\DbNameHereCorrupt-LogBackup.bck'
    
        --Take full backup to begin new TLogChain
        backup database DbNameHereCorrupt to disk = @fullBackupPath with init, differential;
    
        --Immediately after whilst in single user mode, begin the t-log chain, this will also put the db in a restoring state
        backup log DbNameHereCorrupt to disk=@tranLogBackupPath with init, norecovery;
    
        --get corrupted pages
        declare @corruptedPages nvarchar(max) = 
        (
            select stuff
            (
                (
                    select ',' + cast(s.file_id as nvarchar(20)) + ':' + cast(s.page_id as nvarchar(20))
                    from msdb.dbo.suspect_pages s
    
                    where s.database_id = 20
    
                    for xml path('')
                ), 1 ,1, ''
            )
        )
    
        --push page-level restore
        restore database DbNameHereCorrupt
        page=@corruptedPages
        from disk=N'D:\Restore\DbNameHereRepaired.bak'
        with norecovery;
    
        -- restore log over db
        restore log DbNameHereCorrupt from disk=@tranLogBackupPath
        with norecovery;
    
        -- put db back into usable state
        restore database DbNameHereCorrupt
        with recovery
    
        --set db to SIMPLE recovery mode
        alter database DbNameHereCorrupt set recovery simple
    
        alter database DbNameHereCorrupt set multi_user

Điều này dường như hoạt động theo cách tôi nghĩ rằng nó được cho là cho đến khi tuyên bố khôi phục cấp độ trang, trong đó nó báo lỗi:

Msg 4346, Cấp 16, Trạng thái 1, Dòng 35 TRANG RESTORE không được phép với cơ sở dữ liệu sử dụng mô hình khôi phục đơn giản hoặc đã phá vỡ chuỗi sao lưu nhật ký.

Đây là lần đầu tiên tôi sử dụng mô hình khôi phục hoàn toàn, vì vậy tôi có thể đã làm gì đó sai ... Tôi có thể thấy những gì trông giống như một khoảng cách nhỏ giữa lsn cuối cùng của chênh lệch và sao lưu giao dịch, mà tôi đoán rằng ở đó không nên

Bất cứ ai cũng có thể thấy những gì tôi đã làm sai ở đây? Tôi đã cố gắng làm theo các ví dụ trên web rằng tất cả dường như theo một mô hình tương tự, nhưng tôi đoán tôi đang thiếu một cái gì đó?


Bạn có bao nhiêu trang bị hỏng? Nếu bạn có hơn 1000 trang, thì việc khôi phục sẽ thất bại. "Số lượng trang tối đa có thể được khôi phục vào bất kỳ tệp nào trong chuỗi khôi phục là 1000. Tuy nhiên, nếu bạn có nhiều hơn một số lượng trang bị hỏng trong một tệp, hãy xem xét khôi phục toàn bộ tệp thay vì các trang." Báo cáo RESTORE - Đối số (Transact-SQL) . Và một số ...
John aka hot2use

103 trang, 676 lỗi thống nhất. Tôi đã quản lý để chạy khôi phục bản sao và sửa chữa với việc cho phép mất dữ liệu trên máy chủ phát triển của chúng tôi và kiểm tra lại với dbcc checkdb sau đó - nó dường như hoạt động.
DB-GB

@TomV Vâng, tôi có thể nói bằng object_ids & page_ids trong DBCC CHECK, hầu như tất cả đều không được sử dụng bởi bất kỳ ứng dụng nào. Có khoảng 20-30 trang dữ liệu có thể có giá trị nào đó, may mắn thay, chúng tôi có thể xử lý lại dữ liệu từ nguồn thô mà nó đến từ để khôi phục dữ liệu.
DB-GB

1
Trong bước # 1, bạn đã thực hiện sao lưu toàn bộ copy_only chưa?
Andrey Nikolov

@AndreyNikolov Trên cái mà tôi đang sử dụng trong tập lệnh ở trên để thử và lấy db kiểm tra "bị hỏng" trên máy chủ phát triển ở chế độ khôi phục hoàn toàn, không có bản sao lưu chuẩn. Đối với bản sao lưu gốc mà tôi đã sử dụng để sao chép từ sản xuất trước đó, vâng đó là copy_only.
DB-GB

Câu trả lời:


3

Lệnh của bạn để sao lưu đầy đủ

- Thực hiện sao lưu đầy đủ để bắt đầu TLogChain mới

cơ sở dữ liệu sao lưu DbNameHereCorrupt vào đĩa = @fullBackupPath với init, differ;

không sao lưu toàn bộ.

KHÁC BIỆT

Chỉ được sử dụng với BACKUP DATABASE, chỉ định rằng cơ sở dữ liệu hoặc sao lưu tệp chỉ nên bao gồm các phần của cơ sở dữ liệu hoặc tệp đã thay đổi kể từ lần sao lưu đầy đủ cuối cùng.

Như @dbamex đã đề cập đầy đủ và các lệnh khôi phục sử dụng các tên tệp khác nhau.


Cảm ơn mija! Tôi đã thử mà không có từ khóa khác biệt (nó chỉ được thêm vào cho tốc độ, sao lưu toàn bộ mất 3-4 giờ). Vâng, đó là loại ý định, nhưng từ âm thanh của những gì @dbamex đã nói, đó cũng là nguồn gốc của vấn đề của tôi :(.
DB-GB

1

Bạn đang tiến tới các giải pháp mà không xác định được vấn đề trước. Id chỉ mục của các trang bị hỏng là gì? Nếu id chỉ mục không phải là 0 hoặc 1, thì đây là các chỉ mục không được nhóm - script chúng, thả chúng và tạo lại chúng và điều này sẽ khắc phục tham nhũng.

Nếu chúng là chỉ mục id 1 (chỉ mục được nhóm) hoặc 0 (heap), thì bạn cần xem xét liệu bạn có bao gồm các chỉ mục bằng cách sử dụng NCI của bạn để tạo bản sao của dữ liệu hay không, sau đó bạn có thể thả và tạo lại bảng hoặc chỉ mục được nhóm để khắc phục tham nhũng.

Nếu bạn đăng đầu ra từ DBCC CHECKDB có thể giúp xác định các giải pháp có thể khác ngoài khôi phục cấp độ trang.


Hầu như tất cả là -1, 0 hoặc 1 thật không may, tôi đã xoay sở để thoát khỏi việc chỉ xây dựng lại các chỉ mục lần trước, nhưng có vẻ như lần này tôi không may mắn lắm. Chỉ một trong các bảng có các chỉ mục bao trùm và không may chỉ mục che phủ không bao gồm tất cả các cột trong bảng. Từ âm thanh của các bình luận ở trên, có vẻ như khôi phục cấp độ trang (theo cách mà tôi đang cố gắng thực hiện) có thể không thể thực hiện được nếu không có nhiều may mắn và tìm cách làm mờ các LSN.
DB-GB
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.