মূল কন্টেন্টে যান
মডিউল 11 · 3-এর পাঠ 4কোর্সে 43/57~15 min
মডিউল পাঠ (3/4)

লকিং এবং আপডেটের জন্য নির্বাচন করুন

একটি একক টার্মিনালে একটি ডাটাবেস কীভাবে বিচ্ছিন্নভাবে কাজ করে তা বোঝা সহজ... অপেক্ষা করবেন না, আমি আগেই বলেছি! কখনও কখনও "পরমাণু আপডেট" (যেমন stock = stock - 1) যথেষ্ট নয়৷

আসুন কল্পনা করুন যে ব্যবহারকারীর 50€ মূল্যের জিনিস কেনার জন্য যথেষ্ট ব্যালেন্স আছে কিনা তা আপনাকে পরীক্ষা করতে হবে:

  1. SELECT balance FROM users WHERE id = 1;
  2. JS: ব্যালেন্স < 50 হলে, তাদের ব্লক করুন!
  3. অন্যথায় চেকআউট দিয়ে এগিয়ে যান...
  4. ছাড় চালান! (এবং এখানে আপনি একজন ব্যবহারকারীকে খুঁজে পাচ্ছেন যিনি, ধাপ 2-এ চেকটি যাচাই করার সময়, তাদের অ্যাকাউন্টের মাধ্যমে পুড়িয়ে ফেলা অন্য একটি সমান্তরাল একটি বন্ধ করে দিয়েছেন এবং এখন আপনি শূন্যের নিচে যাচ্ছেন!)

আপডেট করার জন্য স্পষ্ট লকিং

একটি SELECT এর শেষে FOR UPDATE যোগ করা যাদুকরীভাবে আপনার নিষ্পাপ পাঠকে পরবর্তী COMMIT পর্যন্ত অন্যান্য ক্লায়েন্টদের বিরুদ্ধে একটি সিল করা লক-এ রূপান্তরিত করে৷ অন্য কেউ সেই নির্দিষ্ট নির্বাচিত সারিগুলিতে আপডেট (বা সমসাময়িক রিড-ফর-আপডেট) করতে সক্ষম হবে না যতক্ষণ না আপনি তাদের সাথে কী করবেন তা নির্ধারণ করেন!

SQL
BEGIN;

-- If id=3 had already been locked by T1, T2 will sit in perpetual loading on this "read"
-- frozen in place, before receiving the raw data, until T1 runs COMMIT freeing everyone!
SELECT balance
FROM users
WHERE id = 3
FOR UPDATE;

-- at this point our Node JS instance lives with the guarantee, knowing for certain that NO ONE ELSE in the world has
-- manipulated (nor been able to read with intent to alter) that balance while we complete the application logic

UPDATE users SET balance = balance - 50 WHERE id = 3;

COMMIT;

এমনকি FOR SHARE রয়েছে যা অন্যান্য পাঠকদের পড়তে দেয় (যদি বেস লক থাকে) স্টেট রিড ব্লক না করে, কিন্তু আপনি প্রতিশ্রুতি না দেওয়া পর্যন্ত পরবর্তী যেকোনো সম্ভাব্য আপডেট ব্লক করে। যদিও পরিবর্তনের জন্য, সর্বদা একচেটিয়া লকিং ক্লজের ব্রুট ফোর্স ব্যবহার করুন:

নিজে চেষ্টা করে দেখুন

ব্যায়াম#sql.m11.l3.e1
প্রচেষ্টা: 0লোড হচ্ছে...

একটি স্বাভাবিক সময়-স্কোপড লেনদেন খুলুন এবং শুধুমাত্র পণ্য ID=5 এর রিড লক করুন।\nএকটি দ্বি-পদক্ষেপ কোয়েরি চালান:\n1। লেনদেন খুলুন (শুরু)\n2. 'আপডেটের জন্য' বিকল্পটি সংযুক্ত করে, কেউ এটিকে পরিবর্তন করবে না এমন গ্যারান্টি সহ আইডি 5-এর জন্য সম্পূর্ণ সারি নিয়ে আসা 'পণ্য' জিজ্ঞাসা করুন।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

শুরু করুন;, নতুন লাইন, নির্বাচন করুন * পণ্য থেকে যেখানে আইডি = 5 আপডেটের জন্য;

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ

ব্যায়াম#sql.m11.l3.e2
প্রচেষ্টা: 0লোড হচ্ছে...

কখনও কখনও লেনদেন বিপর্যয়মূলক সময়ের জন্য হ্যাং হয়ে যায় (অচল বা অসীম অপেক্ষা)।\nএটি প্রতিরোধ করতে আপনি ডাটাবেসকে নির্দেশ দিতে পারেন যে মুহুর্তটি সারিটি অবিলম্বে উপলব্ধ না হওয়া মুহূর্তটি ছেড়ে দিতে: শেষে NOWAIT ব্যবহার করে, যার ফলে SQL সার্ভার ব্যতিক্রমটি JS-এ ফিরে আসতে পারে যাতে এটি চিরতরে ঝুলিয়ে না রেখে চেষ্টা-ক্যাচ করা যায়। এখনই।

সম্পাদক লোড হচ্ছে...
ইঙ্গিত দেখান

এখনই আপডেট করার জন্য id = 1 বিভাগ থেকে নির্বাচন করুন;

সমাধান 3 প্রচেষ্টার পরে উপলব্ধ