একটা একক updateOne() নিজে থেকেই সবসময় atomic — এটা হয় পুরোপুরি apply হয় বা হয় না। একটা transaction সেই একই all-or-nothing গ্যারান্টি বেশ কয়েকটা operation জুড়ে বাড়ায়, সম্ভবত বেশ কয়েকটা document বা collection স্পর্শ করে, আগের SQL কোর্সের transaction lesson-এর একই ধারণা।
এক account থেকে আরেকটাতে টাকা move করতে দুটো write দরকার — একটা document থেকে বিয়োগ, আরেকটাতে যোগ। একটা transaction ছাড়া, দুটো write-এর মাঝে একটা crash data-কে সত্যিকারভাবে ভাঙা, অসামঞ্জস্যপূর্ণ অবস্থায় রেখে দেয়।
const session = db.getMongo().startSession()
try {
session.startTransaction()
const accounts = session.getDatabase('bank').accounts
accounts.updateOne({ _id: 'A' }, { $inc: { balance: -100 } })
accounts.updateOne({ _id: 'B' }, { $inc: { balance: 100 } })
session.commitTransaction()
} catch (error) {
session.abortTransaction()
throw error
} finally {
session.endSession()
}দুটো update একসাথে commit হয়, বা — মাঝখানে কিছু fail করলে — কোনোটাই হয় না, ঠিক আগের SQL transaction lesson-এর BEGIN/COMMIT/ROLLBACK-এর মতো।
Durability-র জন্য MongoDB একাধিক server জুড়ে data replicate করে — write concern আর read concern একটা write বা read done বলে বিবেচিত হওয়ার আগে সেই replication-এর কতটার জন্য অপেক্ষা করে তা tune করে।
| Write concern | যার জন্য অপেক্ষা করে |
|---|---|
| w: 1 (default) | শুধু primary server থেকে acknowledgment |
| w: 'majority' | বেশিরভাগ replica server থেকে acknowledgment — নিরাপদ, সামান্য ধীর |
| w: 0 | কোনো acknowledgment না — সবচেয়ে দ্রুত, সবচেয়ে কম নিরাপদ |
db.accounts.updateOne(
{ _id: 'A' },
{ $inc: { balance: -100 } },
{ writeConcern: { w: 'majority' } }
)Transaction আর write concern আলাদা গ্যারান্টি
নিজে থেকে, একটা transaction শুধু এর ভেতরের write একসাথে সফল বা ব্যর্থ হয় তা গ্যারান্টি দেয় — এগুলো কতটা টেকসইভাবে replicate হয় সে সম্পর্কে কিছু বলে না। সত্যিকারভাবে critical operation-এর জন্য (উপরের money transfer-এর মতো), একটা transaction-কে একটা majority write concern-এর সাথে জোড়া দেওয়াই বেশিরভাগ আসল application আসলে ব্যবহার করে।
একটা default পছন্দ না
অনেক document স্পর্শ করা বা লম্বা সময় চলা একটা transaction পুরো database জুড়ে performance-এর ক্ষতি করতে পারে — একটা operation-এর সত্যিকারভাবে all-or-nothing গ্যারান্টি দরকার হলে specifically এটার জন্য যান, প্রতিটা multi-step write-এর জন্য একটা default habit হিসেবে না।