mysql Chapter Six (Administration)

Documentation Version: 0.75
mysql Version: 3.20.11

Granting Access to a Database

The mysql database system uses a special database to grant access privileges to it's databases. These privileges can be based on hosts and/or users, and can be granted to a single database or many.

User accounts are passworded. When connecting to the database the password is encrypted to assure that it can not be intercepted and used by others.

The mysql database contains three tables. They are defined below.

Database: mysql Table: db
FieldTypeNullKeyDefaultExtra
hostchar(60)PRI
dbchar(32)PRI
userchar(16)PRI
select_privchar(1)N
insert_privchar(1)N
update_privchar(1)N
delete_privchar(1)N
create_privchar(1)N
drop_privchar(1)N
file_privchar(1)N

Database: mysql Table: host
FieldTypeNullKeyDefaultExtra
hostchar(60)PRI
dbchar(32)PRI
select_privchar(1)N
insert_privchar(1)N
update_privchar(1)N
delete_privchar(1)N
create_privchar(1)N
drop_privchar(1)N

Database: mysql Table: user
FieldTypeNullKeyDefaultExtra
hostchar(60)PRI
userchar(16)PRI
passwordchar(8)
select_privchar(1)N
insert_privchar(1)N
update_privchar(1)N
delete_privchar(1)N
create_privchar(1)N
drop_privchar(1)N
reload_privchar(1)N
shutdown_privchar(1)N
process_privchar(1)N


The following is an example of adding new users.

$ mysql mysql

mysql> INSERT INTO user VALUES ('%','monty',password('something'),
    -> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
mysql> INSERT INTO user (host,user,password) values('localhost','dummy','') ;
mysql> INSERT INTO user VALUES ('%','admin','','N','N','N','N','N','N','Y','N','Y','N') ;
mysql> quit

$ mysqladmin reload

This makes three new users:

monty: Full superuser, but must use password when using mysql.

admin: Doesn't need a password but is only allowed to use 'mysqladmin reload' and 'mysqladmin processlist'. May be granted individual database privileges through table 'db'.

dummy: Must be granted individual database privileges through table 'db'.

NOTE: You MUST use the password() function when creating a user that has a password. The mysql database system expects passwords to be stored encrypted.

Attribute assigned in the user table over-ride attribute assigned to a user in a given DB. If you are paranoid or have a server that provides multiple databases you probably want to create users in the user account with no privileges, and then assign appropriate privileges on a database by database basis.

How passwords work

The scrambled password is stored in the mysql 'user' table.

Tuning mysqld

When you issue the -O option by itself you will be given a list of all tunable variables and their current values. This should look similar to the following.

$ mysqld -O

Possible variables to option -O are:
keybuffer             current value: 1048568
max_allowed_packet    current value: 65536
net_buffer_length     current value: 16384
max_connections       current value: 128
table_cache           current value: 64
recordbuffer          current value: 524280
sortbuffer            current value: 2097144

The following table explains a bit about each of the above listed values and gives some hints on how you might want to tweak them for better performance.

keybuffer Buffer to hold all recently used keys. A big buffer gives the best performance. With the -Sl switch only one buffer is allocated.

max_allowed_packet The server connection buffer may be resized up to this if the client gives long commands. The initial buffer is 'net_buffer_length'. One buffer is allocated per connection.

net_buffer_length Initial size of the connection buffer. One buffer is allocated per connection.

max_connections The maximum number of connections that mysqld can have open at the same time.

table_cache Maximum number of tables kept open on the server. Tables are kept open to give better query speed on frequently used tables.

recordbuffer Buffer used to read records sequentially. One buffer will be allocated per connection.

sortbuffer Buffer used when sorting. One buffer will be allocated per connection.

Things to Know

Query Optimization

What optimization is done on the WHERE clause?

Here's a partial list:

const_table.key = constant

const_table.key_part_1 = const_table2.field and
const_table.key_part_2 = constant

  • Find the best join combination to join tables (By trying all possibilities :( )
  • For each table use a ranged key if possibly to read records. Each table index is queried and if there exists a key range that spans < 30% of the records then a key is used, else a quick table scan is used.
  • Before each record is output, skip those that match the HAVING clause.
  • Optimizing Table Space Usage

    There are several things you can do to minimize the amount of space your tables take. First of all, use NOT NULL whenever possible. This will speed up queries, and save 1 bit per field.

    You can save a lot of space by using the smaller integer values. For instance, MEDIUMINT is often sufficient.

    In general you should choose the smallest data-type you will need if you are concerned with space.

    The Client/Server Protocol

    Key:

    < = client 
    > = server
    [] is one byte
    [2: ] is two bytes packed low byte first
    [3: ] is three bytes packed low byte first
    [4: ] is four bytes packed low byte first
    [string: ] is a null byte terminated string
    [length: ] This is a length coded integer. Check
               net_store_length() for this one!
               The main idea is to get most frequent length bytes in 1
               byte but to allow longer data (and NULL)
    
    The Gory Details

    Every sent and received packet has the following prefix.

    [3: packet length] [packet number] packet data

    The packet reader adds a [0] after each received package (to get easy handling of error strings)

    The packet number starts from 0 and increments for each send/receive packet. Its a char (modulo 255)

    Packet Types

    :connect

    > [protocol version] [string: password crypt seed]

    < [2: 0] [3: max_allowed_client_packet_length] [string: user name]

    [string: scrambled password]

    > ok packet

    Check the file password.c from the mysql source release for the method used to encrypt a password. Password should be empty if the user has no password.

    :ok

    [0] [length: affected_rows] [length: unique id]

    :error

    (May come at any time)

    > [255] [string: error message]

    :command

    < [command number]

    enum enum_server_command {SLEEP,QUIT,INIT_DB,QUERY,FIELD_LIST, CREATE_DB,DROP_DB,RELOAD,SHUTDOWN,STATISTICS, PROCESS_INFO,CONNECT}

    :query

    < [QUERY command] [string: query string] (The end null is not sent)

    > [0] [length: affected rows] [length: insert id] (Insert, delete...)

    or

    > [length: column_count] (a query result)

    > column field data packets

    > row data packets

    :data

    : This is done repeatedly until a packet which only consist of a single [254] is found. Beware there may be packets which starts with 254. Each data packet has 'column count' fields.

    Format for each field:

    [:length] == NULL_LENGTH -> NULL field

    or

    [:length] [length data] (Not null terminated strings!)

    The column data package consists of 5 columns with the following data:

    [:string table name]
    [:string column name]
    [:3 create length of column (may be larger in a few cases)]
    [:1 type (as of enum_field_types)]
    [:1 flag] [:1 decimals] (a 2 byte binary column!)

    When using the command list_fields there is a sixth column:
    [:string default]

    Look at libmysql.c, net.c and password.c for more information.