Database
 sql >> डेटाबेस >  >> RDS >> Database

समवर्ती लेनदेन में खोया अद्यतन समस्या

गुम अद्यतन समस्या तब होती है जब 2 समवर्ती लेनदेन समान डेटा को पढ़ने और अद्यतन करने का प्रयास करते हैं। इसे एक उदाहरण की मदद से समझते हैं।

मान लीजिए कि हमारे पास "उत्पाद" नाम की एक तालिका है जो किसी उत्पाद के लिए आईडी, नाम और आइटम्सइनस्टॉक को संग्रहीत करती है।

इसका उपयोग एक ऑनलाइन सिस्टम के हिस्से के रूप में किया जाता है जो किसी विशेष उत्पाद के लिए स्टॉक में वस्तुओं की संख्या प्रदर्शित करता है और इसलिए हर बार उस उत्पाद की बिक्री होने पर इसे अपडेट करने की आवश्यकता होती है।

तालिका इस तरह दिखती है:

Id

नाम

आइटम्सइनस्टॉक

1

लैपटॉप

12

अब एक परिदृश्य पर विचार करें जहां एक उपयोगकर्ता आता है और लैपटॉप खरीदने की प्रक्रिया शुरू करता है। यह एक लेनदेन शुरू करेगा। आइए इस लेन-देन को लेन-देन 1 कहते हैं।

उसी समय एक अन्य उपयोगकर्ता सिस्टम में लॉग इन करता है और लेनदेन शुरू करता है, आइए इस लेनदेन को कॉल करें 2. निम्नलिखित आंकड़े पर एक नज़र डालें।

लेन-देन 1 लैपटॉप के लिए स्टॉक में आइटम पढ़ता है जो 12 है। थोड़ी देर बाद लेनदेन 2 लैपटॉप के लिए आइटम्सइनस्टॉक के लिए मूल्य पढ़ता है जो इस समय अभी भी 12 होगा। लेन-देन 2 फिर तीन लैपटॉप बेचता है, लेन-देन से कुछ समय पहले 1 2 आइटम बेचता है।

लेन-देन 2 तब पहले अपना निष्पादन पूरा करेगा और ItemsinStock को 9 में अपडेट करेगा क्योंकि इसने 12 में से तीन लैपटॉप बेचे हैं। लेनदेन 1 खुद को प्रतिबद्ध करता है। चूंकि लेन-देन 1 ने दो आइटम बेचे हैं, यह आइटम्सइनस्टॉक को 10 में अपडेट करता है।

यह गलत है, सही आंकड़ा है 12-3-2 =7

खोई हुई अद्यतन समस्या का कार्य उदाहरण

आइए SQL सर्वर में कार्रवाई में खोई हुई अद्यतन समस्या पर एक नज़र डालें। हमेशा की तरह, सबसे पहले, हम एक टेबल बनाएंगे और उसमें कुछ डमी डेटा जोड़ेंगे।

हमेशा की तरह, सुनिश्चित करें कि नए कोड के साथ खेलने से पहले आपका ठीक से बैकअप लिया गया है। यदि आप निश्चित नहीं हैं, तो SQL सर्वर बैकअप पर यह लेख देखें।

अपने डेटाबेस सर्वर पर निम्न स्क्रिप्ट निष्पादित करें।

<span style="font-size: 14px;">CREATE DATABASE pos;

USE pos;

CREATE TABLE products
(
	Id INT PRIMARY KEY,
	Name VARCHAR(50) NOT NULL,
	ItemsinStock INT NOT NULL

)

INSERT into products

VALUES 
(1, 'Laptop', 12),
(2, 'Iphon', 15),
(3, 'Tablets', 10)</span>

अब, दो SQL सर्वर प्रबंधन स्टूडियो इंस्टेंस को साथ-साथ खोलें। हम इनमें से प्रत्येक उदाहरण में एक लेन-देन चलाएंगे।

SSMS के पहले उदाहरण में निम्न स्क्रिप्ट जोड़ें।

<span style="font-size: 14px;">USE pos;

-- Transaction 1

BEGIN TRAN

DECLARE @ItemsInStock INT

SELECT @ItemsInStock = ItemsInStock
FROM products WHERE Id = 1

WaitFor Delay '00:00:12'
SET @ItemsInStock = @ItemsInStock - 2

UPDATE products SET ItemsinStock = @ItemsInStock
WHERE Id = 1

Print @ItemsInStock
Commit Transaction</span>

यह लेन-देन की स्क्रिप्ट है। यहां हम लेन-देन शुरू करते हैं और एक पूर्णांक प्रकार चर "@ItemsInStock" घोषित करते हैं। इस चर का मान उत्पाद तालिका से Id 1 वाले रिकॉर्ड के लिए ItemsinStock स्तंभ के मान पर सेट है। फिर 12 सेकंड की देरी जोड़ी जाती है ताकि लेनदेन 2 लेनदेन से पहले अपना निष्पादन पूरा कर सके। देरी के बाद, @ItemsInStock चर का मान 2 उत्पादों की बिक्री को दर्शाता है।

अंत में, Id 1 वाले रिकॉर्ड के लिए ItemsinStock कॉलम का मान @ItemsInStock वैरिएबल के मान के साथ अपडेट किया जाता है। फिर हम स्क्रीन पर @ItemsInStock वैरिएबल की वैल्यू प्रिंट करते हैं और ट्रांजैक्शन करते हैं।

SSMS के दूसरे उदाहरण में, हम लेन-देन 2 के लिए स्क्रिप्ट जोड़ते हैं जो इस प्रकार है:

<span style="font-size: 14px;">USE pos;

-- Transaction 2

BEGIN TRAN

DECLARE @ItemsInStock INT

SELECT @ItemsInStock = ItemsInStock
FROM products WHERE Id = 1

WaitFor Delay '00:00:3'
SET @ItemsInStock = @ItemsInStock - 3

UPDATE products SET ItemsinStock = @ItemsInStock
WHERE Id = 1

Print @ItemsInStock
Commit Transaction</span>

लेन-देन 2 की स्क्रिप्ट लेन-देन 1 के समान है। हालाँकि, यहाँ लेन-देन 2 में, देरी केवल तीन सेकंड के लिए है और @ItemsInStock चर के लिए मूल्य में कमी तीन है, क्योंकि यह तीन वस्तुओं की बिक्री है।

अब, लेन-देन 1 चलाएँ और फिर लेन-देन 2। आप देखेंगे कि लेन-देन 2 पहले अपना निष्पादन पूरा कर रहा है। और @ItemsInStock चर के लिए मुद्रित मूल्य 9 होगा। कुछ समय बाद लेन-देन 1 भी अपना निष्पादन पूरा कर लेगा और इसके @ItemsInStock चर के लिए मुद्रित मूल्य 10 होगा।

ये दोनों मान गलत हैं, Id 1 वाले उत्पाद के लिए ItemsInStock कॉलम का वास्तविक मान 7 होना चाहिए।

नोट:

यहां यह ध्यान रखना महत्वपूर्ण है कि खोई हुई अद्यतन समस्या केवल पढ़ने के लिए प्रतिबद्ध और बिना पढ़े हुए लेनदेन अलगाव स्तरों के साथ होती है। अन्य सभी लेन-देन अलगाव स्तरों के साथ, यह समस्या उत्पन्न नहीं होती है।

दोहराए जाने योग्य लेन-देन अलगाव स्तर पढ़ें

आइए दोनों लेन-देन को दोहराने योग्य पढ़ने के लिए अलगाव स्तर को अपडेट करें और देखें कि क्या खोई हुई अद्यतन समस्या होती है। लेकिन इससे पहले, ItemsInStock के मान को वापस 12 पर अपडेट करने के लिए निम्न कथन निष्पादित करें।

Update products SET ItemsinStock = 12

लेन-देन 1 के लिए स्क्रिप्ट

<span style="font-size: 14px;">USE pos;

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
-- Transaction 1

BEGIN TRAN
DECLARE @ItemsInStock INT

SELECT @ItemsInStock = ItemsInStock
FROM products WHERE Id = 1

WaitFor Delay '00:00:12'
SET @ItemsInStock = @ItemsInStock - 2

UPDATE products SET ItemsinStock = @ItemsInStock
WHERE Id = 1

Print @ItemsInStock
Commit Transaction</span>

लेनदेन 2 के लिए स्क्रिप्ट

<span style="font-size: 14px;">USE pos;

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
-- Transaction 2

BEGIN TRAN
DECLARE @ItemsInStock INT

SELECT @ItemsInStock = ItemsInStock
FROM products WHERE Id = 1

WaitFor Delay '00:00:3'
SET @ItemsInStock = @ItemsInStock - 3

UPDATE products SET ItemsinStock = @ItemsInStock
WHERE Id = 1

Print @ItemsInStock
Commit Transaction</span>

यहां दोनों लेनदेन में, हमने अलगाव स्तर को दोहराने योग्य पढ़ने के लिए सेट किया है।

अब लेनदेन 1 चलाएं और फिर तुरंत लेनदेन 2 चलाएं। पिछले मामले के विपरीत, लेनदेन 2 को लेनदेन 1 के लिए खुद को प्रतिबद्ध करने के लिए इंतजार करना होगा। उसके बाद लेन-देन 2 के लिए निम्न त्रुटि होती है:

संदेश 1205, स्तर 13, राज्य 51, रेखा 15

लेन-देन (प्रक्रिया आईडी 55) एक अन्य प्रक्रिया के साथ लॉक संसाधनों पर गतिरोध था और इसे गतिरोध पीड़ित के रूप में चुना गया है। लेन-देन फिर से चलाएँ।

यह त्रुटि इसलिए होती है क्योंकि रिपीटेबल रीड उस संसाधन को लॉक कर देता है जिसे लेन-देन 1 द्वारा पढ़ा या अपडेट किया जा रहा है और यह दूसरे लेनदेन पर एक गतिरोध बनाता है जो उसी संसाधन तक पहुंचने का प्रयास करता है।

त्रुटि कहती है कि लेन-देन 2 में किसी अन्य प्रक्रिया के साथ संसाधन पर गतिरोध है और यह लेनदेन गतिरोध द्वारा अवरुद्ध कर दिया गया है। इसका मतलब यह है कि अन्य लेन-देन को संसाधन तक पहुंच प्रदान की गई थी, जबकि इस लेनदेन को अवरुद्ध कर दिया गया था और संसाधन तक पहुंच नहीं दी गई थी।

यह लेन-देन को फिर से चलाने के लिए भी कहता है क्योंकि संसाधन अब मुफ़्त है। अब, यदि आप लेन-देन 2 को फिर से चलाते हैं, तो आपको स्टॉक में वस्तुओं का सही मूल्य दिखाई देगा यानी 7. ऐसा इसलिए है क्योंकि लेन-देन 1 ने पहले ही IteminStock के मूल्य को 2 से घटा दिया था, लेन-देन 2 ने इसे 3 से और घटा दिया, इसलिए 12 - (2+) 3) =7.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. AWS समिट्स 2018:शिकागो रिकैप

  2. विभिन्न त्रुटि प्रबंधन तकनीकों का प्रदर्शन प्रभाव

  3. प्रत्येक ग्रुप बाय ग्रुप में पहली पंक्ति का चयन कैसे करें

  4. SQL FLOAT:3 बिंदु जो आपको अजीब गणित त्रुटियों से बचने में मदद करेंगे

  5. डेटा कैटलॉग, व्यावसायिक शब्दावलियों और डेटा शासन के माध्यम से ग्राहक व्यवसाय इंटेलिजेंस सक्षम करें