आप एक बड़ी क्वेरी में सब कुछ समाहित नहीं करना चाहते हैं, क्योंकि यह वास्तव में कुछ भी हल नहीं करेगा, इससे इसकी संभावना कम हो जाती है।
आपको जो चाहिए वह है पंक्तियों पर ताले, या अनुक्रमणिका पर ताले जहाँ नई पंक्ति डाली जाएगी।
तो हम अनन्य ताले कैसे प्राप्त करते हैं?
दो कनेक्शन, mysql1 और mysql2, उनमें से प्रत्येक SELECT ... FOR UPDATE
का उपयोग करके एक विशेष लॉक का अनुरोध करते हैं . तालिका 'इतिहास' में एक कॉलम 'user_id' है जिसे अनुक्रमित किया गया है। (यह भी एक विदेशी कुंजी है।) कोई पंक्तियाँ नहीं मिली हैं, इसलिए वे दोनों सामान्य रूप से आगे बढ़ते हुए प्रतीत होते हैं जैसे कि कुछ भी असामान्य नहीं होने वाला है। user_id 2808 मान्य है लेकिन इतिहास में कुछ भी नहीं है।
mysql1> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql2> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql1> select * from history where user_id = 2808 for update;
Empty set (0.00 sec)
mysql2> select * from history where user_id = 2808 for update;
Empty set (0.00 sec)
mysql1> insert into history(user_id) values (2808);
... और मुझे मेरा संकेत वापस नहीं मिला ... कोई प्रतिक्रिया नहीं ... क्योंकि दूसरे सत्र में भी ताला है ... लेकिन फिर:
mysql2> insert into history(user_id) values (2808);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
फिर mysql1 तुरंत डालने पर सफलता लौटाता है।
Query OK, 1 row affected (3.96 sec)
जो कुछ बचा है वह mysql1 से COMMIT
के लिए है और जादुई रूप से, हमने 0 प्रविष्टियों वाले उपयोगकर्ता को 1 से अधिक प्रविष्टि डालने से रोका। गतिरोध इसलिए हुआ क्योंकि दोनों सत्रों को होने के लिए असंगत चीजों की आवश्यकता थी:mysql1 को इसके लॉक को रिलीज़ करने से पहले mysql2 की आवश्यकता थी, इससे पहले कि यह प्रतिबद्ध हो सके और mysql2 को इसके लॉक को सम्मिलित करने में सक्षम होने से पहले mysql1 की आवश्यकता थी। किसी को उस लड़ाई को हारना है, और आम तौर पर जिस धागे ने सबसे कम काम किया है वह हारने वाला है।
लेकिन क्या होगा यदि SELECT ... FOR UPDATE
. करते समय 1 या अधिक पंक्तियाँ पहले से मौजूद थीं? ? उस स्थिति में, लॉक पंक्तियों पर होता, इसलिए दूसरा सत्र SELECT
करने का प्रयास करने के लिए वास्तव में SELECT
. की प्रतीक्षा को रोक देगा जब तक पहले सत्र ने COMMIT
. का निर्णय नहीं लिया या ROLLBACK
, जिस समय दूसरे सत्र में पंक्तियों की संख्या (पहले सत्र द्वारा सम्मिलित या हटाए गए किसी भी सहित) की एक सटीक गणना देखी गई होगी और सटीक रूप से तय किया जा सकता था कि उपयोगकर्ता के पास पहले से ही अधिकतम अनुमत है।
आप दौड़ की स्थिति से आगे नहीं बढ़ सकते, लेकिन आप उन्हें लॉक कर सकते हैं।