This section covers some general strategies that MySQL administrators can use to keep their databases intact:
Another step you can take is to schedule regular preventive maintenance. Techniques for this are discussed in the "Table Repair and Data Recovery" section later in this chapter because they use the table maintenance utilities described in that section. Using the Server's Auto-Recovery CapabilitiesOne of your first lines of defense in maintaining database integrity is the MySQL server's ability to perform automatic recovery at startup time. When the server begins executing, it can perform certain types of table checking to help deal with problems resulting from an earlier server or machine crash. MySQL is designed to recover from a variety of problems, so if you do nothing more than restart the server normally, it will make the necessary corrections for you in most cases. The possible actions taken by the server include the following:
If InnoDB or BDB auto-recovery fails due to a non-recoverable problem, the server exits after writing a message to the error log. To force the server to start up anyway so that you can attempt a manual recovery procedure, see the "Recovering the InnoDB Tablespace or BDB Tables" section later in the chapter. No automatic table startup timetable checking is available for ISAM tables. Nor is it likely there ever will be; ISAM support in MySQL is essentially frozen because MyISAM tables are preferable. I encourage you to consider converting your ISAM tables to MyISAM tables. To convert a table to MyISAM format, use an ALTER TABLE statement: ALTER TABLE tbl_name TYPE = MYISAM; You can also use the mysql_convert_table_format utility to convert all tables in a database with a single command. This script is written in Perl and requires that you have DBI installed. To see how to use it, invoke it with the --help option. If you don't want to convert your ISAM tables, you can arrange to check them by invoking isamchk before the server starts up. Also, if your server is older than 3.23.25 (prior to the introduction of --myisam-recover), you can check your MyISAM tables by invoking myisamchk before the server starts up. The "Scheduling Preventive Maintenance" section later in this chapter discusses how to arrange for table checking with these utilities before the server starts up. Backing Up and Copying DatabasesIt's important to back up your databases in case tables are lost or damaged. If a serious system crash occurs, you want to be able to restore your tables to the state they were in at the time of the crash with as little data loss as possible. Likewise, a user who issues an unwise DROP DATABASE or DROP TABLE will likely show up at your door requesting that you perform data recovery. Sometimes it's even the MySQL administrator who inadvertently causes the damage, for example, by trying to edit a table file directly using an editor, such as vi or emacs. This is certain to do bad things to the table! The techniques that are used for creating backups are also useful for copying databases to another server. Most commonly, a database is transferred to a server running on another host, but you can also transfer data to another server running on the same host. You might do this if you're running a server for a new release of MySQL and want to test it with some real data from your production server. Another use for backups is to set up a replication server, because one of the first steps in setting up a slave server is to take a snapshot of the master server at a specific point in time. The backup serves as this snapshot, and loading it into the slave server brings it up to date with respect to the master server. Thereafter, updates made on the master server are replicated to the slave server through the standard replication protocol. The procedure for setting up replication is discussed in Chapter 11, "General MySQL Administration." The two main methods for backing up databases are to use the mysqldump program or to directly copy database files (for example, with mysqlhotcopy, cp, tar, or cpio). Each method has its own advantages and disadvantages:
Whichever backup method you choose, there are certain principles to which you should adhere to assure the best results if you ever need to restore database contents:
Using mysqldump to Back Up and Copy DatabasesWhen you use the mysqldump program to generate database backup files, the file is written in SQL format by default, consisting of CREATE TABLE statements that create the tables being dumped and INSERT statements containing the data for the rows in the tables. To re-create the database later, you can take the mysqldump output file and use it as input to mysql to reload it into MySQL. (Note that you do not use mysqlimport to read SQL-format mysqldump output!) You can dump an entire database into a single text file as follows: % mysqldump sampdb > /archive/mysql/sampdb.2002-10-02 The beginning of the output file will look something like this: -- MySQL dump 9.06 -- -- Host: localhost Database: sampdb --------------------------------------------------------- -- Server version 4.0.3-beta-log -- -- Table structure for table 'absence' -- CREATE TABLE absence ( student_id int(10) unsigned NOT NULL default '0', date date NOT NULL default '0000-00-00', PRIMARY KEY (student_id,date) ) TYPE=MyISAM; -- -- Dumping data for table 'absence' -- INSERT INTO absence VALUES (3,'2002-09-03'); INSERT INTO absence VALUES (5,'2002-09-03'); INSERT INTO absence VALUES (10,'2002-09-06'); ... The rest of the file consists of more CREATE TABLE and INSERT statements. Backup files often are large, so you'll likely want to do what you can to make them smaller. One way to do this is to use the --opt option, which optimizes the dump process to generate a smaller file: % mysqldump --opt sampdb > /archive/mysql/sampdb.2002-10-02 You can also compress the dump file. For example, to compress the backup as you generate it, use a command like the following: % mysqldump --opt sampdb | gzip > /archive/mysql/sampdb.2002-10-02.gz If you find large dump files difficult to manage, it's possible to dump the contents of individual tables by naming them after the database name on the mysqldump command line. Then mysqldump will dump just the named tables rather than all the tables in the database. This partitions the dump into smaller, more manageable files. The following example shows how to dump some of the sampdb tables into separate files: % mysqldump --opt sampdb student score event absence > gradebook.sql % mysqldump --opt sampdb member president > hist-league.sql --opt is useful when you're generating backup files that are intended to be used to periodically refresh the contents of another database. That's because it automatically enables the --add-drop-table option, which tells mysqldump to precede each CREATE TABLE statement in the file with a DROP TABLE IF EXISTS statement for the same table. Then, when you take the backup file and load it into the second database, you won't get an error if the tables already exist. If you're running a second test server that's not a replication slave, you can use this technique to periodically reload it with a copy of the data from the databases on your production server. If you want to transfer a database to another server, you may not even need to create backup files. Make sure that the database exists on the other host and then dump the database over the network using a pipe so that mysql mysqldump directly. For example, to copy the sampdb database from the local host to the server on boa.snake.net, do so like this: % mysqladmin -h boa.snake.net create sampdb % mysqldump --opt sampdb | mysql -h boa.snake.net sampdb If you don't have a MySQL account on the local host that allows you to access the boa.snake.net server, but you do have such an account on boa.snake.net itself, use ssh to remotely invoke MySQL commands on that host: % ssh boa.snake.net mysqladmin create sampdb % mysqldump --opt sampdb | ssh boa.snake.net mysql sampdb Later, if you want to refresh the sampdb database on boa.snake.net, repeat the mysqldump command. Other mysqldump options you may find useful include the following:
mysqldump has many other options as well. Consult Appendix E for more information. Using Direct-Copy Database Backup and Copying MethodsAnother way to back up a database or tables that doesn't involve mysqldump is to copy table files directly. Typically, this is done using utilities such as cp, tar, or cpio. When you use a direct-copy backup method, you must make sure the tables aren't being used. If the server is changing a table while you're copying it, the copies will be worthless. The best way to ensure the integrity of your copies is to bring down the server, copy the files, and restart the server. If you don't want to bring down the server, use the read-access locking protocol described in the "Coordinating with the Server" section earlier in this chapter. That will prevent the server from changing the tables while you're copying them. Assuming that the server is either down or that you've read-locked the tables you want to copy, the following example shows how to back up the entire sampdb database to a backup directory. If the data directory is /usr/local/mysql/data, the commands look like this: % cd /usr/local/mysql/data % cp -r sampdb /archive/mysql Individual tables can be backed up as follows: % cd /usr/local/mysql/data/sampdb % cp member.* /archive/mysql/sampdb % cp score.* /archive/mysql/sampdb ... When you're done backing up, you can restart the server if you brought it down. If you left the server running and locked the tables, you can release the locks. Direct-copy methods apply to copying a database from one machine to another, too. For example, you can use scp rather than cp. If the data directory on boa.snake.net is /var/mysql/data, the following commands copy the sampdb database directory to that host: % cd /usr/local/mysql/data % scp -r sampdb boa.snake.net:/var/mysql/data Note that copying databases to another host this way involves some additional constraints:
Making Backups with mysqlhotcopyAs of version 3.23.11, MySQL distributions include mysqlhotcopy, a Perl DBI script that helps you make database backups. The "hot" in the name refers to the fact that the backups are made while the server is running; you need not take it offline. mysqlhotcopy has the following principal benefits:
There are several ways to invoke mysqlhotcopy. Suppose you want to copy the sampdb database. The following command will create a directory sampdb_copy in the server's data directory and copy the files in the sampdb database directory into it: % mysqlhotcopy sampdb To copy the database into a directory named sampdb under a directory you specify, specify that directory after the database name. For example, to copy the sampdb database to a directory /archive/2002-09-12/sampdb, use the following command: % mysqlhotcopy sampdb /archive/2002-09-12 To find out what mysqlhotcopy will do for any given command, include the -n option in your invocation syntax. This runs mysqlhotcopy in "no execution" mode, such that it just prints commands rather than executing them. Making Backups with BACKUP TABLEThe BACKUP TABLE statement, available as of MySQL 3.23.25, provides a way to back up individual tables by having the server itself copy the table's files. It works for MyISAM tables only. To use this statement, name the files you want to back up and a path to the directory on the server host where you want the files copied. For example, BACKUP TABLE tbl1, tbl2, tbl3 TO '/archive/sampdb'; The directory must exist and be writable to the server, you must have the FILE privilege and also the SELECT privilege for the tables. BACKUP TABLE flushes each table to cause any pending changes to be written to disk and then copies each table's .frm and .MYD description and data files from the database directory. It does not copy the .MYI index file, because that can be rebuilt from the other two files. BACKUP TABLE locks the tables one at a time. This means that for a multiple-table backup, it's possible for the backup files to be different than the actual state of the tables when the statement finishes. Suppose you're backing up tbl1 and tbl2. BACKUP TABLE will lock tbl1 only while backing it up, so it might be modified while tbl2 is being backed up. This means that when BACKUP TABLE finishes, the contents of tbl1 will differ from the contents of the backup files. To make sure that the backup files as a group match the contents of the corresponding tables, disable modifications to any of the tables for the duration of the BACKUP TABLE statement by read-locking them all. Issue an UNLOCK TABLES statement afterward to release the locks for example: LOCK TABLES tbl1 READ, tbl2 READ; BACKUP TABLE tbl1, tbl2 TO 'backup_dir_path'; UNLOCK TABLES; A table that has been backed up with BACKUP TABLE can be reloaded into the server with RESTORE TABLE, as described in the "Table Repair and Data Recovery" section later in this chapter. Backing Up the InnoDB Tablespace or BDB TablesInnoDB and BDB tables can be dumped using mysqldump, just like any other kind of tables. You can also use direct-copy methods, but take care to observe the following special requirements:
Using Replication to Help Make BackupsMaking backups is important, but it introduces a conflict of interest into your duties as a MySQL administrator. On the one hand, you want to maximize the availability of your server to the members of your user community, which includes allowing them to make database updates. On the other hand, for recovery purposes, backups are most useful if you make sure your backup file and log file checkpoints are synchronized. These goals conflict because the best way to synchronize backup and log checkpoints is by flushing the logs when you make the backup, combined with making sure no updates occur by either bringing the server down or locking all the tables at once (for example, with the --opt option to mysqldump). Unfortunately, disallowing updates reduces client access to the tables for the duration of the backup. If you have a replication slave server set up, it can help you resolve this conflict. Rather than making backups on the master server, use the slave server instead. Then you need not bring down the master or otherwise make it unavailable to clients during the backup. Instead, suspend replication on the slave server with SLAVE STOP and make a backup from the slave. (If you are using a direct-copy backup method, issue a FLUSH TABLES statement as well.) Afterward, re-enable replication with SLAVE START and the slave will catch up on any updates made by the master server during the backup period. Depending on your backup method, you may not even need to suspend replication. For example, if you're backing up only a single database, you can use mysqlhotcopy or mysqldump with the appropriate options to lock all the tables at once. In that case, the slave server can stay up, but it won't attempt any updates to the locked tables during the backup. When the backup is done and the locks are released, the slave resumes update processing automatically. Using a Backup to Rename a DatabaseMySQL has no command for renaming a database, but you can still do so. Dump the database with mysqldump, create a new empty database with the new name, and then reload the dump file into the new database. After that you can drop the old database. The following example shows how to rename db1 to db2: % mysqldump db1 > db1.sql % mysqladmin create db2 % mysql db2 < db1.sql % mysqladmin drop db1 An easier way to rename a database is to bring down the server, rename the database directory, and restart the server. However, this strategy can be used only if you have no BDB or InnoDB tables in the database. It doesn't work for BDB tables because the pathname to each table is encoded in its .db file. Nor does it work for InnoDB tables because the database name for each table is stored in the InnoDB tablespace, which is unaffected by renaming the database directory. Whichever method you use for renaming a database, remember that access rights to it are controlled through the grant tables in the mysql database. If any of the grant tables have entries that refer specifically to the database that was renamed, you'll need to adjust the entries appropriately to refer to the new name. For a database renamed from db1 to db2, the statements to use look like this: mysql> UPDATE db SET Db = 'db2' WHERE Db = 'db1'; mysql> UPDATE tables_priv SET Db = 'db2' WHERE Db = 'db1'; mysql> UPDATE columns_priv SET Db = 'db2' WHERE Db = 'db1'; mysql> UPDATE host SET Db = 'db2' WHERE Db = 'db1'; No such statement is needed for the user table, because it has no Db column. |