سابترنزکشنهای پستگرس؛ خطری که کل کلاستر رو کند میکنه
خلاصهٔ کاملتر
به گفتهٔ نویسندههای PlanetScale، ریپلیکاهای خواندنی پستگرس با پخش پیوستهٔ WAL (Write-Ahead Log) از سرور اصلی بهروز میمونن. برای اینکه یه ریپلیکا بتونه بهطور امن به کوئریهای خواندنی جواب بده، باید وضعیت تراکنشهای درحالاجرا رو هم از دل همین WAL بفهمه تا بتونه یه snapshot درست بسازه.
سابترنزکشنها که با دستور SAVEPOINT یا بلوکهای EXCEPTION تو PL/pgSQL ساخته میشن، تو یه کش تو حافظه نگه داشته میشن که ظرفیتش معمولاً ۶۴ تا شناسهست (PGPROC_MAX_CACHED_SUBXIDS). وقتی یه تراکنش بیشتر از این تعداد سابترنزکشن بسازه، این کش سرریز میشه و پستگرس مجبوره برای پیدا کردن شناسهٔ تراکنش اصلی، سراغ فایل pg_subtrans رو دیسک بره که کندتره.
رسیدن به این سقف خیلی هم سخت نیست؛ حتی یه حلقهٔ ساده تو PL/pgSQL که هر بار یه بلوک EXCEPTION داره هم بدون اینکه صریحاً SAVEPOINT بزنی، بهراحتی از این مرز رد میشه:
DO $$
BEGIN
FOR i IN 1..70 LOOP
BEGIN
INSERT INTO t VALUES (i);
EXCEPTION WHEN OTHERS THEN RAISE;
END;
END LOOP;
END $$;نکتهٔ نگرانکننده اینجاست که این سرریز فقط به همون تراکنش محدود نمیمونه؛ به محض اینکه یه بکاند گزارش سرریز بده، هر snapshot جدیدی تو کل کلاستر overflow علامت میخوره، یعنی کوئریهای روی جدولها و حتی دیتابیسهای دیگه هم باید این جستوجوی کند رو انجام بدن. تیم PlanetScale تو یه بنچمارک ساده با INSERT/SELECT/DELETE نشون داده که به محض بروز این سرریز، throughput تراکنشها (TPS) فوراً افت میکنه.




