আপনি যা চান তা হ'ল একটি লেনদেনের প্রসঙ্গের মধ্যে থেকে আপডেটের জন্য ... নির্বাচন করুন । নির্বাচন করুন আপডেটের জন্য নির্বাচিত সারিগুলিতে একচেটিয়া লক রাখে ঠিক যেমন আপনি আপডেট আপডেট করছেন। বিচ্ছিন্নতা স্তরটি সুস্পষ্টভাবে সেট করা আছে তা নির্বিশেষে এটি স্পষ্টভাবে READ COMMITTED বিচ্ছিন্নতা স্তরে চলে। কেবল সচেতন থাকুন যে নির্বাচন করুন ... ফরেক্সের জন্য সামঞ্জস্যের জন্য খুব খারাপ এবং এটি যখন একেবারে প্রয়োজন তখনই ব্যবহার করা উচিত। লোকেদের কেটে পেস্ট করার সাথে সাথে কোডবেজে গুন করার প্রবণতাও রয়েছে।
এখানে সাকিলা ডাটাবেস থেকে একটি উদাহরণস্বরূপ অধিবেশন যা ফর আপডেট সম্পর্কিত প্রশ্নের কিছু আচরণ দেখায়।
প্রথমত, কেবলমাত্র আমরা স্ফটিক পরিষ্কার, লেনদেনের বিচ্ছিন্নতা স্তরটিকে পুনরাবৃত্তিযোগ্য পড়ুন set এটি সাধারণত অপ্রয়োজনীয়, কারণ এটি 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 সেশনে লক সেটটি পরীক্ষা করে দেখি। নোট করুন যে সেশন 2 সারিটি আপডেট করতে পারে না।
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 'রয়েছে; এবং তারা উভয়ই একই সারিটি দেখতে পাবে, তারপরে একটি অন্যটিকে লক করবে। আমি আশা করছিলাম যে কোনওরকমভাবে এটি লক করা সারিটি পাশ কাটিয়ে উঠতে সক্ষম হবে এবং পরবর্তী আইটেমটি মুলতুবি ছিল তা ..