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

Nhật ký giao dịch SQL Server - Phần 2

Đây là bài viết thứ hai trong loạt bài viết dành riêng cho nhật ký giao dịch SQL Server và các đặc điểm cụ thể của nó. Ở đây chúng ta sẽ kiểm tra chi tiết bản ghi nhật ký.

Bản ghi nhật ký

Bản ghi nhật ký là cốt lõi của cơ chế ghi nhật ký và phục hồi. Bản ghi nhật ký mô tả một thay đổi duy nhất trong cơ sở dữ liệu. Do đó, mọi thay đổi đối với cơ sở dữ liệu đều có một bản ghi nhật ký hoặc các bản ghi nhật ký giúp mô tả thay đổi cụ thể đó. Mặc dù bạn không cần phải hiểu chi tiết về bản ghi nhật ký, nhưng để hiểu những gì đang diễn ra với việc ghi nhật ký và khôi phục, những chi tiết đó vô cùng thú vị.

Bản ghi nhật ký có một Số thứ tự nhật ký duy nhất mà chúng tôi đã xác định trong bài viết đầu tiên. Số thứ tự nhật ký cho phép tìm thấy bản ghi nhật ký trong nhật ký giao dịch. Ngoài ra, mọi trang tệp dữ liệu đều có LSN trong tiêu đề trang của nó để xác định bản ghi nhật ký gần đây nhất có sự thay đổi được phản ánh trên trang. Điều này rất quan trọng để khôi phục sự cố.

Bản ghi nhật ký cho các giao dịch đồng thời được xen kẽ trong nhật ký giao dịch theo thời điểm chúng xảy ra. Các bản ghi nhật ký được lưu trữ trong các khối nhật ký trong vùng đệm cho đến khi chúng được chuyển vào đĩa.

Không có hoạt động không đăng nhập nào trong cơ sở dữ liệu người dùng hoặc hệ thống. Tuy nhiên, có một ngoại lệ:trong tempdb, hoạt động lưu trữ phiên bản và tệp công việc không được ghi lại. Các bản ghi nhật ký không bao giờ di chuyển trong nhật ký giao dịch.

Bên trong Bản ghi Nhật ký là gì?

Thông tin trong bản ghi nhật ký cho phép nó được làm lại (cuộn về phía trước) hoặc hoàn tác (cuộn lại). Khả năng này của một bản ghi nhật ký là rất quan trọng để cho phép các giao dịch được khôi phục và phục hồi công việc. Bản ghi nhật ký chứa nhiều trường, tùy thuộc vào loại bản ghi nhật ký. Có một số trường chung giữa tất cả các bản ghi, bao gồm:

  • Loại bản ghi nhật ký
    • bắt đầu ghi nhật ký giao dịch
    • bản ghi nhật ký giao dịch cam kết
    • phân bổ một trang bằng cách thay đổi bitmap phân bổ
    • chèn một hàng
    • xóa một hàng
    • sửa đổi một hàng
  • Bối cảnh của bản ghi nhật ký , nếu có.
  • ID giao dịch mà bản ghi nhật ký là một phần của nếu có. Hầu hết các bản ghi nhật ký là một phần của các giao dịch.
  • Độ dài bản ghi nhật ký . Bản ghi nhật ký thường có kích thước cố định và sau đó tùy thuộc vào lượng dữ liệu có trong bản ghi nhật ký, cũng sẽ có một phần thay đổi.
  • LSN của bản ghi nhật ký trước đó trong cùng một giao dịch . Nếu có. LSN về cơ bản là một con trỏ tới bản ghi nhật ký giao dịch trước đó được tạo bởi giao dịch cụ thể đó. Chuỗi LSN trước đó cho phép hoàn nguyên giao dịch cụ thể đó vì quá trình khôi phục được thực hiện theo thứ tự ngược lại, bắt đầu từ bản ghi nhật ký gần đây nhất.
  • Lượng không gian nhật ký được dự trữ trong trường hợp phải hoàn tác bản ghi nhật ký.

Dành riêng không gian nhật ký

Mọi bản ghi nhật ký được tạo trong phần chuyển tiếp của giao dịch phải dành không gian trống trong nhật ký giao dịch để cho phép bản ghi nhật ký được cuộn lại mà nhật ký giao dịch không cần phải phát triển.

Cơ chế đặt trước không gian nhật ký rất thận trọng, luôn dành đủ không gian và thường là nhiều hơn, đề phòng trường hợp bất ngờ xảy ra. Ví dụ:cập nhật hoặc xóa trên bảng được nén sẽ dành nhiều dung lượng hơn so với cập nhật tương tự hoặc xóa trên bảng không được nén. Điều này xảy ra vì quá trình khôi phục bản cập nhật trên bảng được nén có thể phải đối phó với việc hàng cập nhật không còn nằm trên trang nén nữa và do đó sẽ phải ghi các cột có chiều rộng đầy đủ trong bản ghi nhật ký thay vì dữ liệu nén.

Các loại bản ghi nhật ký

Có nhiều loại bản ghi nhật ký, bao gồm:

  • LOP_FORMAT_PAGE Thao tác trang định dạng nhật ký - là nơi một trang đã được định dạng, có nghĩa là tiêu đề của nó đã được tạo. Bản ghi nhật ký sẽ ghi lại ít nhất tiêu đề trang và có khả năng là một số nội dung khác của trang nếu trang đã được tạo và điền vào như một phần của hoạt động như xây dựng hoặc xây dựng lại chỉ mục)
  • LOP_MODIFY_ROW Thao tác này đang thay đổi một phần nhỏ dữ liệu hiện có.
  • LOP_SET_BITS Bản ghi nhật ký này áp dụng cho các bitmap phân bổ.
  • LOP_INSERT_ROWS và LOP_DELETE_ROWS
  • LOP_SET_FREE_SPACE Áp dụng cho PFS - phân bổ bitmap theo dõi trạng thái phân bổ của các trang.

Bất kỳ bản ghi nhật ký nào sẽ thực hiện thay đổi đối với trang dữ liệu hoặc trang chỉ mục trong chỉ mục dạng bảng bao gồm :

    • ID đơn vị phân bổ
    • ID trang và ID vị trí của bản ghi trên trang, về cơ bản là ID bản ghi dựa trên 0 của bản ghi dữ liệu hoặc chỉ mục trên trang.
    • Hình ảnh sau hoặc hình ảnh trước và hình ảnh sau của dữ liệu đã thay đổi. Có thể có nhiều bộ này trong một bản ghi nhật ký duy nhất. Hình ảnh sau cho phép thực hiện lại. Hình ảnh trước cho phép hoàn tác diễn ra.

Khóa ghi nhật ký

Một số bản ghi nhật ký bao gồm một bitmap trong đó các ổ khóa đã được giữ khi thay đổi được mô tả diễn ra. Bản đồ bit chứa:

      • Đếm số lượng khóa.
      • Loại và chế độ khóa nào - ví dụ:khóa trang ở chế độ X.
      • Khóa đang bật

Trong quá trình khôi phục sự cố và sao chép cơ sở dữ liệu / dự phòng nhóm khả dụng, các khóa này sẽ được lấy cho tất cả các bản ghi nhật ký sẽ được hoàn tác. Điều này cho phép tính năng khôi phục nhanh trong Phiên bản Doanh nghiệp từ SQL Server 2005 trở đi.

Bản ghi nhật ký trong các giao dịch

Tất cả các giao dịch tạo ra ít nhất ba bản ghi nhật ký, luôn theo trình tự sau:

        • LOP_BEGIN_XACT - bao gồm thông tin như SPID, tên giao dịch và thời gian bắt đầu. Tất cả các giao dịch do SQL Server bắt đầu đều có tên để mô tả hoạt động (ví dụ:AllocFirstPage, DROPOBJ)
        • Các bản ghi khác cho giao dịch.
        • LOP_COMMIT_XACT - nếu giao dịch được cam kết.
        • LOP_ABORT_XACT - nếu giao dịch quay trở lại.

Cả hai đều bao gồm thời gian kết thúc cho giao dịch. Các bản ghi nhật ký trong một giao dịch được LSN liên kết ngược lại với nhau. Điều này có nghĩa là bản ghi nhật ký tiếp theo được tạo cho một giao dịch có LSN của bản ghi nhật ký trước đó đã được tạo cho giao dịch cụ thể này. Điều này cho phép giao dịch được khôi phục lại một cách chính xác. Một số bản ghi nhật ký hoàn toàn không mang tính giao dịch, bao gồm:

        • Các thay đổi về dung lượng trống PFS (không thể điều chỉnh với các giao dịch khác)
        • Thay đổi bitmap khác biệt (chỉ thay đổi một chiều)

Kiểm tra bản ghi nhật ký

Có hai cách để kiểm tra bản ghi nhật ký. Bạn có thể sử dụng hàm DBCC LOGINFO, nhưng nên sử dụng hàm giá trị bảng fn_dblog. Nó có cú pháp cực kỳ đơn giản:

 CHỌN * TỪ fn_dblog (startLSN, endLSN); ĐI 

Đây là chức năng cực kỳ mạnh mẽ vì nó:

        • trả về tập hợp kết quả dạng bảng có thể dễ dàng quản lý.
        • cho phép sử dụng các vị từ phức tạp.
        • quét tất cả nhật ký giao dịch trong phần hiện hoạt của nhật ký, từ khi bắt đầu giao dịch không cam kết cũ nhất cho đến bản ghi nhật ký gần đây nhất. Điều này có thể được ghi đè bằng cách sử dụng cờ theo dõi 2537

Các trường startLSN và endLSN thường được chuyển dưới dạng NULL
Đây là bản trình diễn:

 SỬ DỤNG DBTest2014GO BẬT TÀI KHOẢN; ĐI - Đặt chế độ khôi phục ĐƠN GIẢN không có số liệu thống kê tự động - để tránh các bản ghi nhật ký không mong muốn. TẠO BẢNG [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT); CHÈN VÀO [TEST_TABLE] VALUES (1,1,1); ĐI --Xóa logCHECKPOINT; ĐI - Giao dịch ngầmINSERT INTO [TEST_TABLE] VALUES (2,2,2); ĐI CHỌN * TỪ fn_dblog (null, null); ĐI 

Đây là tập hợp kết quả rút gọn. Trên thực tế, fn_dblog trả về nhiều loại bản ghi khác nhau như Độ dài bản ghi nhật ký, Flag bit, Dự trữ nhật ký, AllocUnitId, PageID, SlotID, LSN Trang trước và các bản ghi khác.

Sửa đổi nội dung hàng

Các sửa đổi nhật ký được ghi lại theo hai cách:dưới dạng LOP_MODIFY_ROW hoặc LOP_MODIFY_COLUMNS ghi lại. Bất kể phương pháp nào được sử dụng, nó sẽ ghi lại các byte thực sự đang được thay đổi. Ví dụ:việc thay đổi giá trị INT từ 1 thành 24 chỉ ghi lại một byte thay đổi vì ba byte 0 khác không thay đổi. Máy chủ SQL sẽ sử dụng LOP_MODIFY_ROW bản ghi nhật ký nếu có một phần của hàng được cập nhật. Một phần được định nghĩa như sau:mỗi cột có độ dài thay đổi trong hàng là một “phần” và toàn bộ vùng có chiều rộng cố định của hàng là một “phần”, ngay cả khi nhiều cột đang được cập nhật, nhưng chỉ khi các byte được được cập nhật cách nhau 16 byte trở xuống trong hàng.

LOP_MODIFY_ROW chứa:

  • Trước hình ảnh
  • Sau hình ảnh
  • Lập chỉ mục các cột chính nếu có
  • Khóa bitmap

LOP_MODIFY_COLUMNS chứa:

  • Mảng bù trừ trước và sau
  • Mảng độ dài
  • Lập chỉ mục các cột chính nếu có
  • Khóa bitmap
  • Các cặp hình ảnh trước và sau

Bản ghi nhật ký trả thưởng

Đây là một loại bản ghi nhật ký đặc biệt được sử dụng để giúp khôi phục giao dịch. Khi một giao dịch quay trở lại, thay đổi được mô tả bởi từng bản ghi nhật ký trong giao dịch phải được hoàn tác trong cơ sở dữ liệu. Việc khôi phục bắt đầu với bản ghi nhật ký gần đây nhất cho giao dịch và theo các liên kết LSN trước đó cho đến bản ghi nhật ký LOP_BEGIN_XACT. Đối với mỗi bản ghi nhật ký:

  • Thực hiện "hoạt động chống" sẽ phủ nhận các tác động của bản ghi nhật ký
  • Tạo một bản ghi nhật ký, đánh dấu nó là một bản ghi nhật ký COMPENSATION, vì nó bù đắp cho bản ghi nhật ký trong phần chuyển tiếp của giao dịch.
  • LSN trước đó của bản ghi nhật ký COMPENSATION trỏ đến bản ghi nhật ký trước bản ghi mà nó đang bù đắp. Về cơ bản, nó khiến bản ghi nhật ký không còn là một phần của chuỗi các bản ghi nhật ký cho giao dịch.
  • Không gian nhật ký dành riêng cho bản ghi nhật ký được giải phóng

Bản ghi nhật ký COMPENSATION không thể hoàn tác, chỉ được làm lại.

Hoàn trả một giao dịch

Dưới đây là biểu diễn đồ họa về những gì đang diễn ra khi một giao dịch quay trở lại:

Hãy kiểm tra đoạn mã sau:

 SỬ DỤNG DBTest2014GO ĐẶT SỐ TÀI KHOẢN BẬT; ĐI THÊM CƠ SỞ DỮ LIỆU DBTest2014 ĐẶT PHỤC HỒI ĐƠN GIẢN; THAY THẾ CƠ SỞ DỮ LIỆU DBTest2014 ĐẶT AUTO_CREATE_STATISTICS TẮT; TẠO BẢNG [TEST_TABLE] ([C1] INT, [C2] INT, [C3] INT); CHÈN VÀO [TEST_TABLE] GIÁ TRỊ (1,1,1); CHÈN VÀO [TEST_TABLE] GIÁ TRỊ (2,2,2); ĐI - Xóa logCHECKPOINT; ĐI - Giao dịch rõ ràng để chèn bản ghi mới BẮT ĐẦU; CHÈN VÀO [TEST_TABLE] VALUES (3,3,3); ĐI CHỌN * TỪ fn_dblog (null, null); ĐI - Cuộn lại. 

Tại đây, chúng ta có thể thấy một bản ghi nhật ký đặc biệt với mô tả “BỒI THƯỜNG”

Nếu chúng ta nhìn vào LSN trước đó, chúng ta có thể thấy rằng LOP_INSERT_ROWS mà chúng tôi đã làm, liên kết trở lại … 0f40:0001 và đây là giao dịch BEGIN vì phần chuyển tiếp của giao dịch liên kết trở lại bản ghi nhật ký trước đó. LOP_DELETE_ROW bản ghi nhật ký bồi thường không liên kết trở lại bản ghi mà nó đang bồi thường - nó liên kết với nó (tới bản ghi nhật ký giao dịch BEGIN).

Vì vậy, DELEDE đã bù cho INSERT và loại bỏ nó khỏi danh sách các bản ghi nhật ký. LOP_ABORT_XACT là tín hiệu cho thấy giao dịch được kết thúc với việc hoàn vốn. Ngoài ra, bạn có thể thấy rằng LOP_ABORT_XACT liên kết trở lại LOP_BEGIN_XACT.
Khi chúng tôi ghi lại nhật ký bồi thường, Bảo lưu không gian nhật ký sẽ giảm xuống [-74]. Vì vậy, nó thực sự đang trả lại một số không gian đã được dành cho phần chuyển tiếp của giao dịch (LOP_INSERT_ROWS [178]). Như bạn có thể thấy, hệ thống đặt trước không gian nhật ký rất thận trọng - INSERT dự trữ nhiều dung lượng hơn DELETE trả lại.

Khôi phục và sao lưu chênh lệch

Nếu một cơ sở dữ liệu có một bản sao lưu đầy đủ được thực hiện, thì một giao dịch sẽ cập nhật 100.000 bản ghi nhưng giao dịch được khôi phục lại, tại sao một bản sao lưu khác biệt lại có quá nhiều dữ liệu? Chắc chắn rằng việc khôi phục giao dịch có nghĩa là không có gì thay đổi? Mảnh ghép còn thiếu ở đây là việc lùi một giao dịch không xóa sạch tất cả các thay đổi được thực hiện bởi giao dịch. Như chúng ta đã thấy, quá trình khôi phục phải tạo ra các bản ghi nhật ký bồi thường, vì quá trình khôi phục phải tạo ra các thay đổi khác để bù đắp cho phần chuyển tiếp của giao dịch. Tiêu đề trang của tất cả các trang bị ảnh hưởng đã được thay đổi ít nhất hai lần. Một để cập nhật LSN của trang cho phần chuyển tiếp của giao dịch và một lần để cập nhật LSN của trang cho phần lùi của giao dịch. Trong cả hai trường hợp, bản cập nhật sẽ khiến phạm vi được đánh dấu là đã thay đổi trong bitmap vi phân. Nó không quan tâm sự thay đổi đó là gì, chỉ là một cái gì đó trong phạm vi đã thay đổi. Không có cách nào để loại trừ các phạm vi này khỏi bản sao lưu khác biệt.

Tóm tắt

Trong bài viết này, chúng tôi đã xem xét các bản ghi nhật ký. Bản ghi nhật ký là cốt lõi của cơ chế ghi nhật ký và phục hồi. Mỗi thay đổi trong cơ sở dữ liệu có một bản ghi nhật ký được liên kết với nó. Mỗi bản ghi nhật ký mô tả một thay đổi nhỏ. Một thay đổi lớn có nhiều bản ghi nhật ký bên trong một giao dịch. Có nhiều loại bản ghi nhật ký khác nhau và chúng tôi đã xem xét một số loại bản ghi.

Nhật ký giao dịch về cơ bản là một chủ đề rất lớn và một vài bài báo không đủ để tiết lộ tất cả các chi tiết. Vì vậy, nếu bạn muốn biết thêm thông tin chi tiết, tôi đề nghị bạn đọc cuốn sách sau:Quản lý nhật ký giao dịch SQL Server của Tony Davis và Gail Shaw và bài viết này:Quản lý nhật ký giao dịch.

Cũng đọc:

Tìm hiểu nhật ký giao dịch SQL Server - Phần 1
Tìm hiểu nhật ký giao dịch SQL Server - Phần 2


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bắt Hibernate và SQL Server để chơi tốt với VARCHAR và NVARCHAR

  2. Cách tách chuỗi và chèn giá trị vào bảng trong SQL Server

  3. Giải quyết cơ sở dữ liệu SQL Server bị kẹt trong vấn đề chế độ nghi ngờ một cách dễ dàng

  4. Cách giao dịch ngầm hoạt động trong SQL Server

  5. Sao chép bảng vào cơ sở dữ liệu khác trên SQL Server khác