Another update: at least one problem is that I had a table which had lost a column (admin_set_locations_user was missing user_id). This resulted in the update routine trying to add the column. However, it appears that even though adding a table correctly adds a length specifier to blobs and therefore manages key addition correctly, the add_column_field routine in Std.pm does not.
In that there were no data in the table, I manually dropped it (from within mysql), at which point the admin update script ran (and added the table) and it then functions fine.
I'm now testing upgrading other courses, but my initial testing suggests that this is working.
Vaguely related: is there anything that is done differently by upgrade_admin_course.pl from when one runs an upgrade through the admin course? Our server has a lot of courses, and running upgrade_admin_course.pl after changing the variable $upgrade_courseID would be significantly easier than running upgrades through the web interface.