Reputation: 25993
We have a large schema migration to run, and we don't want the site to go down for ages, so we're trying to do it on the fly and without read locking the tables involved. The tables involved only get written to at specific times of the day, so we have a window in which we can afford to have write locks; but while a lot of the mysql docs claim ALTER TABLE
should only write lock tables, in our experience anything nontrivial such as adding an index read locks it.
So, we've had to do the migrations by hand. We've had some success with the following procedure:
CREATE TABLE new_mytable LIKE mytable;
new_mytable
mysqldump -t mydb mytable > mytable.sql
mytable.sql
to insert into the correct columns of new_mytable
mysql mydb < mytable.sql
mytable
- they're not copied by CREATE TABLE ... LIKE ...
new_mytable
RENAME TABLE mytable TO old_mytable, new_mytable TO mytable
DROP TABLE old_mytable
As I say, the tables involved only get written to at specific times of the day, so we're certain that the data stays consistent - otherwise we wouldn't dream of trying something like that. Even so, we've hit a problem. Until now, we've only tried it on tables where the FKs point outwards. Today I tried it on a table which was referred to by several other tables. When I dropped the old table, I was told that a foreign key constraint failed, and was horrified to see that the referring tables now refer to the old table.
Now, we could drop the FKs and re-add them to the new one, but the process is fragile enough as it is; there are a lot of tables pointing to this one; and re-adding the keys may give us read locks. We're certain - certain - that the new table contains all the same data as the first one, so what would be nice would be to change the referent of those FKs without dropping and adding them. Is there a way to manipulate the DB such that the existing FKs are altered to refer to the new table?
Upvotes: 2
Views: 1362
Reputation: 76713
Provided you know how to alter the tables themselves.
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
...Alter the tables and change the keys
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
Upvotes: 2