如何处理Apex批处理中的SerialBatchApexRangeChunkHandler内部Salesforce.com错误

如何处理Apex批处理中的SerialBatchApexRangeChunkHandler内部Salesforce.com错误,salesforce,apex,Salesforce,Apex,我正在批量更新一些帐户记录。但是,每当更新由于某些验证逻辑而失败时(在本例中,数字太长),批处理就会陷入处理模式,我必须手动中止它。在日志中,我看到操作:SerialBatchApexRangeChunkHandler状态:Internal Salesforce.com Error。如果我删除Database.Stateful,那么批处理就会完成,但是我需要在电子邮件中提供错误详细信息,所以我必须实现它 如果需要更多细节,请帮助我并让我知道 global class testBatchSetti

我正在批量更新一些帐户记录。但是,每当更新由于某些验证逻辑而失败时(在本例中,数字太长),批处理就会陷入处理模式,我必须手动中止它。在日志中,我看到操作:SerialBatchApexRangeChunkHandler状态:Internal Salesforce.com Error。如果我删除Database.Stateful,那么批处理就会完成,但是我需要在电子邮件中提供错误详细信息,所以我必须实现它

如果需要更多细节,请帮助我并让我知道

global class testBatchSettingsAndDebug implements Database.Batchable<sobject>, Database.Stateful {

    global String[] email= new String[] {'email@domain.com'};
    global List<Database.saveResult> dsrs = new List<Database.saveResult>();
    global String errorMessages {get; set;}
    global integer count=0;
    global List<String> exception_List;

    global testBatchSettingsAndDebug (){
        errorMessages ='';
    }


    //Start
        global Database.QueryLocator start (Database.BatchableContext bc){
            return Database.getQueryLocator('select id from Account limit 10');

        }    
    //Excecute
    global void execute (Database.BatchableContext bc, List<sobject> scope){
        List<Account > accToUpdateLsit = new List<Account >();//List to hold accs to update
        for (sObject objScope: scope) { 
            Account accObj = (Account )objScope ;//type casting from generic sOject to acc
            accObj.NumberofLocations__c= 123456;
            accToUpdateLsit.add(accObj);
         } 

         count=accToUpdateLsit.size();

         System.debug('Number of Records to update: '+accToUpdateLsit.size());



            if (accToUpdateLsit != null && accToUpdateLsit.size()>0) {//Check if List is empty or not
                dsrs = Database.update(accToUpdateLsit, false);
                System.debug('Records are successfully updated '+accToUpdateLsit);//Update the Records
            }




        for(Database.SaveResult dsr : dsrs){
            if(!dsr.isSuccess()){
                errorMessages += string.valueof(dsr.geterrors() + '\n'); 


           }
        }
        system.debug('Error occured: '+errorMessages);




    }

    //Finish
    global void finish (Database.BatchableContext BC){

       System.debug('**Record Updated**'+count);


       Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

      //Below code will fetch the job Id
          AsyncApexJob a = [Select a.TotalJobItems, a.Status, a.NumberOfErrors, a.JobType, a.JobItemsProcessed, a.ExtendedStatus, a.CreatedById, a.CompletedDate From AsyncApexJob a WHERE id = :BC.getJobId()];//get the job Id
          System.debug('Jobid is'+BC.getJobId());

          //below code will send an email to User about the status
          mail.setToAddresses(email);
          mail.setReplyTo('email@domain.com');//Add here your email address
          mail.setSenderDisplayName('Account Batch Notification');
          mail.setSubject('Account Batch Batch Processing '+a.Status);
          mail.setPlainTextBody('The Batch Apex job processed:  '+a.TotalJobItems+' batches with: '+a.NumberOfErrors+' failures: '+' Error Messages:'+errorMessages );
          Messaging.sendEmail(new Messaging.Singleemailmessage [] {mail});



       System.debug('**Job completed**');

    }
}
全局类TestBatchSettings和Debug实现Database.Batchable、Database.Stateful{
全局字符串[]电子邮件=新字符串[]{'email@domain.com'};
全局列表dsrs=新列表();
全局字符串错误消息{get;set;}
全局整数计数=0;
全局列表异常列表;
全局testBatchSettingsAndDebug(){
errorMessages='';
}
//开始
global Database.QueryLocator启动(Database.BatchableContext bc){
return Database.getQueryLocator('select id from Account limit 10');
}    
//过分的
全局void execute(Database.BatchableContext bc,列表范围){
List ACCTOUPDATESIT=new List();//保存要更新的accs的列表
对于(sObject对象范围:scope){
Account accObj=(Account)objScope;//从泛型sOject到acc的类型转换
accObj.地点数量=123456;
ACCTOUPDATESIT.add(accObj);
} 
count=acctupdatesit.size();
System.debug('要更新的记录数:'+ACCTOUPDATESIT.size());
如果(ACCTOUPDATESIT!=null&&ACCTOUPDATESIT.size()>0){//检查列表是否为空
dsrs=Database.update(acctupdatesit,false);
System.debug('记录已成功更新'+ACCTOUPDATESIT);//更新记录
}
对于(Database.SaveResult dsr:dsrs){
如果(!dsr.issucess()){
errorMessages+=string.valueof(dsr.geterrors()++'\n');
}
}
system.debug('发生错误:'+错误消息);
}
//完成
全局void完成(Database.BatchableContext BC){
系统调试('**记录更新**'+计数);
Messaging.SingleEmailMessage mail=新建消息。SingleEmailMessage();
//下面的代码将获取作业Id
AsyncApexJob a=[从AsyncApexJob a中选择a.TotalJobItems、a.Status、a.NumberOfErrors、a.JobType、a.JobItemsProcessed、a.ExtendedStatus、a.CreatedById、a.CompletedDate,其中id=:BC.getJobId()];//获取作业id
debug('Jobid是'+BC.getJobId());
//下面的代码将向用户发送有关状态的电子邮件
mail.SetToAddresss(电子邮件);
mail.setReplyTo('email@domain.com“);//在这里添加您的电子邮件地址
mail.setSenderDisplayName(“帐户批处理通知”);
mail.setSubject('科目批处理'+a.Status);
mail.setPlainTextBody('处理的批处理作业:'+a.TotalJobItems+'批处理:'+a.NumberOfErrors+'失败:'+'错误消息:'+errorMessages');
Messaging.sendmail(newmessaging.Singleemailmessage[]{mail});
调试(“**作业已完成**”);
}
}

看起来你可以做工作中提到的事情,比如:
声明您的数据库。saveResult

那么为什么您只查询帐户ID,而设置NumberofLocations\uu\c字段呢?这是行不通的。或者这只是一个例子?这只是一个例子来说明我所面临的问题。在实际代码中,它具有基于业务逻辑的where逻辑。但问题是相同的,当更新过程中由于某些验证逻辑而出现错误时,批处理会被卡住。我在一个中断批处理的流程(使用process builder创建)中遇到了类似的问题。但我遇到了一个“正常”Salesforce错误,批处理停止了。在我的情况下,唯一的解决方案是以一种不会干扰批处理的方式更改流程。您是否尝试使用Batchsize 1运行它?也许你会得到更好的错误结果我的要求很简单。假设我正在更新10条记录,如果其中5条由于任何验证而未能更新,我希望在电子邮件中显示计数、记录ID和错误。我不知道为什么不会发生这种情况。请将您的答案更新为“将Database.SaveResult声明为transient”。)我不能做数据库更新(ACCTOUPDATESIT,true);因为我必须接受部分更新。我将Database.SaveResult声明为transient。工作得很好。