MySQL change engine on tables with Foreign Keys - mysql

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

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.

Foreign keys for myISAM and InnoDB tables

I have a DB table that is myISAM, used for fulltext searching. I also have a table that is InnoDB. I have a column in my myISAM table that I want to match with a column in my InnoDB table. Can that be done? I cant seem to work it out!
http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html
Foreign keys definitions are subject to the following conditions:
Both tables must be InnoDB tables and they must not be TEMPORARY tables.
So, I'm afraid you wont be able to achieve what you want done.
I would recommend altering your DB architecture such that you have one set of tables designed with data integrity for writing (all InnoDB), and a second set designed for search - possibly on a different box, and possibly not even using MySQL, but maybe a search server like Solr or Sphinx, which should outperform a fulltext MySQL table. You could then populate your search DB periodically from your write DB.

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.

Quick question about relational one-to many database

I'm doing a venue/events database and I've created my tables and would like some confirmation from someone if I did everything right :)
I have 2 tables:
Venues
Events
The primary key of Venues is VENUE_ID, which is set to auto_increment. I have the same column in Events, which will contain the number of the Venue ID. This should connect them, right?
Also, the table engine is MyISAM.
It does not automatically link the tables to each others, and the referenced columns don't necessarily have to have the same name (in fact, there are situations where this is impossible: e.g. when a table has two columns that both reference the same column in another table).
Read up on foreign keys; they're standard SQL and do exactly what you want. Note, however, that the MyISAM storage engine cannot enforce foreign key constraints, so as long as any of the tables involved uses MyISAM, the foreign key declaration doesn't add much (it does, however, document the relationship, at least in your SQL scripts).
I suggest you use InnoDB (or, if that's feasible, switch to PostgreSQL - not only does it provide foreign key constraints, it also has full support for transactions, unlike MySQL, which will silently commit a pending transaction whenever you do something that's not supported in a transaction, with potentially devastating results). If you have to / want to use MySQL, I suggest you use InnoDB for everything, unless you know you need the extra performance you can get out of MyISAM and you can afford the caveats. Also keep in mind that migrating large tables from MyISAM to InnoDB later in production can be painful or even outright impossible.
Your db structure is right.
You can use Innodb for adding foreign key contraints. Also don't forget to add index to the second table for faster joining two tables.
More info about FK http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
Note to comments:
Innodb allows you to make concurrent select/(insert/update) but MyIsam allows you to do the same things if you don't delete from MyIsam table. Otherwise MyIsam will lock your whole table.
Generally, yes. This is how you indicate a one-to-many relation between two tables. You may also specifically encode the relationship into the database by setting up a Foreign Key constraint. This will allow add'l logic such as cascading.

need help implementing InnoDB storage engine to existing database

I am trying to add primary keys to my tables, via Sequel Pro and it said "This table currently does not support relations. Only tables that use the InnoDB storage engine support them."
I went into phpMyAdmin and looked at the storage engines and saw InnoDB listed, highlighted in blue, then I selected it and it displayed this info: http://cl.ly/68Ph
It is enabled, but I am unsure how to implement it to my existing database, any help is appreciated.
You should tell your tables to use InnoDB:
ALTER TABLE mytable ENGINE=InnoDB
for existing tables,
CREATE TABLE mytable (…) ENGINE=InnoDB
for the new ones.
Note that InnoDB supports neither SPATIAL nor FULLTEXT indexes so don't use it if your application relies on them.