Database Migration: পুরোনো code সচল রেখে schema বদল
Backward-Compatible Database Migrations
এই পাঠের সূচিপত্র
এই পাঠে যা শিখবেন
- Rolling deploy-এ schema compatibility
- Expand, backfill ও contract
- Lock risk ও rollback সীমা
সমস্যা দিয়ে শুরু
নতুন code product.display_name পড়ে, কিন্তু পুরোনো server এখনো name লিখছে। Deploy-এর মাঝখানে column rename করলে কিছু instance error দেয়। Zero-downtime migration শুধু migration command চালানো নয়; পুরোনো ও নতুন code একসঙ্গে কোন schema ব্যবহার করতে পারে তার compatibility plan।
সহজ করে বুঝি
Expand-contract pattern-এ আগে compatible new structure যোগ করা হয়। তারপর code transition ও resumable backfill হয়। Validation শেষে পুরোনো usage বন্ধ করে contract phase-এ old column/index সরানো হয়। Nullable column যোগ করা অনেক ক্ষেত্রে safer initial change, কিন্তু engine/version/table size অনুযায়ী DDL locking ও rewrite behavior পড়তে হবে। Backfill regular workload-এর সঙ্গে resource share করে; chunk size, pause ও progress checkpoint দরকার।
পরিচিত একটি উপমা
চলন্ত দোকানের signboard বদলাতে নতুন sign আগে বসিয়ে দুই নাম কিছুদিন রাখা যায়। Customer ও delivery team নতুন নাম চিনলে পুরোনোটি সরানো হয়। দরজা বন্ধ করে হঠাৎ সব নম্বর পাল্টালে active orders ভুল জায়গায় যেতে পারে।
নকশাটি দেখুন
Diagram লোড হচ্ছে…
Diagram-এর text flow দেখুন
flowchart LR E[Add nullable new field] --> C[Deploy compatible dual handling] C --> B[Resumable throttled backfill] B --> V[Validate coverage and reads] V --> S[Switch all consumers] S --> R[Remove old field in later release]
প্রথম step পুরোনো code ভাঙে না। Compatible code transitional period সামলায়। Backfill শেষে শুধু row count নয়, semantic correctness check করতে হবে। সব consumer switch হয়েছে evidence পাওয়ার পরে old column remove করা হয়। Rollback window-এ পুরোনো code-এর লাগবে এমন field আগে মুছবেন না।
PHP ও Laravel-এ প্রয়োগ
প্রথম PHP block migration up fragment, দ্বিতীয়টি controlled backfill command-এর fragment। products.name source, display_name new field ধরে নেওয়া হয়েছে। Concurrent updates-এর policy compatible application code-এ দরকার। Backfill whereNull condition already-updated target overwrite এড়ায়, কিন্তু নিজে dual-write race সমাধান করে না।
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
Schema::table('products', function (Blueprint $table) {
$table->string('display_name')->nullable();
});
DB::table('products')->select('id', 'name')
->whereNull('display_name')->orderBy('id')
->chunkById(200, function ($products) {
foreach ($products as $product) {
DB::table('products')->where('id', $product->id)
->whereNull('display_name')
->update(['display_name' => $product->name]);
}
});সুবিধা, সীমাবদ্ধতা ও trade-off
Additive releases বেশি deploy step নেয়, কিন্তু rollback ও mixed-version safety বাড়ায়। One-shot rename সহজ মনে হয়, active clients ভাঙতে পারে। Backfill ছোট chunks-এ memory কম, overhead বেশি; বড় chunks locks/IO বাড়াতে পারে। Index concurrently/online build support product-specific; migration framework default transaction behavior-এর সঙ্গে conflict আছে কি না যাচাই করুন।
সাধারণ ভুল
- Huge backfill schema migration transaction-এর মধ্যে রাখা।
- down method data loss ফিরিয়ে দিতে পারবে ধরে নেওয়া।
- Old queue worker এখনো old schema ব্যবহার করছে ভুলে যাওয়া।
আরও একটু গভীরে
Long-lived workers, scheduled tasks, reporting tools ও external consumers schema consumer। শুধু web deploy শেষ মানেই old usage শেষ নয়। New required constraint দেওয়ার আগে violating rows fix ও write path validate করুন। DDL lock timeout এবং statement timeout policy rehearsal করুন। Backup restore disaster recovery tool; routine rollback হিসেবে hours-long restore business objective মেটাবে কি না আলাদা বিচার করুন।
মনে রাখুন
Schema পরিবর্তন release protocol। Expand, compatible transition, validated backfill ও delayed removal রাখুন। Rollback code আর lost data restore আলাদা সক্ষমতা।
নিজে চেষ্টা করুন
একটি non-null phone field যোগ করার চার release plan লিখুন, যেখানে কিছু user-এর phone নেই। Null policy, validation, backfill source ও constraint timing দিন। Staging-এ old worker এবং new app একসঙ্গে চালিয়ে compatibility পরীক্ষা করুন।
নিজের বোঝা যাচাই করুন
1. Rename ঝুঁকিপূর্ণ কেন?
Mixed-version deployment-এ পুরোনো code পুরোনো নাম খুঁজতে পারে। Add-and-transition pattern compatibility window দেয়।
2. Nullable প্রথমে কেন?
Existing row ও old writer new value নাও দিতে পারে। পরে coverage ও valid write path নিশ্চিত করে stronger constraint দেওয়া যায়।
3. Backfill migration-এর ভিতর?
বড় data movement long lock/transaction ও deployment delay আনতে পারে। আলাদা resumable command/job প্রায়ই safer।
4. down মানেই rollback safe?
না। Dropped data automatically ফেরে না। Code rollback, schema rollback ও data recovery আলাদা plan।
5. Queue worker কেন গুরুত্বপূর্ণ?
Long-lived process পুরোনো code ধরে রাখতে পারে। Worker restart/drain ও schema compatibility release plan-এর অংশ।
আরও পড়ুন
এই পাঠের কুইজ
এই পাঠ থেকে ২টি প্রশ্ন। উত্তর দিয়ে ব্যাখ্যা দেখুন; অধ্যায়ের কুইজ আলাদাভাবে দিতে হবে।
এই পাঠের ২টি প্রশ্নের উত্তর দিন। পাস করতে দুটিই সঠিক হতে হবে।
জমা দেওয়ার পর সঠিক উত্তর ও ব্যাখ্যা দেখবেন। ফলাফল এই ব্রাউজারে সংরক্ষিত থাকবে। অনুশীলনের ফল অধ্যায় সম্পন্নের হিসাবে যোগ হয় না।
অগ্রগতি এই ব্রাউজারে সংরক্ষিত থাকে। শুধু পাঠ খুললে সম্পন্ন হয় না।