Bu garip hatayı, son birkaç gün boyunca, 8 hafta boyunca hatasız olduktan sonra üç kez gördük ve güdük oldum.
Bu hata mesajıdır:
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).".
Elimizdeki dizin benzersiz değil . Dikkat ederseniz, hata iletisindeki yinelenen anahtar değeri dizinle aynı hizaya gelmez. Garip bir şey, eğer süreci tekrar çalıştırırsam başarılı olur.
Bu benim sorunlarım var bulabildiğim en son bağlantı ama bir çözüm görmüyorum.
Senaryom hakkında birkaç şey:
- Proc TransactionID (birincil anahtarın bir parçası) güncelleştiriyor - bu hata neden olduğunu düşünüyorum ama neden bilmiyorum? Bu mantığı kaldıracağız.
- Değişiklik izleme tabloda etkin
- İşlem okunmamış gerçekleştiriliyor
Her tablo için 45 alan var, ben esas olarak dizinlerde kullanılanları listeledim. Güncelleme deyiminde (gereksiz) TransactionID (kümelenmiş anahtar) güncelleştiriyorum. Geçen haftaya kadar aylardır herhangi bir sorun yaşamadığımız garip. Ve bu sadece SSIS aracılığıyla ara sıra gerçekleşiyor.
tablo
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
geçici masa
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
Birincil anahtar
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]
Kümelenmemiş dizin
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)
örnek güncelleme bildirimi
-- 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)
Sorum şu: Kaputun altında neler oluyor? Peki çözüm nedir? Referans olarak, yukarıdaki bağlantı bundan bahseder:
Bu noktada birkaç teorim var:
- Bellek baskısı veya büyük paralel güncelleme planı ile ilgili hata, ancak farklı bir hata türü beklerdim ve şimdiye kadar düşük kaynakları ilişkilendiremiyorum bu izole ve düzensiz hataların zaman dilimi olacaktır.
- UPDATE deyimindeki veya verilerindeki bir hata birincil anahtarda gerçek bir yinelenen ihlale neden oluyor, ancak bazı belirsiz SQL Server hatalarına neden oluyor ve yanlış dizin adını gösteren hata mesajı çıkıyor.
- Okuma tamamlanmamış izolasyondan kaynaklanan kirli okumalar, çift insert için büyük bir paralel güncellemeye neden olur. Ancak ETL geliştiricileri varsayılan okumanın kullanıldığını iddia ediyor ve sürecin gerçekte hangi izolasyon seviyesinin gerçek zamanlı olarak kullanıldığını tam olarak belirlemek zor.
Yürütme planını bir çözüm olarak, belki de MAXDOP (1) ipucu olarak veya biriktirme işlemini devre dışı bırakmak için oturum izleme bayrağını kullanırsam, hatanın ortadan kalkacağından şüpheleniyorum, ancak bunun performansı nasıl etkileyeceği belirsiz
versiyon
Microsoft SQL Server 2017 (RTM-CU13) (KB4466404) - 14.0.3048.4 (X64) 30 Kasım 2018 12:57:58 Telif Hakkı (C) 2017 Windows Server 2016 Standard 10.0'da (Derleme 14393) Microsoft Corporation Enterprise Edition (64 bit) :)