4

I have a database whose entire size is ~44GB, out of which ibdata1 is ~35GB. That doesnt make sense, since the size of the data shouldn't be more than 10GB.

I use the following query to get an esstimation of the data size:

    SELECT CONCAT(table_schema, '.', table_name),
       CONCAT(ROUND(table_rows / 1000000, 2), 'M')                                    rows,
       CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G')                    DATA,
       CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G')                   idx,
       CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size,
       ROUND(index_length / data_length, 2)                                           idxfrac
FROM   information_schema.TABLES
ORDER  BY data_length + index_length DESC
LIMIT  30;

Any ideas how to clean ibdata1 and why has it grown so much?

BTW, I use innodb_file_per_table

2 Answers 2

14

Andreas got this answer first in terms of what to do. +1 for Andreas !!!

I would like clarify why that answer is the only way and how to do it.

By default ibdata1 normally houses four types of information

  • Table Data
  • Table Indexes
  • MVCC (Multiversioning Concurrency Control) Data
  • Table Metadata

Running OPTIMIZE TABLE against an InnoDB table stored ibdata1 will make things worse because here is what it does:

  • Makes the table's data and indexes contiguous inside ibdata1
  • It makes ibdata1 grow because the contiguous data is appended to ibdata1

You can segregate Table Data and Table Indexes from ibdata1 and manage them independently using innodb_file_per_table. That way, only MVCC and Table MetaData would reside in ibdata1.

If you already use it, then you must have a high-write environment that stores lots of MVCC to support transaction isolation. Once the transactions holding the MVCC is done, the space is simply abandoned for re-use.

To shrink ibdata1 once and for all you must do the following:

STEP 01) MySQLDump all databases into a SQL text file (call it SQLData.sql)

STEP 02) Drop all databases (except mysql schema)

STEP 03) service mysql stop

STEP 04) Add the following lines to /etc/my.cnf

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

Sidenote: Whatever your set for innodb_buffer_pool_size, make sure innodb_log_file_size is 25% of innodb_buffer_pool_size.

STEP 05) rm -f /var/lib/mysql/ibdata1 /var/lib/mysql/ib_logfile

At this point, there should only be the mysql schema in /var/lib/mysql

STEP 06) service mysql start

This will recreate ibdata1 at 10MB, ib_logfile0 and ib_logfile1 at 1G each

STEP 07) Reload SQLData.sql into mysql

ibdata1 will grow but only contain table metadata

Each InnoDB table will exist outside of ibdata1

Suppose you have an InnoDB table named mydb.mytable. If you go into /var/lib/mysql/mydb, you will see two files representing the table

  • mytable.frm (Storage Engine Header)
  • mytable.ibd (Home of Table Data and Table Indexes for mydb.mytable)

ibdata1 will never contain InnoDB data and Indexes anymore.

With the innodb_file_per_table option in /etc/my.cnf, you can run OPTIMIZE TABLE mydb.mytable; and the file /var/lib/mysql/mydb/mytable.ibd will actually shrink.

I would like to suggest a formula for you to query on sizing your InnoDB Buffer Pool from my post on What are the main differences between InnoDB and MyISAM?

3
  • Rolando, you rock my world!
    – Ran
    Commented Apr 19, 2012 at 14:24
  • Further info in the MySQL manual, section "Decreasing the Size of the InnoDB Tablespace". Commented Mar 12, 2015 at 4:35
  • This was very helpful, thanks! One thing that I had to do is I had to specify innodb_file_per_table=1 and not just innodb_file_per_table
    – redgeoff
    Commented May 6, 2016 at 22:40
3

My best guess is that it has at some point in time been that big.

ibdata1 will never shrink so it will keep at it's maximum size. Perhaps you've had a couple if tables in it before you did innodb_file_per_table that where big.

The only way I know of shrinking it is to do a dump, delete the files (ibdata, iblog and all .idb) and load the dump.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.