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

Bản sửa lỗi R2 2008 làm hỏng RCSI

Một trong những bản sửa lỗi có trong Bản Cập Nhật Tích lũy 11 cho SQL Server 2008 R2 Gói Dịch vụ 2 giải quyết "bế tắc không chính xác" có thể xảy ra trong một trường hợp cụ thể (được giải thích ở phần sau của bài viết này). Thật không may, bản sửa lỗi giới thiệu một lỗi mới, trong đó các truy vấn SELECT trong RCSI (đọc cách ly ảnh chụp nhanh đã cam kết) bắt đầu thực hiện các khóa chia sẻ mục đích cấp bảng. Do đó, bạn có thể thấy việc gia tăng chặn (và có khả năng bị khóa) đối với các truy vấn RCSI sau khi áp dụng 2008 R2 SP2 CU11 (hoặc mới hơn).

Điều này sẽ gây bất ngờ không mong muốn đối với bất kỳ ai quen với việc độc giả không chặn người viết (và ngược lại) khi sử dụng RCSI. Không có bản sửa lỗi nào cho lỗi RCSI tại thời điểm viết bài. Trên thực tế, mục Kết nối do Eugene Karpovich tạo để báo cáo sự cố đã bị đóng là "Sẽ không khắc phục", mặc dù tôi hiểu rằng quyết định này hiện đang được xem xét.

Thông thường, vấn đề này có thể không phải là mối quan tâm lớn như vậy, bởi vì các bản cập nhật tích lũy thường không được áp dụng rộng rãi như các gói dịch vụ đầy đủ. Tuy nhiên, Microsoft gần đây đã thông báo sẽ có Gói dịch vụ cuối cùng 3 cho SQL Server 2008 R2. Gói dịch vụ này sẽ là một tập hợp đơn giản của các bản cập nhật tích lũy SP2 hiện có (tối đa và bao gồm CU13) nhưng không có bản sửa lỗi mới. Kết quả của tất cả những điều này là, trừ khi có điều gì đó thay đổi trong thời gian chờ đợi, người dùng áp dụng SP3 sẽ đột nhiên bắt đầu bị ảnh hưởng bởi lỗi RCSI được giới thiệu trong CU11.

chỉnh sửa:Ngay trước khi bài viết này được xuất bản, Microsoft đã xác nhận rằng sự hồi quy này sẽ được sửa trong SP3.

Lỗi "bế tắc không chính xác" tương tự (có bản sửa lỗi giới thiệu lỗi mới) cũng đã được sửa trong Bản cập nhật tích lũy 8 dành cho SQL Server 2012 Gói dịch vụ 1 như được mô tả trong KB2923460. Bản sửa lỗi cho SQL Server 2012 khác và không giới thiệu vấn đề RCSI mới.

SQL Server 2014 không bao giờ bị ảnh hưởng bởi một trong hai vấn đề, theo như tôi có thể nói. Chắc chắn không có tài liệu nào để chỉ ra cách khác và các thử nghiệm tôi đã thực hiện trên RTM, CU1 và CU2 2014 không tạo ra một trong hai lỗi.

Lỗi RCSI R2 2008

Một truy vấn SELECT chạy trong RCSI thường chỉ lấy một khóa ổn định giản đồ (Sch-S), khóa này tương thích với tất cả các khóa khác ngoại trừ khóa sửa đổi giản đồ (Sch-M). Khi CU11 (hoặc mới hơn) được áp dụng cho phiên bản SQL Server 2008 R2, các truy vấn này bắt đầu thực hiện khóa mục đích chia sẻ (Tab-IS) cấp bảng. Tập lệnh kiểm tra sau có thể được sử dụng để chứng minh sự khác biệt trong các hành vi:

USE master;
GO
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET NOCOUNT ON;
GO
CREATE DATABASE RCSI;
GO
ALTER DATABASE RCSI
SET READ_COMMITTED_SNAPSHOT ON;
GO
ALTER DATABASE RCSI
SET ALLOW_SNAPSHOT_ISOLATION OFF;
GO
USE RCSI;
GO
CREATE TABLE dbo.Test
(
    id integer IDENTITY NOT NULL, 
    col1 integer NOT NULL,
 
    CONSTRAINT PK_Test
    PRIMARY KEY CLUSTERED (id)
);
GO
INSERT dbo.Test 
    (col1) 
VALUES 
    (1), (2), (3), (4);
GO
-- Show locks
DBCC TRACEON (1200, 3604, -1) WITH NO_INFOMSGS;
SELECT * FROM dbo.Test;
DBCC TRACEOFF (1200, 3604, -1) WITH NO_INFOMSGS;
GO
ALTER DATABASE RCSI
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
 
USE master;
 
DROP DATABASE RCSI;

Khi chạy với phiên bản SQL Server 2008 R2 mà không có lỗi, đầu ra gỡ lỗi hiển thị một khóa Sch-S duy nhất được thực hiện cho câu lệnh kiểm tra như mong đợi:

Quá trình nhận khóa Sch-S trên OBJECT:7:2105058535:0 kết quả:OK
Quá trình giải phóng khóa trên OBJECT:7:2105058535:0

Khi chạy với SQL Server 2008 R2 bản dựng 10.50.4302 (hoặc cao hơn), kết quả đầu ra tương tự như:

Quá trình có được khóa IS trên OBJECT:7:2105058535:0 kết quả:OK
Khóa giải phóng quá trình trên OBJECT:7:2105058535:0

Lưu ý rằng khóa Sch-S đã được thay thế bằng khóa Tab-IS.

Hàm ý và Giảm nhẹ

Khóa chia sẻ mục đích (IS) vẫn là một khóa rất tương thích, nhưng nó không hoàn toàn thân thiện với đồng thời như Sch-S. Ma trận khả năng tương thích của khóa cho thấy rằng khóa IS xung đột với:

  • Sch-M (sửa đổi giản đồ) - theo Sch-S
  • BU (cập nhật hàng loạt)
  • X (độc quyền)

Sự không tương thích với các khóa độc quyền (X) có nghĩa là việc đọc trong RCSI sẽ bị chặn nếu một quá trình đồng thời giữ một khóa độc quyền trên cùng một tài nguyên. Tương tự như vậy, một trình viết cần một khóa độc quyền sẽ chặn nếu một đầu đọc RCSI đồng thời giữ một khóa IS. Các khóa miễn phí có được bất cứ khi nào dữ liệu được sửa đổi và được giữ ở cuối giao dịch, do đó, tác động của lỗi là các trình đọc theo RCSI sẽ bị chặn bởi những người viết đồng thời (và ngược lại) khi chúng chưa được áp dụng trước khi CU11 được áp dụng.

Một yếu tố giảm thiểu đáng kể là lỗi chỉ gây ra cấp bảng khóa chia sẻ ý định sẽ được thực hiện. Người viết đồng thời cần có cấp bảng khóa độc quyền sẽ gây ra khóa (và có khả năng là khóa chết). Tuy nhiên, những người viết đồng thời chỉ yêu cầu các khóa riêng ở cấp thấp hơn (ví dụ:hàng, trang hoặc phân vùng) sẽ không gây ra tắc nghẽn hoặc bế tắc. Ở cấp bảng, những người viết này sẽ chỉ có được một khóa dành riêng cho mục đích (IX), khóa này tương thích với Tab-IS. Các khóa độc quyền được thực hiện ở mức độ chi tiết thấp hơn sẽ không gây ra xung đột.

Trong hầu hết các hệ thống, khóa độc quyền cấp bảng (Tab-X) sẽ tương đối không phổ biến. Trừ khi được yêu cầu rõ ràng bằng cách sử dụng gợi ý TABLOCKX, một số nguyên nhân có thể gây ra khóa Tab-X là:

  • Khóa báo cáo từ mức độ chi tiết thấp hơn
  • Sử dụng SERIALIZABLE mà không có chỉ mục hỗ trợ cho các ổ khóa có dải chìa khóa

Một giải pháp kỹ thuật là thêm gợi ý bảng (dự phòng) WITH (READCOMMITTED) vào mọi bảng trong mọi truy vấn chạy dưới RCSI. Điều này xảy ra để bỏ qua lỗi nên chỉ có khóa Sch-S được thực hiện, nhưng nó hầu như không phải là một đề xuất thực tế.

Bất chấp những biện pháp giảm thiểu này, việc sử dụng Tab-IS cho truy vấn chỉ đọc trong RCSI vẫn là hành vi không chính xác. Tôi hy vọng nó có thể được sửa cho SQL Server 2008 R2 trước khi gói dịch vụ 3 được phát hành.

Lỗi "Chốt lại không chính xác"

Như đã đề cập trước đó, lỗi RCSI được giới thiệu là một tác dụng phụ của bản sửa lỗi "deadlock không chính xác". Sự cố trước đó được ghi lại cho SQL Server 2008 R2 trong KB2929464 và cho SQL Server 2012 trong KB2923460. Cả tài liệu đều không phải là mô hình về sự rõ ràng (hoặc độ chính xác), nhưng vấn đề cơ bản khá thú vị, vì vậy tôi muốn dành một chút thời gian để xem xét nó ở đây.

Về cơ bản, bế tắc xảy ra khi:

  • Ba hoặc nhiều giao dịch đồng thời được đọc từ cùng một bảng
  • Gợi ý UPDLOCK và TABLOCK được sử dụng trong cả ba trường hợp
  • Cài đặt cơ sở dữ liệu READ_COMMITTED_SNAPSHOT đang BẬT

Lưu ý rằng không quan trọng mức độ cô lập mà các giao dịch chạy theo. Để tạo lại lỗi, trước tiên hãy chạy tập lệnh thiết lập bên dưới:

USE master;
GO
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
CREATE DATABASE IncorrectDeadlock;
GO
ALTER DATABASE IncorrectDeadlock 
SET READ_COMMITTED_SNAPSHOT ON;
GO
USE IncorrectDeadlock;
GO
CREATE TABLE dbo.Test
(
    id integer IDENTITY NOT NULL, 
    col1 integer NOT NULL,
 
    CONSTRAINT PK_Test
    PRIMARY KEY CLUSTERED (id)
);
GO
INSERT dbo.Test 
    (col1) 
VALUES 
    (1);

Tiếp theo, chạy tập lệnh sau trong ba kết nối riêng biệt (lưu ý rằng giao dịch được để mở):

USE IncorrectDeadlock;
GO
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO
BEGIN TRANSACTION;
SELECT
    T.id,
    T.col1
FROM dbo.Test AS T
    WITH (UPDLOCK, TABLOCK);

Tại thời điểm này, phiên đầu tiên sẽ trả về một tập hợp kết quả và hai phiên còn lại sẽ bị chặn. "Bế tắc không chính xác" phát sinh khi phiên đầu tiên hoàn thành giao dịch của nó (cam kết hoặc quay trở lại). Khi điều này xảy ra, một trong hai phiên còn lại sẽ báo cáo bế tắc:

Bế tắc xảy ra do hai phiên bị chặn trước đó giữ Tab-IX (loại trừ mục đích cấp bảng) và cả hai đều muốn chuyển khóa của chúng thành Tab-X (độc quyền cấp bảng). Tab-IX tương thích với một Tab-IX khác, nhưng không tương thích với Tab-X. Đây là một bế tắc chuyển đổi (và điều trớ trêu ở đây là UPDLOCK thường được sử dụng để tránh tắc nghẽn chuyển đổi).

Vui lòng thay đổi mức cô lập giao dịch cho ba truy vấn như bạn muốn. Bế tắc sẽ xảy ra bất kể, miễn là RCSI được kích hoạt, với các khóa tương tự liên quan. Khi quá trình kiểm tra hoàn tất, hãy xóa cơ sở dữ liệu kiểm tra:

USE IncorrectDeadlock;
 
ALTER DATABASE IncorrectDeadlock
SET SINGLE_USER 
WITH ROLLBACK IMMEDIATE;
 
USE master;
 
DROP DATABASE IncorrectDeadlock;

Phân tích và giải thích

Cá nhân tôi không nhớ đã từng sử dụng UPDLOCK và TABLOCK cùng nhau trong mã của mình hay chưa. Đối với tôi, sự kết hợp của các gợi ý này có vẻ kỳ quặc vì SQL Server không có khóa cập nhật cấp bảng . Vì vậy, nó thậm chí có nghĩa là gì để chỉ định gợi ý UPDLOCK và TABLOCK cùng nhau?

Tài liệu có điều này để nói:

CẬP NHẬT

Chỉ định rằng các khóa cập nhật sẽ được thực hiện và giữ cho đến khi giao dịch hoàn tất. UPDLOCK chỉ thực hiện các khóa cập nhật cho các thao tác đọc ở cấp độ hàng hoặc cấp độ trang. Nếu UPDLOCK được kết hợp với TABLOCK hoặc khóa cấp bảng được sử dụng vì một số lý do khác, thì một khóa (X) độc quyền sẽ được sử dụng thay thế.

Điều này cho thấy rằng sự kết hợp gợi ý phải dẫn đến một khóa bảng độc quyền duy nhất. Trên thực tế, đây không phải là toàn bộ câu chuyện:

Trong SQL Server 2000, việc kết hợp các gợi ý UPDLOCK và TABLOCK dẫn đến Tab-S (khóa bảng dùng chung) được thực hiện theo sau chuyển đổi thành Tab-X (khóa bảng độc quyền) ở tất cả các mức cách ly ngoại trừ READ UNCOMMITTED. Chuỗi khóa này có thể dẫn đến bế tắc trong đó ba phiên trở lên có liên quan:hai phiên có được Tab-S và cả hai phiên chờ kia để chuyển đổi thành Tab-X. Trong READ UNCOMMITTED, SQL Server 2000 sử dụng Sch-S rồi đến Tab-X, không dễ bị deadlock (chỉ là chặn thông thường).

Trong SQL Server 2005 trở đi (không có bản sửa lỗi), các khóa được thực hiện phụ thuộc chỉ về việc RCSI có được bật hay không. Nếu RCSI được bật, tất cả các mức cách ly lấy Tab-IX sau đó chuyển đổi sang Tab-X. Trình tự này gây ra bế tắc các địa chỉ sửa lỗi.

Nếu RCSI không được bật, các mức cô lập phù hợp sẽ hoạt động như chúng đã làm trong SQL Server 2000 (sử dụng Tab-S sau đó chuyển đổi sang Tab-X). Mức cô lập ảnh chụp nhanh (mới cho năm 2005) lấy Sch-S theo sau là Tab-X. Do đó, SI và READ UNCOMMITTED là các mức cách ly duy nhất không dễ bị bế tắc này trong kịch bản UPDLOCK, TABLOCK khi RCSI không được bật.

Khắc phục bế tắc

Bản sửa lỗi thay đổi các khóa được thực hiện khi UPDLOCK và TABLOCK được chỉ định cùng nhau, cho tất cả các mức cách ly bất chấp về việc RCSI có được bật hay không. Sau khi áp dụng bản sửa lỗi, UPDLOCK và TABLOCK khiến công cụ nhận được Tab-SIX (cấp bảng được chia sẻ với mục đích độc quyền), sau đó được chuyển đổi thành Tab-X.

Điều này tránh trường hợp bế tắc vì Tab-SIX không tương thích với một Tab-SIX khác. Hãy nhớ rằng bế tắc xảy ra khi hai tiến trình giữ Tab-IX chờ chuyển đổi thành Tab-X. Với Tab-IX được thay thế bằng Tab-SIX, cả hai không thể giữ Tab-SIX cùng một lúc. Kết quả là một kịch bản chặn bình thường thay vì bế tắc.

Lời kết

Bản sửa lỗi "deadlock không chính xác" giải quyết được một trường hợp deadlock cụ thể, nhưng nó vẫn không dẫn đến hành vi mà tôi tưởng tượng mà những người chỉ định UPDLOCK và TABLOCK đã dự kiến. Nếu SQL Server có khóa Tab-U (cập nhật cấp bảng), nó sẽ ngăn các thay đổi đồng thời đối với bảng nhưng cho phép trình đọc đồng thời. Đây là những gì tôi tưởng tượng mục đích của những người sử dụng các gợi ý này cùng nhau và tôi có thể thấy nó có thể hữu ích như thế nào.

Việc triển khai hiện tại (trong đó Tab-X cuối cùng được sử dụng thay vì Tab-U bị thiếu) không phù hợp với kỳ vọng này vì Tab-X ngăn các lần đọc đồng thời (trừ khi sử dụng mức cách ly lập phiên bản hàng). Chúng tôi cũng có thể chỉ định TABLOCKX trong nhiều trường hợp. Thực tế là bản sửa lỗi cũng tạo ra một lỗi mới (chỉ dành cho người dùng SQL Server 2008 R2) cũng không may, đặc biệt nếu lỗi tiếp tục được đưa vào 2008 R2 SP3.

Lưu ý rằng bản sửa lỗi bế tắc không khả dụng cho các phiên bản SQL Server trước 2008 R2. Các phiên bản này sẽ tiếp tục có hành vi khóa phức tạp đối với UPDLOCK và TABLOCK như được mô tả ở trên.

Tôi gửi lời cảm ơn tới Eugene Karpovich, người đầu tiên đưa vấn đề này đến sự chú ý của tôi trong một nhận xét cho bài viết của tôi về Sửa đổi dữ liệu theo RCSI.


  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ước tới Bắt đầu Phát triển Cơ sở dữ liệu Theo hướng Thử nghiệm (TDDD)

  2. Mô hình dữ liệu cho ứng dụng đặt lịch hẹn khám bệnh

  3. Dell Boomi

  4. Bên trong của WITH ENCRYPTION

  5. ĐẶT HÀNG SQL BẰNG