You are on page 1of 6

MySQL DBA http://www.schwer.us/nblug/dba/mysql.

html

nblug : augie : dba : mysql

Database Administration

1. The Basics

a. Connecting to and Disconnecting from the Server


b. Creating and Using a Database
c. Creating a Table

2. Configuring MySQL

a. my.cnf

3. Security

a. Set the root password


b. Access Control Lists
c. GRANT and REVOKE
d. When privileges take effect
e. Advanced Topics
f. Checking your work

4. User Management

a. Adding Users
b. More on GRANT
c. Limiting User Resources

5. Backup and Restore

a. mysqldump

6. Caveats

a. Foreign Keys
b. Passwords

The Basics

These are some of the basics of using the MySQL DBMS (Database Management System), the lessons learned here should help you function throughout the rest of this tutorial.

Connecting to and Disconnecting from the Server is easy to do. To connect to the server, you'll usually need to provide a MySQL user name when you invoke mysql and, most
likely, a password. If the server runs on a machine other than the one where you log in, you'll also need to specify a hostname.

shell> mysql -h host -u user -p


Enter password: ********

If that works, you should see some introductory information followed by a mysql> prompt:

Welcome to the MySQL monitor. Commands end with ; or \g.


Your MySQL connection id is 584 to server version: 3.23.47

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

mysql>

The prompt tells you that MySQL is ready for you to enter commands. After you have connected successfully, you can disconnect any time by typing QUIT at the mysql> prompt.

Creating and Using a Database. Once you are connected to the server you may create a database like so:

mysql> CREATE DATABASE tutorial;

Creating a database does not select it for use; you must do that explicitly. To make tutorial the current database, use this command:

mysql> USE tutorial


Database changed

Create PDF with GO2PDF for free, if you wish to remove this line, click here to buy Virtual PDF Printer
1 of 6 6/12/2008 1:41 AM
MySQL DBA http://www.schwer.us/nblug/dba/mysql.html

Your database needs to be created only once, but you must select it for use each time you begin a mysql session. You can do this by issuing a USE statement as shown above.
Alternatively, you can select the database on the command-line when you invoke mysql. Just specify its name after any connection parameters that you might need to provide. For
example:

shell> mysql -h host -u user -p tutorial


Enter password: ********

Creating a Table. After connecting to the server and your chosen database you may create a table like so:

mysql> CREATE TABLE cheese (


name VARCHAR(15) NOT NULL,
weight INT NOT NULL,
PRIMARY KEY(name));

Configuring MySQL

The my.cnf file is the configuration file for the MySQL server, and its client applications. The scope and what affect the my.cnf file has depends on where it is placed.

/etc/my.cnf - global options

DATADIR/my.cnf - server specific options

~/.my.cnf - user specified options

DATADIR is specified at compile time. It may be /usr/local/mysql/data , or on my Mandrake 8.2 system it is /var/lib/mysql .

MySQL will try to find my.cnf in the order above. If you have multiple my.cnf files then the options from the most recently read my.cnf will take precedence over previous
options. Options on the command line take precedence over any my.cnf file.

The following programs support my.cnf for their configuration: mysql, mysqladmin, mysqld, mysqld_safe, mysql.server, mysqldump, mysqlimport, mysqlshow, mysqlcheck,
myisamchk, and myisampack.

The basic setup of a my.cnf file is such:


# comment - comments begin with a '#' or ';'.
[group] - group is the name of the program or group for which you want to set options.
option
option=value
set-variable = variable=value

A good use for the client group is to set your password so you are not prompted everytime you log in (see below). Just make sure the my.cnf in your home directory is only
readable by you.

[client]
password=my_password

Below are some examples from the MySQL docs.

Here is a typical global option file:


[client]
port=3306
socket=/tmp/mysql.sock

[mysqld]
port=3306
socket=/tmp/mysql.sock
set-variable = key_buffer_size=16M
set-variable = max_allowed_packet=1M

[mysqldump]
quick

Here is a typical user option file:


[client]
# The following password will be sent to all standard MySQL clients
password=my_password

[mysql]
no-auto-rehash
set-variable = connect_timeout=2

[mysqlhotcopy]
interactive-timeout

Your distribution of MySQL (source or binary) will come with some sample configuration files. For source you will find them in the support-file directory. Binary users will
typically find them under /usr/local/mysql or /usr/share/mysql. They will usually take the form of my-xxxx.cnf where xxxx is an adjective describing what type of configuration
file it is. Currently there are sample configuration files for small, medium, large, and very large systems.

Create PDF with GO2PDF for free, if you wish to remove this line, click here to buy Virtual PDF Printer
2 of 6 6/12/2008 1:41 AM
MySQL DBA http://www.schwer.us/nblug/dba/mysql.html

Security

Set the root password. The default install of MySQL leaves the root password blank. So the first step you take after you install MySQL should be this one:

shell> mysql -u root mysql


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

Access Control Lists. MySQL uses Access Control Lists (ACLs) for all connections, queries, and other operations that a user may attempt to perform. The ACLs are composed of
tables which are used to determine privilege.

MySQL access control involves two stages:


Stage 1 Connection Verification: The server checks whether you are even allowed to connect.
Stage 2 Request Verification: Assuming you can connect, the server checks each request you issue to see whether you have sufficient privileges to perform it.

The server uses the user, db, and host tables in the mysql database at both stages of access control. For the second stage of access control, the server may, if the request involves
tables, additionally consult the tables_priv and columns_priv tables.

A description of these tables can be seen below:


mysql> DESCRIBE user;
+-----------------+-----------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-----------------+------+-----+---------+-------+
| Host | char(60) binary | | PRI | | |
| User | char(16) binary | | PRI | | |
| Password | char(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 | |
+-----------------+-----------------+------+-----+---------+-------+

mysql> DESCRIBE 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 | |
+-----------------+-----------------+------+-----+---------+-------+

mysql> DESCRIBE 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 | |
| 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 | |
+-----------------+-----------------+------+-----+---------+-------+

mysql> DESCRIBE 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') | | | | |
+-------------+----------------------------------------------+------+-----+---------+-------+

mysql> DESCRIBE tables_priv;


+-------------+-----------------------------------------------------------------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |

Create PDF with GO2PDF for free, if you wish to remove this line, click here to buy Virtual PDF Printer
3 of 6 6/12/2008 1:41 AM
MySQL DBA http://www.schwer.us/nblug/dba/mysql.html

+-------------+-----------------------------------------------------------------------------------------------+------+-----+---------+-------+
| Host | char(60) binary | | PRI | |
| Db | char(64) binary | | PRI | |
| User | char(16) binary | | PRI | |
| Table_name | char(60) binary | | PRI | |
| Grantor | char(77) | | MUL | |
| Timestamp | timestamp(14) | YES | | NULL |
| Table_priv | set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') | | | |
| Column_priv | set('Select','Insert','Update','References') | | | |
+-------------+-----------------------------------------------------------------------------------------------+------+-----+---------+-------+

As you can see there is a very wide range of control you can exert. You can choose to control access at the very wide host level on all the way down to the very narrow
columns_priv level. You may use the wildcard symbol % in any of the Host fields in all of these tables. You may also specify a netmask if you wish.

mysql> GRANT ALL PRIVILEGES ON db.* TO david@'192.58.197.0/255.255.255.0';

The server sorts the grant tables on startup. Placing more specific host entries first, and more specific user entries first if there are duplicate host values.
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-

The server then uses this order to determine privilege.

GRANT and REVOKE. Now that you know how the privilege system works you will probably want to implement some security. While you may edit these tables manually
using INSERT and UPDATE you will probably find it easier to use the GRANT and REVOKE syntax. The basic format of a GRANT and REVOKE statement are as follows:

GRANT priv_type ON {tbl_name | * | *.* | dbname.*} TO user_name;

REVOKE priv_type ON {tbl_name | * | *.* | dbname.*} FROM user_name;

Some common privilege types are ALL, ALTER, CREATE, DELETE, DROP, INSERT, SELECT, and UPDATE. There are many others, for a full list of options and a more
descriptive summary of the GRANT and REVOKE syntax view the documentation on it. One more important note here is that you may use wild cards in the table name. So you
may grant or revoke privileges on all tables under a database named dbname by using the statement dbname.* for your table name.

When privileges take effect. Now that you have granted or revoked privileges to your users you will probably want them to take effect immediately, so here's how that works.

When mysqld starts, all grant table contents are read into memory and become effective at that point.

Modifications to the grant tables that you perform using GRANT, REVOKE, or SET PASSWORD are noticed by the server immediately.

If you modify the grant tables manually (using INSERT, UPDATE, etc.), you should execute a FLUSH PRIVILEGES statement or run mysqladmin flush-privileges or
mysqladmin reload to tell the server to reload the grant tables. Otherwise, your changes will have no effect until you restart the server.

Advanced Topics.

--chroot=path
The mysqld can be put into a chroot environment at startup simply by passing this option on the command line or in your my.cnf file. Be forwarned though that the files mysqld
needs to operate must be under this path. This may include an /etc/passwd with one entry for your mysql user. Also any temporary directories that mysql my use will need to be
available underneath this path.

--bind-address=IP
You may tell mysqld to only listen on a specified address. Again this may be passed via the command line or your my.cnf. A common value for this would be
bind-address=127.0.0.1. MySQL will now only listen for connections locally, and external portscans should now turn up empty on port 3306 (the default port for mysqld).

Checking your work is made slightly easier with the mysqlaccess tool. Give it a username and database to check and it will return some useful information, and possibly warnings
about the current state of your grant tables.

mysqlaccess root mysql

You can even pass it wildcards (though you must escape them from your shell).

mysqlaccess \* mysql

Use the --howto option by itself to get some useful examples.

User Management

First an important note on MySQL usernames. MySQL usernames have nothing to do with Linux usernames (login names). By default the client will try to log in with your
current Linux username, but that is strictly for convenience.

Adding Users. MySQL users and their privileges are normally created with GRANT statements. You may however edit the user table manually with INSERT statements. Below
are examples of each.

Using GRANT statements.

shell> mysql --user=root mysql


mysql> GRANT ALL PRIVILEGES ON *.* TO cheese@localhost
-> IDENTIFIED BY 'some_pass' WITH GRANT OPTION;
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost;

Create PDF with GO2PDF for free, if you wish to remove this line, click here to buy Virtual PDF Printer
4 of 6 6/12/2008 1:41 AM
MySQL DBA http://www.schwer.us/nblug/dba/mysql.html

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

Using INSERT statements.

shell> mysql --user=root mysql


mysql> INSERT INTO user VALUES('localhost','cheese',PASSWORD('some_pass'),
-> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user SET Host='localhost',User='admin',
-> Reload_priv='Y', Process_priv='Y';
mysql> INSERT INTO user (Host,User,Password)
-> VALUES('localhost','dummy','');
mysql> FLUSH PRIVILEGES;

cheese
A superuser who can only connect to the database locally, and must provide the password some_pass to do so.

admin
A user who can connect locally without a password and has RELOAD and PROCCESS administrative privileges. This allows the user to execute the mysqladmin reload,
mysqladmin refresh, and mysqladmin flush-* commands, as well as mysqladmin processlist. See the mysqladmin man page for more information on these and other useful options.

dummy
A user who can connect locally without a password. The USAGE privilege allows you to create a user with no privileges.

More on GRANT. MySQL does not support wildcards in usernames. This means if you want to allow access to your database(s) to anonymous users you would leave the User
field blank.

You may have noticed a few new statements in these examples that i did not cover in the previous section. The IDENTIFIED BY statement is how you set a password for a user in
conjuction with the GRANT statement. You may also, as you can see in the above example, set a password using the INSERT statement. A third option is the following:

SET PASSWORD FOR cheese@localhost=PASSWORD('some_pass');

The WITH GRANT OPTION statement gives the user the ability to grant privileges to other users on their database, or on whatever database you are granting them privileges for.

Limiting User Resources. Starting from MySQL 4.0.2 you can limit certain resources per user. The following is the list of resources you can limit:
Number of all queries per hour: All commands that could be run by a user.
Number of all updates per hour: Any command that changes any table or database.
Number of connections made per hour: New connections opened per hour.

All users by default do not have resource limits, unless granted to them. Limits are granted only through global GRANT statements. The syntax is to put these statements at the
end of your other GRANT statements.

GRANT ... WITH MAX_QUERIES_PER_HOUR N1


MAX_UPDATES_PER_HOUR N2
MAX_CONNECTIONS_PER_HOUR N3;

If a user reaches any of the above limits within one hour, their connection will be terminated or refused and the appropriate error message shall be issued.

Backup and Restore

mysqldump. For aspiring MySQL DBA's the best tool for creating backups of databases is the mysqldump tool.

A simple example of creating a backup of one database is the following:

mysqldump --opt database > backup-file.sql

You can then restore it like so:

mysql database < backup-file.sql

It is possible to dump several databases with one command:

mysqldump --databases database1 [database2 ...] > my_databases.sql

If all the databases are wanted, one can use:

mysqldump --all-databases > all_databases.sql

You may view the man page for mysqldump for explanations on --opt and other interesting options. One important note about mysqldump is that if you run mysqldump without
--quick or --opt, mysqldump will load the whole result set into memory before dumping the result. This will probably be a problem if you are dumping a big database.

Caveats

Foreign Keys are not supported by MySQL. Foreign key constraints (a.k.a. Referential Integrity) are used to deter users or applications from entering inconsistent data. MySQL's

Create PDF with GO2PDF for free, if you wish to remove this line, click here to buy Virtual PDF Printer
5 of 6 6/12/2008 1:41 AM
MySQL DBA http://www.schwer.us/nblug/dba/mysql.html

argument is that foreign keys are unnecessary at best and may cause severe problems at worst. The other side to this though is that there are many people out there who feel that
referential integrity is essential to any RDBMS (Relational Database Management System), and that any system without referential integrity is totally unacceptable. PostgreSQL
does support Foreign key constraints.

Passwords in MySQL are different that passwords in Linux. You cannot for example copy over an existing entry in /etc/shadow to your mysql.user table and expect the same
password to work on both systems. As it stands now I have yet to find an easy way to migrate an existing user base to using MySQL with their same passwords. The security
minded ones of us would say that having both passwords be the same increases the odds of both being compromised (thanks eric). However others would say that making users
remember two passwords instead of one is asking for trouble. PostgreSQL however may use the same /etc/shadow value for its client authentication.

Disclaimer: Most of this information is taken directly from the excelent MySQL documentation located here:
http://www.mysql.com/doc/

Author: August Schwer augie@nblug.org

Create PDF with GO2PDF for free, if you wish to remove this line, click here to buy Virtual PDF Printer
6 of 6 6/12/2008 1:41 AM

You might also like