Chúng tôi đã gặp phải lỗi lạ này ba lần trong vài ngày qua, sau khi không có lỗi trong 8 tuần và tôi đã bị bối rối.
Đây là thông báo lỗi:
Executing the query "EXEC dbo.MergeTransactions" failed with the following error: "Cannot insert duplicate key row in object 'sales.Transactions' with unique index 'NCI_Transactions_ClientID_TransactionDate'. The duplicate key value is (1001, 2018-12-14 19:16:29.00, 304050920).".
Chỉ số chúng tôi có không phải là duy nhất. Nếu bạn nhận thấy, giá trị khóa trùng lặp trong thông báo lỗi thậm chí không khớp với chỉ mục. Điều kỳ lạ là nếu tôi chạy lại Proc, nó thành công.
Đây là liên kết gần đây nhất tôi có thể thấy có vấn đề của mình nhưng tôi không thấy giải pháp.
Một vài điều về kịch bản của tôi:
- Công ty đang cập nhật Giao dịch (một phần của khóa chính) - Tôi nghĩ đây là nguyên nhân gây ra lỗi nhưng không biết tại sao? Chúng tôi sẽ loại bỏ logic đó.
- Theo dõi thay đổi được bật trên bàn
- Giao dịch đọc không cam kết
Có 45 trường cho mỗi bảng, tôi chủ yếu liệt kê những trường được sử dụng trong các chỉ mục. Tôi đang cập nhật TransactionID (khóa cụm) trong câu lệnh cập nhật (không cần thiết). Kỳ lạ là chúng tôi đã không có bất kỳ vấn đề nào trong nhiều tháng cho đến tuần trước. Và nó chỉ xảy ra lẻ tẻ qua SSIS.
Bàn
USE [DB]
GO
/****** Object: Table [sales].[Transactions] Script Date: 5/29/2019 1:37:49 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[sales].[Transactions]') AND type in (N'U'))
BEGIN
CREATE TABLE [sales].[Transactions]
(
[TransactionID] [bigint] NOT NULL,
[ClientID] [int] NOT NULL,
[TransactionDate] [datetime2](2) NOT NULL,
/* snip*/
[BusinessUserID] [varchar](150) NOT NULL,
[BusinessTransactionID] [varchar](150) NOT NULL,
[InsertDate] [datetime2](2) NOT NULL,
[UpdateDate] [datetime2](2) NOT NULL,
CONSTRAINT [PK_Transactions_TransactionID] PRIMARY KEY CLUSTERED
(
[TransactionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, DATA_COMPRESSION=PAGE) ON [DB_Data]
) ON [DB_Data]
END
GO
USE [DB]
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[sales].[Transactions]') AND name = N'NCI_Transactions_ClientID_TransactionDate')
begin
CREATE NONCLUSTERED INDEX [NCI_Transactions_ClientID_TransactionDate] ON [sales].[Transactions]
(
[ClientID] ASC,
[TransactionDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, DATA_COMPRESSION = PAGE) ON [DB_Data]
END
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[sales].[DF_Transactions_Units]') AND type = 'D')
BEGIN
ALTER TABLE [sales].[Transactions] ADD CONSTRAINT [DF_Transactions_Units] DEFAULT ((0)) FOR [Units]
END
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[sales].[DF_Transactions_ISOCurrencyCode]') AND type = 'D')
BEGIN
ALTER TABLE [sales].[Transactions] ADD CONSTRAINT [DF_Transactions_ISOCurrencyCode] DEFAULT ('USD') FOR [ISOCurrencyCode]
END
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[sales].[DF_Transactions_InsertDate]') AND type = 'D')
BEGIN
ALTER TABLE [sales].[Transactions] ADD CONSTRAINT [DF_Transactions_InsertDate] DEFAULT (sysdatetime()) FOR [InsertDate]
END
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[sales].[DF_Transactions_UpdateDate]') AND type = 'D')
BEGIN
ALTER TABLE [sales].[Transactions] ADD CONSTRAINT [DF_Transactions_UpdateDate] DEFAULT (sysdatetime()) FOR [UpdateDate]
END
GO
bảng tạm thời
same columns as the mgdata. including the relevant fields. Also has a non-unique clustered index
(
[BusinessTransactionID] [varchar](150) NULL,
[BusinessUserID] [varchar](150) NULL,
[PostalCode] [varchar](25) NULL,
[TransactionDate] [datetime2](2) NULL,
[Units] [int] NOT NULL,
[StartDate] [datetime2](2) NULL,
[EndDate] [datetime2](2) NULL,
[TransactionID] [bigint] NULL,
[ClientID] [int] NULL,
)
CREATE CLUSTERED INDEX ##workingTransactionsMG_idx ON #workingTransactions (TransactionID)
It is populated in batches (500k rows at a time), something like this
IF OBJECT_ID(N'tempdb.dbo.#workingTransactions') IS NOT NULL DROP TABLE #workingTransactions;
select fields
into #workingTransactions
from import.Transactions
where importrowid between two number ranges -- pseudocode
Khóa chính
CONSTRAINT [PK_Transactions_TransactionID] PRIMARY KEY CLUSTERED
(
[TransactionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, DATA_COMPRESSION=PAGE) ON [Data]
) ON [Data]
Chỉ mục không phân cụm
CREATE NONCLUSTERED INDEX [NCI_Transactions_ClientID_TransactionDate] ON [sales].[Transactions]
(
[ClientID] ASC,
[TransactionDate] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, DATA_COMPRESSION = PAGE)
tuyên bố cập nhật mẫu
-- updates every field
update t
set
t.transactionid = s.transactionid,
t.[CityCode]=s.[CityCode],
t.TransactionDate=s.[TransactionDate],
t.[ClientID]=s.[ClientID],
t.[PackageMonths] = s.[PackageMonths],
t.UpdateDate = @UpdateDate
FROM #workingTransactions s
JOIN [DB].[sales].[Transactions] t
ON s.[TransactionID] = t.[TransactionID]
WHERE CAST(HASHBYTES('SHA2_256 ',CONCAT( S.[BusinessTransactionID],'|',S.[BusinessUserID],'|', etc)
<> CAST(HASHBYTES('SHA2_256 ',CONCAT( T.[BusinessTransactionID],'|',T.[BusinessUserID],'|', etc)
Câu hỏi của tôi là, những gì đang xảy ra dưới mui xe? Và giải pháp là gì? Để tham khảo, liên kết ở trên đề cập đến điều này:
Tại thời điểm này, tôi có một vài lý thuyết:
- Lỗi liên quan đến áp lực bộ nhớ hoặc kế hoạch cập nhật song song lớn, nhưng tôi sẽ mong đợi một loại lỗi khác và cho đến nay tôi không thể tương quan tài nguyên thấp sẽ định khung thời gian của các lỗi bị cô lập và lẻ tẻ này.
- Một lỗi trong câu lệnh hoặc dữ liệu CẬP NHẬT đang gây ra sự vi phạm trùng lặp thực tế trên khóa chính, nhưng một số lỗi SQL Server tối nghĩa đang dẫn đến và thông báo lỗi trích dẫn tên chỉ mục sai.
- Đọc bẩn kết quả từ việc đọc cách ly không được cam kết gây ra một bản cập nhật song song lớn để chèn kép. Nhưng các nhà phát triển ETL tuyên bố đọc mặc định đã cam kết được sử dụng và thật khó để xác định chính xác mức độ cô lập mà quá trình thực sự được sử dụng trong thời gian chạy.
Tôi nghi ngờ rằng nếu tôi điều chỉnh kế hoạch thực hiện như một cách giải quyết, có lẽ là gợi ý MAXDOP (1) hoặc sử dụng cờ theo dõi phiên để vô hiệu hóa hoạt động của bộ đệm, lỗi sẽ biến mất, nhưng không rõ điều này sẽ ảnh hưởng đến hiệu suất như thế nào
Phiên bản
Microsoft SQL Server 2017 (RTM-CU13) (KB4466404) - 14.0.3048.4 (X64) 30 tháng 11 năm 2018 12:57:58 Bản quyền (C) 2017 Microsoft Corporation Enterprise Edition (64-bit) trên Windows Server 2016 Standard 10.0 (Build 14393 :)