ACID فقط اسم چهار قانون دیتابیس است؛ بهتنهایی جلوی همه باگها را نمیگیرد. برای جلوگیری از فروشِ دوبارهٔ یک کالا، گمشدن تغییر همزمان و خرابشدن گزارشها باید بدانیم دیتابیس دقیقاً چه چیزی را قفل میکند و هر transaction چه چیزی را میبیند.
MVCC
خواننده نسخه سازگار از سطر میبیند و معمولاً نویسنده را قفل نمیکند؛ نسخههای قدیمی تا پایان transaction لازماند.
Read Committed
هر statement داده commitشده را میبیند؛ non-repeatable read ممکن است.
Repeatable Read
خواندنهای یک transaction snapshot یکسان میبینند؛ در بعضی DBها write skew هنوز ممکن است.
Serializable
رفتار معادل اجرای ترتیبی؛ DB ممکن است transaction را abort کند و client باید retry امن داشته باشد.
Optimistic locking
ستون version در UPDATE شرطی؛ اگر version عوض شده، تعارض را به caller نشان میدهد.
مهاجرت schema بدون downtime
- Expand: ستون/جدول/ایندکس جدیدِ backward-compatible اضافه کن؛ index بزرگ را concurrent یا online بساز.
- Migrate: کد جدید هم زمان با قدیمی بخواند/بنویسد؛ backfill را rate-limit و قابل توقف کن.
- Contract: بعد از حذف تمام خوانندههای قدیمی و مشاهده metrics، ستون قدیمی را حذف کن.
- برای تغییر داده بین سیستمها از transactional outbox یا CDC استفاده کن؛ dual-write بدون recovery path منبع ناسازگاری است.
به زبان ساده
دیتابیس مدرن چند نسخه از هر سطر را نگه میدارد تا خواندن و نوشتن همزمان قاطی نشود؛ و تغییر ساختار جدول را سهمرحلهای انجام میدهیم تا نسخه قدیمی برنامه نسوزد.
مثال واقعی
ستون شماره موبایل را اگر یکشبه اجباری کنی، نسخه قدیمی اپ روی بعضی سرورها crash میکند؛ اول ستون اختیاری، بعد deploy، بعد پرکردن آرام، و در آخر اجباریکردن.