অনন্য-অনন্য সূচীতে সদৃশ কী সারিটি ?োকানো যাবে না?


14

8 সপ্তাহের জন্য ত্রুটিমুক্ত থাকার পরে আমরা গত কয়েক দিন ধরে এই অদ্ভুত ত্রুটির মুখোমুখি হয়েছি এবং আমি স্ট্যাম্পড আছি।

এটি ত্রুটি বার্তা:

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).".

আমাদের সূচকটি অনন্য নয় । যদি আপনি খেয়াল করেন, ত্রুটি বার্তায় সদৃশ কী মানটিও সূচকের সাথে আপ হয় না। আশ্চর্যের বিষয় হ'ল আমি যদি প্রোকে পুনরায় চালু করি তবে এটি সফল হয়।

এটি আমার সাম্প্রতিক লিঙ্কটি হ'ল এটিতে আমার সমস্যা রয়েছে তবে আমি এর সমাধান দেখতে পাচ্ছি না।

https://www.sqlservercentral.com/forums/topic/error-cannot-insert-duplicate-key-row-in-a-non-unique-index

আমার পরিস্থিতি সম্পর্কে কয়েকটি বিষয়:

  • প্রকল্পটি ট্রানজেকশনআইডি আপডেট করছে (প্রাথমিক কীটির অংশ) - আমি মনে করি এটিই ত্রুটি সৃষ্টি করছে তবে কেন জানি না? আমরা সেই যুক্তি সরিয়ে ফেলব।
  • পরিবর্তন ট্র্যাকিং টেবিল সক্ষম করা হয়েছে
  • লেনদেন করণবিহীন পড়ুন

প্রতিটি টেবিলের জন্য 45 টি ক্ষেত্র রয়েছে, আমি মূলত সূচকগুলিতে ব্যবহৃত তালিকাভুক্ত। আমি আপডেট স্টেটমেন্টে (অযথা) লেনদেনের আইডি (ক্লাস্টার কী) আপডেট করছি। আশ্চর্যের বিষয় যে গত সপ্তাহ পর্যন্ত আমাদের কয়েক মাস ধরে কোনও সমস্যা হয়নি। এবং এটি কেবল এসএসআইএসের মাধ্যমে বিক্ষিপ্তভাবে ঘটছে।

টেবিল

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

অস্থায়ী টেবিল

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

প্রাথমিক কী

 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]

নন-ক্লাস্টারড ইনডেক্স

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)

নমুনা আপডেট বিবৃতি

-- 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)

আমার প্রশ্ন, হুডের নীচে কী চলছে? আর এর সমাধান কী? রেফারেন্সের জন্য উপরের লিঙ্কটিতে এটি উল্লেখ করা হয়েছে:

এই মুহুর্তে, আমার কয়েকটি তত্ত্ব রয়েছে:

  • স্মৃতিচাপ চাপ বা বৃহত সমান্তরাল আপডেট পরিকল্পনার সাথে সম্পর্কিত বাগ, তবে আমি অন্য ধরণের ত্রুটি আশা করব এবং এখন পর্যন্ত আমি স্বল্প সংস্থানগুলির সাথে সম্পর্কিত করতে পারি না এই বিচ্ছিন্ন এবং বিক্ষিপ্ত ত্রুটির সময়সীমার জন্য।
  • আপডেটের স্টেটমেন্ট বা ডেটাতে থাকা বাগটি প্রাথমিক কীতে প্রকৃত নকল লঙ্ঘন ঘটাচ্ছে, তবে কিছু অস্পষ্ট এসকিউএল সার্ভার বাগের ফলে ত্রুটি বার্তা তৈরি হচ্ছে যা ভুল সূচকের নাম উল্লেখ করেছে ites
  • ডার্টি রিডগুলি অনাবৃত পড়া বিচ্ছিন্নতার ফলে ডাবল সন্নিবিষ্ট করার জন্য একটি বৃহত সমান্তরাল আপডেটের কারণ। তবে ইটিএল বিকাশকারীরা দাবি করেন যে ডিফল্ট পড়ার জন্য প্রতিশ্রুতিবদ্ধ ব্যবহার করা হয়েছে, এবং প্রক্রিয়াটি রানটাইমটিতে আসলে কী বিচ্ছিন্নতা স্তরের ব্যবহৃত হয় তা নির্ধারণ করা শক্ত।

আমি সন্দেহ করি যে যদি আমি স্প্লুল অপারেশন নিষ্ক্রিয় করতে ম্যাক্সডপ (1) ইঙ্গিতটি বা সেশন ট্রেস পতাকা ব্যবহার করে কার্যকর প্রয়োগের পরিকল্পনাটি টুইঙ্ক করি তবে ত্রুটিটি কেবল চলে যাবে, তবে এটি স্পষ্ট নয় যে এটি কার্য সম্পাদনকে কীভাবে প্রভাবিত করবে it's

সংস্করণ

মাইক্রোসফ্ট এসকিউএল সার্ভার 2017 (আরটিএম-সিইউ 13) (KB4466404) - 14.0.3048.4 (এক্স 64) নভেম্বর 30 2018 12:57:58 কপিরাইট (সি) 2017 মাইক্রোসফ্ট কর্পোরেশন এন্টারপ্রাইজ সংস্করণ (64-বিট) উইন্ডোজ সার্ভার 2016 স্ট্যান্ডার্ড 10.0 (বিল্ড 14393) এ :)

উত্তর:


10

আমার প্রশ্ন, হুডের নীচে কী চলছে? আর এর সমাধান কী?

এটি একটি বাগ। সমস্যাটি হ'ল এটি কেবল মাঝেমধ্যে ঘটে এবং পুনরুত্পাদন করা শক্ত। তবুও, আপনার সর্বোত্তম সুযোগ হ'ল মাইক্রোসফ্ট সমর্থন জড়িত করা। আপডেট প্রক্রিয়াকরণ মন-বাঁকানো জটিল, সুতরাং এটির জন্য খুব বিশদ তদন্তের প্রয়োজন হবে।

জড়িত জটিলতার উদাহরণের জন্য, আমার পোস্টগুলিতে একবার দেখে নিন ফিল্টার সূচকগুলির সাথে মার্জ বাগ এবং সূচক দর্শন সহ ভুল ফলাফল । এগুলির কেউই আপনার ইস্যুতে সরাসরি সম্পর্কিত নয়, তবে তারা স্বাদ দেয়।

একটি নির্ধারিত আপডেট লিখুন

এটি অবশ্যই জেনেরিক। সম্ভবত আরও কার্যকরভাবে, আমি বলতে পারি যে আপনার বর্তমান UPDATEবিবৃতিটি পুনর্লিখনের দিকে নজর দেওয়া উচিত । ডকুমেন্টেশন যেমন বলে:

আপডেট ক্রিয়াকলাপের জন্য মানদণ্ড সরবরাহ করতে FROM ধারাটি নির্দিষ্ট করার সময় সাবধানতা অবলম্বন করুন। কোনও আপডেটের বিবৃতিটির ফলাফল অপরিজ্ঞাত করা হয় যদি বিবৃতিতে এমন কোনও FROM ধারা অন্তর্ভুক্ত থাকে যা আপডেট করা হয় এমন প্রতিটি কলামের উপস্থিতির জন্য কেবল একটি মান পাওয়া যায়, তা হল যদি আপডেট আপডেটটি বিবরণী না হয়।

আপনার UPDATEনির্বিচারবাদী নয় এবং ফলাফলগুলি তাই অপরিজ্ঞাত । আপনার এটিকে পরিবর্তন করা উচিত যাতে প্রতিটি লক্ষ্য সারিটির জন্য সর্বাধিক একটি উত্স সারি চিহ্নিত করা যায়। এই পরিবর্তন ব্যতীত আপডেটের ফলাফলটি কোনও স্বতন্ত্র উত্স সারিটি প্রতিফলিত করতে পারে না ।

উদাহরণ

আমি আপনাকে একটি উদাহরণ দেখাব, প্রশ্নগুলিতে দেওয়া বিষয়গুলির জন্য টেবিলগুলি আলগাভাবে মডেলিং করে:

CREATE TABLE dbo.Transactions
(
    TransactionID bigint NOT NULL,
    ClientID integer NOT NULL,
    TransactionDate datetime2(2) NOT NULL,

    CONSTRAINT PK_dbo_Transactions
        PRIMARY KEY CLUSTERED (TransactionID),

    INDEX dbo_Transactions_ClientID_TranDate
        (ClientID, TransactionDate)
);

CREATE TABLE #Working
(
    TransactionID bigint NULL,
    ClientID integer NULL,
    TransactionDate datetime2(2) NULL,

    INDEX cx CLUSTERED (TransactionID)
);

জিনিসগুলি সহজ রাখতে, লক্ষ্য সারণীতে একটি সারি এবং উত্সটিতে চারটি সারি রাখুন:

INSERT dbo.Transactions 
    (TransactionID, ClientID, TransactionDate)
VALUES 
    (1, 1, '2019-01-01');

INSERT #Working 
    (TransactionID, ClientID, TransactionDate)
VALUES 
    (1, 2, NULL),
    (1, NULL, '2019-03-03'),
    (1, 3, NULL),
    (1, NULL, '2019-02-02');

চারটি উত্স সারি লক্ষ্যবস্তুটির সাথে মেলে TransactionID, সুতরাং আমরা যদি কোনও আপডেট (প্রশ্নটির মতো) চালিত করি তবে কোনটি ব্যবহার করা হবে যা TransactionIDএকা যোগ দেয় ?

UPDATE T
SET T.TransactionID = W.TransactionID,
    T.ClientID = W.ClientID,
    T.TransactionDate = W.TransactionDate
FROM #Working AS W
JOIN dbo.Transactions AS T
    ON T.TransactionID = W.TransactionID;

( TransactionIDকলামটি আপডেট করা ডেমোটির জন্য গুরুত্বপূর্ণ নয়, আপনি যদি এটি চান তবে এটি মন্তব্য করতে পারেন))

প্রথম আশ্চর্যটি হ'ল UPDATEকোনও ত্রুটি ছাড়াই সম্পূর্ণ হয়, লক্ষ্য সারণি কোনও কলামে নাল না দেয় (সমস্ত প্রার্থীর সারিতে একটি নাল থাকে)।

গুরুত্বপূর্ণ বিষয়টি হল ফলাফলটি অপরিজ্ঞাত , এবং এক্ষেত্রে এমন ফলাফল তৈরি হয় যা উত্স সারিগুলির সাথে কোনওটির সাথে মেলে না:

SELECT
    T.TransactionID,
    T.ClientID,
    T.TransactionDate
FROM dbo.Transactions AS T;
╔═══════════════╦══════════╦════════════════════════╗
║ TransactionID ║ ClientID ║    TransactionDate     ║
╠═══════════════╬══════════╬════════════════════════╣
║             1 ║        2 ║ 2019-03-03 00:00:00.00 ║
╚═══════════════╩══════════╩════════════════════════╝

ডিবি <> ফিডাল ডেমো

আরও বিশদ: যে কোনও সমষ্টি ভাঙ্গা

আপডেটটি এমনভাবে লেখা উচিত যাতে সমতুল্য MERGEবিবৃতি হিসাবে লিখিত হয় তবে এটি সফল হবে , যা একই লক্ষ্য সারিটি একাধিকবার আপডেট করার প্রচেষ্টা চেক করে না। আমি সাধারণত MERGEসরাসরি ব্যবহারের পরামর্শ দিই না , কারণ এটি অনেকগুলি বাস্তবায়ন বাগের সাথে সাবলীল হয়েছে এবং সাধারণত খারাপ কর্মক্ষমতা থাকে।

বোনাস হিসাবে, আপনি আবিষ্কার করতে পারেন যে আপনার বর্তমান আপডেটটিকে পুনরায় লেখার জন্য ডিস্টিস্টোনমিক হিসাবে পুনরায় লেখার ফলে আপনার মাঝে মাঝে বাগ সমস্যাটিও চলে যাবে। অবশ্যই পণ্যটির বাগটি এমন লোকদের জন্য উপস্থিত থাকবে যারা অবশ্যই অ-নির্ধারিত আপডেটগুলি লেখেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.