What is the reason for the introduction of Mixed DML Exception in salesforce?
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 behaviour. I can recall a few of those questions:
What would have happened if Salesforce would have allowed a non setup and setup object DML operation in one transaction? Why did the MIXED_DML exception have to be introduced?
Why cannot we call a batch from another batch class in the Start method but only from the Finish method?
Why are Apex calls always asynchronous from LWC?
The introduction of Mixed DML Exception in salesforce Is due to -
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 :
Let's say you insert an Account (A1), and the account is Private shared only with UserRole specific to 'Role1'. So after Account insertion, salesforce runs its sharing recalculation and no users get access except the person inserting the account. After that in the 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
It's because of recursiveness. If salesforce would have allowed batch getting called from the start method. Nothing stops developers from rerunning the same batch again from the start. Which is an infinite batch loop.
Some detailed explanation as requested :
global class LeadProcessor implements Database.Batchable {
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 records) {
// Some Logic
}
global void finish(Database.BatchableContext bc) {
// Some Logic
}
}
Here Database.executeBatch(new LeadProcessor()); like can cause an infinite loop.
Answer 3
Any calls from LWC to apex always are async. As we know salesforce fetches everything in real time 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 it 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