كيفية إصلاح MIXED_DML_OPERATION في عمليات نشر Salesforce

يحاول Apex تعديل كائن setup، مثل User أو Group، وكائن غير setup في نفس المعاملة.

تظهر أثناء: وقت تشغيل Apex، غالبًا داخل تنفيذ الاختبارات المطلوب للنشر

المعنى

MIXED_DML_OPERATION هو exception في وقت تشغيل Apex: لا يسمح Salesforce بتنفيذ DML على كائن setup (User وGroup وGroupMember وما شابه) وكائن غير setup (Account وContact والكائنات المخصصة) ضمن نفس المعاملة. يظهر هذا غالبًا أثناء تنفيذ اختبارات Apex التي يتطلبها النشر إلى الإنتاج، ليتحول إلى فشل اختبار يمنع النشر.

يوجد هذا القيد لأن كائنات setup يمكنها تغيير الوصول على مستوى السجل والمشاركة، ولا يسمح Salesforce لمعاملة واحدة بتغيير من يستطيع رؤية البيانات وكتابة تلك البيانات في الوقت نفسه، وهذا هو سبب أن الإصلاح يتعلق دائمًا بحدود المعاملة، لا بمحتوى السجلات.

التشخيص

الأسباب الشائعة

إعداد الاختبار ينشئ user وسجلات business معًا
تُدرج test method كائن User ثم، في نفس المعاملة، تُدرج سجل Account أو سجل business آخر دون عزل DML.
trigger يعيّن عضوية queue أو group
يُدرج trigger على كائن business عنصر GroupMember أو يحدّث المشاركة أثناء حفظ سجلات business أخرى في نفس السياق.
DML لكائن setup يعمل ضمنيًا بدلاً من أن يكون معزولاً
الكود الذي كان يجب أن يعزل DML لكائن setup في معاملة خاصة به يشغّله بدلاً من ذلك في نفس سياق DML لكائن business.

الحل

  1. انقل DML الخاص بكائن setup إلى معاملة خاصة به
    غلّف إدراج User أو Group داخل method مستقبلية (future)، أو اعزلها بطريقة أخرى، حتى يتم تثبيتها قبل تشغيل DML لكائن business.
    @future
    private static void insertUserAsync(String jsonUser) {
        User u = (User) JSON.deserialize(jsonUser, User.class);
        insert u;
    }
  2. استخدم Test.startTest() وTest.stopTest() لفصل المعاملة
    في الاختبارات، ضع DML لكائن setup قبل Test.startTest() حتى يعمل ضمن حدود معاملته الخاصة قبل DML لكائن business.
  3. لا تجمع أبدًا بين إدراجات كائن setup وكائن business في سياق trigger واحد
    أعد هيكلة الأتمتة بحيث لا تشارك تغييرات كائن setup، مثل تزويد المستخدمين أو عضوية المجموعات، معاملة مع DML لسجلات business أبدًا.
من واقع الاستخدام

إزاي Serpent بتمنع ده

يشغّل خط أنابيب CI الخاص بـ Serpent مجموعة اختبارات Apex الكاملة على كل مهمة قبل أن تصبح مؤهلة للدمج، بحيث يظهر فشل اختبار MIXED_DML_OPERATION على المهمة التي تسببت فيه، لا على إصدار إنتاج. راجع مكتبة أخطاء نشر Salesforce.

أداة بناء pipelines لـ CI/CD بلا كود في Serpent

الوقاية

أدرج دائمًا مستخدمي الاختبار ضمن @TestSetup، قبل أي DML لسجلات business
صمّم test classes بحيث يحدث إنشاء كائنات setup ضمن method مخصصة باسم @TestSetup، منفصلة تمامًا عن منطق العمل قيد الاختبار.
اعزل تغييرات عضوية المجموعات والمشاركة في method خدمة خاصة بها
وجّه كل DML الخاص بـ GroupMember وسجلات المشاركة عبر أداة واحدة تُستدعى بشكل غير متزامن، حتى لا يشارك منطق العمل معاملة معها عن طريق الخطأ أبدًا.
ضع علامة على DML لكائن setup في مراجعة الكود
تعامل مع أي إدراج أو تحديث على User أو Group أو GroupMember كإشارة مراجعة للتأكد من عزله بشكل صحيح عن DML لكائن business في نفس method.
أسئلة شائعة

MIXED_DML_OPERATION، بالإجابات

لماذا يفشل MIXED_DML_OPERATION فقط أثناء النشر، وليس في الاستخدام العادي؟
يفشل كلما تم تنفيذ مسار الكود، لكن عمليات النشر إلى الإنتاج تتطلب نجاح جميع اختبارات Apex، لذا فإن اختبارًا يطلق هذا الـ exception يمنع الإصدار بأكمله حتى لو كان الكود الأساسي نادرًا ما ينفّذ هذا المسار في الإنتاج.
ما الكائنات التي تُعد كائنات setup في هذه القاعدة؟
User وGroup وGroupMember وUserRole وعدد قليل من كائنات المشاركة والأذونات ذات الصلة. لا تتأثر معظم الكائنات business والمخصصة ويمكن مزجها بحرية فيما بينها.
هل يتجنب System.runAs() في اختبار هذا الخطأ؟
لا، تغيّر System.runAs() سياق المستخدم المُشغِّل لاختبار الأذونات؛ لكنها لا تعزل حدود معاملة كما يفعل استدعاء future أو Test.startTest().

ابدأ مجانًا. بدون بطاقة ائتمان، وبدون تثبيت، وبدون التزام.

يتم الإعداد في أقل من 15 دقيقة. دون الحاجة لتوظيف متخصص DevOps.

هل تريد معرفة كيف يمكنكم الشحن أسرع قبل البدء؟ لنتحدث

بدون التزام.