আমি এর আগে মাইএসকিউএল এর মতো সমাবর্তন সমস্যার কথা শুনেছি। পোস্টগ্রিসে তেমন নয়।
ডিফল্ট READ COMMITTEDলেনদেনের বিচ্ছিন্নতার স্তরে অন্তর্নির্মিত সারি-স্তরের লকগুলি যথেষ্ট।
আমি ডেটা-সংশোধনকারী সিটিই (এমন কিছু যা মাইএসকিউএল-তেও নেই) সহ একক বিবৃতি প্রস্তাব করছি কারণ এটি এক টেবিল থেকে অন্য টেবিলের কাছে সরাসরি মানগুলি সরবরাহ করা সুবিধাজনক (যদি আপনার এটির প্রয়োজন হয়)) আপনার যদি couponটেবিলের থেকে কিছু না প্রয়োজন হয় তবে আপনি পৃথক UPDATEএবং INSERTবিবৃতি দিয়েও লেনদেন ব্যবহার করতে পারেন ।
WITH upd AS (
UPDATE coupon
SET used = true
WHERE coupon_id = 123
AND NOT used
RETURNING coupon_id, other_column
)
INSERT INTO log (coupon_id, other_column)
SELECT coupon_id, other_column FROM upd;
এটি একটি বিরল জিনিস হওয়া উচিত যা একাধিক লেনদেন একই কুপনকে ছাড়ানোর চেষ্টা করে। তাদের একটি অনন্য নম্বর আছে, তাই না? সময় একই মুহুর্তে চেষ্টা করা একাধিক লেনদেন এখনও বিরল হওয়া উচিত। (সম্ভবত কোনও অ্যাপ্লিকেশন বাগ বা কেউ কেউ গেমটি খেলার চেষ্টা করছে?)
হতে যে যেমন পারে, UPDATEশুধুমাত্র সফল ঠিক একটি লেনদেন, কোন ব্যাপার কি। একটি আপডেট করার আগে প্রতিটি লক্ষ্য সারিতে UPDATEএকটি সারি স্তরের লক অর্জন করে। যদি UPDATEএকই সারিতে সমবর্তী লেনদেন চেষ্টা করে তবে এটি সারিটির লকটি দেখতে পাবে এবং অবরুদ্ধ লেনদেন শেষ না হওয়া পর্যন্ত অপেক্ষা করবে ( ROLLBACKবা COMMIT), তারপরে লক সারিতে প্রথম হবে:
যদি প্রতিশ্রুতিবদ্ধ হয় তবে শর্তটি পুনরায় পরীক্ষা করুন। যদি এটি এখনও থাকে NOT usedতবে সারিটি লক করুন এবং এগিয়ে যান। অন্যটি UPDATEএখন কোনও যোগ্যতার সারি খুঁজে পায় না এবং কিছুই করে না , কোনও সারি ফিরে না আসে, সুতরাং INSERTএছাড়াও কিছুই করে না।
যদি ঘূর্ণায়মান হয়, সারিটি লক করুন এবং এগিয়ে যান।
নেই একটি জাতি অবস্থার জন্য কোন সম্ভাব্য ।
নেই একটি জন্য কোনো সম্ভাব্য অচলাবস্থা যদি না আপনি একই লেনদেনে মধ্যে আরো লিখেছেন করা বা অন্যথায় শুধু একাধিক সারি লক।
INSERTযত্ন-মুক্ত। যদি, কিছু ভুলক্রমে coupon_idইতিমধ্যে logটেবিলটিতে থাকে (এবং আপনার একটি অনন্য বা পিকে বাধা রয়েছে log.coupon_id), অনন্য লঙ্ঘনের পরে পুরো লেনদেনটি ফিরিয়ে আনা হবে। আপনার ডিবিতে একটি অবৈধ অবস্থা নির্দেশ করবে। যদি উপরের বিবৃতিটি logটেবিলে লেখার একমাত্র উপায় হয় তবে তা কখনই ঘটে না।