Apex Batch未处理全部记录问题排查求助
Apex Batch仅处理部分记录的排查与解决方案
核心问题排查方向
- 静默吞掉异常导致批次失败:代码里的
catch(Exception ex){}是空块,任何批次处理时抛出的异常都会被直接吞掉,Salesforce会认为你已经处理了异常,不会重试该批次,也不会在日志里留下错误记录——这是最可能的原因。比如某个批次触发了Governor Limit、处理逻辑报错,都不会被察觉,直接跳过该批次的记录。 - Governor Limit触发:单独运行处理代码没问题,但Batch是批量上下文,每个批次默认200条(可设到2000),如果
CustomBSNAReportingHandler.updateOpportunityBSNAReporting里有循环SOQL、过量DML、CPU超时等情况,触发限制后抛出异常,被空catch块吞掉,导致该批次记录未处理。 - Batch执行被中断:Salesforce默认限制同时运行5个Batch,如果你的Org有其他Batch在执行,可能导致后续批次无法调度;或者遇到系统维护、资源紧张,Batch执行中途停滞。可以在Setup的「Apex Jobs」里查看任务状态,确认是否有未完成/失败的批次。
- QueryLocator游标异常:虽然查询编辑器验证过逻辑,但百万级数据加
ORDER BY CreatedDate DESC,如果索引使用异常,可能导致QueryLocator游标提前失效,不过这个概率较低。
修复建议
移除空catch块,添加错误日志与重试机制
把空catch块改成记录错误并抛出异常,这样系统会自动重试失败的批次,你也能在日志里找到问题根源:catch(Exception ex){ System.debug(LoggingLevel.ERROR, 'Batch批次处理失败:记录数=' + oppList.size() + ',错误=' + ex.getMessage() + ',堆栈=' + ex.getStackTraceString()); throw ex; // 抛出异常让系统重试该批次 }检查Batch执行状态
进入Setup搜索「Apex Jobs」,找到BatchAssignment任务,查看:- 任务状态是否为「Completed」,如果是但处理记录数少,说明有批次被静默跳过
- 查看失败次数、错误信息,直接定位问题
优化批次大小与处理逻辑
调用Batch时可以设置更大的批次(最大2000),但要确保处理逻辑能承受:Database.executeBatch(new BatchAssignment(), 2000);同时检查
updateOpportunityBSNAReporting里的代码,避免循环内SOQL、批量DML拆分过细等耗资源的写法。拆分查询减少单次Batch压力
如果百万级数据处理压力大,可以按时间拆分查询,比如分三次执行Batch:分别处理最近1年、1-2年、2-3年的记录,降低单次游标负载。
优化后的Batch代码示例
global class BatchAssignment implements Database.Batchable<SObject>{ global Database.QueryLocator start(Database.BatchableContext BC){ return Database.getQueryLocator([ SELECT Id, Booking_Domain__c, Region__c, Primary_LOB__c, NA_Contract_Sales_Type__c, Owner_Sales_Group__c, Connected_Technologies_Opportunity__c FROM Opportunity WHERE CreatedDate > LAST_N_YEARS:3 ORDER BY CreatedDate DESC ]); } global void execute(Database.BatchableContext BC, List<Opportunity> oppList) { try{ if(!oppList.isEmpty()){ CustomBSNAReportingHandler.updateOpportunityBSNAReporting(oppList); } if(Test.isRunningTest()) { throw new DMLException('测试用异常'); } }catch(Exception ex){ System.debug(LoggingLevel.ERROR, 'Batch批次[' + BC.getJobId() + ']处理失败:记录数=' + oppList.size() + ',错误=' + ex.getMessage()); throw ex; } } global void finish(Database.BatchableContext BC){ // 可添加执行完成后的通知,比如发送邮件告知处理结果 } }
内容的提问来源于stack exchange,提问作者unflagged.destination
相关产品推荐
相关产品推荐

