رفتن به مطلب

تغييرات آنلاين جدول‌ها با استفاده از قابليت Edition در Oracle 11g R2


ارسال های توصیه شده

 

 

1004215.jpg

نويسنده: تام‌كايت منبع: سايت شركت اوراكل ترجمه : امين كلانتري

 

اشاره: در مقاله «Edition در Oracle 11g R2»، در شماره 108 ماهنامه با قابليتي به نام Edition Base Redefinition آشنا شديد، اين قابليت مهم‌ترين ويژگي افزوده‌شده به Oracle 11g Release 2 است. همان‌طور كه به خاطر داريد، Edition Base Redefinition يعني توانايي ارتقاي برنامه‌ها و كدها در سطح پايگاه‌داده در همان زمان كه پايگاه‌داده فعال و در حال سرويس‌دهي است.

در مقاله «Edition در Oracle 11g R2»، در شماره 108 ماهنامه با قابليتي به نام Edition Base Redefinition آشنا شديد، اين قابليت مهم‌ترين ويژگي افزوده‌شده به Oracle 11g Release 2 است. همان‌طور كه به خاطر داريد، Edition Base Redefinition يعني توانايي ارتقاي برنامه‌ها و كدها در سطح پايگاه‌داده در همان زمان كه پايگاه‌داده فعال و در حال سرويس‌دهي است. سوابق پايگاه‌داده اوراكل نشان مي‌دهد، اين شركت سعي كرده تا امكان انجام بسياري از كارها را به صورت آنلاين فراهم کند كه از جمله آن‌ها عبارتند از: امكان تغيير اكثر پارامترهاي سيستم (تنها نود مورد از 350 پارامتر سيستم را نمي‌توان به صورت آنلاين تغيير داد)، سازماندهي دوباره اشيا، تبديل يك جدول معمولي به يك جدول پارتيشن‌بندي‌شده، بازيابي فضاي آزاد و...، ايجاد انديس‌ها، اعمال بسته‌هاي‌اصلاحي پايگاه‌داده با استفاده از Oracle RAC (سرنام Oracle Real Application Cluster) ارتقاي پايگاه‌داده از يك نسخه اصلي به نسخه اصلي ديگر. اما اوراكل با عرضه Oracle 11g Release 2، امكان «ارتقاي برنامه‌هاي كاربري» هنگام آنلاين‌بودن سيستم را فراهم مي‌كند. در مقاله قبلي يك سناريوي ساده را بررسي كرديم. در آن مقاله نسخه شماره 1,0 برنامه در سطح پايگاه‌داده، به تغييراتي نياز داشت. به خصوص بايد يكي از كدهاي PL/SQL را اصلاح مي‌كرديم. در اين موارد مدير پايگاه‌داده، بايد يك برنامه‌ زمان‌بندي براي غيرفعال‌كردن سرويس‌ها و اعمال تغييرات مذكور ادامه دهد، زيرا او بايد كدها را دوباره كامپايل كند و اين كار مستلزم عدم استفاده كاربران از برنامه‌هاي مذكور است. همان‌طور كه بيشتر مديران سيستم مطلع هستند، شما نمي‌توانيد زماني كه كسي از يك برنامه PL/SQL استفاده مي‌كند، آن كد را كامپايل كنيد. به علاوه، حتي اگر بتوانيد اين كار را انجام دهيد، در اين صورت كاربران شما با پيام خطاي «ORA-04068: exitsting state of packages has been discarded» مواجه مي‌شوند. اين شرايط انجام هرگونه ارتقا يا اصلاح برنامه‌ها را به صورت آنلاين، غيرممكن مي‌کند و اين همان چيزي است كه به واسطه ارائه Edition-Based Redefinition امكان پياده‌سازي آن وجود دارد. در حال حاضر مي‌توان يك برنامه را به صورت آنلاين و همان زماني كه كاربران در حال استفاده از كد قبلي هستند، اصلاح كرد و ارتقا داد. در شماره قبلي ارتقاي برنامه شامل مراحل ساده‌اي بود، ما كد را جايگزين كرده و بدون آن‌كه كاربر متوجه شود، كد PL/SQL را به صورت آنلاين بررسي كرديم. اين بار نه تنها اشيايي را كه نوع آن‌ها قابل ويرايش (يعني واحدهاي كد PL/SQL) است، تغيير مي‌دهيم، بلكه مي‌خواهيم تغييراتي را در يك شماي فيزيكي ايجاد كنيم. اين بار هدف ما، حداقل كردن زمان غيرفعال‌بودن سيستم است، به نحوي كه اين كاهش زمان براي تغيير كد و اسكيماي فيزيكي قابل قبول باشد.

در Oracle Database 11g Release 2، انواع اشيا همگي در دو گروه دسته‌بندي مي‌شوند: قابل ويرايش و غيرقابل‌ويرايش. اشياي زير از نوع قابل‌ويرايش هستند:

1- Synonym

2- Views ( شامل viewهاي قابل ويرايش كه در اين قسمت، بررسي خواهند شد)

3- همه اشيا نوع PL/SQL (نظير توابع، رويه‌ها، بسته‌ها و...)

ساير اشيا نظير جدول‌ها، از نوع غيرقابل‌ويرايش هستند. اما اين حقيقت ما را از تصور اين كه اشياي غيرقابل ويرايش را نمي‌توان در فرآيند تغيير نسخه دخيل كرد، نادرست است.

 

ابتدا مثالي را بررسي مي‌كنيم كه قرار است مثال‌هاي مقاله بر مبناي آن ارائه شوند. شِماي استاندارد HR، يك جدول با نام EMPLOYEES دارد. اين جدول شامل فهرست همه كارمندان يك شركت است و خصيصه‌هايي نظير نام، نام خانوادگي، آدرس ايميل و شماره تلفن آن‌ها را دربرمي‌گيرد. وانمودمي‌كنيم اين جدول، بخشي از برنامه‌ها و سيستم‌هاي يك شركت مستقر در امريكا است. درنتيجه شماره تلفن‌ها، به صورتي ذخيره‌شده‌اند كه در تمام شركت‌هاي مستقر در امريكا، معمول است، به‌عنوان مثال، به صورت 650،507،9876. شماره‌هاي بين‌المللي به صورتي ذخيره مي‌شوند كه كد escape را داشته باشد و بعد از آن كد كشور و شماره تلفن قرار مي‌گيرد، نظير: 011،44،1644،429262

 

اين شركت فرضي، خريداري شده و اكنون بخشي از يك شركت بين‌المللي است. براي آن‌كه اين شركت، استانداردهاي شركت مادر را رعايت كند، شركت خريداري‌شده بايد نحوه ذخيره شماره‌ تلفن‌ها را تغيير دهد. هم‌اكنون اين شركت بايد همه شماره‌ها را در دو ستون ذخيره و به صورت دو بخشي نمايش دهد: شامل فيلد كد كشور و شماره تلفن. بنابراين، به‌عنوان مثال درباره دو شماره تلفن مثال قبل، نحوه ذخيره شماره، قبل و بعد از تغيير ساختار به‌صورت زير خواهد بود.

قبل بعد كد كشور شماره تلفن

كد كشور شماره تلفن

1+ 6876، 507، 650

9876 ، 507 ، 650 44+ 429262، 1644

262 ، 429 ، 1644 ، 44 ، 011

حال آن تغيير كوچك (كه البته فقط در ظاهر يك تغيير كوچك است) بايد در چنديل مرحله انجام شود. از همه مهم‌تر آن‌كه ما بايد مراحل زير را بگذرانيم:

1- بايد اسكيماي موجود را تغييرداده و دو ستون جديد به نام‌هاي COUNTRY_CODE و # PHONE را به جدول EMPLOYEE اضافه كنيم.

2- بايد اسكيماي موجود را تغيير داده و ستون PHONE_NUMBER را از جدول EMPLOYEE حذف كنيم.

3- يك انديس جديد با نام # PHONE براي جست‌وجوي سريع ايجاد كنيم (به‌احتمال بايد انديس‌هاي ديگري نيز ايجاد كنيم كه فعلاً براي راحتي كار به همين يك مورد اكتفا مي‌كنيم).

4- داده‌هاي موجود را از ستون PHONE_NUMBER به ستون‌هاي COUNTRY_CODE و # PHONE انتقال دهيم.

5- كدهاي برنامه‌‌ها در سطح پايگاه‌داده را كه به ستون

PHONE_NUMBER مربوط هستند، تغيير دهيم.

 

هر يك از اين مراحل، زمان زيادي را مي‌طلبد و آن‌هايي كه زمان بيشتري مي‌خواهند به توليد انديس، انتقال داده و جايگزيني كد مربوط مي‌شوند. هدف ما در اين مثال، کم‌كردن زمان غيرفعال‌بودن سيستم براي پياده‌سازي اين تغييرات است، بنابراين، ما مي‌خواهيم همه اين مراحل را زماني عملياتي كنيم كه نسخه اول برنامه نيز به‌صورت موازي فعال بوده و در حال سرويس‌دهي به كاربران است. به عبارتي، تمام تغييرات فوق بايد موازي با فعال‌بودن سيستم و روي نسخه دوم برنامه، پياده‌سازي شود. درنهايت، مي‌خواهيم زمان غيرفعال‌بودن سرويس را به لحظه‌اي محدود كنيم كه برنامه‌ها از نسخه اول قطع و به نسخه دوم برنامه‌هاي سمت پايگاه‌داده متصل مي‌شوند (اين كار به‌راحتي و با استفاده از يك دستور ALTER DATABASE قابل انجام است). به طور کلي، زمان غيرفعال‌بودن سرويس بايد در حد چند ثانيه باشد و به دقيقه يا ساعت نرسد.

 

در ادامه شما را با موانعي كه در عملي كردن اين ايده وجود دارد آشنا مي‌کنيم. نخستين كاري كه بايد انجام دهيم، افزودن يك ستون جديد و حذف ستون كنوني است. ما بايد ستون‌ها را به نحوي اضافه كنيم كه به برنامه‌هاي كنوني تأثيري نداشته‌باشد. حال اگر كد برنامه از دستورSELECT * FROM EMPLOYEES استفاده كرده‌باشد، چه خواهد شد؟ اين مورد، نمونه‌اي از كدنويسي ابتدايي است، اما در هر صورت بايد احتمال وقوع آن را در نظر داشته‌باشيم يا ممكن است در برنامه كدي مشابه با (…)INSERT INTO EMPLOYEES VALUES وجود داشته‌باشد، بدون آن‌كه هيچ فهرستي از ستون‌ها براي آن مشخص شده‌باشد كه اين مورد نيز نمونه ديگري از كدنويسي ابتدايي و ضعيف است. افزودن دو ستون جديد به جدول موجود مي‌تواند باعث بروز مشكل در چنين برنامه‌هايي شود. به همين ترتيب، حذف يك ستون كه در حال حاضر برنامه‌ها از آن استفاده مي‌كنند نيز مي‌تواند اثر مشابهي داشته‌باشد (بنابراين، در عمل نمي‌توانيم چنين ستون‌هايي را حذف كنيم).

 

براي مقابله با اين معما در Oracle Database 11g Release 2، مفهومي به نام Editioning ارائه ‌شده‌است. اين مفهوم يك بافر را بين برنامه و شماي فيزيكي ايجادمي‌كند. يك view ايجادشده با استفاده از قابليت Editioning يك نوع خاص از view است كه دستور SELECT را روي زيرمجموعه‌اي از ويژگي‌ها يا ستون‌هاي جدول موردنظر اجرا مي‌كند. ممكن است در دستور WHERE هيچ‌مورد از الحاق جدول‌ها وجود نداشته‌باشد، به اين معني كه دستور موجود، تنها شامل SELECT و FROM باشد. قابليت حاصل از Editioning View، بسيار شبيه SYNONYMها است، اما اين قابليت نه‌تنها مي‌تواند نام آنچه را كه به آن اشاره مي‌كند، تغيير دهد، بلكه مي‌تواند ستون‌هاي مورد نظر و نام آن‌ها را نيز انتخاب كند. علاوه براين، Editioning View به نوعي شامل يك Trigger است كه روي آن‌ها تعريف شده، نه تريگرهايي شبيه آنچه كه مي‌توان درباره Viewهاي معمولي تعريف کرد، يعني مي‌تواند همه انواع تريگرها نظير BEFORE، BEFORE EACH ROW و تريگرهاي پيچيده را ايجاد كند. بنابراين، ما مي‌توانيم از Editioning Views براي پنهان‌كردن دو ستون جديد از برنامه‌هاي موجود استفاده كنيم و مي‌توانيم از يك Editioning View جديد براي پنهان‌كردن ستون قديمي از برنامه جديد استفاده كنيم و به جاي آن، دو ستوني را كه به‌تازگي به برنامه افزوده‌شده‌است، نمايش دهيم.

در اين سناريوي ساده افزودن چندستون جديد و حذف يك ستون موجود، موانع ديگري نيز وجود دارد، ازجمله نحوه مسدودكردن و قفل‌كردن در سطح پايگاه داده است. در گذشته براي افزودن يك ستون جديد به يك جدول، بايد آن را به صورت انحصاري در اختيار مي‌گرفتيم، يعني به‌اصطلاح يك Exclusive Lock روي آن جدول ايجاد مي‌كرديم. اگر قبل از اين تلاش كرده‌باشيد، يك ستون جديد را به يك جدول فعال اضافه كنيد، به‌احتمال مي‌توانيد اين مسئله را به خوبي درك كنيد:

 

 

SQL> alter table emp add resume blob;

alter table emp add resume blob

*

ERROR at line 1:

ORA-00054: resource busy and acquire

with NOWAIT specified

 

 

معمولاً انجام دستورات از نوع DDL روي يك سيستم فعال غيرممكن است. هرچند كه در Oracle Database 11g Release 1 و در بعضي موارد در Release 2 امكان انجام دستورات DDL روي يك جدول فعال، بسيار بهبود يافته و ممكن شده‌است. بسياري از اعمال DDL نظير افزودن ستون، در حال حاضر بدون مسدودكردن عمليات طبيعي سيستم، قابل انجام است يا در حالت جايگزين اگر دستور DDL بايد به طور مجزا انجام شود، ديگر درصورت استفاده از اين گروه از دستورات DDL كه به wait نياز دارند، از پيام خطاي ORA-00054 خبري نيست.

 

يكي ديگر از مشكلاتي كه در گذشته هنگام تغييرات از نوع DDL نظير افزودن يك ستون جديد رخ مي‌داد، غيرمعتبرشدن اشياي معتبر با آن شيء يعني آن جدول بود. در اين موارد همه Viewها و تمام كدهاي PL/SQL مرتبط با آن جدول غير‌معتبر مي‌شدند و مشكلات ديگري از اين نوع رخ مي‌داد. اين مسئله مانع از آن بود كه بتوان يك ستون را به صورت آنلاين به جدولي اضافه كرد. اما از نسخه اول Oracle 11g، با افزودن امكان جديدي به نام كنترل جزئي‌تر وابستگي‌هاي بين اشيا ديگر اين مشكل پيش نمي‌آيد. به اين ترتيب، امكان افزودن ستون اول بدون هرگونه مشكل و بدون غيرمعتبرشدن كدهاي موجود فراهم است. مي‌توان اين ستون‌ها را با استفاده از قابليت Editioning View از ديد برنامه‌ها پنهان كرد و با توجه به قابليت كنترل جزئي وابستگي‌ها كدها نيز غيرمعتبر نخواهند شد. علاوه براين، ما در حال حاضر مي‌توانيم ستون‌هاي موجود را نيز به صورت مجازي و با استفاده از قابليت Editioning View حذف كنيم، به طوري كه در نسخه جديد برنامه ستون مذكور موجود نباشد، اما ستون‌هاي جديد قابل مشاهده باشند.

 

حال قرار است يك انديس جديد روي ستون # PHONE ايجاد كنيم. دو مسئله وجود دارد كه نياز به بررسي دارند: ايجاد انديس و نگراني در اين مورد كه انديس مذكور ممكن است بر كارايي سيستم كنوني، تأثير منفي داشته‌باشد. ايجاد يك انديس جديد مي‌تواند زمان پاسخ‌گويي بعضي از پرس‌وجوها را افزايش دهد و در عين حال هيچ تأثيري روي بعضي از پرس‌وجوها ندارد و درعين‌حال ممكن است بر كارايي گروه سومي از پرس‌وجوها تأثير منفي داشته‌باشد. در گذشته و قبل ازOracle Database 11g Release 1، اجراي دستور CREATE INDEX، به دسترسي انحصاري و به اصطلاح exclusive lock روي جدول مرتبط نياز داشت و حتي اجراي CREATE INDEX ONLINE نيز، در آغاز فرآيند ايجاد انديس براي چند لحظه، نياز به دسترسي انحصاري به جدول مذكور داشت. از Oracle Database 11g Release 1 به بعد، ايجاد انديس به صورت آنلاين، بدون نياز به بلاك‌كردن ساير سرويس‌ها ممكن است و از آنجا كه اين فرآيند به هيچ عنوان نيازمند مسدودكردن ساير سرويس‌ها نيست، درنتيجه، مشكل lock و block كه در نسخه‌هاي قبلي رخ مي‌داد، برطرف شده‌است.

 

نكته: قابليت CREATE INDEX ONLINE، يكي از ويژگي‌هاي پايگاه‌داده است كه در نگارش Enterprise Edition، به چشم مي‌خورد. علاوه براين، در حال حاضر امكان آن وجود دارد كه انديس ايجادشده نامرئي باشد، به آن معنا كه انديس مذكور وجود دارد و هنگام تغيير سيستم، فرآيند نگهداري براي آن انجام خواهدشد، اما تا زماني كه يك Session، به طور شفاف درخواست استفاده از آن را نداشته‌باشد، از انديس مذكور به‌عنوان يك مسير دسترسي به داده استفاده نخواهد شد. بنابراين، در حال حاضر مي‌توانيم يك انديس را به ستون # PHONE اضافه کنيم، بدون آن‌كه مشكلات ناشي از blocking/locking رخ دهد و تضمين كنيم كه افزوده‌شدن انديس جديد هيچ تأثيري براي كارايي پرس‌وجوهاي كنوني نخواهدداشت و درنتيجه كارايي پرس‌وجوهايي كه هنوز تأثير وجود انديس كنوني بر آن‌ها بررسي نشده تا زماني كه ما اجازه ندهيم از اين انديس استفاده نخواهند كرد. بنابراين، ما مي‌توانيم اين انديس را بدون تأثير بر نسخه كنوني برنامه به پايگاه‌داده اضافه کنيم.

 

حال نوبت دشوار‌ترين مرحله، يعني انتقال‌داده است ما بايد داده را از ستون PHONE_NUMBER به ستون‌هاي جديد، انتقال دهيم. علاوه براين، بايد تصميم ‌بگيريم كه براي رديف‌هايي كه در طول فرآيند ارتقاي برنامه توسط نسخه كنوني برنامه درج يا به‌روزرساني مي‌شوند، چه اتفاقي رخ‌دهد. كارها فقط با به‌روزرساني يك حجم بزرگ از داده در جدول EMPLOYESS به پايان نمي‌رسد، زيرا:

1- اجراي فرآيند به‌روزرساني به صورت يك‌باره، تمام جدول را قفل مي‌كند كه براي سيستم‌هاي آنلاين مناسب نيست.

2- اگر فرآيند به روزرساني يك‌باره كامل شود، اما برنامه كنوني در همان بازه زماني، رديف جديدي را درج يا به‌روزرساني كند، در اين صورت، ستون PONE_NUMBER مربوط به ركورد كنوني در ستون‌هاي جديد، منعكس نخواهد شد و اين تغييرات از دست خواهد رفت. خوشبختانه، اين دو مشكل برطرف مي‌شود. مشكل اول، يعني قفل‌شدن همه جدول به واسطه اجراي دستوري براي انتقال يكباره كل داده و به‌روزرساني ستون مقصد؛ توسط يك بسته جديد برطرف مي‌شود كه DMBS_PARALLEL_EXECUTE نام دارد. با استفاده ازDBMS-PARALLEL_EECUTE مي‌توانيم همه رديف‌هاي جدول را به صورت بازه‌هاي داده‌‌اي كوچك به‌روزرساني كنيم و براي اين كار مي‌توان از فرآيند اجراي موازي دستور در هر سطحي كه نياز باشد، از يك سطح تا هزار سطح پردازش موازي استفاده كرد. اين كار حجم داده درگير و استفاده‌شده در هر پردازه موازي را كاهش مي‌دهد و به‌عنوان مثال، اگر جدول به صد قسمت تقسيم و فقط از پردازه موازي استفاده شود، فقط يک درصد داده جدول در هربار اجرا قفل خواهد شد. اگر ما جدول را به هزار قسمت تقسيم كنيم و پردازه موازي يك عدد باشد، تنها 1/0درصد از جدول در هر اجرا قفل خواهد شد و به همين ترتيب.

 

مشكل دوم اين است كه انتقال مداوم داده از برنامه‌ كنوني به برنامه جديد، مسئله‌ساز خواهد بود. ما بايد به نحوي به برنامه كنوني بگوييم كه داده‌ها را براي نسخه بعدي حفظ كند، اما بايد اين كار را به روشي انجام دهيم كه نسخه كنوني برنامه به تغيير نياز نداشته‌باشد. با اين همه محدوديت به نظر مي‌رسد كه عملي‌شدن اين كار بيشتر به معجزه شبيه است و اين معجزه به‌واسطه استفاده از نوع جديدي از تريگر، ممكن مي‌شود كه تريگر رابط بين دو نسخه يا Crossedition Trigger نام دارد. تريگرهاي نوع Crossedition، تنها در طول فرآيند ارتقاي برنامه مورداستفاده قرار مي‌گيرند و ما به مجرد كامل‌شدن فرآيند ارتقاي برنامه آن‌ها را حذف مي‌كنيم. تريگرهاي نوع Crossedition را مي‌توان به منظور انتقال تغييرات حاصل از برنامه قديمي به برنامه جديد استفاده كرد. همچنين مي‌توان از آن‌ها براي معكوس‌كردن تغييرات ايجادشده توسط برنامه جديد به منظور در اختيار قراردادن آن براي برنامه و اسكيماي قبلي استفاده كرد. درنهايت آن‌كه بايد كد كنوني برنامه را به منظور استفاده از مزيت‌هاي شماي جديد جايگزين كنيم، بدون آن‌كه براي برنامه كنوني مشكلي ايجاد شود. خوشبختانه، قبلاً ديده‌ايم كه انجام اين كار چقدر آسان است (اين مورد در قسمت اول مقاله در شماره 108 بررسي شده‌است). اين فرآيند دوباره و براي كامل‌شدن مثال كنوني انجام خواهد شد. قبل از آن‌كه فرآيند افزودن و حذف ستون‌ها را آغاز كنيم، بايد قابليتي به نام Editioning Views را مرور كنيم، اين قابليت بافري بين برنامه‌ها و شماي فيزيكي است. اين فرآيند مستلزم صرف زمان است كه يك بار براي برنامه شما بايد انجام شود.

 

نكته: در آينده كه برنامه‌هاي جديد ايجاد مي‌كنيد مي‌توانيد با استفاده از Editioning Views قبل از شروع به كدنويسي، مشكل صرف زمان را نيز برطرف كنيد. اين راهبرد به شما امكان مي‌دهد تا نام‌گذاري و مرتب‌سازي ستون‌هاي برنامه را با كمترين هزينه انجام دهيد و امكان ارتقاي آنلاين برنامه‌ها و تغيير فيزيكي در اسكيماها را فراهم مي‌كند.

 

براي افزودن قابليت Editioning Views به اجراي فرآيند نگهداري نيازداريم، كه فقط يك‌بار لازم است. مراحل كلي براي عملي‌سازي اين فرآيند به شرح زير است:

1- نام‌گذاري دوباره جدول موجود، زيرا قابليت Editioning Views از نام قديمي جدول استفاده خواهد كرد.

2- ايجاد Editioning Views و مشخص كردن نام جدول اصلي براي آن

3- حذف هرگونه تريگر روي جدول موجود و انتقال آن به محيط Editioning Views. اين مرحله اختياري است و پيشهاد مي‌كنيم، آن را انجام دهيد، زيرا دستور CREATE TRIGGER كه مورد نظر شما است، به‌طورمستقيم به نام جدول اشاره مي‌كند. شما در محيط Editioning Viewsبه تريگري نياز داريد كه نام جدول اصلي را داشته‌باشد.

4- در محيط Editioning Views دوباره تريگرها را ايجاد كنيد.

5- تمام مجوزهاي اعطا شده را براي دسترسي به جدول اصلي حذف‌كرده و مجوزهاي متناظر را براي دسترسي به جدول محيط Editioning Views فراهم كنيد.

6- ساير كارها، نظير ايجاد سياست‌هاي دسترسي دقيق از جدول اصلي به Editioning Views را مشخص كنيد.

 

برنامه‌هاي ما هيچ تريگر يا مجوزي را در اختيار ندارد، درنتيجه بعضي از اين مراحل انجام نخواهد شد. اما به طور كلي، فرآيند فوق همان چيزي است كه براي استفاده از Edition-Based Redefinition و به منظور انجام تغيير در كد و اسكيماي فيزيكي به آن نياز داريم.

 

فرض مي‌كنيم حساب‌كاربري DEMO كه در قسمت قبلي ايجاد و استفاده شد، هنوز در اختيار ما قرار دارد. همان‌طور كه به خاطر داريد، حساب كاربري DEMO، يك حساب كاربري ساده با مجوزهاي CREATE SESSION و CREATE PROCEDURE بود و مي‌توانست اديشن‌هاي جديد را در اسكيماي خود ايجاد كند (با استفاده از جمله ALTER SESSION ENABLE EDITIONS) و از نسخه كنوني با نام VERSION2 استفاده کند (با توجه به جمله GRANT USE ON EDITION VERSION2 TO DEMO). در اين مثال ما به حساب كاربري DEMO، امكان ايجاد جدول و Sequence را مي‌دهيم تا بتوانيم جدول EMPLOYEES را در آن كپي كنيم. همچنين مجوز ايجاد Viewها و تريگرها را نيز به كاربر مي‌دهيم. اما ساير مجوزها همانند قبل خواهد بود. اجازه دهيد ابتدا به نسخه 0/1 برنامه و تنظيمات آن نگاهي داشته‌باشيم:

 

SQL> create table

2 employees

3 as

4 select *

5 from hr.employees;

 

Table created.

 

SQL> create sequence emp_seq

2 start with 500;

 

Sequence created.

 

اين يك كپي از داده است كه ما از آن استفاده خواهيم كرد. يك Sequence ايجاد شده كه بايد مقدار اوليه آن از بزرگ‌ترين مقدار در جدول EMPLOYEES بيشتر باشد. كد برنامه كنوني دو سرويس را روي اين جدول ارائه مي‌دهد: نمايش يك گزارش از جدول EMPLOYEES كه عبارت جست‌وجوي آن، شامل شماره تلفن و آدرس ايميل است. همچنين امكان افزودن ركورد جديد به موازات استخدام كارمندان جديد را فراهم مي‌آورد و با اين كار، جدول كنوني تغيير مي‌كند. ويژگي‌هاي بسته، مطابق با فهرست1 قابل مشاهده است.

 

SQL> create or replace package emp_pkg

2 as

3 procedure show

4 ( last_name_like in employees.last_name%type );

5

6 function add

7 ( FIRST_NAME in employees.FIRST_NAME%type := null,

8 LAST_NAME in employees.LAST_NAME%type,

9 EMAIL in employees.EMAIL%type,

10 PHONE_NUMBER in employees.PHONE_NUMBER%type := null,

11 HIRE_DATE in employees.HIRE_DATE%type,

12 JOB_ID in employees.JOB_ID%type,

13 SALARY in employees.SALARY%type := null,

14 COMMISSION_PCT in employees.COMMISSION_PCT%type := null,

15 MANAGER_ID in employees.MANAGER_ID%type := null,

16 DEPARTMENT_ID in employees.DEPARTMENT_ID%type := null )

17 return employees.employee_id%type;

18 end;

19 /

 

Package created.

فهرست 1 : ويژگي‌هاي بسته emp_pkg براي بسته version 1.0

 

 

 

پياده‌سازي بدنه اين كدها، به‌نسبت آسان است. يك روتين ساده «نمايش» و يك تراكنش ساده «افزودن كارمند جديد»، كه مطابق با فهرست2 انجام مي‌شود.

 

 

SQL> create or replace package body emp_pkg

2 as

3

4 procedure show

5 ( last_name_like in employees.last_name%type )

6 as

7 begin

8 for x in

9 ( select first_name, last_name,

10 phone_number, email

11 from employees

12 where last_name like

13 show.last_name_like

14 order by last_name )

15 loop

16 dbms_output.put_line

17 ( rpad( x.first_name || ' ' ||

18 x.last_name, 40 ) ||

19 rpad( nvl(x.phone_number, ' '), 20 ) ||

20 x.email );

21 end loop;

22 end show;

23

24 function add

25 ( FIRST_NAME in employees.FIRST_NAME%type := null,

26 LAST_NAME in employees.LAST_NAME%type,

27 EMAIL in employees.EMAIL%type,

28 PHONE_NUMBER in employees.PHONE_NUMBER%type := null,

29 HIRE_DATE in employees.HIRE_DATE%type,

30 JOB_ID in employees.JOB_ID%type,

31 SALARY in employees.SALARY%type := null,

32 COMMISSION_PCT in employees.COMMISSION_PCT%type := null,

33 MANAGER_ID in employees.MANAGER_ID%type := null,

34 DEPARTMENT_ID in employees.DEPARTMENT_ID%type := null

35 )

36 return employees.employee_id%type

37 is

38 employee_id employees.employee_id%type;

39 begin

40 insert into employees

41 ( EMPLOYEE_ID, FIRST_NAME, LAST_NAME,

42 EMAIL, PHONE_NUMBER, HIRE_DATE,

43 JOB_ID, SALARY, COMMISSION_PCT,

44 MANAGER_ID, DEPARTMENT_ID )

45 values

46 ( emp_seq.nextval, add.FIRST_NAME, add.LAST_NAME,

47 add.EMAIL, add.PHONE_NUMBER, add.HIRE_DATE,

48 add.JOB_ID, add.SALARY, add.COMMISSION_PCT,

49 add.MANAGER_ID, add.DEPARTMENT_ID )

50 returning employee_id into add.employee_id;

51

52 return add.employee_id;

53 end add;

54

55 end;

56 /

 

Package body created.

 

فهرست 2- بدنه package با نام emp_pkg براي پياده‌سازي version 1.0 برنامه

 

 

اكنون مي‌توانيم نحوه كار اين بسته را در محيط SQL*Plus مطابق با كد فهرست 3 مشاهده كنيم.

 

SQL> exec emp_pkg.show( '%K%' );

Payam Kaufling 650.123.3234 PKAUFLIN

Alexander Khoo 515.127.4562 AKHOO

Steven King 515.123.4567 SKING

Janette King 011.44.1345.429268 JKING

Neena Kochhar 515.123.4568 NKOCHHAR

Sundita Kumar 011.44.1343.329268 SKUMAR

 

PL/SQL procedure successfully completed.

 

SQL> begin

2 dbms_output.put_line

3 ( emp_pkg.add

4 ( first_name => 'Tom',

5 last_name => 'Kyte',

6 email => 'TKYTE',

7 phone_number => '703.123.9999',

8 hire_date => sysdate,

9 job_id => 'IT_PROG' ) );

10 end;

11 /

500

 

PL/SQL procedure successfully completed.

 

SQL> exec emp_pkg.show( '%K%' );

Payam Kaufling 650.123.3234 PKAUFLIN

Alexander Khoo 515.127.4562 AKHOO

Janette King 011.44.1345.429268 JKING

Steven King 515.123.4567 SKING

Neena Kochhar 515.123.4568 NKOCHHAR

Sundita Kumar 011.44.1343.329268 SKUMAR

Tom Kyte 703.123.9999 TKYTE

 

PL/SQL procedure successfully completed.

فهرست 3- اجراي نسخه اول برنامه در محيط SQL*Plus

 

 

در ادامه مي‌خواهيم اين اسكيما را براي انجام ارتقاي برنامه‌ها به صورت آنلاين آماده كنيم كه شامل ارتقاي ساختار فيزيكي اسكيما نيز مي‌شود. به خاطر داشته‌باشيد كه اين كار به قطع‌كردن موقتي سرويس نياز دارد و اين كار يك بار براي هميشه انجام مي‌شود تا قابليتEditioning Views فعال شود. در اين مورد ايجاد Editioning Views مستلزم انجام مراحل زير است:

 

SQL> alter table employees

2 rename to employees_rt;

 

Table altered.

 

SQL> create editioning view employees

2 as

3 select

4 EMPLOYEE_ID, FIRST_NAME,

5 LAST_NAME, EMAIL, PHONE_NUMBER,

6 HIRE_DATE, JOB_ID, SALARY,

7 COMMISSION_PCT, MANAGER_ID,

8 DEPARTMENT_ID

9 from employees_rt

10 /

 

View created.

 

به همين سادگي! اين كار يك بار و براي هميشه انجام شد. مي‌توانيم سيستم را دوباره آنلاين كنيم. همچنين اين كار هيچ تأثيري روي عملكرد كنوني برنامه نخواهد داشت. View ايجادشده با استفاده از قابليت Editioning Views كه در اين قسمت بررسي مي‌شود، همانند يك جدول عمل مي‌كند و در نتيجه، برنامه‌هاي موجود همانند سابق كار خواهند كرد.اكنون مي‌توانيم ستون‌هاي مورد نظر را افزوده و براي آن‌ها انديس ايجاد كنيم تا براي ارائه نسخه جديد از برنامه حاضر شويم:

 

 

SQL> alter table employees_rt

2 add

3 ( country_code varchar2(3),

4 phone# varchar2(20)

5 )

6 /

Table altered.

 

SQL> create index employees_phone#_idx

2 on employees_rt(phone#)

3 ONLINE INVISIBLE

4 /

 

Index created.

 

 

افزودن ستون جديد، يك عمليات آنلاين است. اين قابليت از نسخه قبل، يعني از Oracle Database 11g Release 1 فراهم شده‌است. به علاوه توجه داشته‌باشيد كه چگونه انديس‌ها نيز به صورت آنلاين (يعني كاملاً به‌صورت آنلاين و بدون حتي يك لحظه ايجاد وقفه در عملكرد پايگاه‌داده كه از نسخه مذكور به بعد ممكن شده‌است) و INVISIBLE ايجاد مي‌شوند.

 

در اين مثال خاص، ويژگي INVISIBLE بودن كارها، احتمالاً از لحاظ تكنيكي خيلي مهم نيست، زيرا ستون # PHONE به هيچ عنوان و توسط هيچ يك از فرم‌هاي برنامه‌هاي كنوني مورداستفاده قرار نگرفته‌است و فقط براي كامل‌بودن مبحث عنوان شد.

 

حال نوبت به فرآيند مهاجرت‌دادن داده‌‌ها از ويرايش كنوني به ويرايش جديد است. براي انجام اين كار، ما از يك تريگر رابط دو نسخه يا Cross-Edition استفاده خواهيم كرد. تريگري كه ما استفاده خواهيم كرد، به اين منظور به كار مي‌رود تا تضمين كند كه داده وارد شده يا به‌روزرساني‌شده توسط نسخه كنوني برنامه در ستون‌هاي متناظر و مرتبط با نسخه جديد نيز درج خواهند شد.

 

ما از اين تريگر نه‌تنها براي ذخيره تغييرات ايجادشده توسط برنامه قبلي استفاده خواهيم كرد، بلكه از آن براي انتقال كل داده به نسخه ‌جديد نيز استفاده خواهيم كرد. به اين ترتيب كه منطبق لازم براي توليد داده موردنياز COUNTRY_CODE و # PHONE را از روي ستون قديمي PHONE_NUMBER به كد تبديل مي‌كنيم ( ما بايد اين كار را به منظور به‌روزرساني برنامه كنوني و ارسال تغييرات به اسكيماي جديد انجام دهيم). بعد از ايجاد تريگر نوع cross_edition به‌منظور انتقال‌داده، كافي‌است تا دستور «update employees set phone_number=phone_number»را با استفــــــاده از بسته DBMS_PARALLEL_EXECUTE اجرا كنيم. فهرست 4، كد مربوط به تريگر نوع Cross-Edition را نشان مي‌دهد.

 

SQL> alter session set edition = version2;

 

Session altered.

 

SQL> create or replace trigger employees_fwdxedition

2 before insert or update of phone_number on employees_rt

3 for each row

4 forward crossedition

5 declare

6 first_dot number;

7 second_dot number;

8 begin

9 if :new.phone_number like '011.%'

10 then

11 first_dot

12 := instr( :new.phone_number, '.' );

13 second_dot

14 := instr( :new.phone_number, '.', 1, 2 );

15 :new.country_code

16 := '+'||

17 substr( :new.phone_number,

18 first_dot+1,

19 second_dot-first_dot-1 );

20 :new.phone#

21 := substr( :new.phone_number,

22 second_dot+1 );

23 else

24 :new.country_code := '+1';

25 :new.phone# := :new.phone_number;

26 end if;

27 end;

28 /

 

Trigger created.

 

فهرست 4- بدنه package با نام emp_pkg براي پياده‌سازي version 1.0 برنامه

 

چند نكته كه بايد درباره تريگرهاي نوع Cross-Edition بدانيم:

1- در اين كد از عبارت VERSION2 براي ورود به نسخه جديد اسكيما استفاده شده‌است. براي انجام اين كار بايد از عبارت ALTER SESSION استفاده كرد. هدف ما اين است كه برنامه كنوني با هيچ‌گونه مشكلي مواجه نشود و به اين منظور بايد از قابليت Edtioning استفاده كرده و تغييرات را فقط در نسخه جديد، اعمال كرد. بايد تريگر نوع Crossedition را در نسخه‌اي كه قرار است در آينده استفاده شود، ايجاد كنيم و هرگز نبايد آن را در نگارش كنوني برنامه ايجاد كنيم.

 

2- در خط 4 از كد ايجاد تريگر، كلمه كليدي جديد را مشاهده مي‌كنيم: FORWARD CROSSEDITION. اين عبارت، يعني آن‌كه فقط در صورت اجراي جملات INSERT، UPDATE، DELETE در نسخه كنوني يعني كد قديمي، تريگر مذكور اجرا خواهد شد، به عبارت ديگر با اعمال و اجراي دستورات در برنامه قديمي، اين تريگر فعال خواهد شد.

 

حال آماده هستيم تا كل داده را به نسخه جديد و ستون‌هاي ايجاد‌شده، انتقال دهيم. اين كار از طريق يك دستور ساده UPDATE، انجام خواهد شد:

 

SQL> update employees

set phone_number = phone_number;

 

109 rows updated.

 

 

اما به خاطر داشته‌باشيد كه با اين كار كل جدول به يك‌باره قفل مي‌شود، زيرا همه ركوردها، يك‌جا به‌روزرساني مي‌شوند و اين همان چيزي است كه سعي داريم از آن اجتناب كنيم. هنگام بروز هرگونه رخداد، يعني هرگونه تغيير نظير افزوده‌شدن يا به‌روزرساني ستون PHONE_NUMBER توسط برنامه‌ قديمي، تمام تغييرات براي ستون‌هاي مورداستفاده توسط برنامه كنوني نيز ارسال خواهند شد. در مقالات آتي موارد ديگري كه مي‌توانند استفاده از قابليت جادويي را آسان‌تر كنند، بررسي خواهند شد. از جمله:

1- نحوه انجام فرآيند فوق به صورت تكه‌به‌تكه به صورتي كه كل جدول، به يك‌باره قفل نشود.

2- نصب كدجديد شامل نصب يك Editioning Views جديد براي نصب برنامه جديد.

3- فعال‌سازي برنامه كنوني و پاك‌كردن باقي‌مانده‌هاي نسخه قبلي شامل كدها و ستون‌هاي بدون استفاده.

بعد از آن به سراغ يك روش جايگزين مي‌رويم كه در آن به جاي Warm Cutover (خاموش كردن نسخه قديمي و راه‌اندازي نسخه جديد) از Hot Rollover استفاده خواهيم كرد. به اين ترتيب كه نسخه جديد و قديمي به صورت موازي كار مي‌كنند تا زماني كه به برنامه قديمي نيازي نباشد. به اين ترتيب زمان غيرفعال‌بودن سيستم، عملاً صفر مي‌شود و اين فرآيند خود مقدمه‌اي براي انجام ساير فعاليت‌هاي پايگاه‌داده به صورت آنلاين خواهد بود از جمله:

1- نصب اصلاحيه روي سيستم بدون غيرفعال‌كردن آن.

2- حداقل‌كردن زمان Downtime به چند ثانيه در طول زمان ارتقاي برنامه شامل تغييرات در اسكيماي فيزيكي و انجام عمليات‌هاي به‌روزرساني حجم‌هاي زياد داده.

3- حذف كامل زمان Downtime.

لینک به دیدگاه

به گفتگو بپیوندید

هم اکنون می توانید مطلب خود را ارسال نمایید و بعداً ثبت نام کنید. اگر حساب کاربری دارید، برای ارسال با حساب کاربری خود اکنون وارد شوید .

مهمان
ارسال پاسخ به این موضوع ...

×   شما در حال چسباندن محتوایی با قالب بندی هستید.   حذف قالب بندی

  تنها استفاده از 75 اموجی مجاز می باشد.

×   لینک شما به صورت اتوماتیک جای گذاری شد.   نمایش به صورت لینک

×   محتوای قبلی شما بازگردانی شد.   پاک کردن محتوای ویرایشگر

×   شما مستقیما نمی توانید تصویر خود را قرار دهید. یا آن را اینجا بارگذاری کنید یا از یک URL قرار دهید.

×
×
  • اضافه کردن...