You shouldn't use child sub-queries in the start method, as it can have undesirable side effects, including failure to start in time, or errors while processing if the child lists include a QueryLocator. In fact, to make sure you don't have stale data, I usually recommend re-querying the data once you get into the execute method anyways.
Here's how I would rewrite your batch process.
public Database.QueryLocator start(Database.BatchableContext context) {
return Database.getQueryLocator([SELECT Id FROM Account]);
}
public void execute(Database.BatchableContext context, Account[] scope) {
Account[] records = [SELECT Name,(SELECT Name FROM Opps__r) FROM Account WHERE Id = :scope];
// Do something with records
}
This way, you know that you haven't missed any accounts, and can still access all of the opportunities.
Note: If you're trying to handle more than 10,000 opportunities (and you'll need to update potentially all of them), then you're going to have to get more creative by way of a Queueable call. You are allowed one Queueable call per execute method, so you can still handle a larger number of opportunities, but it won't be as easy.