Rolling update to all rows in innodb table (no rollback if aborted)
I ended up doing this, to do it in batches of 1krow (which takes about .2s per batch if there's nothing to update, 2s otherwise; basically it has the same total speed per row if it's in batches of 10k, 5k or 1k):

SET SESSION sql_mode = 'strict_all_tables';
SET SESSION sql_warnings = 1;
\W
DELIMITER //
DROP PROCEDURE IF EXISTS update_dmf_lifespan//
CREATE PROCEDURE update_dmf_lifespan(INOUT i INT)
BEGIN
 SET @i = i;
 SET @max = (select id from death_master_files order by id desc limit 1);
 setloop: LOOP
  UPDATE death_master_files SET lifespan = DATEDIFF(MAKEDATE(death_year, 1) + INTERVAL (death_month-1) MONTH + INTERVAL (IFNULL(IFNULL(death_day,birth_day),1)-1) DAY, MAKEDATE(birth_year, 1) + INTERVAL (birth_month-1) MONTH + INTERVAL (IFNULL(birth_day,1)-1) DAY) WHERE DATEDIFF(MAKEDATE(death_year, 1) + INTERVAL (death_month-1) MONTH + INTERVAL (IFNULL(IFNULL(death_day,birth_day),1)-1) DAY, MAKEDATE(birth_year, 1) + INTERVAL (birth_month-1) MONTH + INTERVAL (IFNULL(birth_day,1)-1) DAY) &gt;= 0 and id BETWEEN @i AND @i+1000;
  SELECT @i, ROW_COUNT(), LAST_INSERT_ID();
  SELECT *, DATEDIFF(MAKEDATE(death_year, 1) + INTERVAL (death_month-1) MONTH + INTERVAL (IFNULL(IFNULL(death_day,birth_day),1)-1) DAY, MAKEDATE(birth_year, 1) + INTERVAL (birth_month-1) MONTH + INTERVAL (IFNULL(birth_day,1)-1) DAY) as diff from death_master_files WHERE DATEDIFF(MAKEDATE(death_year, 1) + INTERVAL (death_month-1) MONTH + INTERVAL (IFNULL(IFNULL(death_day,birth_day),1)-1) DAY, MAKEDATE(birth_year, 1) + INTERVAL (birth_month-1) MONTH + INTERVAL (IFNULL(birth_day,1)-1) DAY) &lt; 0 and id BETWEEN @i AND @i+1000;
  SET @i = @i + 1000;
  IF @i + 1000 &gt; @max THEN
   LEAVE setloop;
  END IF;
 END LOOP setloop;
END
//
SET @i = 1//
CALL update_dmf_lifespan(@i)//
DROP PROCEDURE IF EXISTS update_dmf_lifespan//
DELIMITER ;


… so this'll probably take 2 days to run, plus more for the OPTIMIZE TABLE afterwards. :-/

Also, I haven't figured out how to get both SHOW WARNINGS and ROW_COUNT(), since they don't seem to be joinable in a single statement and both output results based on the previous statement (including each other).

I've set it to strict mode with a resumable point, which lets me manually inspect and resume after warnings. 

That's surely not the best option, though I'm not sure what would be better. For cases where the deathdate is before the birthdate (the data is not exactly 100% reliable), and thus it raises on lifespan being unsigned, it doesn't update and instead outputs with select. This won't catch other sources of warnings, though.