I want to remove a foreign key constraint from a table, it is taking a very long time and I wonder what bad things can happen when doing this on a production environment.
ALTER TABLE table DROP FOREIGN KEY fk_my_foreign_key;
Why is it taking that long?
Can I speed it up?
Is it safe to interrupt the process in the middle?
Is there any side effect to running such an operation on a production server?
Is there any consistency issue when the alter table fails (lost connection to the server)? What to do in this case when you cannot restart the server with a different configuration (max packet size)?
More information as requested:
Mysql Server version: 5.5.34
Foreign key references a column on the same table
Table has around 80 million of rows
Key + Constraint on table, ON UPDATE CASCADE ON DELETE CASCADE
In most cases, ALTER TABLE works by making a temporary copy of the
original table. The alteration is performed on the copy, and then the
original table is deleted and the new one is renamed. While ALTER
TABLE is executing, the original table is readable by other sessions.
Updates and writes to the table are stalled until the new table is
ready, and then are automatically redirected to the new table without
any failed updates. Thanks.
What about the others cases? Can I prevent such locks?
Firstly I must say best practice is always to Test such a change in an offline environment.
Is the table used by replication? if so you would need to remove it first. Also if the table is currently being used it could be locked in a process, check the activity monitor and also look for deadlocks. It would be a good idea to ensure that the key is also not referenced by any index
To safely and correctly remove a foreign key there are many detailed articles that can ben found on Google.
Related
I have a not so big table, around 2M~ rows.
Because some business rule I had to add a new reference on this table.
Right now the application is writing values but not using the column.
Now I need to update all null rows to the correct values, create a FK, and start using the column.
But this table has a lot of reads, and when I try to alter table to add the FK the table is locked and the read queries get blocked.
There is any way to speed this?
Leaving all fields in NULL values helps to speed up (since I think there will be no need to check if the values is valid)?
Creating a index before helps to speed up?
In postgres I could create a not valid FK and then validate it(which caused only row lock, not table lock), there is anything similar in MySQL?
What's taking time is building the index. A foreign key requires an index. If there is already an index on the appropriate column(s), the FK will use it. If there is no index, then adding the FK constraint implicitly builds a new index. This takes a while, and the table is locked in the meantime.
Starting in MySQL 5.6, building an index should allow concurrent read and write queries. You can try to make this explicit:
ALTER TABLE mytable ADD INDEX (col1, col2) LOCK=NONE;
If this doesn't work (like if it gives an error because it doesn't recognize the LOCK=NONE syntax), then you aren't using a version of MySQL that supports online DDL. See https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html
If you can't build an index or define a foreign key without locking the table, then I suggest trying the free tool pt-online-schema-change. We use this at my job, and we make many schema changes per day in production, without blocking any queries.
I'm a very beginner to relations, so this may sound dumb. But, what is the difference (in MySQL) between truncating a table and removing all the records (this answer says only about performance)?
I was playing (in phpMyAdmin) with one of my test tables, to check, how can I reset auto_increment value of table and run into situation, where I was able to delete all the records:
DELETE from managers;
But when I tried to truncate this table (TRUNCATE managers), I've got warning: Cannot truncate a table referenced in a foreign key constraint (probes, CONSTRAINT probes_ibfk_4 FOREIGN KEY (manager_id) REFERENCES managers (id));.
I had to "reset" the auto_increment value with ALTER TABLE managers AUTO_INCREMENT = 1;.
Isn't that something odd? Up until now, I thought, that TRUNCATE = DELETE from managers (in terms of checking and effects, because performance can be different, but this is not the key here).
How can constraint warning pop on TRUNCATE but not on "delete all"?
truncate resets auto_increment after deleting all rows. so it's not the same as deleting all rows with DELETE command.
from mysql reference:
Although TRUNCATE TABLE is similar to DELETE, it is classified as a
DDL statement rather than a DML statement. It differs from DELETE in
the following ways:
Truncate operations drop and re-create the table, which is much faster
than deleting rows one by one, particularly for large tables.
Truncate operations cause an implicit commit, and so cannot be rolled
back. See Section 13.3.3, “Statements That Cause an Implicit Commit”.
Truncation operations cannot be performed if the session holds an
active table lock.
TRUNCATE TABLE fails for an InnoDB table or NDB table if there are any
FOREIGN KEY constraints from other tables that reference the table.
Foreign key constraints between columns of the same table are
permitted.
Truncation operations do not return a meaningful value for the number
of deleted rows. The usual result is “0 rows affected,” which should
be interpreted as “no information.”
As long as the table format file tbl_name.frm is valid, the table can
be re-created as an empty table with TRUNCATE TABLE, even if the data
or index files have become corrupted.
Any AUTO_INCREMENT value is reset to its start value. This is true
even for MyISAM and InnoDB, which normally do not reuse sequence
values.
When used with partitioned tables, TRUNCATE TABLE preserves the
partitioning; that is, the data and index files are dropped and
re-created, while the partition definitions (.par) file is unaffected.
The TRUNCATE TABLE statement does not invoke ON DELETE triggers.
Dropping a foreign key on a table with 215k+ (with alter table) records seems to take a long time (17+ minutes). Is it possible to somehow speed up the process?
SQL: ALTER TABLE sales_flat_order_grid DROP FOREIGN KEY FK_SALES_FLAT_ORDER_GRID_STORE;
It is a magento upgrade that takes ages
Unless you are using InnoDB Plugin (and by default, in MySQL 5.0 and 5.1 you are not), removing an index require rebuilding the whole table.
If you can't upgrade MySQL, you should either look at online-schema-change (involving transfering all of the data to a new table without the index) or stop the site, minimize any I/O activity and wait the operation to complete.
My application writes to a table core; this name is immutable. It's gotten very large (millions of rows) and so its size make INSERTs into it slower than they need be. My solution is to only hold one week's worth of data in core. So I've constructed a table core_archive to put everything older than one week into at scheduled intervals.
At schedule intervals a script gets all the new values in core, operates on them and puts them into a third table core_details. The schema is such that core_details has a foreign key constraint to the PK in core.
My problem is that because of this foreign key constraint (between core_detail and core), I cannot delete any rows from core. So what should I do?
Options:
Do an ALTER TABLE to point the old foreign key constraints at core_archive. This really shouldn't and maybe can't be done safely on a large production database, though.
? [I have no other viable ideas...any thoughts StackO?]
You'll have to create a core_details_archive table as well and archive the rows of core_archive that point to rows of core that are scheduled to be archived. Depending on your data structure, this approach may need to be extended to any number of tables.
A client of mine recently formatted his machine and re-installed MySQL Server and my application. He complained that deleting records from master table is not affecting the child tables. I requested him to send the backup of the database. When I restored the database, I found that the Table Engine has changed to MyISAM whereas they were set to InnoDB.
I deleted the records from the child table that were absent in the primary table. After this when I am not re-setting the Foreign Key Index, it displays error: "Foreign key contraint failed. Error 1005" and sometimes error: 150.
I have double checked the rows that might be left in either the primary table or in the child table, but nothing seems to be working.
The primary table has two columns that combinedly form a Primary Key. The columns are: BillNo, BillDate.
Please assist.
This is a widely known MySQL pitfall; I have hit this problem a few times myself. They probably had some problem with InnoDB, and restored their database from backups. Since InnoDB wasn't working, it fell back to the MyISAM storage engine which doesn't support integrity constraints (like foreign keys).
Basically the problem is that, if the InnoDB engine fails to start for whatever reason (usually configuration problems) -- then MySQL silently falls back to the MyISAM engine. Even if your statement says:
CREATE TABLE () ENGINE=InnoDB
then, if InnoDB isn't active, MySQL will happily create a MyISAM table without even warning you. Bye-bye data integrity! :)
You can run SHOW ENGINES to see which engines are active. See this MySQL bug report for more details.
Check that you're using InnoDB engine for both tables.
Check that both fields are of the same type and that they are indexed.
From http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html:
If you re-create a table that was
dropped, it must have a definition
that conforms to the foreign key
constraints referencing it. It must
have the right column names and types,
and it must have indexes on the
referenced keys, as stated earlier. If
these are not satisfied, MySQL returns
error number 1005 and refers to error
150 in the error message.