MVCC پستگرس بده؛ ولی نسبت به چی؟
خلاصهٔ کاملتر
نویسنده میگه هر شکایتی که از MVCC پستگرس میشنوی از یه تصمیم طراحی میاد نه از یه نقص، و بحث همیشه یه سؤال زودتر تموم میشه: «در مقایسه با چی؟». به گفتهٔ اون MVCC اختیاری نیست؛ هر دیتابیسی که نخواد خوانندهها جلوی نویسندهها رو بگیرن باید چند نسخه از هر ردیف نگه داره. جواب پستگرس اینه: نسخهها تو خود جدول، زنجیره از قدیم به جدید، ایندکسها به مکان فیزیکی، و تمیزکاری با یه پروسهٔ پسزمینه.
هزینهٔ این انتخابها تو مقاله روی یه نمونهٔ زندهٔ PostgreSQL 19 beta2 بازتولید شده. آپدیت ۱۰۰ هزار ردیف روی جدولی با فقط کلید اصلی حدود ۳ رکورد WAL به ازای هر ردیف ساخت، ولی همون آپدیت روی جدولی با چهار ایندکس ثانویه ۷.۱ رکورد — با اینکه ستون تغییرکرده تو هیچ ایندکسی نبود. دلیلش اینه که ردیف جابهجا میشه و همهٔ ایندکسها به مکان فیزیکی اشاره میکنن. مسکّنش HOT هست که با تنظیم fillfactor جواب میده، ولی فرصتطلبانهست.
بقیهٔ اتهامها هم درست از آب دراومدن: یه UPDATE روی یک میلیون ردیف که حتی کامیت هم نشد، جدول رو از ۸۹ به ۱۷۸ مگابایت رسوند و یک میلیون تاپل مرده جا گذاشت؛ یه تراکنش باز تو سشن دیگه جلوی پاکشدن اونها رو نه فقط تو همون جدول بلکه تو کل دیتابیس میگیره؛ و شمارندهٔ ۳۲ بیتی تراکنشها مجبورت میکنه صفحههای دستنخورده رو دورهای freeze کنی.
اوراکل و InnoDB جوابهای برعکس میدن: نسخههای قدیمی بیرون جدول تو undo میمونن، پس جدول همیشه فشردهست، ایندکسهای ثانویه موقع آپدیت دستنخورده میمونن و نه وکیوم لازمه نه wraparound. ولی نویسنده میگه قبض جای دیگهای میاد؛ همون رولبکی که پستگرس تو ۰.۱۲۴ میلیثانیه انجام داد، تو موتور undo یعنی برگردوندن تکتک تغییرها، گاهی طولانیتر از خود تراکنش. خوندن دادهٔ قدیمی هم باید هر بار از روی دلتاها بازسازی بشه.
مشکل «تراکنش بازمونده» هم پاک نشده، فقط شکل خرابیش عوض شده: اوراکل کوئری رو با ORA-01555 میکشه، InnoDB بهجاش تاریخچه رو انبار میکنه، SQL Server نسخهها رو تو tempdb مشترک کل اینستنس میذاره و مونگو با پرشدن کش کند میشه. نکتهٔ جالب مقاله اینه که SQL Server با Accelerated Database Recovery رفت سراغ یه version store داخل خود دیتابیس تا به همون رولبک با زمان ثابت برسه که پستگرس از روز اول مجانی داشته.
نکات کلیدی:
- چهار ایراد MVCC پستگرس واقعیان و روی PostgreSQL 19 beta2 قابل بازتولیدن
- ایندکسهای پستگرس به مکان فیزیکی ردیف اشاره میکنن، برای همین یه آپدیت ساده همهٔ ایندکسها رو بازنویسی میکنه
- موتورهای undo محور مثل اوراکل و InnoDB جدول رو فشرده نگه میدارن، ولی رولبک و خوندن تاریخچه براشون گرونه
- تراکنش باز تو همهٔ موتورها دردسر میسازه؛ فقط شکل شکستش فرق میکنه
- رولبک با زمان ثابت چیزیه که SQL Server تازه با ADR بهش رسید و پستگرس از اول داشته




