27
23 3. Managing MySQL users and privileges 3.1 MySQL security model Each MySQL server installation has a seed database “mysql”, which stores the MySQL databases information on the local machine, the users and their privileges informations. The access to this database has to be secured, since if someone is able to login without a password as “root” user to this database, he can overwrite user privileges or create a rogue user. The tables in the “mysql” database are the following: # mysql -u root mysql Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 to server version: 4.0.22-Yahoo-SMP-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> show tables; +------------------------+ | Tables_in_mysql | +------------------------+ | columns_priv | | db | | func | | host | | tables_priv | | user | +------------------------+ 6 rows in set (0.00 sec) columns_priv table stores all the column privileges granted to users MySQL Administration How-To

MySQL Training Course Part2

Embed Size (px)

Citation preview

Page 1: MySQL Training Course Part2

23

3. Managing MySQL users and privileges

3.1 MySQL security model

Each MySQL server installation has a seed database “mysql”, which stores the MySQLdatabases information on the local machine, the users and their privilegesinformations. The access to this database has to be secured, since if someone is ableto login without a password as “root” user to this database, he can overwrite userprivileges or create a rogue user.

The tables in the “mysql” database are the following:

# mysql -u root mysql

Reading table information for completion of table and column namesYou can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 3 to server version: 4.0.22-Yahoo-SMP-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show tables;

+------------------------+| Tables_in_mysql |+------------------------+| columns_priv || db || func || host || tables_priv || user |+------------------------+

6 rows in set (0.00 sec)

columns_priv table stores all the column privileges granted to users

MySQL Administration How-To

Page 2: MySQL Training Course Part2

24

mysql> desc columns_priv;

+---------------------+--------------------------------------------------------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+---------------------+--------------------------------------------------------------+------+-----+---------+-------+| Host | char(60) binary | | PRI | | || Db | char(64) binary | | PRI | | || User | char(16) binary | | PRI | | || Table_name | char(64) binary | | PRI | | || Column_name | char(64) binary | | PRI | | || Timestamp | timestamp(14) |YES | | NULL | | Column_priv | set('Select','Insert','Update','References') | | | | |+----------------------+---------------------------------------------------------------+----+-----+---------+-------+

7 rows in set (0.00 sec)

db table stores all user privileges for any MySQL database he has acces to:

mysql> desc db;

+---------------------------------+------------------------+------+-------+-----------+---------+| Field | Type | Null | Key | Default | Extra |+---------------------------------+------------------------+-------+------+-----------+---------+| Host | char(60) binary | | PRI | | || Db | char(64) binary | | PRI | | || User | char(16) binary | | PRI | | || Select_priv | enum('N','Y') | | | N | || Insert_priv | enum('N','Y') | | | N | || Update_priv | enum('N','Y') | | | N | || Delete_priv | enum('N','Y') | | | N | || Create_priv | enum('N','Y') | | | N | || Drop_priv | enum('N','Y') | | | N | || Grant_priv | enum('N','Y') | | | N | || References_priv | enum('N','Y') | | | N | || Index_priv | enum('N','Y') | | | N | || Alter_priv | enum('N','Y') | | | N | || Create_tmp_table_priv | enum('N','Y') | | | N | || Lock_tables_priv | enum('N','Y') | | | N | |+---------------------------------+------------------------+---------+------+----------+--------+

15 rows in set (0.00 sec)

mysql> select * from db where user = 'ritzy'\G

Host: a-int.corp.yahoo.com Db: TESTDB

MySQL Administration How-To

Page 3: MySQL Training Course Part2

25

User: ritzy Select_priv: Y Insert_priv: Y Update_priv: Y Delete_priv: Y Create_priv: Y Drop_priv: Y Grant_priv: N References_priv: Y Index_priv: Y Alter_priv: YCreate_tmp_table_priv: Y Lock_tables_priv: Y

*************************** 2. row *************************** Host: % Db: TESTDB User: ritzy Select_priv: Y Insert_priv: Y Update_priv: Y Delete_priv: Y Create_priv: Y Drop_priv: Y Grant_priv: N References_priv: Y Index_priv: Y Alter_priv: YCreate_tmp_table_priv: Y Lock_tables_priv: Y

2 rows in set (0.02 sec)

host table stores all host privileges for any MySQL database this host has acces to:

mysql> desc host;

+-----------------------+-----------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-----------------------+-----------------+------+-----+---------+-------+| Host | char(60) binary | | PRI | | || Db | char(64) binary | | PRI | | || Select_priv | enum('N','Y') | | | N | || Insert_priv | enum('N','Y') | | | N | || Update_priv | enum('N','Y') | | | N | || Delete_priv | enum('N','Y') | | | N | || Create_priv | enum('N','Y') | | | N | |

MySQL Administration How-To

Page 4: MySQL Training Course Part2

26

| Drop_priv | enum('N','Y') | | | N | || Grant_priv | enum('N','Y') | | | N | || References_priv | enum('N','Y') | | | N | || Index_priv | enum('N','Y') | | | N | || Alter_priv | enum('N','Y') | | | N | || Create_tmp_table_priv | enum('N','Y') | | | N | || Lock_tables_priv | enum('N','Y') | | | N | |+-----------------------+-----------------+------+-----+---------+-------+

user table stores all user privileges for any MySQL database he has acces to:

mysql> desc user ;

+-----------------------+-----------------------------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-----------------------+-----------------------------------+------+-----+---------+-------+| Host | varchar(60) binary | | PRI | | || User | varchar(16) binary | | PRI | | || Password | varchar(16) binary | | | | || Select_priv | enum('N','Y') | | | N | || Insert_priv | enum('N','Y') | | | N | || Update_priv | enum('N','Y') | | | N | || Delete_priv | enum('N','Y') | | | N | || Create_priv | enum('N','Y') | | | N | || Drop_priv | enum('N','Y') | | | N | || Reload_priv | enum('N','Y') | | | N | || Shutdown_priv | enum('N','Y') | | | N | || Process_priv | enum('N','Y') | | | N | || File_priv | enum('N','Y') | | | N | || Grant_priv | enum('N','Y') | | | N | || References_priv | enum('N','Y') | | | N | || Index_priv | enum('N','Y') | | | N | || Alter_priv | enum('N','Y') | | | N | || Show_db_priv | enum('N','Y') | | | N | || Super_priv | enum('N','Y') | | | N | || Create_tmp_table_priv | enum('N','Y') | | | N | || Lock_tables_priv | enum('N','Y') | | | N | || Execute_priv | enum('N','Y') | | | N | || Repl_slave_priv | enum('N','Y') | | | N | || Repl_client_priv | enum('N','Y') | | | N | || ssl_type | enum('','ANY','X509','SPECIFIED') | | | | || ssl_cipher | blob | | | | || x509_issuer | blob | | | | || x509_subject | blob | | | | || max_questions | int(11) unsigned | | | 0 | || max_updates | int(11) unsigned | | | 0 | || max_connections | int(11) unsigned | | | 0 | |+-----------------------+-----------------------------------+------+-----+---------+-------+

MySQL Administration How-To

Page 5: MySQL Training Course Part2

27

3.2 Creating MySQL users and granting privileges

To create a new user and also grant privileges in the same time, we can use theGRANT command:

mysql> grant shutdown on *.* to test@localhost identified by 'testpass';Query OK, 0 rows affected (0.02 sec)

mysql> select * from user where user = 'test'\G

Host: localhost User: test Password: 7dcda0d57290b453 Select_priv: N Insert_priv: N Update_priv: N Delete_priv: N Create_priv: N Drop_priv: N Reload_priv: N Shutdown_priv: Y Process_priv: N File_priv: N Grant_priv: N References_priv: N Index_priv: N Alter_priv: N Show_db_priv: N Super_priv: NCreate_tmp_table_priv: N Lock_tables_priv: N Execute_priv: N Repl_slave_priv: N Repl_client_priv: N ssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0 max_updates: 0 max_connections: 01 row in set (0.00 sec)

mysql> grant drop on TESTDB.* to test@localhost;Query OK, 0 rows affected (0.01 sec)

MySQL Administration How-To

Page 6: MySQL Training Course Part2

28

mysql> select * from db where user = 'test'\G

Host: localhost Db: TESTDB User: test Select_priv: N Insert_priv: N Update_priv: N Delete_priv: N Create_priv: N Drop_priv: Y Grant_priv: N References_priv: N Index_priv: N Alter_priv: NCreate_tmp_table_priv: N Lock_tables_priv: N1 row in set (0.00 sec)

HOST, USER, and DB table are very closely connected - if an authorized USER attempts an SQL request from an unauthorized HOST, it is denied. If a request froman authorized HOST is not an authorized USER, it is denied. If a globally authorizedUSER does not have rights to a certain DB, it is denied.

MySQL Administration How-To

Page 7: MySQL Training Course Part2

29

For the GRANT and REVOKE statements, priv_type can be specified as any of thefollowing:

Privilege Meaning

ALL [PRIVILEGES] Sets all simple privileges except GRANT OPTION

ALTER Allows use of ALTER TABLE

CREATE Allows use of CREATE TABLE

CREATETEMPORARYTABLES

Allows use of CREATE TEMPORARY TABLE

CREATE VIEW Allows use of CREATE VIEW

DELETE Allows use of DELETE

DROP Allows use of DROP TABLE

EXECUTE Allows the user to run stored procedures (MySQL 5.0)

FILE Allows use of SELECT ... INTO OUTFILE and LOAD DATA INFILE

INDEX Allows use of CREATE INDEX and DROP INDEX

INSERT Allows use of INSERT

LOCK TABLES Allows use of LOCK TABLES on tables for which you have the SELECTprivilege

PROCESS Allows use of SHOW FULL PROCESSLIST

REFERENCES Not yet implemented

RELOAD Allows use of FLUSH

REPLICATIONCLIENT

Allows the user to ask where the slave or master servers are

REPLICATIONSLAVE

Needed for replication slaves (to read binary log events from themaster)

SELECT Allows use of SELECT

SHOWDATABASES

SHOW DATABASES shows all databases

SHOW VIEW Allows use of SHOW CREATE VIEW

SHUTDOWN Allows use of mysqladmin shutdown

SUPER Allows use of CHANGE MASTER, KILL, PURGE MASTER LOGS, and SETGLOBAL statements, the mysqladmin debug command; allows you toconnect (once) even if max_connections is reached

UPDATE Allows use of UPDATE

USAGE Synonym for ``no privileges''

GRANT OPTION Allows privileges to be granted

MySQL Administration How-To

Page 8: MySQL Training Course Part2

30

Not all privileges can be granted with the “GRANT” command. Some of the privilegeshas to be granted by directly updating the “user” table. For example:

mysql> grant delete_priv on TESTDB.* to test@localhost;

ERROR 1064: You have an error in your SQL syntax. Check the manual thatcorresponds to your MySQL server version for the right syntax to use near'delete_priv on TESTDB.* to test@localhost' at line 1

mysql> update db set Delete_priv = 'Y' where user = 'test' and db = 'TESTDB';

Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from db where user = 'test'\G

Host: localhost Db: TESTDB User: test Select_priv: N Insert_priv: N Update_priv: N Delete_priv: Y Create_priv: N Drop_priv: Y Grant_priv: N References_priv: N Index_priv: N Alter_priv: NCreate_tmp_table_priv: N Lock_tables_priv: N1 row in set (0.00 sec)

When mysqld starts, all grant table contents are read into memory and becomeeffective for access control at that point.

When the server reloads the grant tables, privileges for existing client connections areaffected as follows:

• Table and column privilege changes take effect with the client's next request. • Database privilege changes take effect at the next USE db_name statement. • Changes to global privileges and passwords take effect the next time the client

connects.

If you modify the grant tables using GRANT, REVOKE, or SET PASSWORD, the servernotices these changes and reloads the grant tables into memory again immediately.

If you modify the grant tables directly using statements such as INSERT, UPDATE, orDELETE, your changes have no effect on privilege checking until you either restartthe server or tell it to reload the tables. To reload the grant tables manually, issue a

MySQL Administration How-To

Page 9: MySQL Training Course Part2

32

FLUSH PRIVILEGES statement or execute a mysqladmin flush-privileges ormysqladmin reload command.

The privilege grants doesn't take effect until MySQL server reads the grant tablesfrom the “mysql” database. You can force this by executing the following commands:

mysql> show grants for 'test'@'localhost';

+---------------------------------------------------------------------------------------+| Grants for test@localhost |+---------------------------------------------------------------------------------------+| GRANT SHUTDOWN ON *.* TO 'test'@'localhost' IDENTIFIED BY PASSWORD'7dcda0d57290b453' || GRANT DROP ON `TESTDB`.* TO 'test'@'localhost' |+---------------------------------------------------------------------------------------+

2 rows in set (0.00 sec)

mysql> flush privileges;Query OK, 0 rows affected (0.00 sec)

mysql> show grants for 'test'@'localhost';

+---------------------------------------------------------------------------------------+| Grants for test@localhost |+---------------------------------------------------------------------------------------+| GRANT SHUTDOWN ON *.* TO 'test'@'localhost' IDENTIFIED BY PASSWORD '7dcda0d57290b453' || GRANT DELETE, DROP ON `TESTDB`.* TO 'test'@'localhost' |+---------------------------------------------------------------------------------------+2 rows in set (0.00 sec)

# mysqladmin -u root flush-privileges

# mysqladmin -u root reload

To revoke privileges from a user one can use the REVOKE command:

mysql> revoke drop on TESTDB.* from 'test'@'localhost';Query OK, 0 rows affected (0.01 sec)

MySQL Administration How-To

Page 10: MySQL Training Course Part2

33

mysql> select * from db where user = 'test'\G

Host: localhost Db: TESTDB User: test Select_priv: N Insert_priv: N Update_priv: N Delete_priv: Y Create_priv: N Drop_priv: N Grant_priv: N References_priv: N Index_priv: N Alter_priv: NCreate_tmp_table_priv: N Lock_tables_priv: N1 row in set (0.01 sec)

To change user password use:

For older versions of MySQL the syntax of updating the password was:

mysql> update user set password = 'testpass1' where user = 'test';Query OK, 1 row affected (0.01 sec)Rows matched: 1 Changed: 1 Warnings: 0

mysql> select user, host, password from user where user = 'test';

+------+-----------+-----------+| user | host | password |+------+-----------+-----------+| test | localhost | testpass1 |+------+-----------+-----------+

1 row in set (0.00 sec)

On versions 4.0.x you can use only the statement below, which is equivalent on theabove statement:

mysql> update user set password = PASSWORD('testpass1') where user ='test';Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0

MySQL Administration How-To

Page 11: MySQL Training Course Part2

34

mysql> flush privileges;Query OK, 0 rows affected (0.00 sec)

mysql> select user, host, password from user where user = 'test';

+------+-------------+-------------------------------+| user | host | password |+------+--------------+------------------------------+| test | localhost | 306c24f613692c49 |+------+--------------+------------------------------+

1 row in set (0.00 sec)

mysql> set password for test = password('testpass2');Query OK, 0 rows affected (0.02 sec)

mysql> select user, host, password from user where user = 'test';

+------+--------------+-------------------------------+| user | host | password |+------+--------------+-------------------------------+| test | localhost | 306c2763136928b6 |+------+--------------+-------------------------------+

1 row in set (0.00 sec)

To grant user access to remote users you have to specify the remote host:

mysql> grant shutdown on *.* to trifon@'wine.corp.yahoo.com';Query OK, 0 rows affected (0.01 sec)

mysql> grant shutdown on *.* to trifon@'%.corp.yahoo.com';Query OK, 0 rows affected (0.00 sec)

mysql> grant shutdown on *.* to trifon@'216.145.53.%';Query OK, 0 rows affected (0.00 sec)

You can also group privileges together:

mysql> grant drop, select, insert on TESTDB.* to trifon@'216.145.53.%';Query OK, 0 rows affected (0.00 sec)

MySQL Administration How-To

Page 12: MySQL Training Course Part2

35

To remove user from MySQL:

mysql> delete from user where user='username';

mysql> FLUSH PRIVILEGES;

More examples of adding a new user with different level of privileges:

dummy: A user who can connect without a password, but only from the local host.

mysql> GRANT USAGE ON *.* TO dummy@localhost;

myUser: A full superuser who can connect to the server from anywhere, but whomust use a password 'pass' to do so. GRANT statements should be for bothmyUser@localhost and myUser@"%". to prevent the anonymous user entry forlocalhost take precedence.

mysql> GRANT ALL PRIVILEGES ON *.* TO myUser@localhost IDENTIFIED BY 'pass' WITH GRANT OPTION;

mysql> GRANT ALL PRIVILEGES ON *.* TO myUser@"%" IDENTIFIED BY 'some_pass' WITH GRANT OPTION;

“%" - is a wildcard in MySQL. If you are defining your DB table and in the 'host' field enter '%', that means that any host can access that database (Of course, that host must also have a valid db user).

admin: A user who can connect from localhost without a password and who isgranted the RELOAD and PROCESS administrative privileges. No database-relatedprivileges are granted.

mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost;

Add a user that has full rights to his database only but cannot see other database:

mysql> GRANT USAGE ON *.* TO 'user'@'host' GRANT Select, Insert, Update, Delete, Create, Drop ON `database`.* TO 'user'@'host' FLUSH PRIVELEGS;

MySQL Administration How-To

Page 13: MySQL Training Course Part2

36

The FILE privelege and WITH GRANT OPTION may not be the best way to include, itis only in case of creating another superuser with full set of privileges or givingprivileges to load data using mysql command INLOAD DATA.

Summary of the ways to change the user passwords in MySQL:

- from Unix:

# mysql -u username -h hostname -p password

mysql> SET PASSWORD FOR username@localhost=PASSWORD('new_password');

- directly manipulate the privilege tables:

# mysql -u username -h host -u username -p

mysql> UPDATE user SET Password=PASSWORD('new_password') WHERE user='root';

mysql> FLUSH PRIVILEGES;

- using the mysqladmin command:

# mysqladmin -u username password new_password

3.3 Useful MySQL build-in functions

mysql> select user();

+----------------+| user() |+----------------+| root@localhost |+----------------+

1 row in set (0.00 sec)

MySQL Administration How-To

Page 14: MySQL Training Course Part2

37

mysql> select database();

+------------+| database() |+------------+| mysql |+------------+

1 row in set (0.00 sec)

mysql> select curtime();

+-----------+| curtime() |+-----------+| 15:08:13 |+-----------+1 row in set (0.02 sec)

mysql> select curdate();

+------------+| curdate() |+------------+| 2004-09-27 |+------------+

1 row in set (0.00 sec)

4. Backups of MySQL tables and databases

4.1 Manual backup by using the OS utilities (cp, tar)

MySQL tables are stored as files, so to do a backup we have to make a copies of thetable data files. To get a consistent backup, do a LOCK TABLES on the relevanttables, followed by FLUSH TABLES for the tables.

The LOCK TABLES is placing a read lock on the tables. This allows other clients tocontinue to query the tables while you are making a copy of the files in the databasedirectory.

The FLUSH TABLES statement is needed to ensure that the all active index pagesare written to disk before you start the backup.

MySQL Administration How-To

Page 15: MySQL Training Course Part2

38

mysql> show tables;

+----------------------------+

| Tables_in_TESTDB |

+----------------------------+

| test1 |

+----------------------------+

1 row in set (0.00 sec)

The following command places a read lock on the “test1” table:

mysql> lock tables test1 read;

Query OK, 0 rows affected (0.07 sec)

The following command will flush all the table data from the memory cache to thedisk:

mysql> flush tables;

Query OK, 0 rows affected (0.01 sec)

From another terminal session:

# ls -la /home/y/var/mysql/data/TESTDB

-rw-rw---- 1 mysql users 80 Sep 21 11:40 test1.MYD

-rw-rw---- 1 mysql users 1024 Sep 21 11:57 test1.MYI

-rw-rw---- 1 mysql users 8614 Sep 21 11:23 test1.frm

# tar cvf TESTDB-backup.tar ./test1

*

./test1.MYD

./test1.MYI

./test1.frm

MySQL Administration How-To

Page 16: MySQL Training Course Part2

39

# ls -la /home/y/var/mysql/data/TESTDB

-rw-r--r-- 1 root users 20480 Sep 27 17:28 TESTDB-backup.tar

-rw-rw---- 1 mysql users 80 Sep 21 11:40 test1.MYD

-rw-rw---- 1 mysql users 1024 Sep 21 11:57 test1.MYI

-rw-rw---- 1 mysql users 8614 Sep 21 11:23 test1.frm

mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

You can also use the following command to btain a read lock on the tables and flushthem to the disk:

mysql> flush tables with read lock;

Query OK, 0 rows affected (0.00 sec)

Then again we make a copy of the MySQL data files and unlock the tables:

mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

4.2 SQL level backup

If you want to make an SQL level backup of a table, you can use SELECT INTO ...OUTFILE to dump the table. For SELECT INTO ... OUTFILE, the output file cannotalready exist.

The restore method is with LOAD DATA INFILE 'file_name' REPLACE ... To avoidduplicate records, the table must have a primary key or a unique index. TheREPLACE keyword causes old records to be replaced with new ones when a newrecord duplicates an old record on a unique key value.

In this example, we will do SQL level backup of “test1” table:

mysql> select * into outfile '/tmp/TESTDB-backup.sql' from test1;

Query OK, 4 rows affected (0.00 sec)

MySQL Administration How-To

Page 17: MySQL Training Course Part2

40

# cat /tmp/TESTDB-backup.sql

100 \N \N

101 \N \N

102 \N \N

103 \N \N

To restore the table we can use the LOAD DATA INFILE command:

mysql> create table test2 as select * from test1 where 1 = 2;

Query OK, 0 rows affected (0.02 sec)

Records: 0 Duplicates: 0 Warnings: 0

mysql> load data infile '/tmp/TESTDB-backup.sql' into table test2;

Query OK, 4 rows affected (0.02 sec)

Records: 4 Deleted: 0 Skipped: 0 Warnings: 0

mysql> select * from test2;

+------+------------+-------------------+

| id | salary | department |

+------+------------+-------------------+

| 100 | NULL | NULL |

| 101 | NULL | NULL |

| 102 | NULL | NULL |

| 103 | NULL | NULL |

+------+------------+-------------------+

4 rows in set (0.00 sec)

You can also do a selecting backups by using the WHERE predicate in the SELECTINTO OUTFILE command:

mysql> select * into outfile '/tmp/TESTDB-backup.sql' from test1 where id <103;

MySQL Administration How-To

Page 18: MySQL Training Course Part2

41

For a SQL level backup of a table you can also use the BACKUP TABLE command.The command to restore the backup taken with the BACKUP TABLE command isRESTORE TABLE. The syntax of both commands is provided below:

mysql> BACKUP TABLE tbl_name[,tbl_name...] TO '/path/to/backup/directory';

Copies to the backup directory the minimum number of table files needed to restorethe table, after flushing any buffered changes to disk.

mysql> RESTORE TABLE tbl_name[,tbl_name...] FROM '/path/to/backup/directory';

Restores the table(s) from the backup that was made with BACKUP TABLE. Existingtables will not be overwritten; if you try to restore over an existing table, you will getan error. Restoring will take longer than backing up due to the need to rebuild theindex. The more keys you have, the longer it will take. Just as BACKUP TABLE,RESTORE TABLE currently works only for MyISAM tables !!

mysql> backup table test2 to '/home/tmp/';

+--------------+--------+----------+----------+| Table | Op | Msg_type | Msg_text |+--------------+--------+----------+----------+| TESTDB.test2 | backup | status | OK |+--------------+--------+----------+----------+1 row in set (0.01 sec)

# ls -la | grep test2-rw-rw---- 1 mysql wheel 80 Sep 27 17:55 test2.MYD-rw-rw---- 1 mysql wheel 8614 Sep 27 17:55 test2.frm

4.3 MySQL backup using mysqldump and mysqlhotcopy commands

Another way to back up a database is to use the mysqldump program or themysqlhotcopy scripts. mysqlhotcopy command is a PERL wrapper to the MySQLcommands (you can review the source code freely), so to make this command to workyou have to make sure you have the PERL package and the following PERL modulesinstalled:

MySQL Administration How-To

Page 19: MySQL Training Course Part2

42

ypan/perl-DBD-mysql

ypan/perl-DBI

To check this run these commands:

$ yinst list mysql_client

$ yinst list mysql_server

$ yinst list ypan/perl-DBD-mysql

$ yinst list perl

$ yinst list ypan/perl-DBI

To do a full backup of your database:

# mysqldump -u user_name -p --tab=/path/to/some/dir --opt db_name

or

# mysqlhotcopy -u user_name -p db_name /path/to/some/dir

You can also simply copy all table files (`*.frm', `*.MYD', and `*.MYI' files) as long asthe server isn't updating anything. The mysqlhotcopy script uses this method. (Butnote that these methods will not work if your database contains InnoDB tables.InnoDB does not store table contents in database directories, and mysqlhotcopy worksonly for MyISAM and ISAM tables.)

The following example backups the TESTDB MySQL database:

# mysqldump --add-locks --extended-insert --flush-logs --lock-tables --quickTESTDB > /tmp/TESTDB-backup.sql

# ls -la | grep TESTDB

-rw-rw-rw- 1 mysql wheel 817 Sep 27 17:44 TESTDB-backup.sql

The backup file contains the SQL statements required to restore the tables:

# cat /tmp/TESTDB-backup.sql

MySQL Administration How-To

Page 20: MySQL Training Course Part2

43

-- MySQL dump 9.11

--

-- Host: localhost Database: TESTDB

-- ------------------------------------------------------

-- Server version 4.0.22-Yahoo-SMP-log

--

-- Table structure for table `test1`

--

CREATE TABLE test1 (

id int(11) default NULL,

salary int(11) default NULL,

department text

) TYPE=MyISAM;

--

-- Dumping data for table `test1`

--

LOCK TABLES test1 WRITE;

INSERT INTO test1 VALUES (100,NULL,NULL),(101,NULL,NULL),(102,NULL,NULL),(103,NULL,NULL);

UNLOCK TABLES;

--

-- Table structure for table `test2`

--

CREATE TABLE test2 (

id int(11) default NULL,

salary int(11) default NULL,

department text

) TYPE=MyISAM;

MySQL Administration How-To

Page 21: MySQL Training Course Part2

44

--

-- Dumping data for table `test2`

--

LOCK TABLES test2 WRITE;

INSERT INTO test2 VALUES (100,NULL,NULL),(101,NULL,NULL),(102,NULL,NULL),(103,NULL,NULL);

UNLOCK TABLES;

The backup command for TESTDB using “mysqlhotcopy” would looks like:

# mysqlhotcopy -u root TESTDB > /tmp/TESTDB-hotcopy.sql

4.4 Backing Up and Recovering an InnoDB Database

The key to safe database management is taking regular backups. InnoDB Hot Backup is an online backup tool you can use to backup your InnoDBdatabase while it is running. InnoDB Hot Backup does not require you to shut downyour database and it does not set any locks or disturb your normal databaseprocessing.

InnoDB Hot Backup is a non-free (commercial) additional tool whose annual licensefee is 390 euros per computer where the MySQL server is run. See the InnoDB HotBackup home page for detailed information and screenshots. If you are able to shutdown your MySQL server, you can make a ``binary'' backup that consists of all filesused by InnoDB to manage its tables.

Use the following procedure:

1. Shut down your MySQL server and make sure that it shuts down without errors.2. Copy all your data files into a safe place. 3. Copy all your InnoDB log files to a safe place. 4. Copy your `my.cnf' configuration file or files to a safe place. 5. Copy all the `.frm' files for your InnoDB tables to a safe place.

Replication works with InnoDB type tables, so you can use MySQL replicationcapabilities to keep a copy of your database at database sites requiring highavailability.

In addition to taking binary backups as just described, you should also regularly takedumps of your tables with mysqldump. The reason for this is that a binary file mightbe corrupted without you noticing it. Dumped tables are stored into text files that arehuman-readable, so spotting table corruption becomes easier.

MySQL Administration How-To

Page 22: MySQL Training Course Part2

45

Also, since the format is simpler, the chance for serious data corruption is smaller.mysqldump also has a --single-transaction option that you can use to take a consistentsnapshot without locking out other clients.

To be able to recover your InnoDB database to the present from the binary backupdescribed above, you have to run your MySQL server with binary logging turned on.

Then you can apply the binary log to the backup database to achieve point-in-timerecovery:

# mysqlbinlog yourhostname-bin.123 | mysql

To recover from a crash of your MySQL server process, the only thing you have to dois to restart it. InnoDB will automatically check the logs and perform a roll-forward ofthe database to the present. InnoDB will automatically roll back uncommittedtransactions that were present at the time of the crash.

During recovery, mysqld will display output something like this:

InnoDB: Database was not shut down normally.InnoDB: Starting recovery from log files...InnoDB: Starting log scan based on checkpoint atInnoDB: log sequence number 0 13674004InnoDB: Doing recovery: scanned up to log sequence number 0 13739520InnoDB: Doing recovery: scanned up to log sequence number 0 13805056InnoDB: Doing recovery: scanned up to log sequence number 0 13870592InnoDB: Doing recovery: scanned up to log sequence number 0 13936128...InnoDB: Doing recovery: scanned up to log sequence number 0 20555264InnoDB: Doing recovery: scanned up to log sequence number 0 20620800InnoDB: Doing recovery: scanned up to log sequence number 0 20664692InnoDB: 1 uncommitted transaction(s) which must be rolled backInnoDB: Starting rollback of uncommitted transactionsInnoDB: Rolling back trx no 16745InnoDB: Rolling back of trx no 16745 completedInnoDB: Rollback of uncommitted transactions completedInnoDB: Starting an apply batch of log records to the database...InnoDB: Apply batch completedInnoDB: Startedmysqld: ready for connections

If your database gets corrupted or your disk fails, you have to do the recovery from abackup. In the case of corruption, you should first find a backup that is not corrupted.After restoring the base backup, do the recovery from the binary log files.

In some cases of database corruption it is enough just to dump, drop, and re-createone or a few corrupt tables. You can use the CHECK TABLE SQL statement to checkwhether a table is corrupt, although CHECK TABLE naturally cannot detect everypossible kind of corruption.

MySQL Administration How-To

Page 23: MySQL Training Course Part2

46

You can use innodb_tablespace_monitor to check the integrity of the file spacemanagement inside the tablespace files. In some cases, apparent database pagecorruption is actually due to the operating system corrupting its own file cache, andthe data on disk may be okay. It is best first to try restarting your computer. It mayeliminate errors that appeared to be database page corruption.

5. MySQL Master – Slave Replication

Set up an account on the master server that the slave server can use to connect. Thisaccount must be given the REPLICATION SLAVE privilege. If the account is used onlyfor replication (which is recommended), you don't need to grant any additionalprivileges. Suppose that your domain is mydomain.com and you want to create anaccount with a username of repl such that slave servers can use the account toaccess the master server from any host in your domain using a password ofslavepass. To create the account, this use GRANT statement:

mysql> grant replication slave on *.* TO 'repl'@'p-int.corp.yahoo.com'IDENTIFIED BY 'repl';Query OK, 0 rows affected (0.00 sec)

mysql> select * from user where user = 'repl'\G

Host: p-int.corp.yahoo.com User: repl Password: 5ec3db8f603fcb03 Select_priv: N Insert_priv: N Update_priv: N Delete_priv: N Create_priv: N Drop_priv: N Reload_priv: N Shutdown_priv: N Process_priv: N File_priv: N Grant_priv: N References_priv: N Index_priv: N Alter_priv: N Show_db_priv: N Super_priv: NCreate_tmp_table_priv: N Lock_tables_priv: N Execute_priv: N Repl_slave_priv: Y Repl_client_priv: N

MySQL Administration How-To

Page 24: MySQL Training Course Part2

47

Shutdown the master and enable the replication by setting up these parameters in /etc/my.cnf file:

## Uncomment these if this server will be a master.

log-binserver-id = 1

The log-bin parameter enables MySQL to dump all commited transactions into abinary logs, which are then pulled from the slaves and applied to keep the slaves insync with the master MySQL database.

We also assign an unique ID for the master. We will have number the slavesaccordingly as server-id=2 for the first slave, server-id=2 for the second slave, etc.

Once we change the values in the /etc/my.cnf we have to restart the MySQL server.The binary logs then will be generated in the MySQL data directory - /home/y/var/mysql/data:

# ls -la /home/y/var/mysql/data | grep bin

-rw-rw---- 1 mysql users 929 Sep 16 11:16 a-int-bin.001-rw-rw---- 1 mysql users 311 Sep 16 15:14 a-int-bin.002-rw-rw---- 1 mysql users 11582 Sep 21 11:56 a-int-bin.003-rw-rw---- 1 mysql users 79 Sep 21 11:58 a-int-bin.004-rw-rw---- 1 mysql users 79 Sep 21 12:02 a-int-bin.005-rw-rw---- 1 mysql users 79 Sep 21 17:18 a-int-bin.006-rw-rw---- 1 mysql users 79 Sep 21 17:33 a-int-bin.007-rw-rw---- 1 mysql users 1140 Sep 27 16:04 a-int-bin.008-rw-rw---- 1 mysql users 128 Sep 22 11:59 a-int-bin.index

The binary files are generated and numbered automatically and the list of all binarylog files is kept in the *bin.index file:

#cat /home/y/var/mysql/data/a-int-bin.index

./a-int-bin.001

./a-int-bin.002

./a-int-bin.003

./a-int-bin.004

./a-int-bin.005

./a-int-bin.006

./a-int-bin.007

./a-int-bin.008

MySQL Administration How-To

Page 25: MySQL Training Course Part2

48

DBA can purge all of the replication binary logs except the currently used:

1. On each slave server, use SHOW SLAVE STATUS to check which log it is reading. 2. Obtain a listing of the logs on the master server with SHOW MASTER LOGS. 3. Determine the earliest log among all the slaves. This is the target log. If all theslaves are up to date, this will be the last log on the list. 4. Make a backup of all the logs you are about to delete. (The step is optional, but agood idea.) 5. Purge all logs up to but not including the target log.

Once you identify what is the latest binary log each slave is reading from, you canpurge the binary logs on the master:

PURGE MASTER LOGS TO 'a-int-bin.007';

Once you do that, the the index file for the binary logs will be updated:

# cat /home/y/var/mysql/data/a-int-bin.index

./a-int-bin.008

On the master database dump the database so we can copy it to the slave:

# mysqldump -u root -p --add-locks --extended-insert --flush-logs --lock-tables--quick --databases TESTDB > /var/tmp/TESTDB-backup.sql

Check which is the latest binary log generated after the “mysqldump” command. Thiswill be the starting point for the slave replication:

# ls -la /home/y/var/mysql/data | grep bin

-rw-rw---- 1 mysql users 929 Sep 16 11:16 a-int-bin.001-rw-rw---- 1 mysql users 311 Sep 16 15:14 a-int-bin.002-rw-rw---- 1 mysql users 11582 Sep 21 11:56 a-int-bin.003-rw-rw---- 1 mysql users 79 Sep 21 11:58 a-int-bin.004-rw-rw---- 1 mysql users 79 Sep 21 12:02 a-int-bin.005-rw-rw---- 1 mysql users 79 Sep 21 17:18 a-int-bin.006-rw-rw---- 1 mysql users 79 Sep 21 17:33 a-int-bin.007-rw-rw---- 1 mysql users 1140 Sep 27 16:04 a-int-bin.008-rw-rw---- 1 mysql users 4 Sep 27 16:31 a-int-bin.009-rw-rw---- 1 mysql users 128 Sep 22 11:59 a-int-bin.index

MySQL Administration How-To

Page 26: MySQL Training Course Part2

49

In this case this is the a-int-bin.009 file.

Copy the TESTDB database dump on the slave machine:

# scp awacs-backup.sql [email protected]:/var/tmp

On the slave machine we have to create the TESTDB database first, so we can restorethe initial backup from the master machine:

# mysqladmin create TESTDB

- edit the /etc/my.cnf

## Uncomment these if this server will be a master.

log-binserver-id = 2

## Replication

master-host = a-int.corp.yahoo.commaster-user = replmaster-password = replmaster-port = 3306

Restart the MySQL slave server:

# yinst stop mysql_serveryinst: mysql_server-4.0.22_1: stopping ...

# yinst start mysql_serveryinst: mysql_server-4.0.22_1: starting ...

Now we have to fix the replication starting point. Since we already changed the /etc/my.cnf file and added the master replication details, the replication is started:

mysql> stop slave;Query OK, 0 rows affected (0.00 sec)

mysql> change master to master_log_file='a-int-bin.009', master_log_pos=4;Query OK, 0 rows affected (0.00 sec)

MySQL Administration How-To

Page 27: MySQL Training Course Part2

50

Now we can start the replication and check it's status:

mysql> start slave;Query OK, 0 rows affected (0.00 sec)

mysql> show slave status;

In the output from the above command if the master-slave replication is running, weshould see the following parameters as:

Slave_IO_Running: Yes Slave_SQL_Running: Yes

These parameters show the status of the two threads involved in the MySQLreplication. The Slave_IO thread is pulling the changes from the master binary logsand updates the binary logs on the slave machine. The Slave_SQL thread reads thecommitted transactions from the binary log and applies them on the slave server.

The entries in the binary logs looks like:

^@^@^@^A^@^@^@^E^@^@mysql^@grant shutdown on *.* totrifon@'wine.corp.yahoo.com'G\x9aXA^B^A^@^@^@V^@^@^@^O^C^@^@^@^@^@^@^@^@^@^@^@^E^@^@mysql^@grant shutdown on *.* to trifon@'%.corp.yahoo.com'd\x9aXA^B^A^@^@^@R^@^@^@e^C^@^@^@^@^@^@^@^@^@^@^@^E^@^@mysql^@grant shutdown on *.* totrifon@'216.145.53.%'\xa0\x9aXA^B^A^@^@^@c^@^@^@\xb7^C^@^@^@^@^@^@^@^@^@^@^@^E^@^@mysql^@grant drop, select, insert on TESTDB.* totrifon@'216.145.53.%'o\x9cXA^B^A^@^@^@Z^@^@^@^Z^D^@^@^@^@^@^@^@^@^@^@^@^E^@^@mysql^@SET PASSWORD FOR"test"@"localhost"="306c2763136928b6"\xa9\xa4XA^B^A^@^@^@x^@^@^@t^D^@^@^@^@^K^@^@^@^@^@^@^@^E^@^@mysql^@grant replication slaveon *.* TO 'repl'@'p-int.corp.yahoo.com' IDENTIFIED BY 'repl'

MySQL Administration How-To