MySQL शब्दावली से:

प्रेत: एक पंक्ति जो किसी क्वेरी के परिणाम सेट में दिखाई देती है, लेकिन पिछली क्वेरी के परिणाम सेट में नहीं। उदाहरण के लिए, यदि किसी लेन-देन में कोई क्वेरी दो बार चलाई जाती है, और इस बीच, एक नई पंक्ति डालने या पंक्ति को अपडेट करने के बाद दूसरा लेन-देन होता है ताकि यह क्वेरी के WHERE क्लॉज से मेल खाए

क्या बोल्ड किया गया हिस्सा सही है? अगर मैं

CREATE TABLE  t1 (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `c1` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

और आइसोलेशन लेवल रिपीटेबल रीड है और मैं करता हूं

mysql> start transaction;
mysql> SELECT * FROM t1 WHERE c1 < 10;
+----+------+
| id | c1   |
+----+------+
|  1 | 4    |
+----+------+
mysql> SELECT * FROM t1 WHERE c1 < 10;
+----+------+
| id | c1   |
+----+------+
|  1 | 4    |
+----+------+

मैं कभी-कभी बाद की क्वेरी से अलग परिणाम प्राप्त कर सकता था, भले ही कोई भी INSERTs नहीं बल्कि केवल अद्यतन करता हो? मेरा MySQL संस्करण 5.7 है।

SQL मानक इंगित करता है कि फैंटम रीड्स केवल समवर्ती INSERTs से संबंधित हैं, हालांकि जेनरेट शब्द थोड़ा भ्रमित करने वाला है। ISO/IEC 9075:1992 से, डेटाबेस भाषा SQL- 30 जुलाई 1992 (दूसरा अनौपचारिक समीक्षा ड्राफ्ट):

P3 ("फैंटम"): SQL-लेन-देन T1 पंक्तियों के सेट को पढ़ता है N जो कुछ खोज शर्तों को पूरा करता है। SQL-लेन-देन T2 तब SQL-कथन निष्पादित करता है जो SQL-लेन-देन T1 द्वारा उपयोग की जाने वाली खोज शर्त को पूरा करने वाली एक या अधिक पंक्तियों को उत्पन्न करता है। यदि SQL-लेन-देन T1 फिर उसी खोज स्थिति के साथ प्रारंभिक रीड को दोहराता है, तो उसे पंक्तियों का एक अलग संग्रह प्राप्त होता है।

1
Croco 20 जिंदा 2019, 16:26

1 उत्तर

सबसे बढ़िया उत्तर

InnoDB दोहराने योग्य-पढ़ें लेनदेन अलगाव स्तर प्रेत पंक्तियों को रोकता है, लेकिन केवल तभी जब आपकी चयन क्वेरी एक गैर-लॉकिंग क्वेरी है।

इस प्रकार आप लेन-देन के दौरान एक ही क्वेरी शर्तों के साथ कई बार चयन कर सकते हैं, और आपको समय-समय पर एक ही परिणाम प्राप्त करने की गारंटी दी जाती है, भले ही अन्य सत्र आपके परिणाम सेट को प्रभावित करने वाले तरीकों से पंक्तियों को सम्मिलित, अपडेट या हटा रहे हों। जैसे ही आप एक नया लेन-देन शुरू करते हैं, आपकी क्वेरी में इस बीच चल रही पंक्तियों में परिवर्तन दिखाई देंगे।

लेकिन InnoDB का एक अजीब मामला है: यदि आप एक लॉकिंग चलाते हैं क्वेरी पढ़ें निम्न में से किसी एक की तरह:

SELECT * FROM t1 WHERE c1 < 10 FOR UPDATE

SELECT * FROM t1 WHERE c1 < 10 LOCK IN SHARE MODE

SELECT * FROM t1 WHERE c1 < 10 FOR SHARE -- MySQL 8.0 syntax

फिर एक चयन डेटा में समवर्ती परिवर्तनों के परिणामों को "देखेगा", जैसे कि आपका लेनदेन एक रीड-कमिटेड लेनदेन के रूप में शुरू किया गया था।

आप एक ही रिपीटेबल-रीड ट्रांजैक्शन में लॉकिंग रीड क्वेश्चन और नॉन-लॉकिंग रीड क्वेश्चन के बीच भी आगे और पीछे स्विच कर सकते हैं, और आप प्रत्येक के लिए अलग-अलग परिणाम सेट देखेंगे। इसलिए अगर आप लॉकिंग सेलेक्ट स्टेटमेंट का इस्तेमाल करते हैं तो इस बात का ध्यान रखें।

मुझे लगता है कि आपके द्वारा दिखाए गए अंश में "जेनरेट" शब्द या तो INSERT या UPDATE पर लागू होने के लिए है। उन्हें दोनों मामलों के लिए आवेदन करने के लिए एक शब्द की आवश्यकता थी, क्योंकि मुझे लगता है कि उन्हें "इन्सर्ट या अपडेट" जैसा अधिक स्पष्ट वाक्यांश लिखने का मन नहीं था।

1
Bill Karwin 20 जिंदा 2019, 19:14