حالت تاریک
فصل ۵ — راهبردهای بازآرایی پایگاه داده
اینکه امروز بیشتر از دیروز میدانید خبر خوبی دربارهٔ امروز است، نه خبر بدی دربارهٔ دیروز.
— Ron Jeffries
این فصل برخی تجربیات ما در بازآرایی پایگاه داده در پروژههای واقعی را توصیف میکند و چند راهبرد بالقوه پیشنهاد میدهد که شاید بخواهید در نظر بگیرید. از بسیاری جهات، این فصل مجموعهای از «درسهای آموختهشده» را جمعبندی میکند که امیدواریم به تلاشهای پذیرش شما کمک کند. این درسها عبارتاند از:
- تغییرات کوچکتر اعمالشان آسانتر است.
- بازآراییهای تکی را بهطور یکتا شناسایی کنید.
- تغییر بزرگ را با تغییرات کوچک زیاد پیادهسازی کنید.
- جدول پیکربندی پایگاه داده داشته باشید.
- trigger را بر view یا همگامسازی دستهای ترجیح دهید.
- دورهٔ منسوخسازی (deprecation) کافی انتخاب کنید.
- راهبرد هیئت کنترل تغییر پایگاه داده (CCB) را ساده کنید.
- مذاکرات با تیمهای دیگر را ساده کنید.
- دسترسی به پایگاه داده را کپسوله کنید.
- بتوانید بهراحتی محیط پایگاه داده راهاندازی کنید.
- SQL را تکرار نکنید.
- داراییهای پایگاه داده را تحت کنترل تغییر قرار دهید.
- مراقب سیاست باشید.
۵.۱. تغییرات کوچکتر اعمالشان آسانتر است
وسوسهانگیز است چند تغییر را همزمان در پایگاه داده انجام دهید. مثلاً چه چیزی مانع میشود ستونی را از یک جدول به جدول دیگر منتقل کنید، نامش را عوض کنید و نوع استاندارد به آن اعمال کنید، همه با هم؟ هیچ چیز — جز این دانش که انجام همهٔ اینها یکجا سختتر و در نتیجه پرریسکتر از انجام گامبهگام است. اگر تغییر کوچکی بدهید و ببینید چیزی خراب شده، تقریباً میدانید کدام تغییر مشکل را ایجاد کرده.
تغییرات کوچک ریسک پروژه را کاهش میدهند
امنتر است گامهای کوچک و یکییکی پیش بروید. هرچه تغییر بزرگتر باشد، احتمال بیشتری دارد نقص وارد کنید و یافتن هر نقصی که وارد کردهاید سختتر میشود.
۵.۲. بازآراییهای تکی را بهطور یکتا شناسایی کنید
در طول پروژهٔ توسعهٔ نرمافزار، احتمالاً صدها بازآرایی و/یا تبدیل (transformation) روی طرحوارهٔ پایگاه داده اعمال میکنید. چون این بازآراییها اغلب روی یکدیگر بنا میشوند — مثلاً ممکن است ستونی را تغییر نام دهید و چند هفته بعد به جدول دیگر منتقلش کنید — باید مطمئن شوید بازآراییها به ترتیب درست اعمال شوند. برای این کار باید هر بازآرایی را بهنوعی شناسایی کنید و وابستگیهای بین آنها را مشخص کنید. جدول ۵.۱ سه راهبرد پایه برای این کار را مقایسه میکند. راهبردهای جدول ۵.۱ فرض میکنند در محیط تکبرنامهای و تکپایگاهداده کار میکنید.
جدول ۵.۱. راهبردهای شناسایی نسخه
| رویکرد | مزایا | معایب |
|---|---|---|
| شمارهٔ build. شمارهٔ build برنامه، معمولاً عدد صحیحی که ابزار build (مثلاً CruiseControl) وقتی برنامه کامپایل میشود و همهٔ تستهای واحد پس از تغییر — حتی اگر تغییر بازآرایی پایگاه داده باشد — با موفقیت اجرا میشوند، اختصاص میدهد. | راهبرد ساده. بازآراییها میتوانند بهعنوان صف First In, First Out (FIFO) بر اساس شمارهٔ build به ترتیب اعمال شوند. نسخهٔ پایگاه داده مستقیماً به نسخهٔ برنامه وابسته است. | فرض میکند ابزار بازآرایی پایگاه داده با ابزار build یکپارچه است، یا هر بازآرایی یک یا چند اسکریپت تحت کنترل پیکربندی است. بسیاری از buildها تغییر پایگاه داده ندارند؛ پس شناسههای نسخه برای پایگاه داده پیوسته نیستند (مثلاً ممکن است ۱، ۷، ۱۱، ۱۲، ... باشد نه ۱، ۲، ۳، ۴، ...). وقتی چند برنامه روی یک پایگاه داده توسعه مییابند مدیریت سخت است، چون هر تیم شمارههای build یکسانی دارد. |
| تاریخ/برچسب زمانی. تاریخ/زمان فعلی به بازآرایی اختصاص مییابد. | راهبرد ساده. بازآراییها بهعنوان صف FIFO مدیریت میشوند. | با رویکرد مبتنی بر اسکریپت، استفاده از تاریخ/برچسب زمانی بهعنوان نام فایل میتواند ناجور باشد. به راهبردی برای ارتباط بازآراییها با build مناسب برنامه نیاز دارید. |
| شناسهٔ یکتا. شناسهٔ یکتا، مثل GUID یا مقدار افزایشی، به بازآرایی اختصاص مییابد. | راهبردهای موجود برای تولید مقادیر یکتا (مثلاً میتوان از مولد globally unique identifier (GUID) استفاده کرد). | GUIDها نام فایل ناجوریاند. با GUID هم باید ترتیب اعمال را مشخص کنید. به راهبردی برای ارتباط بازآراییها با build مناسب برنامه نیاز دارید. |
وقتی در محیط چندبرنامهای هستید که چند تیم پروژه ممکن است بازآرایی روی همان طرحوارهٔ پایگاه داده اعمال کنند، باید راهی هم برای شناسایی تیمی که بازآرایی را تولید کرده پیدا کنید. سادهترین راه اختصاص شناسهٔ یکتا به هر تیم و گنجاندن آن در شناسهٔ بازآرایی است. بنابراین با راهبرد شمارهٔ build، تیم ۱ ممکن است بازآراییهایی با شناسههای ۱-۷، ۱-۱۲، ۱-۱۵ و غیره داشته باشد؛ و تیم ۷ بازآراییهایی با شناسههای ۷-۳، ۷-۷، ۷-۱۳ و غیره.
تجربهٔ ما این است که وقتی یک تیم مسئول یک پایگاه داده است، راهبرد شمارهٔ build بهترین کار را میکند. اما وقتی چند تیم میتوانند همان پایگاه داده را تکامل دهند، رویکرد تاریخ/برچسب زمانی بهتر است چون از روی تاریخ/برچسب زمانی بهراحتی میفهمید بازآراییها به چه ترتیبی اعمال شدهاند. با راهبرد شمارهٔ build نمیتوانید — مثلاً نمیتوانید تعیین کنید کدام بازآرایی اول است، ۱-۷ یا ۷-۷؟
با این حال، بهسادگی اعمال بازآراییها به ترتیب نیست. Scott در سازمانی کار میکرد که چهار تیم جدا میتوانستند همان طرحوارهٔ پایگاه داده را تکامل دهند. دو DBA — Fred و Barney — تیمهایی را که نزدیک هم کار میکردند پشتیبانی میکردند. اگرچه تلاش میکردیم تلاشهایشان را هماهنگ کنیم و بیشتر وقتها موفق میشدیم، اشتباه هم پیش میآمد. یکبار Fred بازآرایی Apply Standard Codes (صفحهٔ ۱۵۷) را روی یک ستون اعمال کرد و چند روز بعد Barney همان بازآرایی را برای تیم دیگر اعمال کرد، اما با مجموعهٔ متفاوتی از مقادیر «استاندارد». معلوم شد مقادیر «استاندارد» Barney درست بود، اما تا وقتی دو تیم تغییراتشان را به محیط تست پیشتولید promote نکردند و عملاً همدیگر را از کار انداختند، متوجه نشدیم. نکته این است که در محیط چندتیمی به راهبرد هماهنگی نیاز دارید (چند مورد بعداً در این فصل بحث میشود).
۵.۳. تغییر بزرگ را با تغییرات کوچک زیاد پیادهسازی کنید
تغییرات بزرگ در پایگاه داده، مثل پیادهسازی راهبرد کلید جایگزین (surrogate key) مشترک در همهٔ جدولها یا اعمال راهبرد نامگذاری یکنواخت در کل پایگاه داده، باید بهعنوان مجموعهای از بازآراییهای کوچک پیادهسازی شوند. این راهبرد از ضربالمثل قدیمی پیروی میکند: «فیل را چطور میخورید؟ یک لقمه در هر بار.»
تقسیم جدول موجود به دو جدول را در نظر بگیرید. اگرچه بازآرایی تکی Split Table (صفحهٔ ۱۴۵) داریم، در عمل برای انجامش باید بازآراییهای زیادی اعمال کنید. مثلاً باید تبدیل Introduce New Table (صفحهٔ ۳۰۴) را برای افزودن جدول جدید اعمال کنید، بازآرایی Move Column (صفحهٔ ۱۰۳) را چند بار (برای هر ستون) برای انتقال، و احتمالاً بازآرایی Introduce Index (صفحهٔ ۲۴۸) برای پیادهسازی کلید اصلی جدول جدید. برای پیادهسازی هر Move Column باید تبدیل Introduce New Column (صفحهٔ ۳۰۱) و تبدیل Move Data (صفحهٔ ۱۹۲) را اعمال کنید. هنگام انجام این کار ممکن است بفهمید باید یک یا چند بازآرایی کیفیت داده (فصل ۷، «بازآراییهای کیفیت داده») برای بهبود دادهٔ مبدأ در ستونهای جداگانه اعمال کنید.
۵.۴. جدول پیکربندی پایگاه داده داشته باشید
فصل ۳، «فرایند بازآرایی پایگاه داده»، نیاز به شناسایی نسخهٔ فعلی طرحواره را برای بهروزرسانی مناسب طرحواره بحث کرد. این نسخهٔ طرحواره باید راهبرد بازآرایی پایگاه دادهٔ شما را منعکس کند؛ مثلاً اگر بازآراییها را با راهبرد تاریخ/برچسب زمانی شناسایی میکنید، نسخهٔ فعلی طرحواره را هم با تاریخ/برچسب زمانی مشخص کنید. سادهترین راه داشتن جدولی است که این اطلاعات را نگه میدارد. در کد زیر، جدول تکسطر و تکستونی DatabaseConfiguration را میسازیم که راهبرد شمارهٔ build را منعکس میکند:
sql
CREATE TABLE DatabaseConfiguration
(SchemaVersion NUMBER NOT NULL);
INSERT INTO DatabaseConfiguration
( SchemaVersion ) VALUES (0);این جدول هر وقت بازآرایی پایگاه داده اعمال میشود با مقدار شناسهٔ آن بازآرایی بهروز میشود. مثلاً وقتی بازآرایی شمارهٔ ۱۷ را روی طرحواره اعمال میکنید، DatabaseConfiguration.SchemaVersion به ۱۷ بهروز میشود، همانطور که در کد زیر نشان داده شده:
sql
UPDATE DatabaseConfiguration
SET SchemaVersion = 17;۵.۵. trigger را بر view یا همگامسازی دستهای ترجیح دهید
در فصل ۲، «بازآرایی پایگاه داده»، آموختید وقتی چند برنامه به همان طرحوارهٔ پایگاه داده دسترسی دارند، اغلب به دورهٔ گذاری نیاز دارید که طرحوارهٔ اصلی و جدید هر دو در تولید وجود داشته باشند. به راهی نیاز دارید که صرفنظر از اینکه برنامه به کدام نسخهٔ طرحواره دسترسی دارد، دادهٔ سازگار ببیند. جدول ۵.۲ سه راهبردی که میتوانید برای همگام نگه داشتن داده استفاده کنید مقایسه میکند. تجربهٔ ما این است که trigger برای اکثریت قریب به اتفاق موقعیتها بهترین رویکرد است. چند بار از view استفاده کردهایم و بهندرت رویکرد دستهای. همهٔ مثالهای این کتاب فرض رویکرد همگامسازی مبتنی بر trigger را دارند.
جدول ۵.۲. راهبردهای همگامسازی طرحواره
| راهبرد | مزایا | معایب |
|---|---|---|
| Trigger. یک یا چند trigger پیادهسازی میشود که بهروزرسانی مناسب را روی نسخهٔ دیگر طرحواره انجام میدهد. | بهروزرسانی بلادرنگ. | گلوگاه احتمالی کارایی. احتمال چرخهٔ trigger. احتمال deadlock. اغلب دادهٔ تکراری ایجاد میکند (داده در طرحوارهٔ اصلی و جدید هر دو ذخیره میشود). |
| View. view(هایی) نمایانگر جدول(های) اصلی معرفی میشوند؛ Encapsulate Table With View (صفحهٔ ۲۴۳) را ببینید که هر دو طرحوارهٔ اصلی و جدید را بهدرستی بهروز میکند. | بهروزرسانی بلادرنگ. نیازی به جابهجایی فیزیکی داده بین جدولها/ستونها نیست. | viewهای قابلبهروزرسانی در برخی پایگاههای داده پشتیبانی نمیشوند، یا پایگاه داده join در view قابلبهروزرسانی را پشتیبانی نمیکند. پیچیدگی اضافی معرفی و در نهایت حذف view(ها). |
| بهروزرسانی دستهای. job دستهای که داده را پردازش و بهروز میکند بهطور منظم (مثلاً روزانه) اجرا میشود. | اثر کارایی همگامسازی داده در بارهای غیرپیک جذب میشود. | پتانسیل بزرگ مشکلات یکپارچگی ارجاعی (RI). باید نسخههای قبلی داده را نگه دارید تا تعیین کنید چه تغییراتی روی رکورد شده. وقتی در دورهٔ دستهای چند تغییر انجام میشود — مثلاً کسی دادهای را که در طرحوارهٔ اصلی و جدید هر دو هست بهروز کند — تعیین اینکه کدام تغییر(ها) پذیرفته شوند سخت است. اغلب دادهٔ تکراری ایجاد میکند (داده در طرحوارهٔ اصلی و جدید هر دو ذخیره میشود). |
۵.۶. دورهٔ گذار کافی انتخاب کنید
DBA باید دورهٔ گذار واقعبینانهای به بازآرایی اختصاص دهد که برای همهٔ تیمهای برنامهٔ دیگر کافی باشد. سادهترین رویکردی که یافتهایم توافق روی دورهٔ گذار مشترک برای دستههای مختلف بازآرایی و اعمال یکنواخت آن دوره است. مثلاً بازآراییهای ساختاری ممکن است دورهٔ گذار دو ساله و بازآراییهای معماری سه ساله داشته باشند. معایب اصلی این است که باید طولانیترین دورههای گذار را بپذیرید، حتی وقتی طرحوارهای را بازآرایی میکنید که تعداد کمی برنامهٔ با استقرار مکرر به آن دسترسی دارند. میتوانید این مشکل را با حذف فعال طرحوارهای در پایگاههای دادهٔ تولید که دیگر لازم نیست — حتی اگر دورهٔ گذار هنوز تمام نشده — یا با مذاکره برای دورهٔ گذار کوتاهتر از طریق CCB پایگاه داده یا مذاکرهٔ مستقیم با تیمهای دیگر کاهش دهید.
۵.۷. راهبرد هیئت کنترل تغییر پایگاه داده (CCB) را ساده کنید
Scott با شرکتی کار کرد که CCB پایگاه دادهای داشت متشکل از DBAهای عملیاتی که داراییهای دادهٔ سازمانی را خوب میشناختند. این CCB هفتهای یکبار جلسه داشت و در جلسات، DBAهای پروژه فهرستی از تغییرات پیشنهادی که تیمهایشان میخواستند روی منابع دادهٔ تولید موجود اعمال کنند میآوردند (تیمها آزاد بودند منابع دادهای که هنوز در تولید نبودند را تغییر دهند). CCB تعیین میکرد آیا تغییر مجاز است و اگر بله، دورهٔ منسوخسازی چقدر باشد. مزیتش این است که تصور کنترل سختگیرانهتری از سوی CCB وجود دارد (البته اگر تیم توسعه تصمیم بگیرد از دورشان برود، این راهبرد کاملاً فرو میپاشد). معایبش این است که تلاشهای توسعهٔ تیمها را کند میکند. حتی وقتی تصمیم را در چند ساعت یا روز بگیرید، باز هم زمانی است که تیم توسعه باید طرحوارهٔ اصلی را تحمل کند. پیشنهاد ما این است که یا به DBA پروژه اختیار تغییر طرحوارهٔ پایگاه داده در صورت نیاز داده شود — با این تفاهم که CCB بعداً ممکن است تصمیم بگیرد تغییر را لغو کند — یا CCB روزانه برای بحث تغییرات جلسه داشته باشد.
۵.۸. مذاکرات با تیمهای دیگر را ساده کنید
راهبرد جایگزین برای تعیین دورهٔ گذار، مذاکرهٔ بازآراییهای تکی با مالکان هر سیستمی است که ممکن است تحت تأثیر بازآرایی پایگاه داده قرار گیرند. میتوانید این کار را یکبار برای هر بازآرایی یا بهصورت دستهای در جلسهٔ منظم مذاکرهٔ تغییر طرحوارهٔ پایگاه داده انجام دهید. مزایای این رویکرد این است که تغییرات بالقوه را به همهٔ متأثران اطلاع میدهد و احتمالاً دقیقترین دورهٔ گذار را نتیجه میدهد (بهشرطی که همه در جلسه بتوانند دقیق پیشبینی کنند چه زمانی تغییرات لازم خود را مستقر میکنند). معایب اصلی این است که ممکن است کند و طاقتفرسا باشد. ما هرگز در عمل این را امتحان نکردهایم. اگر امتحان میکنید، پیشنهاد میکنیم همهچیز را تا حد ممکن ساده نگه دارید.
۵.۹. دسترسی به پایگاه داده را کپسوله کنید
در فصل ۲ استدلال کردیم هرچه دسترسی به پایگاه داده بیشتر کپسوله شود، بازآرایی آسانتر است. حداقل، حتی اگر برنامهٔ شما SQL سختکد شده دارد، باید تلاش کنید آن کد SQL را در یک جا قرار دهید تا هنگام نیاز بهراحتی پیدا و بهروز کنید. میتوانید منطق SQL را بهشکل یکنواخت پیادهسازی کنید، مثلاً عملیات save()، delete()، retrieve() و find() برای هر کلاس کسبوکار. یا میتوانید اشیای دسترسی داده (Data Access Objects — DAO) پیادهسازی کنید — کلاسهایی که منطق دسترسی داده را جدا از کلاسهای کسبوکار پیادهسازی میکنند. مثلاً کلاسهای کسبوکار Customer و Account بهترتیب کلاسهای CustomerDAO و AccountDAO دارند. بهتر از آن، میتوانید کلاً از کد SQL صرفنظر کنید و منطق دسترسی پایگاه داده را از متادیتای نگاشت تولید کنید (Ambler 2003).
۵.۱۰. بتوانید بهراحتی محیط پایگاه داده راهاندازی کنید
افراد در طول چرخهٔ عمر پروژه به تیم میپیوندند و در نهایت هم میروند. همانطور که در شکل ۵.۱ میبینید، تیم(های) شما باید بتوانند نمونههایی از پایگاه داده بسازند — اغلب با نسخههای مختلف طرحواره روی محدودهای از ماشینها، همانطور که در فصل ۴، «استقرار در تولید»، آموختید. مؤثرترین راه این است با اسکریپت نصب که DDL اولیه را برای ایجاد طرحوارهٔ پایگاه داده و هر اسکریپت تغییر قابلاعمال اجرا میکند، و سپس مجموعهٔ تست رگرسیون را برای اطمینان از موفقیت نصب اجرا میکند.
شکل ۵.۱. sandboxها.
۵.۱۱. SQL را تکرار ننویسید
یکی از نکات خوب SQL این است که نوشتنش نسبتاً آسان است. متأسفانه چون نوشتنش آسان است، دیدهایم کد SQL اغلب در سراسر برنامه و حتی در خود پایگاه داده در viewها، stored procedureها و triggerها تکرار میشود. هرچه کد SQL بیشتر باشد، بازآرایی طرحوارهٔ پایگاه داده سختتر است چون احتمالاً کد بیشتری به هر چیزی که بازآرایی میکنید وابسته است. بهتر است SQL را در یک بسته یا کلاس بنویسید، از متادیتا تولیدش کنید، یا کد SQL را در فایلهای XML ذخیره کنید که در زمان اجرا خوانده میشوند.
۵.۱۲. داراییهای پایگاه داده را تحت کنترل تغییر قرار دهید
فصل ۱، «توسعهٔ تکاملی پایگاه داده»، توضیح داد چقدر مهم است همهٔ داراییهای پایگاه داده، مثل مدلهای داده و اسکریپتهای پایگاه داده، تحت مدیریت کنترل تغییر (change control) قرار گیرند. هر دوی ما در تیمهایی بودهایم که DBAها و گاهی حتی توسعهدهندگان این کار را نمیکردند. همانطور که انتظار میرود، این تیمها اغلب برای شناسایی نسخهٔ درست مدل داده یا اسکریپت تغییر هنگام استقرار برنامهها در تست پیشتولید و گاهی حتی در تولید مشکل داشتند. داراییهای پایگاه داده، مثل سایر داراییهای حیاتی پروژه، باید مؤثر مدیریت شوند. مفیدترین حالت وقتی است که داراییهای پایگاه داده در همان مخزن برنامه co-locate شوند تا ببینیم چه کسی تغییر داده و قابلیت rollback پشتیبانی شود.
۵.۱۳. مراقب سیاست باشید
معرفی تکنیکهای تکاملی پایگاه داده، و بهویژه بازآرایی پایگاه داده، احتمالاً تغییر بزرگی در سازمان شماست. همانطور که Manns و Rising (2005) در Fearless Change اشاره میکنند، هنگام تلاش برای بهبود روش کار، سیاست احتمالاً سر برمیآورد. اگرچه بسیاری از متخصصان IT ترجیح میدهند سیاست را نادیده بگیرند و سادهانگارانه باور کنند بالاتر از آناند، این کار را بهخطر خودشان انجام میدهند. تکنیکهایی که در این کتاب توصیف میکنیم کار میکنند؛ چون خودمان انجام دادهایم. همچنین میدانیم بسیاری از متخصصان سنتی داده از این تکنیکها تهدید میشوند — و حق هم دارند — چون مجبورشان میکند تغییرات مهمی در روش کار آیندهشان بدهند. اگر میخواهید بازآرایی پایگاه داده را در سازمان بپذیرید، احتمالاً باید «بازی سیاسی» را هم انجام دهید.
۵.۱۴. آنچه آموختید
بازآرایی پایگاه داده تکنیک توسعهٔ نسبتاً جدیدی است، اما هنوز میتوانید از تجربیات دیگران بیاموزید. در این فصل برخی تجربیات خود را به اشتراک گذاشتیم و چند راهبرد جدید پیشنهاد دادیم که شاید بخواهید امتحان کنید.
منابع آنلاین
ما لیست پستی Agile Databases را در Yahoo Groups مدیریت میکنیم. آدرس گروه: groups.yahoo.com/group/agileDatabases/. شما را دعوت میکنیم در بحثها شرکت کنید و تجربیاتتان را به اشتراک بگذارید.
همچنین www.databaserefactoring.com و www.agiledata.org را نگه میداریم که فهرستهای بهروز بازآراییهای پایگاه داده در آنها نگهداری میشود. بازآراییهای جدید با کشف شدن اضافه خواهند شد.