क्या आप चाहते हैं का चयन करें ... लेनदेन के संदर्भ में अद्यतन के लिए । अद्यतन के लिए चयन चयनित पंक्तियों पर एक विशेष ताला लगाता है, जैसे कि आप अद्यतन कर रहे थे। यह भी स्पष्ट रूप से अलग-थलग है कि क्या अलगाव स्तर स्पष्ट रूप से निर्धारित है की परवाह किए बिना अलग-थलग अलगाव स्तर में चलता है। बस इस बात का ध्यान रखें कि सेलेक्ट ... फॉर UPDATE कंसिस्टेंसी के लिए बहुत खराब है और इसका उपयोग केवल तभी किया जाना चाहिए जब बिल्कुल आवश्यक हो। यह भी एक कोडबेस में गुणा करने की प्रवृत्ति है क्योंकि लोग कट और पेस्ट करते हैं।
यहां सकीला डेटाबेस से एक उदाहरण सत्र है जो कुछ अद्यतन प्रश्नों के व्यवहार को प्रदर्शित करता है।
सबसे पहले, बस इतना ही कि हम क्रिस्टल स्पष्ट हैं, लेन-देन अलगाव स्तर को READATABLE READ में सेट करें। यह सामान्य रूप से अनावश्यक है, क्योंकि यह InnoDB के लिए डिफ़ॉल्ट अलगाव स्तर है:
session1> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
session1> BEGIN;
session1> SELECT first_name, last_name FROM customer WHERE customer_id = 3;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| LINDA | WILLIAMS |
+------------+-----------+
1 row in set (0.00 sec)
अन्य सत्र में, इस पंक्ति को अपडेट करें। लिंडा ने शादी की और अपना नाम बदल लिया:
session2> UPDATE customer SET last_name = 'BROWN' WHERE customer_id = 3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
सत्र 1 में वापस, क्योंकि हम दोहराए गए विवरण में थे, लिंडा अभी भी लिंडा विलियम्स है:
session1> SELECT first_name, last_name FROM customer WHERE customer_id = 3;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| LINDA | WILLIAMS |
+------------+-----------+
1 row in set (0.00 sec)
लेकिन अब, हम इस पंक्ति के लिए अनन्य पहुँच चाहते हैं, इसलिए हम पंक्ति पर अद्यतन के लिए कॉल करते हैं। ध्यान दें कि अब हमें पंक्ति के सबसे हाल के संस्करण मिलते हैं, जिसे इस लेनदेन के बाहर सत्र 2 में अपडेट किया गया था। यह दोहराई गई खबर नहीं है, यह पढ़ी गई टिप्पणी है
session1> SELECT first_name, last_name FROM customer WHERE customer_id = 3 FOR UPDATE;
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| LINDA | BROWN |
+------------+-----------+
1 row in set (0.00 sec)
सत्र 1 में लॉक सेट का परीक्षण करते हैं। ध्यान दें कि session2 पंक्ति को अपडेट नहीं कर सकता है।
session2> UPDATE customer SET last_name = 'SMITH' WHERE customer_id = 3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
लेकिन हम अभी भी इससे सेलेक्ट कर सकते हैं
session2> SELECT c.customer_id, c.first_name, c.last_name, a.address_id, a.address FROM customer c JOIN address a USING (address_id) WHERE c.customer_id = 3;
+-------------+------------+-----------+------------+-------------------+
| customer_id | first_name | last_name | address_id | address |
+-------------+------------+-----------+------------+-------------------+
| 3 | LINDA | BROWN | 7 | 692 Joliet Street |
+-------------+------------+-----------+------------+-------------------+
1 row in set (0.00 sec)
और हम अभी भी एक विदेशी कुंजी संबंध के साथ एक चाइल्ड टेबल को अपडेट कर सकते हैं
session2> UPDATE address SET address = '5 Main Street' WHERE address_id = 7;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
session1> COMMIT;
एक और दुष्प्रभाव यह है कि आप गतिरोध पैदा करने की संभावना को बहुत बढ़ा देते हैं।
अपने विशिष्ट मामले में, आप शायद चाहते हैं:
BEGIN;
SELECT id FROM `items` WHERE `status`='pending' LIMIT 1 FOR UPDATE;
-- do some other stuff
UPDATE `items` SET `status`='working', `updated`=NOW() WHERE `id`=<selected id>;
COMMIT;
यदि "कुछ अन्य सामान करते हैं" टुकड़ा अनावश्यक है और आपको वास्तव में पंक्ति के बारे में जानकारी रखने की आवश्यकता नहीं है, तो चयन के लिए अद्यतन अनावश्यक और बेकार है और आप इसके बजाय बस एक अद्यतन चला सकते हैं:
UPDATE `items` SET `status`='working', `updated`=NOW() WHERE `status`='pending' LIMIT 1;
आशा है कि यह कुछ समझ में आता है।
items
व्हेयरstatus
= 'लंबित' लिमिट 1 फॉर अपडेट के साथ आ रहे हैं ;" और वे दोनों एक ही पंक्ति को देखते हैं, तो एक दूसरे को बंद कर देगा। मैं किसी तरह उम्मीद कर रहा था कि यह लॉक की गई पंक्ति को पास-पास करने में सक्षम हो जाएगा और इसके साथ ही अगला आइटम भी लंबित हो जाएगा ..