امنیت، هویت، استقرار و تاب‌آوری · فصل ۷ — Dependency، Contract، Event و Network Failure · 113

Schema Drift

failure را بعد از وقوع و به‌صورت موردی تحلیل می‌کند و هنوز detection، containment و repair path از قبل طراحی نشده است. موضوع جاری: «Schema Drift». می‌تواند failure family «Schema Drift» را بازتولید/تشخیص دهد و detection، containment و recovery مناسب را تعیین کند.

Schema Drift — en-US

خلاصهٔ درس

failure را بعد از وقوع و به‌صورت موردی تحلیل می‌کند و هنوز detection، containment و repair path از قبل طراحی نشده است. موضوع جاری: «Schema Drift».

می‌تواند failure family «Schema Drift» را بازتولید/تشخیص دهد و detection، containment و recovery مناسب را تعیین کند.

خروجی این درس

می‌تواند failure family «Schema Drift» را بازتولید/تشخیص دهد و detection، containment و recovery مناسب را تعیین کند.

پیش‌نیازها

1. مسئله واقعی چیست؟

Schema Drift زمانی رخ می‌دهد که شکل داده‌ای که یک writer تولید می‌کند، شکلی که یک reader انتظار دارد، یا projection واقعی یک environment با هم از مسیر توافق‌شده خارج شوند. نکته مهم این است که «متفاوت بودن» مساوی «خراب بودن» نیست. ممکن است producer یک ستون nullable جدید اضافه کند و reader قدیمی آن را نادیده بگیرد؛ این تفاوت واقعی است، اما در آن مسیر الزاماً failure ایجاد نمی‌کند. هدف درس این است که drift را از روی evidence و boundary واقعی تشخیص دهیم، نه از روی وجود یک migration file یا یک diff متنی.

2. سه projection را جدا نگه دار

برای هر incident سه تصویر مستقل بساز: writer schema، reader schema و environment/runtime projection. writer می‌گوید چه چیزی تولید یا نوشته می‌شود؛ reader می‌گوید چه چیزی decode/parse/consume می‌شود؛ environment projection نشان می‌دهد مقصد واقعی چه object، column، type یا constraintی دارد. اگر این سه را یکی کنیم، خیلی زود نتیجه‌گیری اشتباه می‌کنیم. Schema Drift Failure Record v1 باید مشخص کند هر مشاهده از کدام projection آمده است.

3. ادعای رسمی PostgreSQL درباره logical replication

در PostgreSQL 18، logical replication خود schema definition و DDL را replicate نمی‌کند؛ published table باید روی subscriber وجود داشته باشد و تغییرات schema باید جداگانه هماهنگ شوند. بنابراین وجود replication سالم برای data به‌تنهایی اثبات نمی‌کند که schema دو سمت sync است. این claim فقط درباره رفتار PostgreSQL logical replication است و به همه replication systemها تعمیم داده نمی‌شود.

4. pg_dump --schema-only چه چیزی را ثابت می‌کند؟

pg_dump --schema-only تعریف objectها را بدون table data یا statistics خروجی می‌دهد. این ابزار می‌تواند یک snapshot محدود از schema بسازد و برای comparison مفید است؛ اما snapshot به‌تنهایی اثبات نمی‌کند application با آن schema سازگار است، migration واقعاً همه environmentها را به‌روز کرده، یا data موجود با constraint جدید سازگار است. آن را evidence input بدان، نه proof نهایی.

5. compatible drift و incompatible drift

Compatibility باید نسبت به یک path واقعی سنجیده شود. اضافه شدن nullable field که reader قدیمی ignore می‌کند می‌تواند compatible باشد. rename شدن required field، حذف field موردنیاز، type change غیرقابل‌تبدیل، یا constraintی که یک environment داده‌ای را می‌پذیرد و دیگری رد می‌کند می‌تواند incompatible باشد. پس classification به «نوع diff + رفتار reader/writer + evidence failure» نیاز دارد.

6. counterexample: nullable field جدید

در fixture دوم، writer فیلد nickname را nullable اضافه می‌کند، در حالی که reader قدیمی unknown field را ignore می‌کند. اگر صرفاً schema diff را ببیند، ممکن است learner آن را breaking بداند؛ اما هیچ failure بازتولیدشده‌ای در path نداریم. این case عمداً نشان می‌دهد schema equality شرط لازم compatibility نیست.

7. rename required field؛ اولین failure قابل دفاع

در fixture سوم، writer از customer_id به account_id می‌رود اما reader هنوز customer_id را required می‌داند. اینجا failure را با decode/validation error بازتولید می‌کنیم. affected path روشن است: writer payload → reader decoder. containment می‌تواند توقف rollout یا compatibility alias باشد؛ repair باید order مشخص داشته باشد، مثلاً reader اول هر دو نام را بپذیرد، writer بعد تغییر کند و در پایان legacy field حذف شود.

8. constraint drift فقط یک diff متنی نیست

ممکن است دو environment columnهای یکسان داشته باشند اما constraint متفاوت باشد. اگر staging مقدار NULL را بپذیرد و subscriber یا production برای همان field NOT NULL داشته باشد، acceptance behavior تغییر می‌کند. این failure در storage boundary ظاهر می‌شود. مقایسه نام columnها کافی نیست؛ constraintها و accepted-data domain نیز بخشی از schema projection هستند.

9. logical replication schema lag

در یک fixture، publisher یک column جدید تولید می‌کند اما subscriber هنوز projection قدیمی دارد. PostgreSQL به‌صورت خودکار DDL را logical replicate نمی‌کند، بنابراین lag می‌تواند تا رسیدن داده ناسازگار پنهان بماند. containment باید reversible باشد: rollout/replication path را محدود کن، subscriber schema را با order امن اصلاح کن و بعد همان mutation را دوباره اجرا کن. «resume شد» به‌تنهایی proof نیست؛ rerun oracle باید همان boundary را بسنجند.

10. type drift و تبدیل‌پذیری

Type difference همیشه failure نیست و همیشه هم compatible نیست. اگر text representation قابل تبدیل باشد، برخی مسیرها می‌توانند کار کنند؛ اگر reader integer می‌خواهد و writer مقدار non-numeric string می‌دهد، failure واقعی داریم. به‌جای قانون کلی، value domain، conversion behavior و reader requirement را ثبت کن. Classification باید از fixture evidence بیاید.

11. containment با repair فرق دارد

Containment برای محدود کردن blast radius است: pause rollout، freeze writer، route به version سازگار یا موقتاً block کردن mutation. Repair یعنی boundary دوباره به حالت پشتیبانی‌شده برگردد: reader-first migration، additive compatibility window، environment schema synchronization یا اصلاح mapper. containment را closure اعلام نکن؛ بعد از repair باید independent rerun داشته باشی.

12. OPEN وقتی evidence ناقص است

اگر writer snapshot را داری ولی reader snapshot یا runtime projection را نداری، علت را حدس نزن. state باید OPEN_BOUNDARY_UNRESOLVED بماند و unknownها صریح ثبت شوند. تصمیم حرفه‌ای همیشه diagnosis قطعی نیست؛ گاهی بهترین تصمیم این است که بگویی کدام evidence کم است و چه probe محدودی آن را جمع می‌کند.

13. transfer: event payload و database projection

در transfer، row-shaped data جای خود را به event payload + mapper + database projection می‌دهد. event v2 فیلد total_cents را به amount_cents تغییر می‌دهد، mapper قدیمی هنوز total_cents را می‌خواند، اما database column total_cents عمداً می‌تواند نام متفاوتی داشته باشد. drift واقعی در event→mapper boundary است؛ تفاوت نام database به‌تنهایی failure نیست. learner باید boundary را از صفر بازسازی کند.

14. Lab و 64 assertion

Lab کاملاً local و synthetic است و ۸ fixture دارد. evaluator هشت بُعد را برای هر case می‌سنجد: schema projection، reader/writer boundary، compatibility class، failure reproduction، affected path، containment، repair order و rerun oracle. مجموعاً ۶۴ assertion داریم. هدف حفظ evidence discipline است، نه حفظ کردن labelها.

15. چک‌لیست خروج

برای خروج مستقل باید writer/reader/environment projection را جدا ثبت کنی؛ exact drift object را نام ببری؛ compatibility را نسبت به path واقعی بسنجی؛ حداقل یک alternative ضعیف را با negative evidence رد کنی؛ containment را از repair جدا کنی؛ repair order را مشخص کنی؛ mutation را بعد از repair دوباره اجرا کنی؛ و اگر evidence ناقص است OPEN را حفظ کنی. این درس درباره fixture مصنوعی است و هیچ ادعایی درباره وضعیت یک production database واقعی نمی‌کند.

ارزیابی

پاسخ‌نامه‌ی این درس در بسته‌ی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار می‌فرستد.

FLR-003-AF1 formative

lesson ✗AI ✗notes ✗

FLR-003-AF2 formative

lesson ✗AI ✗notes ✗

FLR-003-AF3 formative

lesson ✗AI ✗notes ✗

FLR-003-AS1 summative

lesson ✗AI ✗notes ✗

FLR-003-AS2 transfer

lesson ✗AI ✗notes ✗
ملاک‌های ارزیابی (rubric)
DimensionSufficient evidenceBlocking failure
Schema projectionsWriter, reader, and environment projections remain separateMigration artifact treated as universal runtime proof
BoundaryExact reader/writer or storage boundary identifiedGeneric “schemas differ” label only
CompatibilityCompatible/breaking judgment tied to observed pathEvery textual diff labeled breaking
Repair orderReversible containment and ordered repair are explicitTemporary containment presented as closure
Verification/transferMutation rerun and event-transfer case rebuild the decisionGreen rerun or copied row answer treated as causal proof

منابع و تازگی

PostgreSQL 18 — Logical Replication Restrictions / Subscription
PostgreSQL Global Development Group ·
PostgreSQL 18 — pg_dump
PostgreSQL Global Development Group ·

مطالعهٔ موارد (case studies)

تصاویر درس

FLR-003-A1

فایل‌های آزمایشگاه

Use only the supplied deterministic synthetic fixtures. For each case, build Schema Drift Failure Record v1.

Keep writer schema, reader schema, and environment projection separate. A migration artifact or schema-only snapshot is evidence, not proof that every environment is compatible. Do not classify every difference as breaking; reproduce impact on the observed reader/writer path. Preserve UNKNOWN when evidence is incomplete.

The transfer case changes from row-shaped data to event payload plus database projection. Rebuild the affected boundary from event, mapper, and projection evidence instead of copying the row-based answer.

رسانه و اسلایدهای درس

MAKNOW_FLR-003_DECISION_EVIDENCE_TABLE_v1.0.svg
DECISION EVIDENCE TABLE v1.0.svg
MAKNOW_FLR-003_FAILURE_REPAIR_v1.0.svg
FAILURE REPAIR v1.0.svg
MAKNOW_FLR-003_PRIMARY_MODEL_v1.0.svg
PRIMARY MODEL v1.0.svg
MAKNOW_FLR-003_WORKED_EXAMPLE_v1.0.svg
WORKED EXAMPLE v1.0.svg

فایل‌های آموزشی (دانلود)

XLSXSchema Drift Failure Record v1 v1.0.0.xlsxفایل‌های آموزشی (دانلود)
DOCXSchema Drift Failure Record v1 WORKSHEET v1.0.0.docxفایل‌های آموزشی (دانلود)
PDFSchema Drift Failure Record v1 WORKSHEET v1.0.0.pdfفایل‌های آموزشی (دانلود)