1. क्या ट्रिगर रिलेशनल डेटाबेस के ACID सिद्धांत का अनुसरण करता है? वहाँ एक मौका है एक डालने के लिए प्रतिबद्ध हो सकता है, लेकिन ट्रिगर विफल?
यह प्रश्न आंशिक रूप से संबंधित प्रश्न में उत्तर दिया गया है जिससे आप जुड़े हुए हैं। ट्रिगर कोड को उसी ट्रांजेक्शनल संदर्भ में डीएमएल स्टेटमेंट के रूप में क्रियान्वित किया जाता है, जो आपके द्वारा उल्लिखित ACID सिद्धांतों के परमाणु भाग को संरक्षित करते हुए आग के कारण होता है । ट्रिगर स्टेटमेंट और ट्रिगर कोड एक इकाई के रूप में सफल या विफल दोनों होते हैं।
एसिड गुण भी पूरे लेन-देन (ट्रिगर कोड सहित) की गारंटी एक राज्य है कि उल्लंघन नहीं करता है किसी भी स्पष्ट की कमी (में डेटाबेस छोड़ देंगे अनुरूप ) और किसी भी वसूली योग्य प्रतिबद्ध प्रभाव एक डेटाबेस दुर्घटना (बच जाएगा टिकाऊ )।
जब तक आस-पास (शायद निहित या ऑटो-कमिट) लेन-देन SERIALIZABLE
अलगाव स्तर पर नहीं चल रहा है , तब तक पृथक संपत्ति की स्वचालित रूप से गारंटी नहीं होती है। अन्य समवर्ती डेटाबेस गतिविधि आपके ट्रिगर कोड के सही संचालन में हस्तक्षेप कर सकती है। उदाहरण के लिए, खाते की शेष राशि आपके द्वारा इसे पढ़ने के बाद और इसे अपडेट करने से पहले एक अन्य सत्र द्वारा बदला जा सकता है - एक क्लासिक दौड़ की स्थिति।
2. मेरे विचार और अद्यतन कथन अजीब लगते हैं। क्या सही [खाता] पंक्ति को अपडेट करने का कोई बेहतर तरीका है?
बहुत अच्छे कारण हैं जो आपके द्वारा जुड़े अन्य प्रश्न किसी भी ट्रिगर-आधारित समाधान की पेशकश नहीं करते हैं। एक विकृत संरचना को संतुलित रखने के लिए डिज़ाइन किया गया ट्रिगर कोड सही पाने और ठीक से परीक्षण करने के लिए बेहद मुश्किल हो सकता है। यहां तक कि बहुत उन्नत SQL सर्वर लोगों को इसके साथ कई वर्षों के अनुभव संघर्ष के साथ।
सभी परिदृश्यों में शुद्धता बनाए रखने और गतिरोध जैसी समस्याओं से बचने के लिए एक ही समय में अच्छा प्रदर्शन बनाए रखना कठिनाई के अतिरिक्त आयाम जोड़ता है। आपका ट्रिगर कोड कहीं भी मजबूत नहीं है, और हर खाते के शेष को अद्यतन करता है, भले ही केवल एक ही लेन-देन संशोधित हो। ट्रिगर-आधारित समाधान के साथ सभी प्रकार के जोखिम और चुनौतियां हैं, जो इस प्रौद्योगिकी क्षेत्र में अपेक्षाकृत नए किसी व्यक्ति के लिए कार्य को गहराई से अनुपयुक्त बना देता है।
कुछ समस्याओं का वर्णन करने के लिए, मैं नीचे कुछ नमूना कोड दिखाता हूं। यह एक कठोर-परीक्षणित समाधान नहीं है (ट्रिगर कठिन हैं!) और मैं आपको यह सुझाव नहीं दे रहा हूं कि आप इसे सीखने की कवायद के अलावा किसी अन्य चीज के रूप में उपयोग करें। एक वास्तविक प्रणाली के लिए, गैर-ट्रिगर समाधान के महत्वपूर्ण लाभ हैं, इसलिए आपको अन्य प्रश्न के उत्तर की सावधानीपूर्वक समीक्षा करनी चाहिए , और ट्रिगर विचार से पूरी तरह से बचना चाहिए।
नमूना तालिकाओं
CREATE TABLE dbo.Accounts
(
AccountID integer NOT NULL,
Balance money NOT NULL,
CONSTRAINT PK_Accounts_ID
PRIMARY KEY CLUSTERED (AccountID)
);
CREATE TABLE dbo.Transactions
(
TransactionID integer IDENTITY NOT NULL,
AccountID integer NOT NULL,
Amount money NOT NULL,
CONSTRAINT PK_Transactions_ID
PRIMARY KEY CLUSTERED (TransactionID),
CONSTRAINT FK_Accounts
FOREIGN KEY (AccountID)
REFERENCES dbo.Accounts (AccountID)
);
रोकथाम TRUNCATE TABLE
ट्रिगर से फायर नहीं किया जाता है TRUNCATE TABLE
। निम्न खाली तालिका विशुद्ध रूप से Transactions
तालिका को छंटनी से बचाने के लिए मौजूद है (एक विदेशी कुंजी द्वारा संदर्भित होने से तालिका छंटनी को रोकता है):
CREATE TABLE dbo.PreventTransactionsTruncation
(
Dummy integer NULL,
CONSTRAINT FK_Transactions
FOREIGN KEY (Dummy)
REFERENCES dbo.Transactions (TransactionID),
CONSTRAINT CHK_NoRows
CHECK (Dummy IS NULL AND Dummy IS NOT NULL)
);
ट्रिगर परिभाषा
निम्न ट्रिगर कोड सुनिश्चित करता है कि केवल आवश्यक खाता प्रविष्टियाँ ही बनी हुई हैं, और SERIALIZABLE
वहां शब्दार्थ का उपयोग किया जाता है। एक वांछनीय साइड-इफेक्ट के रूप में, यह गलत परिणामों से भी बचता है जो एक पंक्ति-संस्करण अलगाव स्तर का उपयोग होने पर परिणाम हो सकता है। कोड भी ट्रिगर कोड को निष्पादित करने से बचता है यदि स्रोत विवरण से कोई पंक्तियां प्रभावित नहीं हुई थीं। अस्थायी तालिका और RECOMPILE
संकेत का उपयोग गलत तरीके से किए गए कार्डिनैलिटी अनुमानों के कारण होने वाली निष्पादन योजना की समस्याओं से बचने के लिए किया जाता है:
CREATE TRIGGER dbo.TransactionChange ON dbo.Transactions
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
IF @@ROWCOUNT = 0 OR
TRIGGER_NESTLEVEL
(
OBJECT_ID(N'dbo.TransactionChange', N'TR'),
'AFTER',
'DML'
) > 1
RETURN;
SET NOCOUNT, XACT_ABORT ON;
CREATE TABLE #Delta
(
AccountID integer PRIMARY KEY,
Amount money NOT NULL
);
INSERT #Delta
(AccountID, Amount)
SELECT
InsDel.AccountID,
Amount = SUM(InsDel.Amount)
FROM
(
SELECT AccountID, Amount
FROM Inserted
UNION ALL
SELECT AccountID, $0 - Amount
FROM Deleted
) AS InsDel
GROUP BY
InsDel.AccountID;
UPDATE A
SET Balance += D.Amount
FROM #Delta AS D
JOIN dbo.Accounts AS A WITH (SERIALIZABLE)
ON A.AccountID = D.AccountID
OPTION (RECOMPILE);
END;
परिक्षण
निम्न कोड शून्य बैलेंस के साथ 100,000 खाते बनाने के लिए संख्याओं की तालिका का उपयोग करता है :
INSERT dbo.Accounts
(AccountID, Balance)
SELECT
N.n, $0
FROM dbo.Numbers AS N
WHERE
N.n BETWEEN 1 AND 100000;
नीचे दिए गए परीक्षण कोड में 10,000 यादृच्छिक लेनदेन सम्मिलित हैं:
INSERT dbo.Transactions
(AccountID, Amount)
SELECT
CONVERT(integer, RAND(CHECKSUM(NEWID())) * 100000 + 1),
CONVERT(money, RAND(CHECKSUM(NEWID())) * 500 - 250)
FROM dbo.Numbers AS N
WHERE
N.n BETWEEN 1 AND 10000;
SQLQueryStress टूल का उपयोग करते हुए , मैंने अच्छे प्रदर्शन, कोई गतिरोध और सही परिणामों के साथ 32 थ्रेड्स पर यह परीक्षण 100 बार चलाया। मैं अभी भी इसे सीखने की कवायद के अलावा किसी और चीज की सलाह नहीं देता।