একটা দৃশ্য কল্পনা করুন। Customer order করল, আপনার কোড order টেবিলে সারি যোগ করল, ঠিক তারপর stock কমানোর আগেই server crash করল। ফলাফল: order আছে, কিন্তু stock কমেনি - হিসাব মিলছে না। কিংবা টাকা কাটা হয়ে গেল কিন্তু order তৈরি হলো না। এই 'অর্ধেক হয়ে যাওয়া' কাজই backend-এর সবচেয়ে ভয়ংকর bug, কারণ এটা চুপচাপ data নষ্ট করে।
Transaction এই সমস্যার সমাধান। একদল কাজকে একটা বান্ডিল বানিয়ে দেওয়া হয় - হয় সবগুলো হবে, নয়তো একটাও না। মাঝখানে কোনো ধাপ ব্যর্থ হলে পুরোটা rollback হয়ে আগের অবস্থায় ফিরে যায়, যেন কিছুই ঘটেনি।
await db.$transaction(async (tx) => {
const order = await tx.order.create({ data: { userId, total } });
await tx.product.update({
where: { id: productId },
data: { stock: { decrement: quantity } },
});
await tx.payment.create({ data: { orderId: order.id, amount: total } });
});
// যেকোনো ধাপে error হলেই পুরোটা rollbackACID - চারটা গুণের নাম
- Atomicity - সব হবে, নয়তো কিছুই না। আজকের পর্বের মূল কথা এটাই।
- Consistency - প্রতিটা transaction database-কে একটা বৈধ অবস্থা থেকে আরেকটা বৈধ অবস্থায় নিয়ে যায়, নিয়ম ভাঙে না।
- Isolation - একসাথে চলা transaction-গুলো একে অপরের অর্ধেক কাজ দেখতে পায় না।
- Durability - একবার commit হলে data থাকবেই, server crash হলেও।
কখন transaction লাগবে বোঝার সহজ নিয়ম: যখন একটা কাজে একাধিক টেবিল বা একাধিক ধাপ জড়িত এবং মাঝখানে থেমে গেলে হিসাব ভাঙবে - টাকা, order, stock, balance - সেখানে transaction ছাড়া কোড লিখবেন না। শুধু একটা সারি পড়া বা একটা field আপডেটে এর দরকার নেই।
সবাই যে ভুলটা করে
সবচেয়ে দামি ভুল: টাকা বা stock জড়িত কাজ ধাপে ধাপে আলাদা query দিয়ে করা, মাঝখানে কোনো জায়গায় error হলে ধরার ব্যবস্থা না রাখা। Bug-টা হয়তো মাসে একবার ঘটবে, কিন্তু প্রতিবারই তা হিসাবে গণ্ডগোল রেখে যাবে, যেটা খুঁজে বের করা প্রায় অসম্ভব।
আজকের Practice
আপনার project-এ order তৈরি করার flow-টা transaction-এ মুড়ে দিন। তারপর ইচ্ছা করে মাঝের ধাপে একটা error ঘটান (যেমন অস্তিত্বহীন product id) আর যাচাই করুন - order টেবিলে কোনো সারি জমা হয়নি, stock-ও বদলায়নি।
Interview-এ কীভাবে বলবেন
Transaction দিয়ে আমি একদল কাজকে atomic বানাই - হয় সব হবে, নয়তো rollback হয়ে কিছুই হবে না। টাকা, order, stock-এর মতো জায়গায় এটা বাধ্যতামূলক, কারণ অর্ধেক কাজ মানে ভাঙা হিসাব। ACID-এর বাকি গুণ - consistency, isolation, durability - নিশ্চিত করে একসাথে অনেক request এলেও data ঠিক থাকে।