Question :
I’m trying to convert some MyISAM tables in my database to InnoDB (MySQL 5.1). The server has quite a bit of memory (96G), and the tables that are giving me problems can be on the order of 50 millions rows – 160 million rows (anywhere from 10G to 25G), but the same thing is happening regardless of table size.
During the “INSERT INTO … SELECT * FROM…” MySQL starts using swap memory and I have to kill the conversion because it will take over 10 hours or so. While researching the conversion process, I found multiple sources that say that innodb_buffer_pool_size should be about 70% of your server RAM, so I made it about that, but I think that may be what’s causing the issue.
Here are some important my.cnf settings:
innodb_buffer_pool_size=64G
innodb_flush_method=O_DIRECT
innodb_log_file_size=224K
innodb_log_buffer_size=24M
innodb_flush_log_at_trx_commit=0
innodb_additiona_mem_pool_size=24M
key_buffer_size=8G
sort_buffer_size=4M
read_buffer_size=128K
Any ideas what I’m doing wrong/why it’s going to swap? Any ideas would be helpful.
Answer :
To switch of MySQL engine you could :
1 Make a ALTER TABLE myTable ENGINE=InnoDB
2 Make a mysqldump of your table, then edit the CREATE TABLE statement to replace MyISAM by InnoDB and restore the dump in the new table (i called it myTable_InnoDB):
DROP TABLE IF EXISTS `mytable`;
CREATE TABLE `mytable` (
`id` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
.
DROP TABLE IF EXISTS `mytable_InnoDB`;
CREATE TABLE `mytable_InnoDB` (
`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Best regards
Here is the reason why you are hitting swap: You are using MySQL 5.1.
The InnoDB Storage Engine in MySQL 5.1 isn’t as aware of memory as MySQL 5.5+.
What I have seen over the years is this: Whenever the InnoDB Buffer Pool is bigger than 50% of installed RAM, you get lots of swap happening. I wrote about this with regard to MySQL 5.5 (See my post How do you tune MySQL for a heavy InnoDB workload?)
I would further suggest you read
Please implement 1 or more of the following suggestons:
SUGGESTION #1
Upgrade to MySQL 5.6 and set innodb_buffer_pool_instances to 2 or more.
SUGGESTION #2
Reduce innodb_buffer_pool_size to 48G (I would use 44G just to be well under the 50% RAM mark)
SUGGESTION #3
You could mysqldump the data, but I would reduce the chunks of data to 1 row at a time as follows:
STEP 1 : Make the InnoDB table
CREATE TABLE mytable_innodb LIKE mytable_myisam;
ALTER TABLE mytable_innodb ENGINE=InnoDB;
STEP 2 : mysqldump the data
MYSQLDUMP_OPTIONS="--no-create-info --skip-extended-insert"
mysqldump ${MYSQLDUMP_OPTIONS} mydb mytable_myisam | sed 's/mytable_myisam/mytable_innodb/g' > mydata.sql
Note: The mysqldump will insert only one row at a time (–skip-extended-insert). If you think mysql and InnoDB can handle it with a smaller Buffer Pool, remove the –skip-extended-insert.
STEP 2a : OPTIONAL
Restart mysql with the InnoDB Double Write Buffer Off. This will make for fast writes to InnoDB tables.
service mysql restart --innodb-doublewrite=0
STEP 3 : import the data
mysql -Dmydb < mydata.sql
STEP 3a (if you ran STEP 2a)
service mysql restart