Oracle إلى SQL Server و SQL Server إلى Oracle Migration Guide

نشرت: 2022-03-11

"التبعية للبائع" هي كلمة مخيفة للعديد من رجال الأعمال التنفيذيين. من ناحية أخرى ، من المفهوم على نطاق واسع في الصناعة أن "الاستقلال الكامل للبائع" لا يمكن تحقيقه. وهذا صحيح بشكل خاص في حالة قواعد البيانات.

اثنان من أكثر منصات RDBMS للمؤسسات انتشارًا هما Oracle Database و Microsoft SQL Server (للإيجاز ، بالنسبة لبقية هذه المقالة ، سأطلق عليها اسم "Oracle" و "SQL Server" على التوالي). بالتأكيد ، يتنافس IBM Db2 مع Oracle على منصات الحاسب الرئيسية التي تتقلص باستمرار - لكنها لا تزال مهمة في العديد من المجالات. والبدائل مفتوحة المصدر التي تتقدم بسرعة ، مثل PostgreSQL ، تكتسب أساسًا ثابتًا في البيئات الديناميكية على الأجهزة السلعية ذات المستوى المنخفض إلى المتوسط ​​وعلى الويب.

لكن Oracle مقابل SQL Server هو الخيار الذي يواجهه العديد من رجال الأعمال التنفيذيين عندما تحتاج مؤسساتهم إلى RDBMS جديد. يعتمد الاختيار النهائي على عدة عوامل: تكلفة الترخيص ، والخبرة الداخلية المتاحة والخبرة السابقة ، والتوافق مع البيئات الحالية ، والعلاقات مع الشركاء ، وخطط الأعمال المستقبلية ، وما إلى ذلك ، ولكن حتى مع التقييم المسبق الأكثر شمولاً واتخاذ القرار الأفضل تعليماً ، فإن العوامل في بعض الأحيان التغيير ومن ثم يجب تغيير النظام الأساسي أيضًا. أعلم هذا لأنه خلال مسيرتي المهنية ، قمت بتنفيذ مثل هذه الترحيلات مرتين ، وأعدت تقييم جدوى النقل مرة واحدة ، وأنا أعمل على ترحيل الوظائف عبر الأنظمة الأساسية في هذا الوقت بالذات.

يعد كل من Oracle و SQL Server من تطبيقات "المدرسة القديمة" المتوافقة جزئيًا مع ANSI RDBMS. عند ترك الامتدادات الإجرائية جانبًا - PL / SQL و Transact-SQL لهما صيغ مختلفة ، لكنهما عمومًا يسهل ترجمتهما بين - والعقود المستقبلية الأحدث الموجهة للكائنات ، يمكن أن تبدو تعليمات SQL البرمجية متشابهة بشكل مخادع. وهذا فخ عسل خطير.

اثنان من أهم النقاط لأي مشروع ترحيل بين Oracle و SQL Server (في أي من الاتجاهين) هما المعاملات والجداول المؤقتة وثيقة الصلة ، والتي تعد أداة رئيسية في حل نطاق المعاملة. سنغطي أيضًا المعاملات المتداخلة - تلك الموجودة في نطاق معاملة أخرى - لأنها جزء أساسي من تنفيذ تدقيق أمان المستخدم في Oracle. ولكن في SQL Server ، يحتاج تدقيق أمان المستخدم إلى نهج مختلف بسبب سلوكه COMMIT في هذا السياق.

فهم هيكل المعاملة: مراقبة Oracle مقابل SQL Server من عشرة آلاف قدم

معاملات أوراكل ضمنية. هذا يعني أنك لست بحاجة إلى بدء معاملة - فأنت دائمًا في صفقة. وهذه المعاملة مفتوحة حتى يتم إصدار بيان الالتزام أو التراجع. نعم ، يمكنك بدء معاملة بشكل صريح ، وتحديد نقاط التراجع الآمنة ، وتعيين المعاملات الداخلية / المتداخلة ؛ ولكن المهم هو أنك لا "تدخل في صفقة" أبدًا ويجب عليك دائمًا إصدار التزام أو التراجع. لاحظ أيضًا أن إصدار بيان لغة تعريف البيانات (DDL) ( CREATE ، ALTER ، إلخ ؛ في معاملة يمكن إجراؤها من خلال SQL الديناميكي) يؤدي إلى تنفيذ المعاملة التي تم إصدارها فيها.

على عكس Oracle ، يحتوي SQL Server على معاملات صريحة. هذا يعني أنه ما لم تبدأ معاملة صريحة ، فسيتم تنفيذ جميع التغييرات "تلقائيًا" - فور معالجة كشف حسابك ، حيث أن كل بيان DML ( INSERT ، UPDATE ، DELETE ) ينشئ معاملة من تلقاء نفسه ويلتزم بها ما لم تكن هناك أخطاء خارج.

هذا هو نتيجة الاختلاف في تطبيقات تخزين البيانات - كيفية كتابة البيانات في قاعدة بيانات وكيف يقرأها محرك قاعدة البيانات.

في Oracle ، تغير بيانات DML السجلات مباشرة في ملف البيانات. تتم كتابة النسخة القديمة من السجل (أو استبدال السجل الفارغ ، في حالة INSERT ) في ملف التراجع الحالي ، ويتم تمييز الوقت المحدد للتغيير في السجل.

عند إصدار بيان SELECT ، تتم معالجته بناءً على البيانات التي تم تعديلها قبل إصدارها. إذا تم تعديل أي سجلات بعد إصدار SELECT ، فإن Oracle تستخدم الإصدار الأقدم من ملف التراجع.

هذه هي الطريقة التي نفذت بها Oracle اتساق القراءة وعدم حظر القراءة / الكتابة. وهذا أيضًا هو السبب في أن الاستعلامات طويلة الأمد في قواعد بيانات المعاملات النشطة جدًا قد تتعرض أحيانًا للخطأ السيئ السمعة ORA-01555 ، snapshot too old: rollback segment ... too small . (هذا يعني أن ملف التراجع المطلوب بواسطة الاستعلام عن إصدار أقدم من السجل قد تمت إعادة استخدامه بالفعل.) وهذا هو سبب الإجابة الصحيحة على السؤال "ما المدة التي يجب أن تستغرقها معاملة Oracle الخاصة بي؟" هو "طالما هناك حاجة ولم يعد".

يختلف تطبيق SQL Server: يقوم محرك قاعدة البيانات بالكتابة والقراءة مباشرة من / إلى ملفات البيانات فقط. كل عبارة SQL ( SELECT / INSERT / UPDATE / DELETE ) هي معاملة ما لم تكن جزءًا من معاملة صريحة تجمع عدة عبارات معًا ، مما يسمح بالتراجع عن التغييرات.

كل معاملة تغلق الموارد التي تحتاجها. تم تحسين الإصدارات الحالية من Microsoft SQL Server بشكل كبير في تأمين الموارد المطلوبة فقط ، ولكن ما هو مطلوب يتم تحديده بواسطة رمز SQL - لذا فإن تحسين استعلاماتك أمر بالغ الأهمية). وهذا يعني ، على عكس Oracle ، أن تكون المعاملات في SQL Server قصيرة قدر الإمكان ، وهذا هو السبب في أن الالتزامات التلقائية هي السلوك الافتراضي.

وأي بنية SQL في Oracle و SQL Server تتأثر بالاختلاف في تنفيذ المعاملات؟ الجداول المؤقتة.

الجداول المؤقتة في Oracle و SQL Server

عندما يحدد معيار ANSI SQL الجداول المؤقتة المحلية والعالمية ، فإنه لا ينص صراحة على كيفية تنفيذها. يقوم كل من Oracle و SQL Server بتطبيق الجداول المؤقتة العمومية. يقوم SQL Server أيضًا بتنفيذ الجداول المؤقتة المحلية. نفذت Oracle 18c أيضًا جداول مؤقتة محلية "حقيقية" (والتي يطلقون عليها "الجداول المؤقتة الخاصة".) وهذا يجعل ترجمة كود SQL Server إلى Oracle 18c أبسط بشكل واضح مما هي عليه في الإصدارات الأقدم - مما يؤدي إلى تقريب إضافة Oracle السابقة لعدد قليل ذي صلة ميزات مثل زيادة أعمدة الهوية تلقائيًا.

ولكن من منظور التحليل الوظيفي البحت ، يمكن أن يكون إدخال الجداول المؤقتة الخاصة نعمة مختلطة لأنه يجعل SQL Server إلى Oracle مشاكل الترحيل تبدو أقل مما هي عليه. هذا فخ آخر للعسل ، لأنه قد يقدم بعض التحديات الجديدة من تلقاء نفسه. على سبيل المثال ، لا يمكن التحقق من صحة رمز وقت التصميم على جداول مؤقتة خاصة ، لذا فإن أي رمز يستخدمها سيكون دائمًا أكثر عرضة للخطأ. إذا كنت قد استخدمت SQL الديناميكي ، فلنضع الأمر على هذا النحو: تعد الجداول المؤقتة الخاصة معقدة بنفس القدر في تصحيح الأخطاء ، ولكن بدون حالة الاستخدام الفريدة الظاهرة. ولهذا السبب أضافت Oracle الجداول المؤقتة المحلية (الخاصة) فقط في 18c وليس قبل ذلك.

باختصار ، لا أرى حالة استخدام للجداول المؤقتة الخاصة في Oracle التي لا يمكن تنفيذها باستخدام الجداول المؤقتة العامة نفسها أو أفضل. لذلك بالنسبة لأي تحويل جدي ، نحتاج إلى فهم الفرق بين جداول Oracle المؤقتة العالمية و SQL Server.

الجداول المؤقتة العالمية في Oracle و SQL Server

جدول Oracle المؤقت العام هو كائن قاموس بيانات دائم يتم إنشاؤه بشكل صريح في وقت التصميم بواسطة عبارة DDL. إنه "عالمي" فقط لأنه كائن على مستوى قاعدة البيانات ويمكن الوصول إليه من خلال أي جلسة قاعدة بيانات لديها الأذونات المطلوبة. ومع ذلك ، على الرغم من أن هيكلها عالمي ، فإن جميع البيانات الموجودة في الجدول المؤقت العالمي يتم تحديد نطاقها فقط للجلسة التي يعمل فيها ولا يمكن رؤيتها خارج هذه الجلسة بأي حال من الأحوال. بمعنى آخر ، يمكن أن تحتوي الجلسات الأخرى على بياناتها الخاصة في نسختها الخاصة من نفس الجدول المؤقت العالمي. لذلك ، في Oracle ، يحتوي الجدول المؤقت العالمي على البيانات المحلية للجلسة - المستخدمة في الغالب في PL / SQL لتبسيط التعليمات البرمجية وتحسين الأداء.

في SQL Server ، الجدول المؤقت العمومي هو كائن مؤقت تم إنشاؤه في كتلة من التعليمات البرمجية لـ Transact-SQL. إنه موجود ما دامت جلسة إنشائه مفتوحة ، ويكون مرئيًا - سواء في البنية أو البيانات - للجلسات الأخرى في قاعدة البيانات. لذلك ، فهو كائن مؤقت عالمي لمشاركة البيانات عبر الجلسات.

يختلف الجدول المؤقت المحلي في SQL Server عن الجدول العام من خلال إمكانية الوصول إليه فقط في الجلسة التي أنشأته. كما أن استخدام الجداول المؤقتة المحلية في SQL Server أكثر انتشارًا (وأود القول أنه أكثر أهمية لأداء قاعدة البيانات) من استخدام الجداول المؤقتة العالمية.

إذن ، كيف يتم استخدام الجداول المؤقتة المحلية في SQL Server ، وكيف ينبغي ترجمتها إلى Oracle؟

يتمثل الاستخدام الهام (والصحيح) للجداول المؤقتة المحلية في SQL Server في تقصير أو إزالة قفل مورد المعاملة ، وخاصة:

  • عندما تحتاج مجموعة من السجلات إلى المعالجة بواسطة بعض التجميع
  • عندما تحتاج مجموعة البيانات إلى التحليل والتعديل
  • عندما يلزم استخدام نفس مجموعة البيانات عدة مرات في نفس النطاق

في هذه الحالات ، غالبًا ما يكون من الأفضل تحديد هذه المجموعة من السجلات في جدول محلي مؤقت لإزالة القفل من الجدول المصدر.

من الجدير بالذكر أن تعبيرات الجدول الشائعة (CTEs ، أي عبارات WITH <alias> AS (SELECT...) ) في SQL Server هي مجرد "سكر نحوي". يتم تحويلها إلى استعلامات فرعية مضمنة قبل تنفيذ SQL. يتم تحسين الأداء في Oracle CTE (مع /*+ materialize */ تلميح) وإنشاء نسخة مؤقتة من العرض الفعلي. في مسار تنفيذ Oracle ، تصل CTE إلى بيانات المصدر مرة واحدة فقط. بناءً على هذا الاختلاف ، قد يعمل SQL Server بشكل أفضل باستخدام الجداول المؤقتة المحلية بدلاً من المراجع المتعددة لنفس CTE ، كما يمكن القيام به في استعلام Oracle.

نظرًا للاختلاف بين عمليات تنفيذ المعاملات ، فإن الجداول المؤقتة تخدم أيضًا وظيفة مختلفة. ونتيجة لذلك ، فإن نقل جداول SQL Server المؤقتة إلى Oracle "كما هي" (حتى مع تطبيق Oracle 18c للجداول المؤقتة الخاصة) لا يمكن أن يكون ضارًا بالأداء فحسب ، بل خطأ وظيفيًا.

من ناحية أخرى - عند الانتقال من Oracle إلى SQL Server - يجب الانتباه إلى طول المعاملة ونطاق رؤية الجداول المؤقتة العالمية وأداء كتل CTE مع التلميح "الفعلي".

في كلتا الحالتين ، بمجرد أن تتضمن التعليمات البرمجية المُرحّلة جداول مؤقتة ، يجب ألا نتحدث عن ترجمة الكود ، ولكن عن إعادة تنفيذ النظام.

أدخل متغيرات الجدول

ربما يتساءل المطورون: ماذا عن متغيرات الجدول؟ هل نحتاج إلى إجراء أي تغييرات أو يمكننا نقل متغيرات الجدول "كما هي" في خطوات الترحيل من Oracle إلى SQL Server؟ حسنًا ، هذا يعتمد على سبب وكيفية استخدامها في الكود.

لنلقِ نظرة على كيفية استخدام كل من الجداول المؤقتة ومتغيرات الجدول. سأبدأ بـ Microsoft SQL Server.

يتطابق تنفيذ متغيرات الجدول في Transact-SQL إلى حد ما مع الجداول المؤقتة ولكنه يضيف بعض الوظائف الخاصة به. يتمثل الاختلاف الرئيسي في القدرة على تمرير متغيرات الجدول كمعلمات للوظائف والإجراءات المخزنة.

هذه هي النظرية ، لكن اعتبارات الاستخدام العملية متضمنة أكثر قليلاً.

تم تكليفي أولاً بتحسين Transact-SQL الجاد عندما كنت قادمًا من خلفية Oracle الراسخة بعمق ، توقعت أن تكون على هذا النحو: متغيرات الجدول موجودة في الذاكرة بينما الجداول المؤقتة على القرص. لكنني وجدت أن إصدارات Microsoft SQL Server حتى عام 2014 لم تخزن متغيرات الجدول في الذاكرة. وبالتالي فإن فحص الجدول الكامل على متغير مؤقت هو في الواقع مسح كامل للجدول على القرص. لحسن الحظ ، يدعم SQL Server 2017 والإصدارات الأحدث تحسين الذاكرة التقريرية لكل من الجداول المؤقتة ومتغيرات الجدول.

إذن ، ما هي حالة استخدام متغيرات الجدول في Transact-SQL إذا كان كل شيء يمكن القيام به بشكل جيد أو أفضل باستخدام الجداول المؤقتة؟ الخاصية الرئيسية لمتغير الجدول أنه متغير وبالتالي لا تتأثر بالتراجع عن المعاملة ويمكن تمريرها كمعامل.

وظائف Transact-SQL مقيدة للغاية: نظرًا لأن مهمة الوظيفة هي إرجاع بعض القيمة المرجعة الفردية ، فلا يمكن أن يكون لها - حسب التصميم - آثار جانبية . يرى Transact-SQL حتى SELECT كأثر جانبي ، لأنه في SQL Server يؤدي أي وصول إلى جدول إلى إنشاء معاملة ضمنية وقفل المعاملة المرتبط بها. هذا يعني أنه داخل دالة ، لا يمكننا الوصول إلى البيانات في جدول مؤقت موجود ، ولا إنشاء جدول مؤقت. نتيجة لذلك ، إذا احتجنا إلى تمرير أي مجموعة من السجلات إلى دالة ، فعلينا استخدام متغيرات الجدول.

تختلف اعتبارات Oracle لاستخدام الجداول المؤقتة ومتغيرات المجموعة (العامة) (مكافئ Oracle PL / SQL لمتغيرات جدول Transact-SQL). متغيرات مجموعة Oracle موجودة في الذاكرة ، بينما توجد الجداول المؤقتة في مساحات جداول مؤقتة. تسمح وظائف Oracle بالوصول للقراءة فقط إلى الجداول ، الدائمة أو المؤقتة ؛ لا يضع SELECT البسيط في Oracle أبدًا قفلًا على الموارد.

في Oracle ، يعتمد اختيار استخدام متغيرات المجموعة مقابل الجداول المؤقتة على المقدار المتوقع من البيانات ، والمدة التي يجب خلالها حفظ هذه البيانات ، والذاكرة مقابل تخصيص القرص وتوافره. أيضًا ، تعد متغيرات المجموعة هي الطريقة القياسية لأخذ صف معين كإخراج إلى برنامج مضيف.

نظرًا لأن معظم عناصر بناء جملة SQL تبدو متشابهة جدًا بين SQL Server و Oracle ، فإن تحويل كتل التعليمات البرمجية مع متغيرات الجدول من SQL Server Transact-SQL إلى Oracle PL / SQL هو عملية أبسط وأكثر تسامحًا من الناحية التركيبية. يمكن أن يجتاز اختبار التحقق الأساسي ، ولكنه لن يكون صحيحًا وظيفيًا ما لم يتم اتخاذ خطوات إعادة تنفيذ الجدول المؤقت ، كما هو موضح أعلاه. من ناحية أخرى ، فإن الكود الذي تم نقله من Oracle إلى SQL Server يتضمن خطوات تعديل أكثر لمجرد أن يكون صالحًا من الناحية التركيبية. لكي تكون صحيحة وظيفيًا أيضًا ، ستحتاج إلى معالجة الحالات المتعمقة لاستخدام الجداول المؤقتة والاعتراضات الاعتلال الدماغي الرئوية.

المعاملات الداخلية ("المعاملات المتداخلة")

فيما يتعلق بتحديات ترحيل Oracle إلى SQL Server ، فإن المجال الرئيسي التالي الذي يجب النظر إليه هو المعاملات المتداخلة.

تمامًا كما هو الحال مع الجداول المؤقتة ، إذا اشتمل رمز Transact-SQL على أي معاملة ، سواء كانت متداخلة أم لا ، أو كان رمز Oracle يتضمن أي معاملات متداخلة ، فإننا لا نتحدث فقط عن ترحيل رمز عادي ، بل عن إعادة تنفيذ وظيفي.

أولاً ، دعنا نلقي نظرة على كيفية تصرف معاملات Oracle المتداخلة وكيف نميل إلى استخدامها.

المعاملات المتداخلة في Oracle

تعتبر معاملات Oracle المتداخلة ذرية تمامًا ومستقلة عن النطاق الخارجي. لا يوجد استخدام فعلي للمعاملات المتداخلة في استعلامات Oracle SQL التفاعلية العادية. عندما تعمل مع Oracle في الوضع التفاعلي ، فإنك تقوم يدويًا بتنفيذ التغييرات عندما ترى أنك وصلت إلى حالة. إذا أجريت بعض التغييرات التي لا يمكنك الالتزام بها حتى الآن ، فستقوم بالخطوة الأخيرة - على سبيل المثال ، غير مؤكد بالنسبة لك - والتي قد تحتاج إلى التراجع ، ولكنك تريد الحفاظ على العمل الذي قمت بإنجازه بالفعل ، ستنشئ نقطة آمنة للرجوع إليها دون الالتزام أو التراجع عن المعاملة الكاملة.

إذن ، أين يتم استخدام المعاملات المتداخلة؟ في PL / SQL التعليمات البرمجية. بشكل أكثر تحديدًا في الإجراءات المستقلة - تلك المعلنة مع PRAGMA AUTONOMOUS_TRANSACTION . هذا يعني أنه عندما يتم استدعاء هذا الرمز (كإجراء مخزن مسمى أو مجهول) ، يتم تنفيذ المعاملة أو التراجع عنها بشكل مستقل عن المعاملة التي تسمى هذا الرمز.

الهدف من استخدام المعاملات المتداخلة هو الحصول على وحدة عمل قائمة بذاتها يتم الالتزام بها أو التراجع عنها بغض النظر عما سيحدث لكود الاستدعاء. عندما يمكن الالتزام بمعاملة داخلية أو التراجع عنها ، فسيتم استخدامها للتحقق من توفر (أو حجز) الموارد المشتركة - على سبيل المثال في تنفيذ نظام حجز الغرف. الاستخدام الأساسي للمعاملات الداخلية للالتزام فقط هو مراقبة النشاط وتتبع الكود وتدقيق الوصول الآمن (على سبيل المثال ، لم يُسمح للمستخدم بإجراء تغييرات ، ولكن حاول ذلك.)

المعاملات المتداخلة في تعليمات SQL Server Transact-SQL البرمجية مختلفة تمامًا.

المعاملات المتداخلة في SQL Server

في Transact-SQL ، يعتمد تنفيذ معاملة داخلية بالكامل على المعاملة الخارجية. إذا تم التراجع عن معاملة داخلية ، فسيتم التراجع عنها للتو. ولكن إذا تم الالتزام بمعاملة داخلية ، فإنها لا تزال غير ملتزمة تمامًا ، حيث يمكن التراجع عنها إذا تم التراجع عن أي مستوى من معاملات النطاق الخارجي الخاصة بها.

إذن ، ما فائدة المعاملات الداخلية إذا كان من الممكن التراجع عن التزاماتها عن طريق التراجع عن معاملتها الخارجية؟ الإجابة هي نفسها كما في حالة الاستخدام للجداول المؤقتة المحلية: تحرير القفل على الموارد. الفرق هو أنه ليس إصدار قفل عالمي ، ولكنه قفل ضمن نطاق المعاملة الخارجية المباشرة (المباشرة "الأصل"). يتم استخدامه في كود Transact-SQL المعقد لإصدار الموارد الداخلية للمعاملة الخارجية. إنها أداة لتحسين الأداء وإدارة الموارد.

نظرًا لأن المعاملات الداخلية / المتداخلة في Oracle و SQL Server لها سلوك مختلف (ربما حتى عكس ذلك) وحالات استخدام مختلفة تمامًا ، فإن الترحيل من نظام أساسي إلى آخر لا يتطلب إعادة الكتابة فحسب ، بل يتطلب إعادة تصميم أي نطاق يحتوي على كتل معاملات متداخلة بالكامل .

عوامل اخرى

هل هذه الاعتبارات المتعلقة بالجدول المؤقت والمعاملات التي تتمحور حول المعاملات هي الأشياء الوحيدة التي يجب معالجتها في ترحيل Oracle إلى SQL Server؟ على الرغم من أنها قد تكون الأهم ، إلا أن هناك بالتأكيد آخرين ، لكل منهم مراوغاته الخاصة التي تستحق التغطية. فيما يلي بقية ما وجدته من أكثر الموضوعات التي أسيء فهمها:

  1. أعمدة الهوية في SQL Server
  2. التسلسلات في Oracle
  3. المرادفات في Oracle
  4. الفهارس المصفاة
  5. قراءة التناسق (Oracle إلى SQL Server فقط)
  6. استخدام أدوات الترحيل

يستمر الجزء التالي من هذه السلسلة من خلال استكشاف هذه ، ولا سيما الثلاثة الأولى.

الجداول المؤقتة ، ومتغيرات الجدول / المجموعة ، والمعاملات المتداخلة: أهم 3 نقاط ألم للترحيل

لقد بدأت بالجداول المؤقتة ومتغيرات الجدول / المجموعات والمعاملات المتداخلة لأن هذه هي أكثر نقاط الفشل شيوعًا ووضوحًا في مشاريع التحويل. لا شك في أن أي نظام غير تافه في Oracle Database أو Microsoft SQL Server سيستخدم بعضها ، واستخدام هذه العناصر يقترن بشدة بالتصميم المحدد لدعم المعاملات من خلال تطبيقات RDBMS المعنية.

واصل القراءة في الجزء 2!

شارة شريك مايكروسوفت الذهبية. (Toptal شريك ذهبي لمايكروسوفت).