MySQL foreign key problem - mysql

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.

Related

Geodjango and Innodb, mixed innodb and myisam models

I keep hearing that InnoDB is better for data integrity, unfortunately as of MySQL 5.6 it has yet to support SPATIAL indexes. A fast SPATIAL index is pretty critical to my app, though what's nice about my model that it's pretty much results in a fairly static (write once, read many) table of (ID, POINT), so I could use MyISAM and not care too much.
I'd like to restrict the use of MyISAM to just that table, and migrate it over when InnoDB support for SPATIAL is ready. Problem is, if I ALTER TABLE after my models are migrated (by having an app/sql/app_model.sql) to switch the table to MyISAM, MySQL complains:
ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails
That makes sense, my other models refer to this one and Django automatically makes FOREIGN KEY constraints between those models and this one.
What's the best strategy here? Should I abandon InnoDB and switch everything back to MyISAM? Can I just drop all the FOREIGN KEY constraints?
I tried automating the FOREIGN KEY drops by looking in INFORMATION_SCHEMA.TABLE_CONSTRAINTS, but that only lists the tables that have the constraints, not the tables referred to by those constraints. I would have to do some fuzzy column name matching which feels very brittle.
To solve this I gave up on using InnoDB by default. Because Amazon RDS makes Inno the default, I did this by adding an init_command in my settings.py:
'default': {
'OPTIONS': {
'init_command' : 'SET storage_engine=MYISAM', # Can't make SPATIAL keys on InnoDB
},
}
Then for all but the table with a SPATIAL index I created a $modelname.sql file under the $appname/sql directory that changes the engine after it's created.
-- Alter to InnoDB so we can make concurrent insertions w/o full table lock.
ALTER TABLE <modeltable> ENGINE=INNODB;
Switching to MYISAM default means Django doesn't automatically create the FOREIGN KEY constraints for you for your Inno tables which isn't ideal. I wish there was a way to make Django create them after-the-fact.

MySQL: Dropping a foreign key constraint on an InnoDB table

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.

reorder a column with phpMyAdmin using InnoDB storage engine does not work

Today I tried to reorder a column of a table using phpMyAdmin (as I have done many times before).
Although the result was displayed as successful no reordering effectively happened.
It appears the problem is caused by using InnoDB as storage engine which is the default value from MySQL 5.5 onward.
When I changed back to myIsam the problem was solved. It clarified why it was working on some tables.
Is this a solvable mySQL problem? Or is this regular expected behavior for InnoDB ?
In the latter case phpMyAdmin should perhaps be adapted to not offer the functionality while using InnoDB.
MySQL: 5.5.29
phpMyAdmin: 4.0.4
If by ...reordering column... you meant
ALTER TABLE ... ORDER BY ...
then for InnoDB table that has a PRIMARY or UNIQUE KEY it doesn't work. It's by design:
ALTER TABLE
ORDER BY does not make sense for InnoDB tables that contain a
user-defined clustered index (PRIMARY KEY or NOT NULL UNIQUE index).
InnoDB always orders table rows according to such an index if one is
present.
On the other hand if you don't have PRIMARY or UNIQUE KEY in your table, which is highly unlikely, then MySQL will allow you to change the order.
Here is SQLFiddle demo that demonstrates that behavior.

MySQL change engine on tables with Foreign Keys

So, in the process of creating our tables, we weren't paying close enough attention to our system and all of the tables were created with the InnoDB engine. This is really only bad because we want to have a FULLTEXT index on a few of the columns.
So, now I want to convert. And while I'm at it, I just want to convert all the tables to MyISAM so that if we ever add columns in the future that we want to index, we have that option. So I've got my .sql file with the following:
ALTER TABLE tableName1 Engine = MyISAM;
ALTER TABLE tableName2 Engine = MyISAM;
However, when I try to run it, I get the following error:
Error Code: 1217 Cannot delete or update a parent row: a foreign key constraint fails
As you might have guessed, we have foreign keys in our tables. Not my style, but also not my department, nor my creation script.
My question boils down to, is there anyway for me to change the engine on these tables without having to wipe the DB?
Edit: Note that this will need to be done on multiple development and test copies of the database, so something I can script would definitely be preferred.
Well, to my knowledge, sort of but not really. mysqldump the database and edit out the foreign key constraints in the dumped sql file. And of course change the engine in the CREATE TABLE script.
InnoDB unlike MyISAM support foreign keys and has lots of great features like transactional system that ensures integrity across all tables. MyISAM tables tend to fail now and then when you have large data in tables or for many other reasons.
In the near future InnoDB will implement FullText search. I recommend not to change tables' engine but have something like Sphinx in place. Sphinx is much more powerful and much more flexible than Fulltext Search which works for InnoDB.
More about fulltext search in InnoDB:
InnoDB Fulltext search

Copying data over to innodb from myisam

I currently have a database based on a MYISAM storage engine that has a few thousand records. I want to convert my database over to InnoDb storage engine.
It won't be a simple ALTER storage engine command, since I need to add foreign keys to to the current database schema( the current MyISAM db schema does have primary keys though) before I convert it over to InnoDb.
My question is once I convert the DB over to InnoDb would restoring the data from the current MYISAM engine to InnoDb engine would be as simple as firing a PhpMyAdmin instance and back up the data (minus the db schema or structure) and then restore it to the Innodb engine?
What are the potential hurdles in doing this?
Is this the correct way to go about this or what are the various other easier or better ways to restore data?
It won't be a simple ALTER storage engine command, since i need to add foreign keys to to the current database schema
Why not? Sure backup the data first, that is always a good idea, but you don't need to dump and restore the data, you can issue your simple ALTER TABLE, such as:
ALTER TABLE `tablename` ENGINE = InnoDB;
After that you can add any index and foreign key. If any new foreign key fails, you've to fix your data and try again.
When you add foreign keys first, you have to copy your data in a certain order, otherwise your data won't be added because of foreign key constraints.
Therefore, the best thing is checking (through SQL queries) if you can fulfill your foreign key constraints with your current dataset, then copy the data, afterwards, define foreign keys.
But if you export your data from an InnoDB database with PHPMyAdmin, the order is already fulfilled and you can re-import it without any problems.
You could probably add the foreign keys later
Alter the table to use a new engine
Alter each table to use foreign keys
I only see one issue with that and that would be if the foreign keys are broken to start with.