The reason that salesforce introduced Mixed DML Exception

apexbatchlightning-web-components

I attended an interview in the past and some questions really left me wondering why salesforce behaves the way it does. I am seeking answers to these questions, mostly every blog talks about how to avoid these errors and what is the workaround, but not why Salesforce made a particular behavior. I can recall a few of those questions:

  1. What would have happened if Salesforce would have allowed a non setup and setup object DML operation in one transaction? Why MIXED_DML exception had to be introduced?

  2. Why cannot we call a batch from another batch class in the Start method but only from the Finish method?

  3. Why Apex calls are always asynchronous from LWC?

I have always known the workarounds to the technical blockers but these questions gave me another perspective to think about. Any help would be much appreciated. Thanks

Best Answer

Answer to 1 is given in documentation:

https://developer.salesforce.com/docs/atlas.en-us.234.0.apexcode.meta/apexcode/apex_dml_non_mix_sobjects.htm

This restriction exists because some sObjects affect the user’s access to 
records in the org. You must insert or update these types of sObjects in a 
different transaction to prevent operations from happening with incorrect 
access-level permissions. For example, you can’t update an account and a user 
role in a single transaction.

Some detailed explanation as requested :

Lets say you insert an Account (A1), and account is Private shared only with UserRole specific to 'Role1'. So after Account insertion, salesforce runs its sharing recalculation and no users got access except the person inserting the account. After that in same transaction you inserted a new User with role 'Role1', now salesforce again fires its recalculation logic but is not able to find A1 because that is not yet committed to DB. And thus the other user never gets access to A1, until again an update happens.

Answer 2

Its because to control recursiveness. If salesforce would have allowed batch getting called from start metthod. Nothing stops developer to rerun the same batch again from start. Which is an infinite batch loop.

Some detailed explanation as requested :

global class LeadProcessor implements Database.Batchable<SObject> {
    
    global Database.QueryLocator start(Database.BatchableContext BC) {
        Database.executeBatch(new LeadProcessor());
        String queryStr = 'SELECT Id, LeadSource FROM Lead';
        return Database.getQueryLocator(queryStr);
    }

    global void execute(Database.BatchableContext bc, List<SObject> records) {

        // Some Logic
    }

    global void finish(Database.BatchableContext bc) {
        // Some Logic
    }
}

Here Database.executeBatch(new LeadProcessor()); like can cause infinite loop.

Answer 3 : Any calls from LWC to apex always is async. As we know salesforce fetches everything in realtime via rest calls (internal js files, css, page layouts etc). The Apex calls are also made using rest api. Each browser has some limitation of how many concurrent network calls can be made. As apex can contain some heavy calculations, it can stop other HTTP connections if made in a sync manner. Thus the apex calls are actually enqueued in the browser and tt gets executed based on priority (this priority is based on many factors). When the data is received back from Apex then your Promise then gets called. If this is made sync, then it will block other threads to be executed

Related Topic