Frequently Asked Questions about MySQL.


Introduction

Frequently Asked Questions about MySQL. $Revision$

This document contains answers to some of the most frequently asked questions about MySQL. They're all good questions, but they come up often enough that substantial net bandwidth can be saved by looking here first before asking.

The latest version of this FAQ can be found at http://www.tcx.se/

This FAQ is currently available in TeXInfo, ASCII, Info, Postscript and HTML versions.

The primary document is the TeXInfo file. The HTML version is automatically produced with texi2html. The ASCII and info version is produced using makeinfo. The Postscript version is produced using texi2dvi and divps.

If you have any suggested additions or corrections, please send them to the MySQL mailing list <mysql@tcx.se> with a subject line of the form FAQ Suggestion: [Insert Topic Here]. See section Subscribing to/un-subscribing from the MySQL mailing list..

This FAQ is written and maintained by David Axmark and Michael (monty) Widenius.

Absolutely Important

Subscribing to/un-subscribing from the MySQL mailing list.

Requests to be added or dropped from the MySQL list should be sent to the electronic mail address mdomo@tcx.se. Sending a one line message saying either subscribe mysql or un-subscribe mysql will suffice. If your reply address is not valid you may use subscribe mysql your@address.your-domain or un-subscribe mysql your@address.your-domain.

Please do not send mail about [un]subscribing to mysql@tcx.se since any mail sent to this address is automatically forwarded to hundreds of other users.

Your local site may have many subscribers to MySQL. In that case, it may have a local mailing list, so that a single message from tcx.se is sent to the site and propagated to the local list. In this case please contact your system administrator to be added to or dropped from the local MySQL list.

Mail to mdomo is handled automatically by majordomo.

Asking questions or reporting bugs.

Before you ask a question of the mailing list it's a good idea to check in the manual. If you can't find an answer in the manual, check with your local MySQL expert. If you don't have any luck there, read through this FAQ. If you still don't have an answer to your question go ahead and send mail to mysql@tcx.se.

I think I have found a bug. What information do you need to help me?

If you can use the mysqlbug script that you can find in the scripts directory in the distribution. Othervise remember to specify (if relevant):

  1. Which version of MySQL. You can find out which version you are running by typing mysqladmin version. If you know which distribution file file you used add that (for example mysql-3.20.0.tgz).
  2. The manufacturer and model of machine you are working on.
  3. The operating system. For most relevant operating systems you cant get this from uname -a.
  4. Sometimes the amount of memory (real and virtual) is also relevant.
  5. If this is a bug when compiling: Include the exact error messages and also a few lines around the offending code in the file from which you got the error.
  6. If this is a run time bug, please describe exactly how you got the error. If you can include a test program which shows the error you can a more exact answer.
  7. If you are a support customer please post to the specified mailing list for higher priority treatment.

When answers are sent to you individually and not to the mailing list, it is considered good etiquette to summarize the answers and mail them to the mailing list.

Guidelines for answering questions on the mailing list.

Try to make your answer broad enough that people other than the original poster may benefit from it. If you consider your answer to have broad interest, you may want to post it to the mailing list instead of replying directly to the individual who asked. In this case, please make sure that your answer is not a duplication of a previous answer.

Try to summarize the essential part of the question in your reply, but don't feel obliged to quote the whole question.

General Information

What is MySQL?

MySQL is a SQL (Structured Query Language) database server. MySQL was written by Michael (monty) Widenius. Se the CREDITS file in the distribution for more credits for MySQL and related things.

History of MySQL

Our first intension was to use mSQL to connect to our own fast low level (ISAM) tables. After some testing we came to the conclusion that mSQL wasn't fast or flexible enough. This resulted in a new SQL interface to our database but with almost the same API interface as mSQL. This API was choosed to encourage code sharing.

Where the name MySQL comes from is not perfectly clear. Our base directory and lots of librarys and tools has had the prefix my for well over 10 years. But Monty's daughter (some years younger) are also named My. So there the names comes from is not perfectly clear.

What is the current MySQL version?

You can always check http://www.tcx.se/ for the latest version of MySQL.

How do I get MySQL?

On the Internet try using a web browser to http://www.tcx.se/

Or ftp to ftp://ftp.sunet.se/pub/unix/databases/relational/mysql/. That isSunet's (Swedish University Network) FTP archive in Sweden.

Should I get MySQL in source form or binary?

If you want to read (and/or modify) the C and C++ code that makes up MySQL you should always get a source distribution. The code is always the ultimate manual. The source distribution also contains more tests and examples.

For most people who want to run MySQL on a platform that has binary releases, a binary version of MySQL is more convenient. But tcx's binary release is not compiled in the same way as the source release so some differences in where support files are located exist.

Which operating systems does MySQL support?

We use GNU autoconf so it will be possible to port to all modern systems with working Posix threads and a C++ compiler. The client code does require C++ but not threads. We use the software ourselves primarily on Solaris (currently 2.5.1) and some on Linux (currently 2.0.27).

A working Posix thread library is needed for the server. On Solaris 2.5 we use SUN PThreads (the native thread support in 2.4 and before is not good enough) and on Linux we use LinuxThreads by Xavier Leroy (Xavier.Leroy@inria.fr).

There is a patched version of Provenzano's Pthreads from MIT (see http://www.mit.edu:8001/people/proven/pthreads.html) in thedistribution. This can be used for some operating systems that doesn't have posix threads.

We have alose tried to use another user level thread package named FSU Pthreads (see http://www.informatik.hu-berlin.de/~mueller/pthreads.html).

This didn't work with MySQL because of problems with the implementations. See the thr_lock and thr_alarm programs in the mysys directory for some tests/examples of these problems. More information can be found in the `PORTING' file in the distribution.

Which languages does MySQL support.

mysqld can give error messages in the following languages: English (default), Germany and Swedish.

To start mysqld with a language use the --language (-L) switch:

mysqld --language swedish mysqld --language /usr/local/share/swedish

The language files are located (by default) in

`mysql_base_dir/share/LANGUAGE/'

How/when will you release updates?

We are going to use the following policy when updating MySQL:

Each minor patch made will increment the last number in the version string. When there is new features or minor incompatibilities with previous versions the second number in the version string will get incremented.

What is UNIREG ?

Unireg is our tty interface builder, but it uses a low level connection to our NISAM (with is used by MySQL) and because of this it's very quick. It has existed since 1979 (on Unix in C since ~1986).

It has the following components:

We update most our production databases with the UNIREG interface and serve web pages through MySQL (and in some extreme cases the UNIREG report generator).

Unireg takes about 3M of disk space and works on at least the following platforms: SUN OS 4.x, Solaris, Linux, HPUX, ICL Unix, DNIX, SCO and MSDOS.

Unireg is currently only available in Swedish and Finnish.

The price tag for UNIREG is 10,000 swedish kr (about 1500$ US), but this includes support. UNIREG is distributed as a binary. (But all the isam source can be found in MySQL). Usually we compile the binary for the customer at their site.

New development is concentrated to MySQL.

Licensing. When do I have to pay for MySQL?

Basic licensing issues:

For more information se the rest of this chapter and the file `PUBLIC' in the distribution.

How much does MySQL cost?

For normal use MySQL costs nothing. When you sell MySQL directly or as a part of another product you have to pay for it. See the file `PUBLIC' in the distribution.

The client access part of MySQL is in the public domain. The command line client inlcudes parts that is under the GNU Public Licence (readline).

The current price is $200 for one licence and $1000 for 10 licences if payed for at the same time.

If you have a low margin high volume product you can always talk to us about other terms.

How do I get support

A licence includes really basic support. This means that we are trying to answer any relevant question. If the answer is in the FAQ, we are going to redirect the answer to the FAQ. If you do not have a licence/support we will probably not answer at all.

If you discover what we consider a real bug, we are likely to fix it in any case. But if you pay for support we will notify you about the fix status instead of just fixing it in a later release.

More comprehensive support will be sold separately. One year of basic email support costs $200. One year of more extensive email/telnet support costs $2000.

How do I pay for a licence?

Well currently we can take SWIFT payments or cheques. We are working on payment by credit card but that will take a some time. Se the contact information.

We will try to make a ssl-web server in the future for ordering of MySQL things.

Payment should be made to:

          Postgirot Bank AB
          105 06 STOCKHOLM, SWEDEN

          T.C.X DATAKONSULT AB
          BOX 6434
          11382 STOCKHOLM

          SWIFT address: PGSI SESS
          Account number: 96 77 06 - 3

          Specify: license and/or support and your name and email address.

In europe and japan you can use EuroGiro (that should be cheaper) to the same account.

If you want to pay by cheque make it payable to "Detron HB". And mail it to the address below.

Detron HB
David Axmark
Kungsgatan 65 B
753 21 UPPSALA
SWEDEN

In a couple of weeks we hope to make all this much easier by allowing credit cards.

Who do I contact when I want support/a licence?

For commercial licensing or if you have any questions about any of the information in this document, please contact:

Detron HB
David Axmark
Kungsgatan 65 B
753 21 UPPSALA
SWEDEN
Voice Phone +46-18-10 22 80
Fax +46-8-729 69 05 (I prefer email if possible)
E-Mail: mysql-c@detron.se

What Copyright does MySQL use?

There are four different copyright's on the MySQL distribution.

  1. The MySQL specific source needed to make the mysqlclient library and programs in the `client' directory is in the public domain. Each file which is in the public domain has a header which clearly states so. This is everything in `client' directory and some parts of mysys, mystring and dbug libraries.
  2. Some small parts of the source (GNU getopt) are covered by the "GNU LIBRARY GENERAL PUBLIC LICENSE". See the `mysys/COPYING.LIB' file.
  3. Some parts of the source (GNU readline) are covered by the "GNU GENERAL PUBLIC LICENSE". See the `readline/COPYING' file.
  4. Some parts of the source (the regexp library) are covered by a Berkeley style copyright.
  5. The other source needed for the MySQL server is AGPL. See the file PUBLIC for more info.

Our philosophy behind this is:

When may I distribute MySQL commercially without a fee

This is a clarification of the information in the `PUBLIC' file.

MySQL may be *used* freely, including by commercial entities for evaluation or unsupported internal use. However, *distribution* for commercial purposes of MySQL, or anything containing or derived from MySQL in whole or in part, requires a written commercial license from TcX AB, the sole entity authorized by to grant such licenses.

You may not include MySQL "free" in a package containing anything for which a charge is being made exept as noted below.

The intent of the exception provided in the second clause is to allow commercial organizations operating an FTP server or a bulletin board to distribute MySQL freely from it, provided that:

  1. the organization complies with the other provisions of the FPL, which include among other things a requirement to distribute the full source code of MySQL and of any derived work, and to distribute the FPL itself along with MySQL;
  2. the only charge for downloading MySQL is a charge based on the distribution service and not one based on the content of the information being retrieved (i.e., the charge would be the same for retrieving a random collection of bits of the same size);
  3. the server or BBS is accessible to the general public, i.e., the phone number or IP address is not kept secret, and anyone may obtain access to the information (possibly by paying a subscription or access fee that is not dependent on or related to purchasing anything else).

If you want to distribute software in a commercial context that incorporates MySQL and you do *not* want to meet these conditions, you should contact TcX AB to find out about commercial licensing. Commercial licenses involve a payment, and include support and other benefits. These are the only ways you legally can distribute MySQL or anything containing MySQL: either by distributing MySQL under the requirements of the FPL, or by getting a commercial license from TcX AB.

I'm selling a product that can be configured to use MySQL

I'm selling a product that can be configured to use MySQL although my customer is responsible for obtaining/installing MySQL (or some other supported alternative). Does one of us owe you money if my customer choses to use MySQL?

If your product REQUIRED MySQL to work you would have to pay a licence. If MySQL just added some new features it should fall inside normal use. For example is using MySQL added logging to a database instead of a text file it should not require a licence. This would of course mean that the user has to fetch and install MySQL by himself. If the program is (almost) useless without MySQL you would have to get a MySQL licence to sell your product.

I am running a commercial web server using MySQL.

Do I have to get a licence for my copy?

No you are not selling MySQL itself. But is this case we would like you to purchase MySQL support. That is either your support of MySQL or our support of you (the later is more expensive since our time is limited).

Possible future changes in the licensing.

We may choose to distribute older versions of MySQL with the GPL in the future. However these versions will be identified as "GNU MySQL". Also all copyright notices in the relevant files will be changed to the GPL.

Features of MySQL

Main features of MySQL

What column (column) types are available with MySQL?

The following column types are supported:

TINYINT
A very small integer. Can be a (part of) a key. Signed range -128-127. Unsigned range 0-255. Takes 1 byte (8 bits).
SMALLINT
A small integer. Can be a (part of) a key. Signed range -32768-32767. Unsigned range 0-65535. Takes 2 bytes (16 bits).
MEDIUMINT
A medium integer. Can be a (part of) a key. Signed range -8388608-8388607. Unsigned range 0-16777215. Takes 3 bytes (24 bits).
INT
A normal integer. Can be a (part of) a key. Signed range -2147483648-2147483647. Unsigned range 0-4294967295. Takes 4 bytes (32 bits).
BIGINT
A large integer. Can be a (part of) a key. Signed range -9223372036854775808-9223372036854775807. Unsigned Range 0-18446744073709551615. Takes 8 bytes (64 bits).
FLOAT
A small floating point number. Can be a (part of) a key. Cannot be unsigned. Range -3.402823466E+38F - -1.175494351E-38, 0, -1.175494351E-38 - 3.402823466E+38F. Takes 4 bytes (32 bits).
DOUBLE
A normal floating point number. Can be a (part of) a key. Cannot be unsigned. Range -1.7976931348623157E+308 - -2.2250738585072014E-308, 0, 2.2250738585072014E-308 - 1.7976931348623157E+308. Takes 8 bytes (64 bits).
DECIMAL
A unpacked floating point number. Can be a (part of) a key. Cannot be unsigned. Currently the same range maximum range as a double. The number behaves as a CHAR column and takes length+decimals bytes.
TIMESTAMP
A automatic timestamp. Has a range of 1 Dec 1970 kl 0.00 to sometime in the year 2106 and a resolution of a second. Will be automaticly updated if not used in a statement that updates a row or if set to NULL. Can be a (part of) a key. Takes 4 bytes (32 bits). Note that if you have many timestamp fields in a row, then only the first timestamp field will be automaticly updated. Any timestamp field will be set to the current time if set to NULL.
DATE
A type to store date information. Uses the "YYYY-MM-DD" syntax, but may be updated with a number or a string. Understand at least the following syntaxes: 'YY-MM-DD', 'YYYY-MM-DD', 'YYMMDD', 'YYMM', 'YY'. Range 0000-00-00 to 9999-12-31. Takes 4 byte.
TIME
A type to store time information. Uses the "HH:MM:SS" syntax, but may be updated with a number or a string. Understand at least the following syntaxes: 'HH:MM:DD, 'HHMMDD', 'HHMM', 'HH'. Takes 3 bytes.
FIXED LENGTH STRING
A string that is always filled up with spaces to the specified length. Can be a (part of) a key. Range 1-255 characters. Takes the same amount of space in the table.
VARIABLE LENGTH STRING
A string that is stored with its length. Can be a (part of) a key. Maximum range 1-255 characters. Takes the (varying per row) length + 1 byte in the table.
TINYBLOB
A binary object that is stored with its length. Can NOT be a key. Max length 255 characters (8 bits length). Takes the (varying per row) length + 1 byte in the table.
BLOB
A binary object that is stored with its length. Can NOT be a key. Max length 16535 characters (16 bits length). Takes the (varying per row) length + 2 bytes in the table.
MEDIUMBLOB
A binary object that is stored with its length. Can NOT be a key. Max length 16777216 characters (24 bits length). Takes the (varying per row) length + 3 bytes in the table.
LONGBLOB
A binary object that is stored with its length. Can NOT be a key. Range 4294967295 characters (32 bits length). Takes the (varying per row) length + 4 bytes in the table. This column type

What is a BLOB?

A BLOB is a binary large object which can hold any amount of data :) There are 4 kinds of blobs See section What column (column) types are available with MySQL?. Normaly one can regard a BLOB as a VARCHAR without specified limit.

There are some constraints because of the message buffer used. The default size of the buffer is 64K for the server and 512K for the clients. To change the buffer length for the server, use mysqld -O max_allowed_packet=max_blob_length. This allows the message buffer to grow up to this limit when needed.

myODBC defines BLOB:s as LONGVARCHAR.

Restrictions for blobs:

  1. BLOB columns can't be keys.
  2. One can't group or sort on BLOB. One can group on a expression involving a blob though: SELECT id,SUBSTR(blob,1,100) GROUP BY 2
  3. I blob is regarded as 'binary data'. This means that there is no end space truncation for BLOB columns.

What extension has MySQL to ANSI SQL?

The following are useful extensions that MySQL that you probably won't find in other SQL:s. Be warned that if you use this your code won't be portable to other SQL servers.

Compiling and installing MySQL

Compiling MySQL

Se the file `INSTALL-SOURCE' in the MySQL distribution.

Problems starting MySQL

Check the log file to see if mysqld started up correctly

cd <localstatedir default /usr/local/var>
tail <your host name>.log

To verify that MySQL is working run the following tests:

> cd /usr/local/bin
> ./mysqlshow
+-----------+
| Databases |
+-----------+
| mysql     |
+-----------+

> ./mysqlshow mysql
Database: mysql
+--------+
| Tables |
+--------+
| db     |
| host   |
| user   |
+--------+

> ./mysql -e "select host,db,user from db" mysql
+------+--------+------+
| host | db     | user |
+------+--------+------+
| %    | test   |      |
| %    | test_% |      |
+------+--------+------+

You can also run the test in the test subdirectory. To run `auto_increment.tst':

./mysql -vf test < ./tests/auto_increment.tst

Expected results are shown in the file `./tests/auto_increment.res'

Automatic start/stop of MySQL

To start or stop MySQL you may use the following commands:

scripts/mysql.server stop
scripts/mysql.server start

You will probably want to add these start and stop commands to the appropriate places in your /etc/rc* files when you start using MySQL for production applications.

Compatibility

What functionality is missing in MySQL.

The following functionality is missing in the current version of MySQL. For the priority of new extensions you should consult: http://www.tcx.se/TODO

How about msql tools like msql-tcl, msqljava?

According to my experience it would would just take a few hours to convert a tool using the mSQL C API to the MySQL C API.

The procedure:

  1. Run the shell script msql2mysql on the source. This needs the binary program replace, which is distributed with MySQL.
  2. Compile
  3. Fix all compiler errors:

Differences between the MySQL and mSQL C API's.

How different from mSQL are the MySQL client/server communications protocols?

Enough different that it's impossible (at least not easy) to support both.

The biggest differences between MySQL and mSQL:

I don't think it makes sense to give a full spec, as we have plans to optimize this in the near future.

What are the differences in the SQL syntax between MySQL & mSQL 2.0?

Problems with AND and OR priority

Remember that AND has higher priority in boolean algebra than OR. It's like 1+2*3 is = 1+ (2*3) = 7.

Always when you are in doubt:

  1. Remove all distinct keywords.
  2. Write all fields from all tables.

This will make it easier to see what goes wrong. Distinct may also be a lot slower than a normal select.

What standards do MySQL follow

Entry level SQL92. ODBC level 0-2.

What functions exist only for compability?

Optimizations

How does MySQL use memory ?

You can get the currently used buffer sizes with:

> ./mysqld --help

This should result in a all mysqld options and a list of configurable variables like the following this. See section How can I change the buffer sizes of mysqld ?.

Possibly variables to option --set-variable (-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

How should I arrange my table to be as fast/small as possible.

To check how you are doing, run isamchk -evi on the .ISM file.

What factors MySQL insert statement speeds.

The time to insert a record consists of:

Where (number) is proportional time. Here is not calculated the initial overhead to open tables (which is done 1 time for every simultaneous running query).

The size of the table slows down the insert of keys with N log N (B-trees).

What kind of optimization is done on the WHERE clause?

(Incomplete, MySQL does a lot of optimizations)

How can I change the buffer sizes of mysqld ?

With the mysqld -O variable=size command. Example run:

> mysqld --help (or > mysqld -?)

>mysqld --help
/my/monty/sql/mysqld  Ver 3.20.5-beta for SOLARIS 2.5 (SPARCstation)
TCX Datakonsult AB, by Monty. This is FPL, not free software
This software comes with NO WARRANTY: see the file PUBLIC for details.

Starts the mysql server

Usage: /my/monty/sql/mysqld [OPTIONS]

  -b, --basedir=path	path to installation directory
  -h, --datadir=path	path to the database root
  -#, --debug=...       output debug log. Often this is 'd:t:o,filename`
  -T, --debug-info	print some debug info at exit
  -?, --help		display this help and exit
  -L, --language=...	client error messages in given language
  -l, --log[=filename]	log connections and queries to file
      --log-isam[=filename]
			log all isam changes to file
  -O, --set-variable var=option
			give a variable an value. --help lists variables
  --skip-new-routines	don't use new possible wrong routines.
  --skip-grant-tables	start without grant tables. This gives anyone FULL
			ACCESS to all tables!
  --skip-locking	don't use system locking. To use isamchk one has
			to shut down the server.
  --skip-unsafe-select  skipp unsafe select optimizations.
  -V, --version		output version information and exit

Current base_dir: /my/monty
Current data_dir: data/
Current language: english/

Possibly variables to option --set-variable (-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

> mysqld -O keybuffer=512k -O sortbuffer=100k -O recordbuffer=100k

What options to use to get mysqld to run at full speed?

mysqld -O keybuffer=16m -O sortbuffer=1m -O recordbuffer=512k --skip-locking

--skip-locking disables file locking between SQL requests. If this is used then the following can happen:

The --skip-locking is default when compiling with MIT threads.

What is the different row formats? Or when to use VARCHAR/CHAR?

Actually using no VARCHAR or BLOB types results in a fixed row size. Otherwise CHAR and VARCHAR are the same. Se the below for a more exact definition.

You can check the format used for a table with isamchk -d.

MySQL has three different table formats:

  1. Fixed length tables;
  2. Dynamic tables
  3. Compressed tables (this is only with UNIREG/pack_isam)

MySQL C API

After mysql_query() returns success, mysql_store_result() sometimes returns NULL.

It means one of the following:

  1. Malloc failure.
  2. The data couldn't be read (Error on connection).
  3. The statement was a statement which doesn't ever return data (INSERT or UPDATE or DELETE).

You can always check if the statement should given a result by checking that mysql_num_columns(MYSQL *) isn't 0. If this is 0 the last query was a statement that did not return values INSERT, DELETE....

You have got an error if mysql_error(MYSQL *) isn't empty!

What results can I get from a query?

mysql_affected_rows(MYSQL *) returns the number of affected rows in the last query when doing an INSERT, UPDATE or DELETE.

mysql_insert_id(MYSQL *) returns the given ID of the last query when inserting a row into a table with a AUTO_INCREMENT key.

Some querries, LOAD DATA INFILE... and INSERT INTO ... SELECT ..., return additional info. This result is returned in mysql_info(MYSQL *). mysql_info() returns a null pointer if there is no additional information.

How can I get the unique ID for the last row?

If you insert a record which have a AUTO_INCREMENT key then you can get the given id with mysql_insert_id(MYSQL *).

You can check if an auto_increment key is used by the following code. This also checks if the query was a insert with a auto_increment key.

if (mysql_error(MYSQL)[0] == 0 &&
    mysql_num_fields(MYSQL_RESULT) == 0 &&
    mysql_insert_id(MYSQL) != 0)
  used_id = mysql_insert_id(MYSQL);

What is the difference between mysql_use_result() and mysql_store_result() modes?

This says to MySQL to use the result directly from the server (no local store like in mSQL), which is somewhat faster and doesn't use memory to buffer the hole result.

This shouldn't be used if there is much processing for each row at the client side, or if the output is sent to a screen on which the user may do a ^S (stop scroll), because this would tie up the server. One can't use mysql_data_seek when using mysql_use_result.

MySQL Syntax

Literals. How do you write strings and numbers?

STRINGS

A string may have ' or " around it.

\ is a escape character. The following escape characters are recognized:

\0
A ascii 0 character.
\n
A newline character.
\t
A tab character.
\r
A return character.
\b
A backspace character.
\'
A ' character.
\"
A " character.
\\
A \ character.
\%
A % character. This is used in wild-card strings to search after %.
\_
A _ character. This is used in wild-card strings to search after _.
A ' inside a string started with ' may be written as ".
A " inside a string started with " may be written as "".
MySQL> select 'hello', "'hello'", '""hello""', "'h"e"l"l"o"', "hel""lo";
1 rows in set (0.00 sec)

+-------+---------+-----------+-------------+--------+
| hello | 'hello' | ""hello"" | 'h'e'l'l'o' | hel"lo |
+-------+---------+-----------+-------------+--------+
| hello | 'hello' | ""hello"" | 'h'e'l'l'o' | hel"lo |
+-------+---------+-----------+-------------+--------+

mysql> select 'hello', "hello", '""hello""', "'ello", 'e"l"lo', '\'hello';
1 rows in set (0.00 sec)

+-------+-------+-----------+-------+--------+--------+
| hello | hello | ""hello"" | 'ello | e'l'lo | 'hello |
+-------+-------+-----------+-------+--------+--------+
| hello | hello | ""hello"" | 'ello | e'l'lo | 'hello |
+-------+-------+-----------+-------+--------+--------+

mysql> select "This\nIs\nFour\nlines";
1 rows in set (0.00 sec)

+--------------------+
| This
Is
Four
lines |
+--------------------+
| This
Is
Four
lines |
+--------------------+

If you want to insert binary data into a blob the following characters must be represented by escape sequences:

\0
Ascii 0. Should be replaced with "\0" (A backslash and a 0 digit).
\
Ascii 92, backslash
'
Ascii 39, Single quote
"
Ascii 33, Double quote

NUMBERS

Integers are just a sequence of digits. Floats use . as a decimal separator.

Examples of valid numbers are: 1221, 294.42, -32032.6809e+10.

NULL

When using the text file export formats, NULL may be represented by \N. See section LOAD DATA INFILE syntax

CREATE TABLE syntax.

CREATE TABLE table_name ( create_definition,... )

create_definition:
	column_name type NOT NULL [DEFAULT default_value] [ PRIMARY KEY ]
  or	column_name type [NULL] [ PRIMARY KEY ]
  or	PRIMARY KEY ( key_column_name,... )
  or	KEY [key_name] KEY( key_column_name,...)
  or	INDEX [key_name] ( key_column_name,...)
  or	UNIQUE [key_name] ( key_column_name,...)
  or    FOREIGN KEY key_name ( key_column_name,...) REFERENCES table_name [ ON DELETE { RESTRICT | CASCADE | SET NULL }]

key_column_namne:
	column_namn [ (length) ]

To have a DEFAULT the column must be declared as NOT NULL.

TINYINT [(length)] [UNSIGNED] [ZEROFILL]
SMALLINT [(length)] [UNSIGNED] [ZEROFILL]
MEDIUMINT [(length)] [UNSIGNED] [ZEROFILL]
INT [(length)] [UNSIGNED] [ZEROFILL]
INTEGER [(length)] [UNSIGNED] [ZEROFILL]
BIGINT [(length)] [UNSIGNED] [ZEROFILL]
A packed integer of length 1,2,3,4 or 8 bytes. See section What column (column) types are available with MySQL?. Unsigned means that only number from 0 and up are allowed. ZEROFILL means that the column will be padded with zeroes to length number of characters.
FLOAT [(precision)]
Floating point number. FLOAT(4) and FLOAT is single precision. FLOAT(8) is double precision.
FLOAT [(length,decimals)].
A single precision number with a max length and a fixed number of decimals.
DOUBLE [(length,decimals)].
A double precision number with a max length and a fixed number of decimals. Length and decimals are for formating and calculation of max column width.
REAL [(length,decimals)].
This is the same as DOUBLE.
DOUBLE PRECISION [(length,decimals)].
This is the same as DOUBLE.
DECIMAL [(length,decimals)]
Unpacked fixed size integer/floating point number. If the number of decimals is zero the number is handled like an integer.
NUMERIC [(length,decimals)]
Synonym for DECIMAL.
CHAR(NUM)
Fixed with string (1 <= NUM <= 255).
VARCHAR(NUM)
Variable length string (1 <= NUM <= 255).
TINYBLOB
BLOB
MEDIUMBLOB
LONGBLOB
Binary Large OBject with a length integer of 1,2,3 or 4 bytes.
DATE
A date type. Format "YYYY-MM-DD". Takes 4 bytes.
TIME
A time type. Format "HH:MM:SS". Takes 3 bytes.
DATETIME
A Date and time type. Format "YYYY-MM-DD HH:MM:SS". Takes 8 bytes. Range '0000-01-01 00:00:00' - '9999-12-31 23:59:59'
TIMESTAMP[(LENGTH)]
Changes automatically on insert/update (YYYYMMDDHHMMSS). The length determines how the output is formatted. (YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYMMDDHHMM, YYYYMMDD, YYMMDD, YYMM, YY) Range '1970-01-01 00:00:00' - About '2050-12-31 23:59:59'. Takes 4 bytes.

ALTER TABLE syntax

ALTER [IGNORE] TABLE table_name alter_specification [, alter_specification ...]

alter_specification:
	ADD [COLUMN] create_definition
or	CHANGE [COLUMN] old_column_name create_definition
or	ALTER [COLUMN] column_name { SET default | DROP DEFAULT }
or	DROP [COLUMN] column_name
or	DROP PRIMARY KEY
	DROP INDEX key_name

DROP TABLE syntax.

DROP TABLE table_name [, table_name....]

Removes one or more tables. All the data and the definition is removed so take it easy with this command!

DELETE syntax.

DELETE FROM table_name WHERE where_definition

Returns records affected.

If one does a delete without a where clause then the table is truncated (This is much faster). In this case it returns records affected as zero. This will work even if the datafiles doesn't exists, because it uses only information from the table definition file, table_name.frm.

where_definition:
	where_expr
or	where_expr [ AND | OR ] where_expr

where_expr:
	column_name [> | >= | = | <> | <= | < ] column_name_or_constant
or	column_name LIKE column_name_or_constant
or	column_name IS NULL
or	column_name IS NOT NULL
or	( where_definition )

SELECT syntax

SELECT [DISTINCT | ALL] select_expression,... [ FROM tables... [WHERE where_definition ] [GROUP BY column,...] [ ORDER BY column [ASC | DESC] ,..] HAVING full_where_definition [LIMIT [offset,] rows] [PROCEDURE procedure_name]] [INTO OUTFILE 'file_name' ...]

+
-
*
/
Normal math operations. A divide by zero results in a NULL.
|
&
Bit functions (These has a range of maximum 48 bits because MySQL uses double arithmetic).
-
Sign
(,)
Parenthesis
NOT
!
NOT returns TRUE (1) or FALSE (0).
OR
AND
Normal logical operators. Returns TRUE (1) or FALSE (0).
=
<>
<=
<
>=
>
comparison operators. Returns TRUE (1) or FALSE (0)
expr LIKE expr
SQL simple regular expression comparison. Returns TRUE (1) or FALSE (0).
expr NOT LIKE expr
Returns TRUE (1) or FALSE (0).
expr REGEXP expr
Check string against extended regular expr.
expr NOT REGEXP expr
Check string against extended regular expr.
ABS()
FLOOR()
CEILING()
ROUND()
EXP()
LOG()
LOG10()
POW()
SQRT()
Math functions. These returns NULL in the case of a error.
RAND([integer_expr])
Returns a random float, 0 <= x <= 1.0, using integer_expr as the option seed value.
SIGN()
Sign of argument. Returns -1, 0 or 1.
BIT_COUNT()
Number of set bits in argument.
MOD()
%
Module (like in C)
MIN()
MAX()
Min or max value of argument. Must have 2 or more arguments, else this is group functions
CONCAT()
Concatenate strings. May have more than 2 arguments.
DATABASE()
Returns current database name.
LENGTH()
Length of string
STRCMP()
Returns 0 if the strings are the same. Otherwise return -1 if first argument is smaller according to sort-order, else return 1.
LOCATE(A,B)
Return position of B substring in A. The first position is 1. Returns 9 if b is not in A.
LOCATE(A,B,C)
Return position of B substring in A starting at C.
LEFT(str,length)
Get length characters from beginning of string.
RIGHT(str,right)
Get length characters from end of string.
LTRIM(str)
Remove space characters from the beginning of str.
RTRIM(str)
Remove space characters from the end of str.
SOUNDEX(str)
Get a soundex string from str. Two strings that sounds 'about the same' should have identical soundex strings. A 'standard' soundex string is 4 long, but this function returns a arbitrary long string. One can use SUBSTRING on the result to get a 'standard' soundex string. All non alpha characters are ignored in the given string. All characters outside the A-Z range are treated as vocals.
SUBSTRING(A,B,C)
Get substring from A starting at B with C chars.
REPLACE(A,B,C)
Replace all occurrences of B in A with C.
INSERT(org,start,length,new)
Replace substring org[start...length] with new. First position in string=1.
LCASE(A)
Change A to lower case.
UCASE(A)
Change A to upper case.
PASSWORD()
Calculate a password string. This must be used to store a password in the 'user' grant table.
INTERVAL(A,a,b,c,d)
Return 1 if A == a, 2 if A == b. If no match return 0. A,a,b,c,d... are strings.
ELT(N,a,b,c,d,...)
Return a if N == 1, b if N == 2. a,b,c,d are strings.
FIELD(A,a,b,c,d,...)
Return index of A in the a,b,c... list. The complement of ELT().
BETWEEN(A,B,C)
Is the same as (A >= B AND A <= C). B and C may be numbers or strings.
PERIOD_ADD(P:N)
Add N months to period P (of type YYMM).
PERIOD_DIFF(A,B)
Returns months between periods A,B.
TO_DAYS(DATE)
Change a DATE to a daynumber. DATE may be a date string, a datetime string, a timestamp([6 | 8 | 14]) or a number of format YYMMDD or YYYYMMDD.
FROM_DAYS()
Change a daynumber to a DATE.
WEEKDAY(DATE)
Get weekday for date (0 = Monday, 1 = Tuesday). DATE may be a date string, a datetime string, a timestamp([6 | 8 | 14]) or a number of format YYMMDD or YYYYMMDD.
CURDATE()
Return date of today. In form YYYYMMDD or "YYYY-MM-DD". depending of if CURDATE() is used in a number or string context.
NOW()
Return current time. In format YYYYMMDDHHMMSS or "YYYY-MM-DD HH:MM:SS" depending of if NOW() is used in a number or string context.
UNIX_TIMESTAMP([DATE])
If called without any arguments returns a unix timestamp (seconds in GMT since 1970.01.01 00:00:00). Normally is called with a timestamp column as argument in which case it returns the timestamp. DATE may also be a date string, a datetime string, or a number of format YYMMDD or YYYMMDD in local time.
ISNULL(A)
Returns 1 if A is NULL else 0. Same as '( A == NULL ').
IFNULL(A,B)
If A is not null return A, else B.
IF(A,B,C)
If A is true (!= 0 and != NULL) then return B, else return C.
USER()
Returns current user name.
FORMAT(nr,NUM)
Format number to a format like '#,###,###.##' with NUM decimals.

Functions for GROUP BY clause:

count(expr)
Number of rows.
avg(expr)
Average value of expr.
min(expr)
max(expr)
Minimum/Maximum value of expr. sum(expr) Sum of expr. std(expr) Standard derivation of expression. This is a extension to ANSI SQL.

min() and max() may take string arguments. count(*) is optimized to return directly if no other column is used.

These can't be used in expression, even if argument may be an expression. Eg: SUM(value/10) is allowed but SUM(value)/10 is not (yet!).

MySQL has extended the use of GROUP BY. You can use columns or calculations in the SELECT expressions with doesn't appear in the GROUP BY part. This stands for 'any possible value for this group'. By using this one can get much higher performance by avoiding sorting and grouping on unnecessary items. For example, in the following query one doesn't need to sort on b.name:

SELECT a.id,b.name,COUNT(*) from a,b WHERE a.id=b.id GROUP BY a.id

Strings are automatically converted to numbers and numbers to strings when needed (ala perl). If in a compare operation ((=, <>, <= ,<, >=, >)) either if the arguments are a numerical the arguments are compared as numbers, else the arguments are compared as strings. All string compares are done case-independent by ISO8859-1.

INSERT syntax

	INSERT INTO table [ (column_name,...) ] VALUES (expression,...)
or	INSERT INTO table [ (column_name,...) ] SELECT ....

An expression make use any previous column in column_name list (or table if no column name list is given).

The following holds for a multi-row INSERT statement:

LOAD DATA INFILE syntax

LOAD DATA INFILE 'table_interval.text' [REPLACE | IGNORE] INTO TABLE table_interval [FIELDS [TERMINATED BY ',' [OPTIONALLY] ENCLOSED BY '"' ESCAPED BY '\\' ]] [LINES TERMINATED BY '\n'] [(field list)]

This is used to read rows from a textfile.

To write data to a textfile, use the SELECT ... INTO OUTFILE 'interval.tab' fields terminated by ',' enclosed by '"' escaped by '\\' lines terminated by '\n' syntax.

Normally you don't have to specify any of the textfile type options. The default is a compact textfile with columns sepearated with tab characters and all rows ends with a newline. Tabs, newlines and \ inside fields are prefixed with a \. NULL's are read and written as \N.

FIELDS TERMINATED BY has default value of \t. FIELDS [OPTIONALLY] ENCLOSED BY has default value of " FIELDS ESCAPED BY has default value of '\\'. LINES TERMINATED BY has default value of '\n'.

FIELDS TERMINATED BY and LINES TERMINATED BY may be more than 1 character.

If LINES TERMINATED BY is a empty string and FIELDS TERMINATED BY is not empty then lines are also terminated by FIELDS TERMINATED BY.

If FIELDS TERMINATED BY and FIELDS ENCLOSED BY both are empty strings (") then this gives a fixed row size. With a fixed row size NULL values are outputed as a blank string.

If you specify OPTIONALLY in ENCLOSED BY, then only strings are enclosed in ENCLOSED BY by the SELECT ... INTO statement.

When using LOAD duplicated ENCLOSED BY are removed inside an ENCLOSED BY. For example 'He"llo' is read as 'He'llo'.

If ESCAPED BY is not empty then the following characters will be prefixed with the escape character: ESCAPED BY, ASCII 0, and the first character in any of fields terminated by, FIELDS ENCLOSED BY and LINES TERMINATED BY.

If FIELDS ENCLOSED BY is not empty then NULL is read as a NULL value. If FIELDS ESCAPED is not empty then \N is also read as a NULL value.

If REPLACE is used the new row will replace all rows which has a same unique key. If IGNORE is used the row will be skipped if there already exist a record with a identical unique key. If no of the above options is used an error will be issued. The rest of the textfile will be ignored if one gets a duplicate key error.

Some possible cases that's not supported by LOAD DATA:

All rows are read into table. If a row has too few fields the rest fields are set to default values.

For security reasons the textfile must either reside in the database directory or be readable by all.

For more info about the escaped syntax See section Literals. How do you write strings and numbers?.

When the LOAD DATA query is done one can get the following info string with the C API function mysql_info().

@result{Records: 1 Deleted: 0 Skipped: 0 Warnings: 0}

Warnings is incremented for each column which can't be stored without loss of precision, for each column which didn't get a value from the read text line (happens if the line is too short) and for each line which has more data than can fit into the given columns.

Example that load all fields;

LOAD DATA INFILE 'persondata.text' INTO TABLE persondata;

UPDATE syntax

UPDATE table SET column=expression,... WHERE where_definition

All updates are done from left to right. IF one accesses a column in the expression it uses the current value (a given value or the default value).

SHOW syntax. Get information about names of columns.

	SHOW DATABASES [LIKE wild]
or 	SHOW TABLES [FROM database] [LIKE wild]
or	SHOW COLUMNS FROM table [FROM database] [LIKE wild]

Gives information about databases, tables or columns. The wild is a LIKE string. FIELDS may be used as an alias for COLUMNS.

DESCRIBE syntax. Get information about names of columns.

(DESCRIBE | DESC) table [column]

Gives information about columns. This command is for Oracle compability. See section SHOW syntax. Get information about names of columns. Column may be a column name or a string. Strings may contain wildcards.

SET OPTION syntax.

	SET OPTION SQL_VALUE_OPTON=value, ...

The used options remain in effect for the hole current session.

The different options are:

SQL_SELECT_LIMIT=value
The maximun number of records to return in any select. If a select has a limit clause it overrides this statement.

GRANT syntax. (Compability function).

  GRANT (ALL PRIVILEGES | (SELECT, INSERT, UPDATE, DELETE,
        REFERENSES (column list), USAGE))
        ON table TO user,... [WITH GRANT OPTION]

This command doesn't do anything. It's only in mysql for compability reasons. Privileges in MySQL is handled with the mysql grant tables. See section How does the privilege system work?

CREATE INDEX syntax (Compability function).

CREATE [UNIQUE] INDEX index_name ON table_name ( column_name,... )

This function doesn't do anything. It's only in mysql for compability reasons. You can create new index with ALTER TABLE. See section ALTER TABLE syntax

DROP INDEX syntax (Compability function).

DROP INDEX index_name

This always succeeds. You can drop an index with ALTER TABLE. See section ALTER TABLE syntax

Is MySQL picky about reserved words?

It seems that I can't create a table with column names timestamp or group.

Functions doesn't clash with table or column names. (For example ABS is an allowed column name). The only restriction is that space is not allowed between a function name and the '(' when using functions.

The following are reserved words in MySQL. Most of them (for example) group, are forbidden by ANSI SQL92 as column and/or and a few are because MySQL needs them and (currently) is using a Yacc parser:

add, all, alter, and, as, asc, auto_increment, between, bigint, blob,by, cascade, char, character, change, column, columns create, data, databases, date, datetime, dec, decimal, default, delete, desc, describe, distinct, double, drop, fields, float, float4, float8, foreign, from, grant, group,having, ignore, in, index, infile, insert, int, int1, int2, int3, int4, int8, integer, interval, into, is, key, keys, like, lines, limit, load, longblob, mediumblob, mediumint, middleint, not, null, numeric, on, option, or, order, precision, primary, procedure, privileges, real, references, regexp, replace, restrict, rlike, select, set, show, smallint, sql_big_tables, sql_big_selects, sql_select_limit,straight_join, table, tables, terminated, time, timestamp, tinyblob, tinyint, unique, unsigned, update, usage, values, varchar, varying, where, zerofill.

MySQL Use

What does the executables do?

mysql
A SQL shell (with gnu readline). Supports interactive use or as a non interactive query tool. When used interactively gives result in a ascii-table format, when using as a filter gives tab-separated output.
mysqladmin
Administration utility. Create/Drop of databases. reload (read new users and flush tables to disk). Version and process info.
mysqld
The SQL deamon. This should always be running.
mysqldump
Dump a MySQL database. Freeware by Igor Romanenko.
mysqlshow
Show information about database, tables and fields.
safe_mysqld
Start the mysqld demon with some safety features. Restarts on error and has logging of runtime info to a logfile.
mysqlaccess
Script to check the priviliges for a host, user and database combination.
mysqlbug
This script should always be used when filing a bug report to the mysql list.
mysql_install_db
Creates the mysql grant tables with default privileges. This is usually only executed when installing the first MySQL release on a new system.
isamchk
Check, optimize and repair MySQL tables.
msql2mysql
A shell script to convert a mSQL program to MySQL. Doesn't handle all cases but gives a good start when converting.
replace
Binary used for msql2mysql. Utility program to change strings inplace in files or on stdin. Uses a finite state machine to match longer strings first. Can be used to swap strings, for example 'replace a b b a -- files' swaps 'a' and 'b' in the given files.
make_binary_release
Makes a binary release of a compiled MySQL. This could be sent by ftp to www.tcx.se/pub/mysql/Incoming for the convenience of other MySQL users.

Limitations of BLOB's

If you want to group or sort on a blob, make the BLOB into a fixed length object with the SUBSTRING or similar functions.

How do you check/repair/reconstruct an MySQL table?

If MySQL crashed (f ex if the computer is turned off) when all data is not written to disk the tables may be crashed. To check a table use

isamchk table_name
This finds 99.99 % of all errors. What is can't find is when only the data file has been corrupted.
isamchk -e table_name
This goes through all data and does a compleat check.
isamchk -ei table_name
As the above but with some statistics.

Always backup a table before trying to repair it.

To repair a table(REMEMBER TO BACKUP A TABLE BEFORE TRYING TO REPAIR IT!):

isamchk -r table_name
Does a fast rebuild of the index and data files. This needs disk space for about two tables.
isamchk -rq table_name
Updates only the index file. Quicker but can't fix errors in the data file.

How to get a description of a table.

To get a description/statistics from a table us the forms below. Sometimes we will explain some of the information in more detail.

isamchk -d table_name
A short form.
ISAM file:     company.ISM
Data records:           1403698  Deleted blocks:              0
Recordlength:               226
Record format: Fixed length

table description:
Key Start Len Index   Type
1   2     8   unique  double
2   15    10  multip. text packed stripped
3   219   8   multip. double
4   63    10  multip. text packed stripped
5   167   2   multip. unsigned short
6   177   4   multip. unsigned long
7   155   4   multip. text
8   138   4   multip. unsigned long
9   177   4   multip. unsigned long
    193   1           text
For explanations se below.
isamchk -d -v table_name
A little more verbose.
ISAM file:     company.ISM
Isam-version:  2
Creation time: 1996-08-28 11:44:22
Recover time:  1997-01-12 18:35:29
Data records:           1403698  Deleted blocks:              0
Datafile: Parts:        1403698  Deleted data:                0
Datafilepointer (bytes):      3  Keyfile pointer (bytes):     3
Max datafile length: 3791650815  Max keyfile length: 4294967294
Recordlength:               226
Record format: Fixed length

table description:
Key Start Len Index   Type                       Root  Blocksize    Rec/key
1   2     8   unique  double                 15845376       1024          1
2   15    10  multip. text packed stripped   25062400       1024          2
3   219   8   multip. double                 40907776       1024         73
4   63    10  multip. text packed stripped   48097280       1024          5
5   167   2   multip. unsigned short         55200768       1024       4840
6   177   4   multip. unsigned long          65145856       1024       1346
7   155   4   multip. text                   75090944       1024       4995
8   138   4   multip. unsigned long          85036032       1024         87
9   177   4   multip. unsigned long          96481280       1024        178
    193   1           text
ISAM file
Name of isam file.
Isam-version
Version of isam format. Currently always 2.
Creation time
When was the data file created.
Recover time
When was the index/data file last reconstructed.
Data records
How many records/rows.
Deleted blocks
How many deleted blocks do still have reserved space. See section How do you check/repair/reconstruct an MySQL table?.
Datafile: Parts
For dynamic record format this shows how many data blocks there are. For a just optimized table without splits this is the same as Data records.
Deleted data
How many bytes of non reclaimed deleted data.
Datafilepointer
How many bytes is the datafile pointer. This is usually 2, 3 or 4 bytes. Most tables manage with 2 bytes but this cannot be controlled from MySQL yet. For fixed tables this is a record address. For dynamic tables this is a byte address.
Keyfile pointer
How many bytes is the datafile pointer. This is usually 1, 2 or 3 bytes. Most tables manage with 2 bytes but this is calculated automatically by MySQL. This is always a block address.
Max datafile length
For this table how long (in bytes) can the data file (.ISD) get.
Max keyfile length
For this table how long (in bytes) can the key file (.ISM) get.
Recordlength
How much space does each record/row take.
Record format
Which format does each record/row have. This example uses Fixed length.
table description
A list of all keys in the table. For each key some low level information is presented.
Key
This keys number.
Start
Where in the record/row does this index-part start.
Len
How long is this index-part. For packed numbers this should always be the full length of the field. For string it may be shorter than the full length.
Index
unique or multip.. If one value can exist multiple times in this index.
Type
What data-type does this index part have. This is a C data-type with a optional packed or stripped.
Root
Address of the root index block.
Blocksize
The size of each index block. This is by default 1024 but may be changed compile time.
Rec/key
This is a statistical value used by the optimizer. It tell how many records there are per value for this key. A unique key always has a value of 1. This may be updated after a table is loaded (or greatly changed) with isamchk -a. If this is not updated at all a default value of 30 is given.
The 9th key is a multiple part key with two parts.
isamchk -eis table_name
Show only the most important information from table. Slow since it must read the whole table.
Checking ISAM file: company.ISM
Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
Total:    Keyblocks used:  98%  Packed:   17%

Records:          1403698    M.recordlength:     226   Packed:             0%
Recordspace used:     100%   Empty space:          0%  Blocks/Record:   1.00
Recordblocks:     1403698    Deleteblocks:         0
Recorddata:     317235748    Deleted data:         0
Lost space:             0    Linkdata:             0

User time 1626.51, System time 232.36
Maximum resident set size 0, Integral resident set size 0
Non physical pagefaults 0, Physical pagefaults 627, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary contexts switches 639, Involuntary contexts switches 28966
Keyblocks used
How many percent of the keyblocks are used. Since this table has just been reorganized with isamchk the values are very high (Very near theoretical maximum).
Packed
MySQL tries to pack keys with a common suffix. This only can be used for CHAR/VARCHAR/DECIMAL keys. For long string like names this can reduce the spaced used significantly. In the above example the 4 key is 10 characters long and gets a 60% reduction in space.
Max levels
How deep is the btree for this key. Big tables with long keys get high values.
Records
How many rows does the table have.
M.recordlength
Average recordlength. For fixed tables this is the recordlength.
Packed
MySQL strips spaces from the end of strings. How many percent did we save by doing this.
Recordspace used
How many percent of the datafile is used.
Empty space
How many percent of the datafile is unused.
Blocks/Record
How many blocks are there per record. This is always 1 for fixed format tables. This value should stay as close to 1.0 as possible. If it gets to great you can reorganize the table with isamchk. Se See section How do you check/repair/reconstruct an MySQL table?.
Recordblocks
How many blocks is used. For fixed format this is the same as the number of records.
Deleteblocks
How many block are deleted.
Recorddata
How many bytes of actual user data there are in the datafile.
Deleted data
How many bytes of deleted data there are in the datafile.
Lost space
If a record is updated to a shorter length some space is lost. This is the sum of all such.
Linkdata
When the dynamic format is used blocks are linked with pointers (length 4-7 bytes). This is the sum of all such pointers.
isamchk -eiv table_name
Same as above but tells you what it is doing.
Checking ISAM file: company.ISM
Data records: 1403698   Deleted blocks:       0
- check file-size
- check delete-chain
index  1:
index  2:
index  3:
index  4:
index  5:
index  6:
index  7:
index  8:
index  9:
No recordlinks
- check index reference
- check data record references index: 1
Key:  1:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
- check data record references index: 2
Key:  2:  Keyblocks used:  98%  Packed:   50%  Max levels:  4
- check data record references index: 3
Key:  3:  Keyblocks used:  97%  Packed:    0%  Max levels:  4
- check data record references index: 4
Key:  4:  Keyblocks used:  99%  Packed:   60%  Max levels:  3
- check data record references index: 5
Key:  5:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 6
Key:  6:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 7
Key:  7:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 8
Key:  8:  Keyblocks used:  99%  Packed:    0%  Max levels:  3
- check data record references index: 9
Key:  9:  Keyblocks used:  98%  Packed:    0%  Max levels:  4
Total:    Keyblocks used:   9%  Packed:   17%

- check records and index references
[LOTS OF ROW NUMBERS DELETED]

Records:          1403698    M.recordlength:     226   Packed:             0%
Recordspace used:     100%   Empty space:          0%  Blocks/Record:   1.00
Recordblocks:     1403698    Deleteblocks:         0
Recorddata:     317235748    Deleted data:         0
Lost space:             0    Linkdata:             0

User time 1639.63, System time 251.61
Maximum resident set size 0, Integral resident set size 0
Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0
Blocks in 4 out 0, Messages in 0 out 0, Signals 0
Voluntary contexts switches 10604, Involuntary contexts switches 122798

Here is the data file sizes of the table used above.

-rw-rw-r--   1 monty    tcx     317235748 Jan 12 17:30 company.ISD
-rw-rw-r--   1 davida   tcx      96482304 Jan 12 18:35 company.ISM

How does the privilege system work?

The MySQL privilege system makes sure that each user may do exactly the things that she is supposed to be allowed to. The system decides to grant different privileges depending on which user connects from which host to which database. The decision is based on the contents of the three tables in the MySQL database: user, host and db.

The grantable privileges on rows are select, insert, update and delete.

The table and database privileges are create and drop. Create and drop are for both tables and databases. Since a user with a drop grant can delete any table, this is the same thing as a drop grant for the database.

Other privileges give the right to use files (for LOAD DATA INFILE and SELECT INTO OUTFILE) and to use the administrative commands shutdown, reload and process (to get the current process list).

The privilege tables are read into mysqld with mysqladmin reload. If the privilege tables are empty or non-existent or if the server is started with --skip-grant-tables, full access is granted to everyone.

You can always test your privileges with the script mysqlaccess, which Yves Carlier has provided for the MySQL distribution. See section Why do I get 'Access denied'?

Everything granted in the user table is valid for every database that cannot be found in the db table. For this reason, it might be wise to grant users (apart from superusers) priviliges on a per-database basis only.

The host table is mainly there to maintain a list of "secure" servers. At TCX host contains a list of all machines on the local network. These are granted all privileges.

The connecting user's privileges are calculated by the following algorithm:

  1. First sort all three tables by host by putting hosts without wildcards first, followed by hosts with wildcards and entries with host = "". Within each host (i.e. very much like GROUP BY Host), sort by user using the same rules. Finally, in the db table sort by db using the same rules. In the steps below, we will look through the sorted tables and always use the first match found.
  2. Get the privileges for the connecting user from the db table using the first match found. Call this set of privileges P.
  3. If host = "" for the entry found in the db table, AND P with the privileges for the host in the host table, i.e. remove all privileges that are not "Y" in both. (If host <> "", P is not affected. In this case, host must have matched the connecting host's name at least partially. Therefor it can be assumed that the privileges found in this row match the connecting host's profile.)
  4. OR (add) P with the privileges for the user from the user table, i.e. add all privileges that are "Y" in user.

The connecting user gets the set of privileges P.

Let's show an example of the sorting and matching! Suppose that the user table contains this:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ...
| %         | jeffrey  | ...
| localhost | root     | ...
| localhost |          | ...
+-----------+----------+-

Then the search order will be:

So jeffrey attempting to connect on localhost will be matched by the localhost/any line, not by the any/jeffrey line. The first match found is used!

So if you have access problems, print out the user table, sort it by hand, and see where the match is being made.

Adding new user privileges to MySQL

To add privileges to the MySQL database:

This assumes the current user has insert privileges for the mysql db table and reload privileges. The server (mysqld) has to be running. If it is not, start it with safe_mysqld --log &.

> mysql mysql
  insert into user values ('%','monty',password('something'),'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y') ;
  insert into user (host,user,password) values('localhost','dummy',") ;
  insert into user values ('%','admin',",'N','N','N','N','N','N','Y','N','Y','Y') ;
  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.

Default privileges.

The default privileges (set in `scripts/mysql_install_db') is that root can do anything. Any user can do anything with any database whose name is 'test' or start with 'test_'. A normal user can't use mysqladmin shutdown or mysqladmin processlist. See the script (`scripts/mysql_install_db') for a example on how to add other users.

The privilege tables are read into mysqld with 'mysqladmin reload'. If the privilege tables are empty (or non-existent) full access are granted to everyone.

A example of permission setup.

A common mistake is to try something like:

INSERT INTO user VALUES ('%','jeffrey','bLa81m0','Y','Y','Y','N','N','N','N','N', 'N','N');

Then (of course) a mysqladmin reload to make the authentication change take effect, then trying to connect to the server:

$ ./mysql -h sqlserver -u jeffrey -p bLa81m0 test Access denied

Try with this instead:

INSERT INTO user VALUES ('%','jeffrey',password('bLa81m0'),'Y','Y','Y','N','N','N','N','N','N','N');

And like before mysqladmin reload to make the authentication change take effect.

Now things should work.

Can I install MySQL without root access?

Yes. You just have to make some user to be able to create databases. The easiest way to do this is to change the word root to your user name in the script `scripts/mysql_install_db'. And then run this script.

Why so many open tables?

When you run mysqladmin status you get something like:

Uptime: 426  Running threads: 1  Questions: 11082  Reloads: 1  Open tables: 12

This can be somewhat perplexing if you only have 6 tables.

Because MySQL is multithread it may have many queries on the same table at once. To minimize the problem with two threads having different states on the same file, I open the table again for each concurrent thread. This takes some memory and one extra file descriptor for the data file. The index file descriptor is shared for all threads.

Adding functionality to mysql

Adding new functions to MySQL

If you need it as sql function (like SOUNDEX()), its real easy:

  1. Add one line in sql_lex.cc defining the function name in the sql_functions array.
  2. Add two lines in sql_yacc.y. On defines the preprocessor symbol yacc can define (this should be added at the start of the file). Then define the function parameters and create a 'item' with theese parameters. Check for example all occurrences of SOUNDEX in sql_yacc.y
  3. In item_func.h declare a class inheriting from Item_num_func or Item_str_func depending of if your function returns a number or a string.
  4. In `item_func.cc' add: double *Item_func_newname::val() If you are defining a number function or String *Item_func_newname::Str(String *str) If you are defining a string function.
  5. You should probably also define the following function: void Item_func_newname::fix_length_and_dec() This should at least calcutate max_length based on the given arguments. max_length is the maximal number of chars the function may return. If the function can't return a NULL, one should set maybe_null = 0.

About string functions:

  1. For string functions the 'String *str' argument provides is a string buffer that may be used to hold the result.
  2. A string function should return the string that holds the result.
  3. All current string functions tries to avoid to alloc any memory unless absolutely necessary!

Porting

What files must be changed when porting to another system ?

Se the file PORTING in the distribution.

ODBC

Which operating systems does MySQL ODBC support?

MySQL ODBC is a 32 bit ODBC (2.50) level 0 for Windows95 and NT. We hope somebody will port it to Windows 3.x.

How should I report problems with MySQL ODBC?

We have only tested ODBC with Admndemo, some C programs, Msquery and Excel.

To give some light about any problem we would like to have the log file from the ODBC manager (the log you get when requesting logs from ODBCADMIN) and a MYODBC log.

To get a MYODBC log, please put this MYSQL_DEBUG=d:t:O,filename in your AUTOEXEC.BAT and restart.

The log will be written to file `filename'.

How do I fill in the various fields in the ODBC administrator program.

There are three possibilities for sepcifying the server name on windows95:

  1. Use the IP.
  2. Add a file lmhosts with the following info: ip hostname For example: 194.216.84.21 my
  3. Configure the PC to use DNS.

Example to fill in the 'ODBC setup'.

Data Source Name:   test
Description:        This is my test database
Server:             194.216.84.21
User:               monty
Password:           my
Port:

These are default values to be given when prompting for a Driver connect. You don't have to give 'server', 'user' or 'password' in this screen. If port is not given the default port (3333) is used.

When connection to a ODBC source you have the option to change the server, user, password and port.

Problems

Why do I get 'Access denied'?

Problems using DATE fields.

The format of DATE is 'YYYY-MM-DD'. Actually nothing else is allowed (ANSI SQL). One should use this format to update or in the WHERE clouse. Ie: select * from table_1 where idate >= '1997-05-05';

As a convinience MySQL automaticly converts the date to a number if used in a number context. It's also smart enough to allow a 'relaxed' string form when updating, but only when updating.

This means that the following works:

insert into table_1 (idate) values (19970505) ;
insert into table_1 (idate) values ('19970505') ;
insert into table_1 (idate) values ('1997-05-05');
insert into table_1 (idate) values ('1997.05.05');
insert into table_1 (idate) values ('1997 05 05');

select idate from table_1 where idate >= '1997-05-05';
select idate from table_1 where idate >= 19970505;
select mod(idate,100)1 from table_1 where idate >= 19970505;

The following will not work:

select idate from table_1 where idate >= '19970505';

Because '19970505' is compared as a string to '1997-05-05'.

How MySQL uses keys

All keys, PRIMARY, UNIQUE and INDEX(), are stored in B trees. Strings are automaticly prefix- and end-space compressed.

INDEX(col1, col2) creates a multiple index over the two columns. The key can be seen like a concatenation of the given columns. If you use INDEX(col1), INDEX(col2) instead of INDEX(col1,col2) you get two separate keys instead.

SELECT * FROM table WHERE col1=# AND col2=#

In case of INDEX(col1,col2) the right row(s) can be fetched directly. In case of INDEX(col1), INDEX(col2) the optimizer decides which index will find fewer rows and this index will be used to fetch the rows.

If the table have a index INDEX(col1,col2,col3....) and prefix of this can be used by the optimizer to find the rows. This means that above gives you search capabilities on: INDEX(col1) and INDEX(col1,col2) and INDEX(col1,col2,col3)...

MySQL can't use a sub part of a key to locate rows through a key.

With the definition INDEX(col1,col2,col3):

SELECT * FROM table WHERE col1=#
SELECT * FROM table WHERE col2=#
SELECT * FROM table WHERE col2=# and col3=#

Only the first query will use keys.


This document was generated on 27 May 1997 using the texi2html translator version 1.51.