Transactions & ACID Properties

Transaction কী?

Transaction হলো একগুচ্ছ অপারেশনের একটি সেট, যা হয় পুরোপুরি সফল হবে, নয়তো পুরোপুরি বাতিল হয়ে আগের অবস্থায় ফিরে যাবে (Rollback)। ব্যাংকে টাকা ট্রান্সফার, অনলাইন অর্ডার কনফার্মেশন বা ইউজারের তথ্য আপডেটের মতো কাজে ডাটা যেন সবসময় সঠিক থাকে, Transaction তা নিশ্চিত করে।

উদাহরণ: এক অ্যাকাউন্ট থেকে অন্য অ্যাকাউন্টে টাকা পাঠানো দুটি ধাপে হয়:

  1. প্রথম অ্যাকাউন্ট থেকে টাকা কাটা

  2. দ্বিতীয় অ্যাকাউন্টে টাকা যোগ করা

দ্বিতীয় ধাপ ব্যর্থ হলে প্রথম ধাপের কাটা টাকা ফেরত যেতে হবে, নইলে ডাটা অসঙ্গতিপূর্ণ হয়ে যাবে।

ACID Properties

১. Atomicity

"সব, নয়তো কিছুই না।" অর্থাৎ, transaction সম্পূর্ণ সফল হবে অথবা একটুও কার্যকর হবে না। কোনো partial change database এ যাবে না।
উদাহরণ: টাকা ট্রান্সফারের মাঝপথে সার্ভার ক্র্যাশ করলেও টাকা হারাবে না। Bank এ টাকা transfer করলে, sender থেকে amount deduct এবং receiver এ add দুটোই complete হবে, না হলে কোনো action হবে না।

২. Consistency

Transaction এর আগে ও পরে ডাটাবেস সবসময় valid state এ থাকবে। সব rules, constraints, এবং relationships maintain হবে।
উদাহরণ: ব্যালেন্স নেগেটিভ হতে পারে না এমন নিয়ম থাকলে কোনো Transaction ব্যালেন্স নেগেটিভ করে শেষ হতে পারবে না।

৩. Isolation

একাধিক Transaction একই সময়ে চললেও তারা একে অপরকে প্রভাবিত করবে না। অর্থাৎ, Concurrent transactions একে অপরকে interfere করতে পারবে না। প্রতিটি transaction independent ভাবে execute হবে।
উদাহরণ: দুজন একই অ্যাকাউন্ট থেকে একসাথে টাকা তুললে Database নিশ্চিত করে যেন ফলাফল এমন হয়, যেন তারা একের পর এক করেছে। অর্থাৎ, দুইজন user একসাথে same account update করলে data corrupt হবে না।

৪. Durability

Transaction একবার Commit হলে সেটি স্থায়ীভাবে সংরক্ষিত থাকে, সার্ভার রিস্টার্ট বা ক্র্যাশ হলেও হারায় না। অর্থাৎ, একবার transaction complete হলে, তার changes permanent এবং system crash হলেও loss হবে না।
উদাহরণ: পেমেন্ট সফল হওয়ার পর সার্ভার রিস্টার্ট হলেও পেমেন্টের রেকর্ড থাকবে। বা Transaction commit হলে data permanent save থাকবে।

Transaction এর ধরন

ধরন

বিবরণ

উদাহরণ

Single-Step

একটি মাত্র ধাপে সম্পন্ন হয়

ইনভেন্টরিতে একটি প্রোডাক্ট যোগ করা

Multi-Step

একাধিক ধাপ, সবগুলো একসাথে সফল হতে হয়

ফান্ড ট্রান্সফার

Distributed

একাধিক সার্ভার বা ডাটাবেসজুড়ে চলে

ই-কমার্স অর্ডারে পেমেন্ট গেটওয়ে, স্টক ও শিপিং সার্ভিস একসাথে

Transaction কীভাবে কাজ করে?

মূল ধাপগুলো:

  • BEGIN / START TRANSACTION: Transaction শুরু

  • অপারেশন চালানো: টাকা কাটা, টাকা যোগ করা ইত্যাদি

  • COMMIT: সব ঠিক থাকলে পরিবর্তন স্থায়ী করা

  • ROLLBACK: কোনো ধাপে সমস্যা হলে আগের অবস্থায় ফেরা

ভেতরে Database সাধারণত Write-Ahead Log (WAL) ব্যবহার করে। পরিবর্তন আগে Log-এ লেখা হয়, ফলে ক্র্যাশের পরেও Committed ডাটা পুনরুদ্ধার (Durability) ও অসম্পূর্ণ Transaction বাতিল (Atomicity) করা যায়।

Isolation Level

Isolation নিখুঁতভাবে নিশ্চিত করতে গেলে Performance কমে, তাই Database-এ একাধিক স্তর থাকে:

স্তর

কী ঘটতে পারে

Read Uncommitted

অন্য Transaction-এর অসম্পূর্ণ ডাটা পড়া যায় (Dirty Read)

Read Committed

শুধু Commit হওয়া ডাটা পড়া যায়, তবে একই ডাটা দুবার পড়লে ভিন্ন মান আসতে পারে

Repeatable Read

একই ডাটা বারবার পড়লে একই মান আসে, তবে নতুন রো (Phantom) দেখা দিতে পারে

Serializable

সবচেয়ে কঠোর, যেন Transaction-গুলো একটির পর একটি চলেছে

স্তর যত কঠোর, নিরাপত্তা তত বেশি কিন্তু Performance তত কম। এটি সিস্টেম ডিজাইনের একটি সাধারণ Trade-off।

Distributed Transaction এর চ্যালেঞ্জ

একাধিক সার্ভার বা সার্ভিস জড়িত হলে সাধারণ ACID Transaction যথেষ্ট নয়। এখানে দুটি জনপ্রিয় পদ্ধতি:

  • Two-Phase Commit (2PC): প্রথমে সব অংশগ্রহণকারী "প্রস্তুত" জানায়, তারপর সবাই একসাথে Commit করে। নির্ভরযোগ্য, কিন্তু ধীর এবং Coordinator ব্যর্থ হলে আটকে যেতে পারে।

  • Saga Pattern: বড় Transaction-কে ছোট ছোট স্থানীয় Transaction-এ ভাগ করা হয়। কোনোটি ব্যর্থ হলে আগের ধাপগুলো Compensating Transaction দিয়ে বাতিল করা হয় (যেমন পেমেন্ট হয়ে স্টক ব্যর্থ হলে পেমেন্ট Refund)। Microservice আর্কিটেকচারে বেশি ব্যবহৃত, তবে এখানে Eventual Consistency মেনে নিতে হয়।

এখানে CAP Theorem ও Consistency বনাম Availability-এর Trade-off সরাসরি কাজ করে।

Idempotency

ধরো, একটি পেমেন্ট ট্রানজ্যাকশন ডেটাবেসে সফলভাবে COMMIT হলো, কিন্তু ক্লায়েন্টের কাছে 200 OK রেসপন্স পৌঁছানোর আগেই নেটওয়ার্ক ড্রপ করলো। ক্লায়েন্ট ভাববে পেমেন্ট ফেইল করেছে এবং আবার রিকোয়েস্ট (Retry) পাঠাবে। এতে গ্রাহকের অ্যাকাউন্ট থেকে দুবার টাকা কেটে যাওয়ার ঝুঁকি থাকে।

এই সমস্যা এড়াতে API ডিজাইনে Idempotency Key ব্যবহার করা হয়। ক্লায়েন্ট প্রতিটি পেমেন্ট রিকোয়েস্টের সাথে একটি ইউনিক কী (Key) পাঠায়। ডেটাবেস ট্রানজ্যাকশন শুরু করার আগে চেক করে এই কী-এর কাজ আগেই সফল হয়েছে কিনা। যদি হয়ে থাকে, তবে নতুন করে কোনো ট্রানজ্যাকশন এক্সিকিউট না করে সিস্টেম সরাসরি আগের সাকসেস রেসপন্সটিই ফেরত দিয়ে দেয়।

Transaction কেন গুরুত্বপূর্ণ?

  • ডাটার সুরক্ষা ও শুদ্ধতা নিশ্চিত করে

  • ব্যবসায়িক লেনদেন নির্ভরযোগ্য করে

  • সিস্টেম ক্র্যাশ বা ব্যর্থতা থেকে ডাটা রক্ষা করে

  • ব্যবহারকারীর আস্থা বাড়ায়

ডিজাইনের সময় মনে রাখবেন

  • Transaction ছোট ও দ্রুত রাখুন, কারণ দীর্ঘ Transaction Lock ধরে রাখে এবং অন্যদের আটকে দেয়।

  • Transaction-এর ভেতরে বাইরের API Call বা ধীর কাজ করবেন না।

  • একাধিক Lock নেওয়ার ক্রম সবসময় একই রাখুন, নইলে Deadlock হতে পারে।

  • Payment-এর মতো কাজে Idempotency Key ব্যবহার করুন, যাতে Retry হলে দুবার টাকা না কাটে।

  • Transaction ছাড়া ডাটা পরিবর্তন করলে Inconsistency, ডাটা হারানো ও নিরাপত্তা ঝুঁকি তৈরি হতে পারে।

Transaction হলো সিস্টেম ডিজাইনের নির্ভরযোগ্যতার ভিত্তি। ACID এর মাধ্যমে এটি নিশ্চিত করে যে ডাটা সবসময় সঠিক ও সুরক্ষিত থাকে। একক ডাটাবেসে ACID Transaction, আর Distributed সিস্টেমে 2PC বা Saga, প্রয়োজন অনুযায়ী সঠিক পদ্ধতি বেছে নেওয়াই সিস্টেম ডিজাইনারের কাজ।