داده، SQL، قراردادها و ماشین حالت · فصل ۳ — Migration، ORM و Backup/Restore · 64
Migration Discipline و Schema Evolution
داده را ذخیره یا query میکند اما constraint، consistency، compatibility و recovery را به یک contract مهندسی تبدیل نمیکند. موضوع جاری: «Migration Discipline و Schema Evolution». میتواند «Migration Discipline و Schema Evolution» را برای یک domain محدود مدل کند و constraint، compatibility یا recovery evidence لازم را مشخص کند.
خلاصهٔ درس
داده را ذخیره یا query میکند اما constraint، consistency، compatibility و recovery را به یک contract مهندسی تبدیل نمیکند. موضوع جاری: «Migration Discipline و Schema Evolution».
میتواند «Migration Discipline و Schema Evolution» را برای یک domain محدود مدل کند و constraint، compatibility یا recovery evidence لازم را مشخص کند.
خروجی این درس
میتواند «Migration Discipline و Schema Evolution» را برای یک domain محدود مدل کند و constraint، compatibility یا recovery evidence لازم را مشخص کند.
پیشنیازها
۱. صفحه اول — migration یک فرمان DDL نیست؛ یک تغییر سازگاری است
فرض کنید جدول customer_contact سالها یک ستون phone_legacy داشته است. نسخهٔ قدیمی برنامه هنوز از همان ستون میخواند و مینویسد، اما نسخهٔ جدید باید شمارهٔ نرمالشدهٔ phone_e164 را مصرف کند. اجرای یک ALTER TABLE ADD COLUMN فقط ثابت میکند ستون جدید ایجاد شده؛ ثابت نمیکند دادهٔ قدیمی آماده است، old reader و old writer در پنجرهٔ همزیستی سالماند، enforcement زودهنگام نیست، lock/rewrite risk فهمیده شده، و در صورت شکست recovery تصمیم قابل دفاعی داریم.
خروجی این درس Schema Evolution Migration Review Record v1 است. برای هر phase باید «contract قبل»، «schema change»، «data transition»، «سازگاری old/new reader-writer»، «lock یا rewrite risk»، «verification»، «fallback»، «removal gate» و «residual risk» ثبت شود. یک migration وقتی پذیرفتنی است که evidence مثبت و منفی و recovery evidence داشته باشد؛ نه صرفاً چون فایل migration یا schema جدید وجود دارد.
شش مرز از ابتدا قفلاند: migration یک compatibility change است؛ lock level هر ALTER TABLE را نباید یکسان فرض کرد؛ schema existence با data readiness یکی نیست؛ expand/contract تضمین zero downtime نیست؛ rollback و forward repair و restore یک چیز نیستند؛ و artifact presence جای observation واقعی را نمیگیرد.
۲. مسیرها — scaffold تغییر میکند، evidence bar نه
Foundation مسیر phaseها را با checkpointهای صریح میبیند. Repair فقط misconception تشخیصدادهشده را بازسازی میکند؛ مثلاً کسی که «ستون اضافه شد پس migration تمام شد» میگوید، باید data-readiness و compatibility gate را دوباره اجرا کند. Experienced میتواند syntax را فشرده کند، اما باید همان شش dimension و transfer مستقل را تحویل دهد.
قبل از هر phase چهار سؤال را بنویسید: contract فعال کدام است؟ چه چیزی هنوز نباید حذف/اجباری شود؟ observation چه چیزی اجازهٔ عبور به phase بعد میدهد؟ اگر عبور شکست خورد، fallback واقعی چیست؟ اگر پاسخ فقط «migration ran successfully» باشد، evidence ناقص است.
۳. مدل ذهنی — current → expand → transition → overlap → enforce → contract
مدل این درس یک زنجیرهٔ stage و gate است:
current contract → expand schema → backfill/verify → old+new overlap → enforce invariant → contract/remove old path
در current contract نسخهٔ قدیمی و دادهٔ موجود authority هستند. در expand ساختار جدید اضافه میشود ولی هنوز نباید contract قدیمی را بشکند. در data transition دادهٔ موجود به representation جدید منتقل و اندازهگیری میشود. در overlap old/new reader و writer همزمان بررسی میشوند. فقط بعد از evidence کافی میتوان invariant جدید را enforce کرد. در contract مسیر قدیمی زمانی حذف میشود که removal gate ثابت کند مصرفکنندهٔ قدیمی باقی نمانده است.
asset://DAT-005/DAT-005-A1 همین flow را با evidence gate و abort path نمایش میدهد. هیچ arrow صرفاً زمانی نیست؛ هر عبور باید یک observation داشته باشد.
۴. لایه پایه — شش قرارداد فنی
Migration contract
Migration را بهصورت «قبل/بعد + transition states» تعریف کنید. old contract، target contract و intermediate stateها باید مشخص باشند. DDL بدون این مدل نمیتواند compatibility را اثبات کند.
ALTER lock scope
منبع frozen PG18-ALTERTABLE میگوید subformهای ALTER TABLE lock levelهای متفاوت دارند و در حالت کلی ACCESS EXCLUSIVE گرفته میشود مگر subform خلافش را مشخص کند. نتیجهٔ عملی: از یک ALTER TABLE مشاهدهشده برای همهٔ subformها generalize نکنید. قبل از production planning، exact subform را با مرجع همان نسخه تطبیق دهید.
Data transition
ایجاد phone_e164 به معنای آمادهبودن rowهای موجود نیست. backfill باید count و invalid/null residue داشته باشد. enforcement مثل SET NOT NULL قبل از data readiness ممکن است fail کند یا old writer را بشکند.
Compatibility window
Expand/backfill/switch/contract یک pattern برای کاهش ریسک overlap است، نه promise «zero downtime». باید old reader، old writer، new reader و new writer را جداگانه model کنید. اگر old writer فقط phone_legacy بنویسد ولی phone_e164 زود NOT NULL شود، compatibility window شکسته است.
Recovery decision
Rollback schema، forward repair data و restore از backup سه response جدا هستند. وقتی transformation اطلاعات را از دست میدهد، down migration ممکن است فقط shape قبلی را برگرداند، نه data قبلی را. recovery باید از reversibility واقعی و evidence انتخاب شود.
Migration evidence
Completion یعنی schema apply شده + invariant evidence + compatibility evidence + failure/recovery evidence. وجود فایل migration، generated SQL یا یک happy-path query کافی نیست.
۵. توضیح عمیق — چرا ترتیب gateها اهمیت دارد
Fixture درس با phone_legacy شروع میشود. Expand امن ابتدا ستون nullable میافزاید:
ALTER TABLE customer_contact ADD COLUMN phone_e164 text;
این phase هنوز data readiness را ادعا نمیکند. سپس backfill bounded اجرا میشود. در fixture محلی فقط دادههایی که قابل نرمالسازیاند تبدیل میشوند و verification residue را اندازه میگیرد. اگر حتی یک row مورد انتظار هنوز phone_e164 IS NULL باشد، enforcement gate بسته است. اما اگر target contract شامل NOT NULL است، صفر بودن همین شمارنده کافی نیست: باید تمام ردیفهای phone_e164 IS NULL نیز شمرده شوند. lab بنابراین unresolved_legacy_rows و target_null_rows را جدا گزارش میکند. ردیف synthetic بدون legacy phone فقط با یک تصمیم صریح و مخصوص fixture حل میشود؛ حذف خاموش row بهعنوان migration repair پذیرفته نیست.
یک shortcut بد این است:
ALTER TABLE customer_contact
ALTER COLUMN phone_e164 SET NOT NULL;
اگر قبل از backfill اجرا شود، روی دادهٔ موجود شکست میخورد. حتی اگر بعد از backfill فعلی موفق شود، old writer ممکن است row تازهای بسازد که فقط phone_legacy دارد؛ پس compatibility writer باید قبل از enforcement حل شده باشد، مثلاً با dual-write یا switch کنترلشده.
Contract phase نیز خطر مستقل دارد. DROP COLUMN phone_legacy ممکن است schema را تمیز کند، اما اگر old reader هنوز deploy شده باشد، compatibility را میشکند. removal gate باید evidence مصرفکنندهها را داشته باشد، نه حدس زمانی.
درباره lock/rewrite نیز دو overclaim ممنوع است. از «constant default در یک مورد بهینه بوده» نمیتوان نتیجه گرفت هر تغییر column بدون rewrite است. از «ALTER TABLE معمولاً ACCESS EXCLUSIVE» هم نباید نتیجه گرفت تمام subformها همیشه یک lock level دارند. exact subform و نسخه را source-check کنید.
۶. مثال کامل — مهاجرت شماره تماس در هفت phase
lab://DAT-005/DAT005-LAB1 روی schema تصادفی disposable کار میکند.
- Baseline: old reader و old writer روی
phone_legacyکار میکنند. baseline counts و sample rows ثبت میشوند. - Expand:
phone_e164nullable اضافه میشود. old contract هنوز باید کار کند. - Negative enforcement probe: قبل از backfill،
SET NOT NULLعمداً اجرا میشود و باید failure path ثبت شود؛ این failure evidence بخشی از درس است. - Backfill + verification: دادهٔ قابل تبدیل به E.164 منتقل میشود. null/invalid residue و row counts ثبت میشود.
- Overlap: old reader، old writer، new reader و dual/new writer جدا بررسی میشوند. enforcement قبل از writer switch ممنوع است.
- Enforce: فقط پس از gate، invariant جدید enforce میشود. اگر old writer هنوز فقط legacy بنویسد، باید این probe compatibility break را آشکار کند.
- Contract: legacy column فقط پس از removal gate حذف میشود. چون normalization میتواند formatting قدیمی را از دست بدهد، rollback data را بدیهی فرض نکنید؛ forward repair یا restore ممکن است پاسخ درستتر باشد.
برای lock-risk probe یک session table را با lock سازگار با read نگه میدارد و session دیگر subform هدف را با lock_timeout محدود امتحان میکند. authoring build نتیجهٔ PostgreSQL را جعل نمیکند؛ learner باید stdout/stderr/SQLSTATE واقعی fixture خودش را ثبت کند.
۷. Failure modeها — shortcutهایی که باید رد شوند
«ستون ایجاد شد، پس migration complete است»
Schema existence فقط یک phase است. data readiness و application compatibility هنوز اثبات نشدهاند.
«اول NOT NULL را میگذارم، بعد backfill میکنم»
این ترتیب failure کلاسیک است. pre-existing nullها یا old writerهایی که column جدید را نمینویسند gate را میشکنند.
«old reader بعداً update میشود؛ الان legacy را drop میکنیم»
این تصمیم بدون removal evidence، contract break است. deployment plan بهتنهایی observation نیست.
«همه ALTER TABLEها همین lock را میگیرند»
منبع frozen دقیقاً خلاف generalization را میگوید: subformها میتوانند متفاوت باشند؛ exact operation را بررسی کنید.
«down migration یعنی rollback امن»
اگر transformation lossy بوده یا writes جدید فقط در representation جدید ثبت شده باشند، schema reversal لزوماً state قبلی را بازسازی نمیکند.
«یک successful apply یعنی recovery آماده است»
Recovery باید failure scenario و decision boundary داشته باشد؛ forward repair، restore و rollback interchangeable نیستند.
۸. پل Experienced — matrix را مستقیم پر کن
اگر syntax DDL و deployment را میدانید، مستقیماً با این matrix کار کنید:
Phase | Schema Change | Data Transition | Old R/W | New R/W | Lock/Rewrite Risk | Verification | Fallback | Removal Gate | Residual Risk
حداقل evidence Experienced همچنان شامل یک failure deliberate، یک compatibility rejection، یک source-bounded lock/rewrite decision، یک recovery decision و transfer مستقل است. حذف walkthrough مجاز است؛ حذف evidence مجاز نیست.
۹. Alternatives و trade-offها — migration strategy را از contract انتخاب کن
Big-bang change steps کمتری دارد اما overlap window را حذف میکند و coupling deploy/schema را بالا میبرد. فقط وقتی bounded evidence نشان دهد consumer overlap و rollback assumptions مسئله نیستند قابل دفاع است.
Expand/contract compatibility window میدهد اما مدت نگهداری دو representation، dual-write risk و removal discipline را افزایش میدهد. این pattern بهخودیخود zero downtime نیست.
Backfill در یک transaction بزرگ reasoning سادهتری دارد اما lock/WAL/time risk ممکن است زیاد شود. Batch backfill blast radius را محدود میکند ولی progress tracking و idempotency میخواهد. این درس performance benchmark نمیدهد؛ فقط trade-off را ثبت میکند.
Rollback-first وقتی reversible state واقعاً حفظ شده مناسب است. Forward repair وقتی data transformation یا writes جدید برگشت کامل را نامطمئن میکند منطقیتر است. Restore هزینه و data-loss window خودش را دارد و نباید نام «rollback» روی آن گذاشت.
۱۰. تمرین هدایتشده و مستقل
هدایتشده
Baseline را اجرا و old reader/writer behavior را ثبت کنید. ستون nullable را اضافه کنید و قبل از backfill عمداً SET NOT NULL را امتحان کنید. failure را نگه دارید. سپس backfill و verification residue را اجرا کنید و فقط اگر gate سبز است وارد overlap شوید.
old writer و dual writer را مقایسه کنید. اگر enforcement old writer را میشکند، تصمیم transition را اصلاح کنید. قبل از drop legacy، old reader را بهعنوان negative compatibility probe اجرا کنید.
مستقل
برای case انتقال شماره تماس، یک recovery table بنویسید: در هر phase اگر deploy جدید fail شد، آیا rollback schema ممکن است؟ آیا data transformation reversible است؟ آیا forward repair بهتر است؟ چه evidence لازم است تا تصمیم قطعی شود؟
۱۱. Verification و evidence — چهار نوع statement را جدا نگه دار
هر row در Schema Evolution Migration Review Record v1 باید این چهار کلاس را جدا کند:
- Prediction: قبل از اجرا چه outcomeای انتظار دارید.
- Observation: output واقعی PostgreSQL، count، error یا query result.
- Inference: observation داخل fixture چه چیزی را پشتیبانی میکند.
- Decision: عبور/توقف phase، recovery انتخابی و residual risk.
هر شش dimension migration_contract, alter_lock_scope, data_transition, compatibility_window, recovery_decision, migration_evidence باید traceable باشند. حداقل یک negative observation و یک repair/recovery result اجباری است.
۱۲. Assessment و transfer — tax region را بدون کپی حل کن
سیستم billing باید tax_region_text nullable و آزاد را به tax_region_code validated تبدیل کند، در حالی که دو نسخهٔ application overlap دارند. sequence تماس را کپی نکنید. old/new readers و writers را مشخص کنید، data transition و validation gate را تعریف کنید، lock/rewrite assumption را source-bound کنید و removal gate را بنویسید.
اگر mapping بعضی regionها ambiguous است، «backfill completed» ادعا نکنید؛ unresolved set باید evidence باشد. اگر format قدیمی بعد از normalization قابل بازیابی نیست، down migration را recovery قطعی معرفی نکنید. final decision باید learner-owned باشد.
۱۳. References و freshness boundary
این candidate فقط از دو source frozen استفاده میکند:
PG18-DDL-ALTER— PostgreSQL 18 table modification behavior برای columns, constraints, defaults و type changes؛ retrieved2026-09-02، review due2026-12-31.PG18-ALTERTABLE— PostgreSQL 18ALTER TABLEforms و lock-level behavior؛ retrieved2026-09-02، review due2026-12-31.
در تاریخ 2026-09-15 review due نرسیده است؛ بنابراین source scope گسترش داده نمیشود. fixture محلی production zero downtime، disaster readiness یا performance عمومی را اثبات نمیکند.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
DAT-005-S1 retrieval
DAT-005-S2 application
DAT-005-S3 diagnosis
DAT-005-S4 decision
DAT-005-S5 transfer
ملاکهای ارزیابی (rubric)
Critical dimensions: contract/recovery correctness, evidence quality, scope discipline, transfer independence. A blocking failure occurs when the learner treats DDL success or artifact presence as sole proof, omits compatibility/failure evidence, or fabricates runtime observations.
منابع و تازگی
مطالعهٔ موارد (case studies)
فایلهای آزمایشگاه
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)