If you're a webhosting company hosting dozens of various websites that use MySQL with InnoDB engine as a backend you've probably already experienced the annoying problem of MySQL's ibdata1 growing too large / eating all server's disk space and triggering disk space low alerts. The ibdata1 file, taking up hundreds of gigabytes is likely to be encountered on virtually all Linux distributions which run default MySQL server <= MySQL 5.6 (with default distro shipped my.cnf). The excremental ibdata1 raise appears usually due to a application software bug on how it queries the database. In theory there are no limitation for ibdata1 except maximum file size limitation set for the filesystem (and there is no limitation option set in my.cnf) meaning it is quite possible that under certain conditions ibdata1 grow over time can happily fill up your server LVM (Storage) drive partitions.
Unfortunately there is no way to shrink the ibdata1 file and only known work around (I found) is to set innodb_file_per_table option in my.cnf to force the MySQL server create separate *.ibd files under datadir (my.cnf variable) for each freshly created InnoDB table.
1. Checking size of ibdata1 file
On Debian / Ubuntu and other deb based Linux servers datadir is /var/lib/mysql/ibdata1
server:~# du -hsc /var/lib/mysql/ibdata1
45G /var/lib/mysql/ibdata1
45G total
2. Checking info about Databases and Innodb storage Engine
server:~# mysql -u root -p
password:
mysql> SHOW DATABASES;
+——————–+
| Database |
+——————–+
| information_schema |
| bible |
| blog |
| blog-sezoni |
| blogmonastery |
| daniel |
| ezmlm |
| flash-games |
Next step is to get some understanding about how many existing InnoDB tables are present within Database server:
mysql> SELECT COUNT(1) EngineCount,engine FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','performance_schema','mysql') GROUP BY engine;
+————-+——–+
| EngineCount | engine |
+————-+——–+
| 131 | InnoDB |
| 5 | MEMORY |
| 584 | MyISAM |
+————-+——–+
3 rows in set (0.02 sec)
To get some more statistics related to InnoDb variables set on the SQL server:
mysqladmin -u root -p'Your-Server-Password' var | grep innodb
Here is also how to find which tables use InnoDb Engine
mysql> SELECT table_schema, table_name
-> FROM INFORMATION_SCHEMA.TABLES
-> WHERE engine = 'innodb';
+————–+————————–+
| table_schema | table_name |
+————–+————————–+
| blog | wp_blc_filters |
| blog | wp_blc_instances |
| blog | wp_blc_links |
| blog | wp_blc_synch |
| blog | wp_likes |
| blog | wp_wpx_logs |
| blog-sezoni | wp_likes |
| icanga_web | cronk |
| icanga_web | cronk_category |
| icanga_web | cronk_category_cronk |
| icanga_web | cronk_principal_category |
| icanga_web | cronk_principal_cronk |
…
3. Check and Stop any Web / Mail / DNS service using MySQL
server:~# ps -efl |grep -E 'apache|nginx|dovecot|bind|radius|postfix'
…
Below cmd should return empty output, (e.g. Apache / Nginx / Postfix / Radius / Dovecot / DNS etc. services are properly stopped on server).
4. Create Backup dump all MySQL tables with mysqldump
Next step is to create full backup dump of all current MySQL databases (with mysqladmin):
server:~# mysqldump –opt –allow-keywords –add-drop-table –all-databases –events -u root -p > dump.sql
server:~# du -hsc /root/dump.sql
940M dump.sql
940M total
If you have free space on an external backup server or remotely mounted attached (NFS or SAN Storage) it is a good idea to make a full binary copy of MySQL data (just in case something wents wrong with above binary dump), copy respective directory depending on the Linux distro and install location of SQL binary files set (in my.cnf).
To check where are MySQL binary stored database data (check in my.cnf):
server:~# grep -i datadir /etc/mysql/my.cnf
datadir = /var/lib/mysql
If server is CentOS / RHEL Fedora RPM based substitute in above grep cmd line /etc/mysql/my.cnf with /etc/my.cnf
if you're on Debian / Ubuntu:
server:~# /etc/init.d/mysql stop
server:~# cp -rpfv /var/lib/mysql /root/mysql-data-backup
Once above copy completes, DROP all all databases except, mysql, information_schema (which store MySQL existing user / passwords and Access Grants and Host Permissions)
5. Drop All databases except mysql and information_schema
server:~# mysql -u root -p
password:
mysql> SHOW DATABASES;
…
DROP DATABASE blog;
DROP DATABASE sessions;
DROP DATABASE wordpress;
DROP DATABASE micropcfreak;
DROP DATABASE statusnet;
…
etc. etc.
ACHTUNG !!! DON'T execute! – DROP database mysql; DROP database information_schema; !!! – cause this might damage your User permissions to databases
6. Stop MySQL server and add innodb_file_per_table and few more settings to prevent ibdata1 to grow infinitely in future
server:~# /etc/init.d/mysql stop
server:~# vim /etc/mysql/my.cnf
[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G
Delete files taking up too much space – ibdata1 ib_logfile0 and ib_logfile1
server:~# cd /var/lib/mysql/
server:~# rm -f ibdata1 ib_logfile0 ib_logfile1
server:~# /etc/init.d/mysql start
server:~# /etc/init.d/mysql stop
server:~# /etc/init.d/mysql start
server:~# ps ax |grep -i mysql
…
You should get no running MySQL instance (processes), so above ps command should return blank.
7. Re-Import previously dumped SQL databases with mysql cli client
server:~# cd /root/
server:~# mysql -u root -p < dump.sql
Hopefully import should went fine, and if no errors experienced new data should be in.
Altearnatively if your database is too big and you want to import it in less time to mitigate SQL downtime, instead import the database with:
server:~# mysql -u root -p
password:
mysql> SET FOREIGN_KEY_CHECKS=0;
mysql> SOURCE /root/dump.sql;
mysql> SET FOREIGN_KEY_CHECKS=1;
…
If something goes wrong with the import for some reason, you can always copy over sql binary files from /root/mysql-data-backup/ to /var/lib/mysql/
8. Connect to mysql and check whether databases are listable and re-check ibdata file size
Once imported login with mysql cli and check whther databases are there with:
server:~# mysql -u root -p
SHOW DATABASES;
Next lets see what is currently the size of ibdata1, ib_logfile0 and ib_logfile1
server:~# du -hsc /var/lib/mysql/{ibdata1,ib_logfile0,ib_logfile1}
19M /var/lib/mysql/ibdata1
1,1G /var/lib/mysql/ib_logfile0
1,1G /var/lib/mysql/ib_logfile1
2,1G total
Now ibdata1 will grow, but only contain table metadata. Each InnoDB table will exist outside of ibdata1.
To better understand what I mean, lets say you have InnoDB table named blogdb.mytable.
If you go into /var/lib/mysql/blogdb, you will see two files
representing the table:
- mytable.frm (Storage Engine Header)
- mytable.ibd (Home of Table Data and Table Indexes for blogdb.mytable)
Now construction will be like that for each of MySQL stored databases instead of everything to go to ibdata1.
MySQL 5.6+ admins could relax as innodb_file_per_table is enabled by default in newer SQL releases.
Now to make sure your websites are working take few of the hosted websites URLs that use any of the imported databases and just browse.
In my case ibdata1 was 45GB after clearing it up I managed to save 43 GB of disk space!!!
Enjoy the disk saving! 🙂
More helpful Articles

Tags: blog, case, check, checking, cli, client, cmd line, cnf, com, company, Connect, copy, databases, Delete, disk space, Engine, Enjoy, enormous ibdata1, file, filesystem, fix, fix ibdata size, future, ibdata, ibdata1 fill disk space, init, lib, mysqladmin, net, passwords, reduce ibdata, server, size, stackoverflow, too large, var, www
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Chrome/4.0.221.7 Safari/532.2
Right now it seems like Movable Type is the preferred blogging platform available right now. (from what I've read) Is that what you are using on your blog?
View CommentView CommentMozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
test
View CommentView Comment