Mysql Innodb Optimize table - mysql

I have a 100Gb innodb table on C:\ drive and the C:\ drive is out of space now.I deleted many rows but the the ibd file did not shrink.
I have more than 200Gb available on D:\drive and subsequently configured tmpdir to be in d:\drive and tried to optimize table .But when I optimize table it is taking up whatever space is left on c:\ drive and not using d:\
What parameter should I change?

You cannot shrink the innodb data file (default name is ibdata1) without deleting it :S .
Using innodb engine you should use innodb_file_per_table=1
To solve you space issue you should:
1) Execute a full database backup: mysqldump -u root -pMyPassword -R --all-databases > full.sql
2) Stop mysql service
3) Add (or change value of) the parameter innodb_file_per_table=1
4) Drop the existing innodb data file (/$mysqldir/ibdata1)
5) Start mysql service
6) Restore the backup: mylsql -u root -pMyPassword mysql < full.sql
Now the innodb data file will not growth too much anymore, and an optimize table will allow you to shrink the involve table data file since now each table will amnage it's own data file.
Using symbolic links (at least under Linux), it allows you to locate databases on different disks.

There is tmpdir parameter for that. And I think you can set that with
SET GLOBAL tmpdir = D:/temp
before any optimization operation or add following under mysld
set-variable = tmpdir=/var/tmp
As a bonus I strongly suggest you to use
innodb_file_per_table=1
to have separate file for each table if of course you have innodb tables.
And also using compressed data will reduce your disk usage.

Related

How to drop a local DB but keep included ndbcluster table in the NDB cluster

I have the following case, but no possibility to make a test. Would be thankful for the advice.
A) local host with the MySQL server (an old mysql 5.0)
A.1) This MySQL server has a few databases
A.2) One of these databases contains some innoDB tables, but also a few "ndbcluster" (ENGINE=ndbcluster) ones.
B) remote NDB cluster with a huge set of data used on the local host in A)
My goal is to shrink the DB (remove tabledata files) on the local host.
For this, I will have to drop all the databases and then remove the physical DB files. Then, add innodb_file_per_table to my.cnf and start MySQL server.
The questions:
1) AFAIK when I execute DROP DATABASE db_name, it first removes all the tables inside the DB. How can I ensure that when I drop the database, the tables/data inside the remote NDB cluster is not affected (it is used by other similar local servers)?
2) When I insert the dump back (it will recreate the dropped database) to the refreshed local MySQL server, will it add/connect the ndbcluster tables from the NDB cluster automatically?
local my.cnf has the following lines:
ndbcluster
ndb-connectstring="nodeid=35,1.2.64.69,1.2.64.70"
3) Do I really need to drop all the database to remove the physical files and recreate the DB in the folder per table mode?
DROP DATABASE will remove all tables in the database, both
InnoDB and NDB. So you will have to remove table by table
if you want to keep the NDB tables.
Not sure of the answers relating to InnoDB.
To ensure that I am not touching the NDB tables, I skipped removing the virtual databases. So, the procedure briefly looked like this:
Dump the mysql db and other important DBs
Stop the MySQL service
Move/remove the db files:
cd /var/lib/mysql/ && rm -f ib_logfile0 ib_logfile1 tablespace1 tablespace2
Re-initialize mysql and add the root user (as it would not start normally):
cd /var/lib/mysql && mysql_install_db
Start the mysql server
Insert the mysql db (from dump) using the default root user without a password.
Insert other databases using the old (restored) user.
When the database that includes an NDB table is inserted, the NDB table will be connected automatically.

transfer all the databases in phpmyadmin

is there a more efficient method to transfer all the databases from phpmyadmin,rather than to create database copies and manually import them on other machines.
Earlier I tried to copy the entire folder and replace the older config.inc.php but I am unable to see all the databases
there are a couple of options which usually depends on your needs/db size/tables engine and so on:
mysqldump + rsync dump + restore (if you do not have a good connection between hosts)
mysqldump | mysql -h H -u -p
If you can't stand with big downtime you can setup replication between two hosts using innodbbackup utility
If you use MyISAM tables you can shutdown MySQL you copy related files to destination datadir. This option will not work for InnoDB tables.

MySql backup and restoration

Trying to find out how people do a full backup/restore procedure: The user defined database schema and data can be easily backed up via mysqldump, but what about the master tables and data? i.e. if the server goes completely bananas, how can I rebuild the database, i.e. including all the settings in Mysql? is it just a matter of dumping/importing the information_schema and mysql databases + restore my.cnf ? (innodb or MyISAM, not ISAM)
--
edit: Thanks!
You don't back up information_schema, but otherwise, yes, keep a copy of your my.cnf and a dump of the mysql db tables and log settings. To do this do:
mysqldump -u$user -p$pass --all-databases > db_backup.sql
If you're going to restore to the 100% same version of MySQL, you could also backup by shutting down your server and doing a full copy of the contents of /var/lib/mysql (or wherever your data files are) along with your my.cnf file. Then just drop the copy back in place when you want to go live and turn on your server.

completely delete sonar project [duplicate]

I am using MySQL in localhost as a "query tool" for performing statistics in R, that is, everytime I run a R script, I create a new database (A), create a new table (B), import the data into B, submit a query to get what I need, and then I drop B and drop A.
It's working fine for me, but I realize that the ibdata file size is increasing rapidly, I stored nothing in MySQL, but the ibdata1 file already exceeded 100 MB.
I am using more or less default MySQL setting for the setup, is there a way for I can automatically shrink/purge the ibdata1 file after a fixed period of time?
That ibdata1 isn't shrinking is a particularly annoying feature of MySQL. The ibdata1 file can't actually be shrunk unless you delete all databases, remove the files and reload a dump.
But you can configure MySQL so that each table, including its indexes, is stored as a separate file. In that way ibdata1 will not grow as large. According to Bill Karwin's comment this is enabled by default as of version 5.6.6 of MySQL.
It was a while ago I did this. However, to setup your server to use separate files for each table you need to change my.cnf in order to enable this:
[mysqld]
innodb_file_per_table=1
https://dev.mysql.com/doc/refman/5.6/en/innodb-file-per-table-tablespaces.html
As you want to reclaim the space from ibdata1 you actually have to delete the file:
Do a mysqldump of all databases, procedures, triggers etc except the mysql and performance_schema databases
Drop all databases except the above 2 databases
Stop mysql
Delete ibdata1 and ib_log files
Start mysql
Restore from dump
When you start MySQL in step 5 the ibdata1 and ib_log files will be recreated.
Now you're fit to go. When you create a new database for analysis, the tables will be located in separate ibd* files, not in ibdata1. As you usually drop the database soon after, the ibd* files will be deleted.
http://dev.mysql.com/doc/refman/5.1/en/drop-database.html
You have probably seen this:
http://bugs.mysql.com/bug.php?id=1341
By using the command ALTER TABLE <tablename> ENGINE=innodb or OPTIMIZE TABLE <tablename> one can extract data and index pages from ibdata1 to separate files. However, ibdata1 will not shrink unless you do the steps above.
Regarding the information_schema, that is not necessary nor possible to drop. It is in fact just a bunch of read-only views, not tables. And there are no files associated with the them, not even a database directory. The informations_schema is using the memory db-engine and is dropped and regenerated upon stop/restart of mysqld. See https://dev.mysql.com/doc/refman/5.7/en/information-schema.html.
Adding to John P's answer,
For a linux system, steps 1-6 can be accomplished with these commands:
mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
mysqladmin -u [username] -p[root_password] drop [database_name]
sudo /etc/init.d/mysqld stop
sudo rm /var/lib/mysql/ibdata1
sudo rm /var/lib/mysql/ib_logfile*
sudo /etc/init.d/mysqld start
mysqladmin -u [username] -p[root_password] create [database_name]
mysql -u [username] -p[root_password] [database_name] < dumpfilename.sql
Warning: these instructions will cause you to lose other databases if you have other databases on this mysql instance. Make sure that steps 1,2 and 6,7 are modified to cover all databases you wish to keep.
When you delete innodb tables, MySQL does not free the space inside the ibdata file, that's why it keeps growing. These files hardly ever shrink.
How to shrink an existing ibdata file:
https://dev.mysql.com/doc/refman/5.6/en/innodb-system-tablespace.html#innodb-resize-system-tablespace
You can script this and schedule the script to run after a fixed period of time, but for the setup described above it seems that multiple tablespaces are an easier solution.
If you use the configuration option innodb_file_per_table, you create multiple tablespaces. That is, MySQL creates separate files for each table instead of one shared file. These separate files a stored in the directory of the database, and they are deleted when you delete this database. This should remove the need to shrink/purge ibdata files in your case.
More information about multiple tablespaces:
https://dev.mysql.com/doc/refman/5.6/en/innodb-file-per-table-tablespaces.html
Quickly scripted the accepted answer's procedure in bash:
#!/usr/bin/env bash
dbs=$(mysql -BNe 'show databases' | grep -vE '^mysql$|^(performance|information)_schema$')
mysqldump --events --triggers --databases $dbs > alldatabases.sql && \
echo "$dbs" | while read -r db; do
mysqladmin drop "$db"
done && \
mysql -e 'SET GLOBAL innodb_fast_shutdown = 0' && \
/etc/init.d/mysql stop && \
rm -f /var/lib/mysql/ib{data1,_logfile*} && \
/etc/init.d/mysql start && \
mysql < alldatabases.sql
Save as purge_binlogs.sh and run as root.
Excludes mysql, information_schema, performance_schema (and binlog directory).
Assumes you have administrator credendials in /root/.my.cnf and that your database lives in default /var/lib/mysql directory.
You can also purge binary logs after running this script to regain more disk space with:
PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;
If you use the InnoDB storage engine for (some of) your MySQL tables, you’ve probably already came across a problem with its default configuration. As you may have noticed in your MySQL’s data directory (in Debian/Ubuntu – /var/lib/mysql) lies a file called ‘ibdata1′. It holds almost all the InnoDB data (it’s not a transaction log) of the MySQL instance and could get quite big. By default this file has a initial size of 10Mb and it automatically extends. Unfortunately, by design InnoDB data files cannot be shrinked. That’s why DELETEs, TRUNCATEs, DROPs, etc. will not reclaim the space used by the file.
I think you can find good explanation and solution there :
http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/
If your goal is to monitor MySQL free space and you can't stop MySQL to shrink your ibdata file, then get it through table status commands. Example:
MySQL > 5.1.24:
mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'
MySQL < 5.1.24:
mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'
Then compare this value to your ibdata file:
du -b ibdata1
Source: http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
In a new version of mysql-server recipes above will crush "mysql" database.
In old version it works. In new some tables switches to table type INNODB, and by doing so you will damage them.
The easiest way is to:
dump all you databases
uninstall mysql-server,
add in remained my.cnf:
[mysqld]
innodb_file_per_table=1
erase all in /var/lib/mysql
install mysql-server
restore users and databases
What nobody seems to mention is the impact innodb_undo_log_truncate setting can have.
After reading Percona's blog post about the topic, I've enabled in my MariaDB 10.6 the truncation of UNDO LOG entries which filled 95% of ibdata1, and, after a complete drop and restore, from that moment on my ibdata1 never grew anymore.
With the default innodb_undo_log_truncate = 0 my ibdata1 easily reached 10% of databases space occupation, aka tens of Gigabytes.
With innodb_undo_log_truncate = 1, ibdata1 it's firm at 76 Mb.
As already noted you can't shrink ibdata1 (to do so you need to dump and rebuild), but there's also often no real need to.
Using autoextend (probably the most common size setting) ibdata1 preallocates storage, growing each time it is nearly full. That makes writes faster as space is already allocated.
When you delete data it doesn't shrink but the space inside the file is marked as unused. Now when you insert new data it'll reuse empty space in the file before growing the file any further.
So it'll only continue to grow if you're actually needing that data. Unless you actually need the space for another application there's probably no reason to shrink it.

How to shrink/purge ibdata1 file in MySQL

I am using MySQL in localhost as a "query tool" for performing statistics in R, that is, everytime I run a R script, I create a new database (A), create a new table (B), import the data into B, submit a query to get what I need, and then I drop B and drop A.
It's working fine for me, but I realize that the ibdata file size is increasing rapidly, I stored nothing in MySQL, but the ibdata1 file already exceeded 100 MB.
I am using more or less default MySQL setting for the setup, is there a way for I can automatically shrink/purge the ibdata1 file after a fixed period of time?
That ibdata1 isn't shrinking is a particularly annoying feature of MySQL. The ibdata1 file can't actually be shrunk unless you delete all databases, remove the files and reload a dump.
But you can configure MySQL so that each table, including its indexes, is stored as a separate file. In that way ibdata1 will not grow as large. According to Bill Karwin's comment this is enabled by default as of version 5.6.6 of MySQL.
It was a while ago I did this. However, to setup your server to use separate files for each table you need to change my.cnf in order to enable this:
[mysqld]
innodb_file_per_table=1
https://dev.mysql.com/doc/refman/5.6/en/innodb-file-per-table-tablespaces.html
As you want to reclaim the space from ibdata1 you actually have to delete the file:
Do a mysqldump of all databases, procedures, triggers etc except the mysql and performance_schema databases
Drop all databases except the above 2 databases
Stop mysql
Delete ibdata1 and ib_log files
Start mysql
Restore from dump
When you start MySQL in step 5 the ibdata1 and ib_log files will be recreated.
Now you're fit to go. When you create a new database for analysis, the tables will be located in separate ibd* files, not in ibdata1. As you usually drop the database soon after, the ibd* files will be deleted.
http://dev.mysql.com/doc/refman/5.1/en/drop-database.html
You have probably seen this:
http://bugs.mysql.com/bug.php?id=1341
By using the command ALTER TABLE <tablename> ENGINE=innodb or OPTIMIZE TABLE <tablename> one can extract data and index pages from ibdata1 to separate files. However, ibdata1 will not shrink unless you do the steps above.
Regarding the information_schema, that is not necessary nor possible to drop. It is in fact just a bunch of read-only views, not tables. And there are no files associated with the them, not even a database directory. The informations_schema is using the memory db-engine and is dropped and regenerated upon stop/restart of mysqld. See https://dev.mysql.com/doc/refman/5.7/en/information-schema.html.
Adding to John P's answer,
For a linux system, steps 1-6 can be accomplished with these commands:
mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
mysqladmin -u [username] -p[root_password] drop [database_name]
sudo /etc/init.d/mysqld stop
sudo rm /var/lib/mysql/ibdata1
sudo rm /var/lib/mysql/ib_logfile*
sudo /etc/init.d/mysqld start
mysqladmin -u [username] -p[root_password] create [database_name]
mysql -u [username] -p[root_password] [database_name] < dumpfilename.sql
Warning: these instructions will cause you to lose other databases if you have other databases on this mysql instance. Make sure that steps 1,2 and 6,7 are modified to cover all databases you wish to keep.
When you delete innodb tables, MySQL does not free the space inside the ibdata file, that's why it keeps growing. These files hardly ever shrink.
How to shrink an existing ibdata file:
https://dev.mysql.com/doc/refman/5.6/en/innodb-system-tablespace.html#innodb-resize-system-tablespace
You can script this and schedule the script to run after a fixed period of time, but for the setup described above it seems that multiple tablespaces are an easier solution.
If you use the configuration option innodb_file_per_table, you create multiple tablespaces. That is, MySQL creates separate files for each table instead of one shared file. These separate files a stored in the directory of the database, and they are deleted when you delete this database. This should remove the need to shrink/purge ibdata files in your case.
More information about multiple tablespaces:
https://dev.mysql.com/doc/refman/5.6/en/innodb-file-per-table-tablespaces.html
Quickly scripted the accepted answer's procedure in bash:
#!/usr/bin/env bash
dbs=$(mysql -BNe 'show databases' | grep -vE '^mysql$|^(performance|information)_schema$')
mysqldump --events --triggers --databases $dbs > alldatabases.sql && \
echo "$dbs" | while read -r db; do
mysqladmin drop "$db"
done && \
mysql -e 'SET GLOBAL innodb_fast_shutdown = 0' && \
/etc/init.d/mysql stop && \
rm -f /var/lib/mysql/ib{data1,_logfile*} && \
/etc/init.d/mysql start && \
mysql < alldatabases.sql
Save as purge_binlogs.sh and run as root.
Excludes mysql, information_schema, performance_schema (and binlog directory).
Assumes you have administrator credendials in /root/.my.cnf and that your database lives in default /var/lib/mysql directory.
You can also purge binary logs after running this script to regain more disk space with:
PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;
If you use the InnoDB storage engine for (some of) your MySQL tables, you’ve probably already came across a problem with its default configuration. As you may have noticed in your MySQL’s data directory (in Debian/Ubuntu – /var/lib/mysql) lies a file called ‘ibdata1′. It holds almost all the InnoDB data (it’s not a transaction log) of the MySQL instance and could get quite big. By default this file has a initial size of 10Mb and it automatically extends. Unfortunately, by design InnoDB data files cannot be shrinked. That’s why DELETEs, TRUNCATEs, DROPs, etc. will not reclaim the space used by the file.
I think you can find good explanation and solution there :
http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/
If your goal is to monitor MySQL free space and you can't stop MySQL to shrink your ibdata file, then get it through table status commands. Example:
MySQL > 5.1.24:
mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'
MySQL < 5.1.24:
mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'
Then compare this value to your ibdata file:
du -b ibdata1
Source: http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
In a new version of mysql-server recipes above will crush "mysql" database.
In old version it works. In new some tables switches to table type INNODB, and by doing so you will damage them.
The easiest way is to:
dump all you databases
uninstall mysql-server,
add in remained my.cnf:
[mysqld]
innodb_file_per_table=1
erase all in /var/lib/mysql
install mysql-server
restore users and databases
What nobody seems to mention is the impact innodb_undo_log_truncate setting can have.
After reading Percona's blog post about the topic, I've enabled in my MariaDB 10.6 the truncation of UNDO LOG entries which filled 95% of ibdata1, and, after a complete drop and restore, from that moment on my ibdata1 never grew anymore.
With the default innodb_undo_log_truncate = 0 my ibdata1 easily reached 10% of databases space occupation, aka tens of Gigabytes.
With innodb_undo_log_truncate = 1, ibdata1 it's firm at 76 Mb.
As already noted you can't shrink ibdata1 (to do so you need to dump and rebuild), but there's also often no real need to.
Using autoextend (probably the most common size setting) ibdata1 preallocates storage, growing each time it is nearly full. That makes writes faster as space is already allocated.
When you delete data it doesn't shrink but the space inside the file is marked as unused. Now when you insert new data it'll reuse empty space in the file before growing the file any further.
So it'll only continue to grow if you're actually needing that data. Unless you actually need the space for another application there's probably no reason to shrink it.