The only solution I can think of to avoid a long table lock, is to create a new table with the desired structure. Then use INSERT INTO ... SELECT
to populate that table, re-create all indexes (including the new one) and then rename the new table to the old table.
Renaming the table can be done in a transaction so that no client will notice this (although this might take some time, because I think the RENAME will wait until it gets an exclusive lock).
You will have to recreate foreign keys referencing that table as well (not sure about the level of locking involved in that).
This of course is only possible if you have enough space so that you can keep a complete copy of the table around.