Home -- Michael's Blog :: Just Do IT -- Manuals   Ŀ¼

MySQL Reference Manual for version 4.1.0-alpha.


7 MySQL Table Types

As of MySQL Version 3.23.6, you can choose between three basic table formats (ISAM, HEAP and MyISAM). Newer versions of MySQL support additional table types (InnoDB, or BDB), depending on how you compile it.

When you create a new table, you can tell MySQL what type of table to create. The default table type is usually MyISAM.

MySQL will always create a `.frm' file to hold the table and column definitions. The table's index and data will be stored in one or more other files, depending on the table type.

If you try to use a table type that is not compiled-in or activated, MySQL will instead create a table of type MyISAM. This behaviour is convenient when you want to copy tables between MySQL servers that support different table types. (Perhaps your master server supports transactional storage engines for increased safety, while the slave servers use only non-transactional storage engines for greater speed.)

This automatic change of table types can be confusing for new MySQL users. We plan to fix this by introducing warnings in the new client-server protocol in version 4.1 and generating a warning when a table type is automatically changed.

You can convert tables between different types with the ALTER TABLE statement. See section 6.5.4 ALTER TABLE Syntax.

Note that MySQL supports two different kinds of tables: transaction-safe tables (InnoDB and BDB) and not transaction-safe tables (HEAP, ISAM, MERGE, and MyISAM).

Advantages of transaction-safe tables (TST):

Note that to use InnoDB tables you have to use at least the innodb_data_file_path startup option. See section 7.5.2 InnoDB Startup Options.

Advantages of not transaction-safe tables (NTST):

You can combine TST and NTST tables in the same statements to get the best of both worlds.

7.1 MyISAM Tables

MyISAM is the default table type in MySQL Version 3.23. It's based on the ISAM code and has a lot of useful extensions.

The index is stored in a file with the `.MYI' (MYIndex) extension, and the data is stored in a file with the `.MYD' (MYData) extension. You can check/repair MyISAM tables with the myisamchk utility. See section 4.4.6.7 Using myisamchk for Crash Recovery. You can compress MyISAM tables with myisampack to take up much less space. See section 4.7.4 myisampack, The MySQL Compressed Read-only Table Generator.

The following is new in MyISAM:

MyISAM also supports the following things, which MySQL will be able to use in the near future:

Note that index files are usually much smaller with MyISAM than with ISAM. This means that MyISAM will normally use less system resources than ISAM, but will need more CPU time when inserting data into a compressed index.

The following options to mysqld can be used to change the behaviour of MyISAM tables. See section 4.5.6.4 SHOW VARIABLES.

Option Description
--myisam-recover=# Automatic recovery of crashed tables.
-O myisam_sort_buffer_size=# Buffer used when recovering tables.
--delay-key-write=ALL Don't flush key buffers between writes for any MyISAM table
-O myisam_max_extra_sort_file_size=# Used to help MySQL to decide when to use the slow but safe key cache index create method. Note that this parameter is given in megabytes before 4.0.3 and in bytes starting from this version.
-O myisam_max_sort_file_size=# Don't use the fast sort index method to created index if the temporary file would get bigger than this. Note that this parameter is given in megabytes before 4.0.3 and in bytes starting from this version.
-O bulk_insert_buffer_size=# Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!

The automatic recovery is activated if you start mysqld with --myisam-recover=#. See section 4.1.1 mysqld Command-line Options. On open, the table is checked if it's marked as crashed or if the open count variable for the table is not 0 and you are running with --skip-external-locking. If either of the above is true the following happens.

If the recover wouldn't be able to recover all rows from a previous completed statement and you didn't specify FORCE as an option to myisam-recover, then the automatic repair will abort with an error message in the error file:

Error: Couldn't repair table: test.g00pages

If you in this case had used the FORCE option you would instead have got a warning in the error file:

Warning: Found 344 of 354 rows when repairing ./test/g00pages

Note that if you run automatic recover with the BACKUP option, you should have a cron script that automatically moves file with names like `tablename-datetime.BAK' from the database directories to a backup media.

See section 4.1.1 mysqld Command-line Options.

7.1.1 Space Needed for Keys

MySQL can support different index types, but the normal type is ISAM or MyISAM. These use a B-tree index, and you can roughly calculate the size for the index file as (key_length+4)/0.67, summed over all keys. (This is for the worst case when all keys are inserted in sorted order and we don't have any compressed keys.)

String indexes are space compressed. If the first index part is a string, it will also be prefix compressed. Space compression makes the index file smaller than the above figures if the string column has a lot of trailing space or is a VARCHAR column that is not always used to the full length. Prefix compression is used on keys that start with a string. Prefix compression helps if there are many strings with an identical prefix.

In MyISAM tables, you can also prefix compress numbers by specifying PACK_KEYS=1 when you create the table. This helps when you have many integer keys that have an identical prefix when the numbers are stored high-byte first.

7.1.2 MyISAM Table Formats

MyISAM supports 3 different table types. Two of them are chosen automatically depending on the type of columns you are using. The third, compressed tables, can only be created with the myisampack tool.

When you CREATE or ALTER a table you can for tables that doesn't have BLOBs force the table format to DYNAMIC or FIXED with the ROW_FORMAT=# table option. In the future you will be able to compress/decompress tables by specifying ROW_FORMAT=compressed | default to ALTER TABLE. See section 6.5.3 CREATE TABLE Syntax.

7.1.2.1 Static (Fixed-length) Table Characteristics

This is the default format. It's used when the table contains no VARCHAR, BLOB, or TEXT columns.

This format is the simplest and most secure format. It is also the fastest of the on-disk formats. The speed comes from the easy way data can be found on disk. When looking up something with an index and static format it is very simple. Just multiply the row number by the row length.

Also, when scanning a table it is very easy to read a constant number of records with each disk read.

The security is evidenced if your computer crashes when writing to a fixed-size MyISAM file, in which case myisamchk can easily figure out where each row starts and ends. So it can usually reclaim all records except the partially written one. Note that in MySQL all indexes can always be reconstructed:

7.1.2.2 Dynamic Table Characteristics

This format is used if the table contains any VARCHAR, BLOB, or TEXT columns or if the table was created with ROW_FORMAT=dynamic.

This format is a little more complex because each row has to have a header that says how long it is. One record can also end up at more than one location when it is made longer at an update.

You can use OPTIMIZE table or myisamchk to defragment a table. If you have static data that you access/change a lot in the same table as some VARCHAR or BLOB columns, it might be a good idea to move the dynamic columns to other tables just to avoid fragmentation:

7.1.2.3 Compressed Table Characteristics

This is a read-only type that is generated with the optional myisampack tool (pack_isam for ISAM tables):

7.1.3 MyISAM Table Problems

The file format that MySQL uses to store data has been extensively tested, but there are always circumstances that may cause database tables to become corrupted.

7.1.3.1 Corrupted MyISAM Tables

Even if the MyISAM table format is very reliable (all changes to a table is written before the SQL statements returns) , you can still get corrupted tables if some of the following things happens:

Typial typical symptoms for a corrupt table is:

You can check if a table is ok with the command CHECK TABLE. See section 4.4.4 CHECK TABLE Syntax.

You can repair a corrupted table with REPAIR TABLE. See section 4.4.5 REPAIR TABLE Syntax. You can also repair a table, when mysqld is not running with the myisamchk command. myisamchk syntax.

If your tables get corrupted a lot you should try to find the reason for this! See section A.4.1 What To Do If MySQL Keeps Crashing.

In this case the most important thing to know is if the table got corrupted if the mysqld died (one can easily verify this by checking if there is a recent row restarted mysqld in the mysqld error file). If this isn't the case, then you should try to make a test case of this. See section E.1.6 Making a Test Case If You Experience Table Corruption.

7.1.3.2 Clients is using or hasn't closed the table properly

Each MyISAM `.MYI' file has in the header a counter that can be used to check if a table has been closed properly.

If you get the following warning from CHECK TABLE or myisamchk:

# clients is using or hasn't closed the table properly

this means that this counter has come out of sync. This doesn't mean that the table is corrupted, but means that you should at least do a check on the table to verify that it's okay.

The counter works as follows:

In other words, the only ways this can go out of sync are:

7.2 MERGE Tables

MERGE tables are new in MySQL Version 3.23.25. The code is still in gamma, but should be reasonable stable.

A MERGE table (also known as a MRG_MyISAM table) is a collection of identical MyISAM tables that can be used as one. You can only SELECT, DELETE, and UPDATE from the collection of tables. If you DROP the MERGE table, you are only dropping the MERGE specification.

Note that DELETE FROM merge_table used without a WHERE will only clear the mapping for the table, not delete everything in the mapped tables. (We plan to fix this in 4.1).

With identical tables we mean that all tables are created with identical column and key information. You can't merge tables in which the columns are packed differently, doesn't have exactly the same columns, or have the keys in different order. However, some of the tables can be compressed with myisampack. See section 4.7.4 myisampack, The MySQL Compressed Read-only Table Generator.

When you create a MERGE table, you will get a `.frm' table definition file and a `.MRG' table list file. The `.MRG' just contains a list of the index files (`.MYI' files) that should be used as one. All used tables must be in the same database as the MERGE table itself.

For the moment, you need to have SELECT, UPDATE, and DELETE privileges on the tables you map to a MERGE table.

MERGE tables can help you solve the following problems:

The disadvantages with MERGE tables are:

When you create a MERGE table you have to specify with UNION(list-of-tables) which tables you want to use as one. Optionally you can specify with INSERT_METHOD if you want insert for the MERGE table to happen in the first or last table in the UNION list. If you don't specify INSERT_METHOD or specify NO, then all INSERT commands on the MERGE table will return an error.

The following example shows you how to use MERGE tables:

CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2");
CREATE TABLE total (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20))
             TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;

Note that you can also manipulate the `.MRG' file directly from the outside of the MySQL server:

shell> cd /mysql-data-directory/current-database
shell> ls -1 t1.MYI t2.MYI > total.MRG
shell> mysqladmin flush-tables

Now you can do things like:

mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table   |
| 3 | t1      |
| 1 | Testing |
| 2 | table   |
| 3 | t2      |
+---+---------+

Note that the a column, though declared as PRIMARY KEY, is not really unique, as MERGE table cannot enforce uniqueness over a set of underlying MyISAM tables.

To remap a MERGE table you can do one of the following:

7.2.1 MERGE Table Problems

The following are the known problems with MERGE tables:

7.3 ISAM Tables

You can also use the deprecated ISAM table type. This will disappear rather soon (probably in MySQL 5.0) because MyISAM is a better implementation of the same thing. ISAM uses a B-tree index. The index is stored in a file with the `.ISM' extension, and the data is stored in a file with the `.ISD' extension. You can check/repair ISAM tables with the isamchk utility. See section 4.4.6.7 Using myisamchk for Crash Recovery.

ISAM has the following features/properties:

Most of the things true for MyISAM tables are also true for ISAM tables. See section 7.1 MyISAM Tables. The major differences compared to MyISAM tables are:

If you want to convert an ISAM table to a MyISAM table so that you can use utilities such as mysqlcheck, use an ALTER TABLE statement:

mysql> ALTER TABLE tbl_name TYPE = MYISAM;

The embedded MySQL versions doesn't support ISAM tables.

7.4 HEAP Tables

HEAP tables use hashed indexes and are stored in memory. This makes them very fast, but if MySQL crashes you will lose all data stored in them. HEAP is very useful for temporary tables!

The MySQL internal HEAP tables use 100% dynamic hashing without overflow areas. There is no extra space needed for free lists. HEAP tables also don't have problems with delete + inserts, which normally is common with hashed tables:

mysql> CREATE TABLE test TYPE=HEAP SELECT ip,SUM(downloads) AS down
    ->                   FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;

Here are some things you should consider when you use HEAP tables:

The memory needed for one row in a HEAP table is:

SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))

sizeof(char*) is 4 on 32-bit machines and 8 on 64-bit machines.

7.5 InnoDB Tables

7.5.1 InnoDB Tables Overview

InnoDB provides MySQL with a transaction-safe (ACID compliant) storage engine with commit, rollback, and crash recovery capabilities. InnoDB does locking on row level and also provides an Oracle-style consistent non-locking read in SELECTs. These features increase multiuser concurrency and performance. There is no need for lock escalation in InnoDB, because row level locks in InnoDB fit in very small space. InnoDB tables support FOREIGN KEY constraints as the first table type in MySQL.

InnoDB has been designed for maximum performance when processing large data volumes. Its CPU efficiency is probably not matched by any other disk-based relational database engine.

Technically, InnoDB is a complete database backend placed under MySQL. InnoDB has its own buffer pool for caching data and indexes in main memory. InnoDB stores its tables and indexes in a tablespace, which may consist of several files. This is different from, for example, MyISAM tables where each table is stored as a separate file. InnoDB tables can be of any size also on those operating systems where file-size is limited to 2 GB.

You can find the latest information about InnoDB at http://www.innodb.com/. The most up-to-date version of the InnoDB manual is always placed there, and you can also order commercial licenses and support for InnoDB.

InnoDB is currently (October 2001) used in production at several large database sites requiring high performance. The famous Internet news site Slashdot.org runs on InnoDB. Mytrix, Inc. stores over 1 TB of data in InnoDB, and another site handles an average load of 800 inserts/updates per second in InnoDB.

InnoDB tables are included in the MySQL source distribution starting from 3.23.34a and are activated in the MySQL -Max binary. For Windows the -Max binaries are contained in the standard distribution.

If you have downloaded a binary version of MySQL that includes support for InnoDB, simply follow the instructions of the MySQL manual for installing a binary version of MySQL. If you already have MySQL-3.23 installed, then the simplest way to install MySQL -Max is to replace the server executable `mysqld' with the corresponding executable in the -Max distribution. MySQL and MySQL -Max differ only in the server executable. See section 2.2.11 Installing a MySQL Binary Distribution. See section 4.7.5 mysqld-max, An Extended mysqld Server.

To compile MySQL with InnoDB support, download MySQL-3.23.34a or newer version from http://www.mysql.com/ and configure MySQL with the --with-innodb option. See the MySQL manual about installing a MySQL source distribution. See section 2.3 Installing a MySQL Source Distribution.

cd /path/to/source/of/mysql-3.23.37
./configure --with-innodb

To use InnoDB you have to specify InnoDB startup options in your `my.cnf' or `my.ini' file. The minimal way to modify it is to add to the [mysqld] section the line

innodb_data_file_path=ibdata:30M

but to get good performance it is best that you specify options as recommended. See section 7.5.2 InnoDB Startup Options.

InnoDB is distributed under the GNU GPL License Version 2 (of June 1991). In the source distribution of MySQL, InnoDB appears as a subdirectory.

7.5.2 InnoDB Startup Options

To use InnoDB tables in MySQL-Max-3.23 you MUST specify configuration parameters in the [mysqld] section of the configuration file `my.cnf', or on Windows optionally in `my.ini'.

At the minimum, in 3.23 you must specify innodb_data_file_path where you specify the names and the sizes of datafiles. If you do not mention innodb_data_home_dir in `my.cnf' the default is to create these files to the datadir of MySQL. If you specify innodb_data_home_dir as an empty string, then you can give absolute paths to your data files in innodb_data_file_path. In MySQL-4.0 you do not need to specify even innodb_data_file_path: the default for it is to create an auto-extending 10 MB file `ibdata1' to the datadir of MySQL. (In MySQL-4.0.0 and 4.0.1 the datafile is 64 MB and not auto-extending.)

If you don't want to use InnoDB tables, you can add the skip-innodb option to your MySQL option file.

But to get good performance you MUST explicitly set the InnoDB parameters listed in the following examples.

Starting from versions 3.23.50 and 4.0.2 InnoDB allows the last datafile on the innodb_data_file_path line to be specified as auto-extending. The syntax for innodb_data_file_path is then the following:

pathtodatafile:sizespecification;pathtodatafile:sizespecification;...
...  ;pathtodatafile:sizespecification[:autoextend[:max:sizespecification]]

If you specify the last datafile with the autoextend option, InnoDB will extend the last datafile if it runs out of free space in the tablespace. The increment is 8 MB at a time. An example:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:100M:autoextend

instructs InnoDB to create just a single datafile whose initial size is 100 MB and which is extended in 8 MB blocks when space runs out. If the disk becomes full you may want to add another data file to another disk, for example. Then you have to look the size of `ibdata1', round the size downward to the closest multiple of 1024 * 1024 bytes (= 1 MB), and specify the rounded size of `ibdata1' explicitly in innodb_data_file_path. After that you can add another datafile:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend

Be cautious on filesystems where the maximum file-size is 2 GB! InnoDB is not aware of the OS maximum file-size. On those filesystems you might want to specify the max size for the datafile:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:100M:autoextend:max:2000M

A simple `my.cnf' example. Suppose you have a computer with 128 MB RAM and one hard disk. Below is an example of possible configuration parameters in `my.cnf' or `my.ini' for InnoDB. We assume you are running MySQL-Max-3.23.50 or later, or MySQL-4.0.2 or later. This example suits most users, both on Unix and Windows, who do not want to distribute InnoDB datafiles and log files on several disks. This creates an auto-extending data file `ibdata1' and two InnoDB log files `ib_logfile0' and `ib_logfile1' to the datadir of MySQL (typically `/mysql/data'). Also the small archived InnoDB log file `ib_arch_log_0000000000' ends up in the datadir.

[mysqld]
# You can write your other MySQL server options here
# ...
#                                  Data file(s) must be able to
#                                  hold your data and indexes.
#                                  Make sure you have enough
#                                  free disk space.
innodb_data_file_path = ibdata1:10M:autoextend
#                                  Set buffer pool size to
#                                  50 - 80 % of your computer's
#                                  memory
set-variable = innodb_buffer_pool_size=70M
set-variable = innodb_additional_mem_pool_size=10M
#                                  Set the log file size to about
#                                  25 % of the buffer pool size
set-variable = innodb_log_file_size=20M
set-variable = innodb_log_buffer_size=8M
#                                  Set ..flush_log_at_trx_commit
#                                  to 0 if you can afford losing
#                                  some last transactions 
innodb_flush_log_at_trx_commit=1

Check that the MySQL server has the rights to create files in datadir.

Note that datafiles must be < 2G in some file systems! The combined size of the log files must be < 4G. The combined size of datafiles must be >= 10 MB.

When you for the first time create an InnoDB database, it is best that you start the MySQL server from the command prompt. Then InnoDB will print the information about the database creation to the screen, and you see what is happening. See below next section what the printout should look like. For example, in Windows you can start `mysqld-max.exe' with:

your-path-to-mysqld>mysqld-max --console

Where to put `my.cnf' or `my.ini' in Windows? The rules for Windows are the following:

Where to specify options in Unix? On Unix `mysqld' reads options from the following files, if they exist, in the following order:

`COMPILATION_DATADIR' is the MySQL data directory which was specified as a ./configure option when `mysqld' was compiled (typically `/usr/local/mysql/data' for a binary installation or `/usr/local/var' for a source installation).

If you are not sure from where `mysqld' reads its `my.cnf' or `my.ini', you can give the path as the first command-line option to the server: mysqld --defaults-file=your_path_to_my_cnf.

InnoDB forms the directory path to a datafile by textually catenating innodb_data_home_dir to a datafile name or path in innodb_data_file_path, adding a possible slash or backslash in between if needed. If the keyword innodb_data_home_dir is not mentioned in `my.cnf' at all, the default for it is the 'dot' directory `./' which means the datadir of MySQL.

An advanced `my.cnf' example. Suppose you have a Linux computer with 2 GB RAM and three 60 GB hard disks (at directory paths `/', `/dr2' and `/dr3'). Below is an example of possible configuration parameters in `my.cnf' for InnoDB.

Note that InnoDB does not create directories: you have to create them yourself. Use the Unix or MS-DOS mkdir command to create the data and log group home directories.

[mysqld]
# You can write your other MySQL server options here
# ...
innodb_data_home_dir =
#                                  Data files must be able to
#                                  hold your data and indexes
innodb_data_file_path = /ibdata/ibdata1:2000M;/dr2/ibdata/ibdata2:2000M:autoextend
#                                  Set buffer pool size to
#                                  50 - 80 % of your computer's
#                                  memory, but make sure on Linux
#                                  x86 total memory usage is
#                                  < 2 GB
set-variable = innodb_buffer_pool_size=1G
set-variable = innodb_additional_mem_pool_size=20M
innodb_log_group_home_dir = /dr3/iblogs
#                                  .._log_arch_dir must be the same
#                                  as .._log_group_home_dir
innodb_log_arch_dir = /dr3/iblogs
set-variable = innodb_log_files_in_group=3
#                                  Set the log file size to about
#                                  15 % of the buffer pool size
set-variable = innodb_log_file_size=150M
set-variable = innodb_log_buffer_size=8M
#                                  Set ..flush_log_at_trx_commit to
#                                  0 if you can afford losing
#                                  some last transactions 
innodb_flush_log_at_trx_commit=1
set-variable = innodb_lock_wait_timeout=50
#innodb_flush_method=fdatasync
#set-variable = innodb_thread_concurrency=5

Note that we have placed the two datafiles on different disks. InnoDB will fill the tablespace formed by the datafiles from bottom up. In some cases it will improve the performance of the database if all data is not placed on the same physical disk. Putting log files on a different disk from data is very often beneficial for performance. You can also use raw disk partitions (raw devices) as datafiles. In some Unixes they speed up I/O. See the manual section on InnoDB file space management about how to specify them in `my.cnf'.

Warning: on Linux x86 you must be careful you do not set memory usage too high. glibc will allow the process heap to grow over thread stacks, which will crash your server. It is a risk if the value of

innodb_buffer_pool_size + key_buffer +
max_connections * (sort_buffer + read_buffer_size) + max_connections * 2 MB

is close to 2 GB or exceeds 2 GB. Each thread will use a stack (often 2 MB, but in MySQL AB binaries only 256 kB) and in the worst case also sort_buffer + read_buffer_size additional memory.

How to tune other `mysqld' server parameters? Typical values which suit most users are:

skip-locking
set-variable = max_connections=200
set-variable = read_buffer_size=1M
set-variable = sort_buffer=1M
#                                  Set key_buffer to 5 - 50%
#                                  of your RAM depending on how
#                                  much you use MyISAM tables, but
#                                  keep key_buffer + InnoDB
#                                  buffer pool size < 80% of
#                                  your RAM
set-variable = key_buffer=...

Note that some parameters are given using the numeric `my.cnf' parameter format: set-variable = innodb... = 123, others (string and boolean parameters) with another format: innodb_... = ... .

The meanings of the configuration parameters are the following:

Option Description
innodb_data_home_dir The common part of the directory path for all InnoDB datafiles. If you do not mentioned this option in `my.cnf' the default is the datadir of MySQL. You can specify this also as an empty string, in which case you can use absolute file paths in innodb_data_file_path.
innodb_data_file_path Paths to individual datafiles and their sizes. The full directory path to each datafile is acquired by concatenating innodb_data_home_dir to the paths specified here. The file-sizes are specified in megabytes, hence the 'M' after the size specification above. InnoDB also understands the abbreviation 'G', 1G meaning 1024M. Starting from 3.23.44 you can set the file-size bigger than 4 GB on those operating systems which support big files. On some operating systems files must be < 2 GB. The sum of the sizes of the files must be at least 10 MB.
innodb_mirrored_log_groups Number of identical copies of log groups we keep for the database. Currently this should be set to 1.
innodb_log_group_home_dir Directory path to InnoDB log files.
innodb_log_files_in_group Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.
innodb_log_file_size Size of each log file in a log group in megabytes. Sensible values range from 1M to 1/nth of the size of the buffer pool specified below, where n is the number of log files in the group. The bigger the value, the less checkpoint flush activity is needed in the buffer pool, saving disk I/O. But bigger log files also mean that recovery will be slower in case of a crash. The combined size of log files must be < 4 GB on 32-bit computers.
innodb_log_buffer_size The size of the buffer which InnoDB uses to write log to the log files on disk. Sensible values range from 1M to 8M. A big log buffer allows large transactions to run without a need to write the log to disk until the transaction commit. Thus, if you have big transactions, making the log buffer big will save disk I/O.
innodb_flush_log_at_trx_commit Normally you set this to 1, meaning that at a transaction commit the log is flushed to disk, and the modifications made by the transaction become permanent, and survive a database crash. If you are willing to compromise this safety, and you are running small transactions, you may set this to 0 or 2 to reduce disk I/O to the logs. Value 0 means that the log is only written to the log file and the log file flushed to disk approximately once per second. Value 2 means the log is written to the log file at each commit, but the log file is only flushed to disk approximately once per second. The default value is 1 starting from MySQL-4.0.13, previously it was 0.
innodb_log_arch_dir The directory where fully written log files would be archived if we used log archiving. The value of this parameter should currently be set the same as innodb_log_group_home_dir.
innodb_log_archive This value should currently be set to 0. As recovery from a backup is done by MySQL using its own log files, there is currently no need to archive InnoDB log files.
innodb_buffer_pool_size The size of the memory buffer InnoDB uses to cache data and indexes of its tables. The bigger you set this the less disk I/O is needed to access data in tables. On a dedicated database server you may set this parameter up to 80% of the machine physical memory size. Do not set it too large, though, because competition of the physical memory may cause paging in the operating system.
innodb_additional_mem_pool_size Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures. A sensible value for this might be 2M, but the more tables you have in your application the more you will need to allocate here. If InnoDB runs out of memory in this pool, it will start to allocate memory from the operating system, and write warning messages to the MySQL error log.
innodb_file_io_threads Number of file I/O threads in InnoDB. Normally, this should be 4, but on Windows disk I/O may benefit from a larger number.
innodb_lock_wait_timeout Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. InnoDB automatically detects transaction deadlocks in its own lock table and rolls back the transaction. If you use LOCK TABLES command, or other transaction-safe storage engines than InnoDB in the same transaction, then a deadlock may arise which InnoDB cannot notice. In cases like this the timeout is useful to resolve the situation.
innodb_flush_method (Available from 3.23.40 up.) The default value for this is fdatasync. Another option is O_DSYNC.

7.5.3 Creating InnoDB Tablespace

Suppose you have installed MySQL and have edited `my.cnf' so that it contains the necessary InnoDB configuration parameters. Before starting MySQL you should check that the directories you have specified for InnoDB datafiles and log files exist and that you have access rights to those directories. InnoDB cannot create directories, only files. Check also you have enough disk space for the data and log files.

When you now start MySQL, InnoDB will start creating your datafiles and log files. InnoDB will print something like the following:

~/mysqlm/sql > mysqld
InnoDB: The first specified datafile /home/heikki/data/ibdata1
did not exist:
InnoDB: a new database to be created!
InnoDB: Setting file /home/heikki/data/ibdata1 size to 134217728
InnoDB: Database physically writes the file full: wait...
InnoDB: datafile /home/heikki/data/ibdata2 did not exist:
new to be created
InnoDB: Setting file /home/heikki/data/ibdata2 size to 262144000
InnoDB: Database physically writes the file full: wait...
InnoDB: Log file /home/heikki/data/logs/ib_logfile0 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile0 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile1 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile1 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile2 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile2 size to 5242880
InnoDB: Started
mysqld: ready for connections

A new InnoDB database has now been created. You can connect to the MySQL server with the usual MySQL client programs like mysql. When you shut down the MySQL server with `mysqladmin shutdown', InnoDB output will be like the following:

010321 18:33:34  mysqld: Normal shutdown
010321 18:33:34  mysqld: Shutdown Complete
InnoDB: Starting shutdown...
InnoDB: Shutdown completed

You can now look at the datafiles and logs directories and you will see the files created. The log directory will also contain a small file named `ib_arch_log_0000000000'. That file resulted from the database creation, after which InnoDB switched off log archiving. When MySQL is again started, the output will be like the following:

~/mysqlm/sql > mysqld
InnoDB: Started
mysqld: ready for connections

7.5.3.1 If Something Goes Wrong in Database Creation

If InnoDB prints an operating system error in a file operation, usually the problem is one of the following:

If something goes wrong in an InnoDB database creation, you should delete all files created by InnoDB. This means all datafiles, all log files, the small archived log file, and in the case you already did create some InnoDB tables, delete also the corresponding `.frm' files for these tables from the MySQL database directories. Then you can try the InnoDB database creation again.

7.5.4 Creating InnoDB Tables

Suppose you have started the MySQL client with the command mysql test. To create a table in the InnoDB format you must specify TYPE = InnoDB in the table creation SQL command:

CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A)) TYPE = InnoDB;

This SQL command will create a table and an index on column A into the InnoDB tablespace consisting of the datafiles you specified in `my.cnf'. In addition MySQL will create a file `CUSTOMER.frm' to the MySQL database directory `test'. Internally, InnoDB will add to its own data dictionary an entry for table 'test/CUSTOMER'. Thus you can create a table of the same name CUSTOMER in another database of MySQL, and the table names will not collide inside InnoDB.

You can query the amount of free space in the InnoDB tablespace by issuing the table status command of MySQL for any table you have created with TYPE = InnoDB. Then the amount of free space in the tablespace appears in the table comment section in the output of SHOW. An example:

SHOW TABLE STATUS FROM test LIKE 'CUSTOMER'

Note that the statistics SHOW gives about InnoDB tables are only approximate: they are used in SQL optimisation. Table and index reserved sizes in bytes are accurate, though.

7.5.4.1 Converting MyISAM Tables to InnoDB

InnoDB does not have a special optimisation for separate index creation. Therefore it does not pay to export and import the table and create indexes afterwards. The fastest way to alter a table to InnoDB is to do the inserts directly to an InnoDB table, that is, use ALTER TABLE ... TYPE=INNODB, or create an empty InnoDB table with identical definitions and insert the rows with INSERT INTO ... SELECT * FROM ....

To get better control over the insertion process, it may be good to insert big tables in pieces:

INSERT INTO newtable SELECT * FROM oldtable
   WHERE yourkey > something AND yourkey <= somethingelse;

After all data has been inserted you can rename the tables.

During the conversion of big tables you should set the InnoDB buffer pool size big to reduce disk I/O. Not bigger than 80% of the physical memory, though. You should set InnoDB log files big, and also the log buffer large.

Make sure you do not run out of tablespace: InnoDB tables take a lot more space than MyISAM tables. If an ALTER TABLE runs out of space, it will start a rollback, and that can take hours if it is disk-bound. In inserts InnoDB uses the insert buffer to merge secondary index records to indexes in batches. That saves a lot of disk I/O. In rollback no such mechanism is used, and the rollback can take 30 times longer than the insertion.

In the case of a runaway rollback, if you do not have valuable data in your database, it is better that you kill the database process and delete all InnoDB data and log files and all InnoDB table `.frm' files, and start your job again, rather than wait for millions of disk I/Os to complete.

7.5.4.2 Foreign Key Constraints

Starting from version 3.23.43b InnoDB features foreign key constraints. InnoDB is the first MySQL table type which allows you to define foreign key constraints to guard the integrity of your data.

The syntax of a foreign key constraint definition in InnoDB:

[CONSTRAINT symbol] FOREIGN KEY (index_col_name, ...)
                  REFERENCES table_name (index_col_name, ...)
                  [ON DELETE {CASCADE | SET NULL | NO ACTION
                              | RESTRICT}]
                  [ON UPDATE {CASCADE | SET NULL | NO ACTION
                              | RESTRICT}]

Both tables have to be InnoDB type and there must be an index where the foreign key and the referenced key are listed as the FIRST columns. InnoDB does not auto-create indexes on foreign keys or referenced keys: you have to create them explicitly.

Corresponding columns in the foreign key and the referenced key must have similar internal data types inside InnoDB so that they can be compared without a type conversion. The size and the signedness of integer types has to be the same. The length of string types need not be the same. If you specify a SET NULL action, make sure you have not declared the columns in the child table NOT NULL.

If MySQL gives the error number 1005 from a CREATE TABLE statement, and the error message string refers to errno 150, then the table creation failed because a foreign key constraint was not correctly formed. Similarly, if an ALTER TABLE fails and it refers to errno 150, that means a foreign key definition would be incorrectly formed for the altered table.

Starting from version 3.23.50 you can also associate the ON DELETE CASCADE or ON DELETE SET NULL clause with the foreign key constraint. Starting from version 4.0.8 you can use also similar ON UPDATE actions.

If ON DELETE CASCADE is specified, and a row in the parent table is deleted, then InnoDB automatically deletes also all those rows in the child table whose foreign key values are equal to the referenced key value in the parent row. If ON DELETE SET NULL is specified, the child rows are automatically updated so that the columns in the foreign key are set to the SQL NULL value.

Starting from version 3.23.50, InnoDB does not check foreign key constraints on those foreign key or referenced key values which contain a NULL column.

Starting from version 3.23.50 the InnoDB parser allows you to use backquotes (`) around table and column names in the FOREIGN KEY ... REFERENCES ... clause but the InnoDB parser is not yet aware of the option lower_case_table_names you can specify in `my.cnf'.

An example:

CREATE TABLE parent(id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB;
CREATE TABLE child(id INT, parent_id INT, INDEX par_ind (parent_id),
             FOREIGN KEY (parent_id) REFERENCES parent(id)
             ON DELETE SET NULL
) TYPE=INNODB;

Starting from version 3.23.50 InnoDB allows you to add a new foreign key constraint to a table through

ALTER TABLE yourtablename
ADD [CONSTRAINT symbol] FOREIGN KEY (...) REFERENCES anothertablename(...)
[on_delete_and_on_update_actions]

Remember to create the required indexes first, though. In InnoDB versions < 3.23.50 ALTER TABLE or CREATE INDEX should not be used in connection with tables which have foreign key constraints or which are referenced in foreign key constraints: Any ALTER TABLE removes all foreign key constrainst defined for the table. You should not use ALTER TABLE to the referenced table either, but use DROP TABLE and CREATE TABLE to modify the schema. When MySQL does an ALTER TABLE it may internally use RENAME TABLE, and that will confuse the foreign key costraints which refer to the table. A CREATE INDEX statement is in MySQL processed as an ALTER TABLE, and these restrictions apply also to it.

When doing foreign key checks InnoDB sets shared row level locks on child or parent records it has to look at. InnoDB checks foreign key constraints immediately: the check is not deferred to transaction commit.

InnoDB allows you to drop any table even though that would break the foreign key constraints which reference the table. When you drop a table the constraints which were defined in its create statement are also dropped.

If you re-create a table which was dropped, it has to have a definition which conforms to the foreign key constraints referencing it. It must have the right column names and types, and it must have indexes on the referenced keys, as stated above. If these are not satisfied, MySQL returns error number 1005 and refers to errno 150 in the error message string.

Starting from version 3.23.50 InnoDB returns the foreign key definitions of a table when you call

SHOW CREATE TABLE yourtablename

Then also `mysqldump' produces correct definitions of tables to the dump file, and does not forget about the foreign keys.

You can also list the foreign key constraints for a table T with

SHOW TABLE STATUS FROM yourdatabasename LIKE 'T'

The foreign key constraints are listed in the table comment of the output.

7.5.5 Adding and Removing InnoDB Data and Log Files

From version 3.23.50 and 4.0.2 you can specify the last InnoDB datafile to autoextend. Alternatively, you can increase to your tablespace by specifying an additional datafile. To do this you have to shut down the MySQL server, edit the `my.cnf' file adding a new datafile to innodb_data_file_path, and then start the MySQL server again.

Currently you cannot remove a datafile from InnoDB. To decrease the size of your database you have to use `mysqldump' to dump all your tables, create a new database, and import your tables to the new database.

If you want to change the number or the size of your InnoDB log files, you have to shut down MySQL and make sure that it shuts down without errors. Then copy the old log files into a safe place just in case something went wrong in the shutdown and you will need them to recover the database. Delete then the old log files from the log file directory, edit `my.cnf', and start MySQL again. InnoDB will tell you at the startup that it is creating new log files.

7.5.6 Backing up and Recovering an InnoDB Database

The key to safe database management is taking regular backups.

InnoDB Hot Backup is an online backup tool you can use to backup your InnoDB database while it is running. InnoDB Hot Backup does not require you to shut down your database and it does not set any locks or disturb your normal database processing. InnoDB Hot Backup is a non-free additional tool which is not included in the standard MySQL distribution. See the InnoDB Hot Backup homepage http://www.innodb.com/hotbackup.html for detailed information and screenshots.

If you are able to shut down your MySQL server, then to take a 'binary' backup of your database you have to do the following:

In addition to taking the binary backups described above, you should also regularly take dumps of your tables with `mysqldump'. The reason to this is that a binary file may be corrupted without you noticing it. Dumped tables are stored into text files which are human-readable and much simpler than database binary files. Seeing table corruption from dumped files is easier, and since their format is simpler, the chance for serious data corruption in them is smaller.

A good idea is to take the dumps at the same time you take a binary backup of your database. You have to shut out all clients from your database to get a consistent snapshot of all your tables into your dumps. Then you can take the binary backup, and you will then have a consistent snapshot of your database in two formats.

To be able to recover your InnoDB database to the present from the binary backup described above, you have to run your MySQL database with the general logging and log archiving of MySQL switched on. Here by the general logging we mean the logging mechanism of the MySQL server which is independent of InnoDB logs.

To recover from a crash of your MySQL server process, the only thing you have to do is to restart it. InnoDB will automatically check the logs and perform a roll-forward of the database to the present. InnoDB will automatically roll back uncommitted transactions which were present at the time of the crash. During recovery, InnoDB will print out something like the following:

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

If your database gets corrupted or your disk fails, you have to do the recovery from a backup. In the case of corruption, you should first find a backup which is not corrupted. From a backup do the recovery from the general log files of MySQL according to instructions in the MySQL manual.

7.5.6.1 Checkpoints

InnoDB implements a checkpoint mechanism called a fuzzy checkpoint. InnoDB will flush modified database pages from the buffer pool in small batches, there is no need to flush the buffer pool in one single batch, which would in practice stop processing of user SQL statements for a while.

In crash recovery InnoDB looks for a checkpoint label written to the log files. It knows that all modifications to the database before the label are already present on the disk image of the database. Then InnoDB scans the log files forward from the place of the checkpoint applying the logged modifications to the database.

InnoDB writes to the log files in a circular fashion. All committed modifications which make the database pages in the buffer pool different from the images on disk must be available in the log files in case InnoDB has to do a recovery. This means that when InnoDB starts to reuse a log file in the circular fashion, it has to make sure that the database page images on disk already contain the modifications logged in the log file InnoDB is going to reuse. In other words, InnoDB has to make a checkpoint and often this involves flushing of modified database pages to disk.

The above explains why making your log files very big may save disk I/O in checkpointing. It can make sense to set the total size of the log files as big as the buffer pool or even bigger. The drawback in big log files is that crash recovery can last longer because there will be more log to apply to the database.

7.5.7 Moving an InnoDB Database to Another Machine

InnoDB data and log files are binary-compatible on all platforms if the floating-point number format on the machines is the same. You can move an InnoDB database simply by copying all the relevant files, which we already listed in the previous section on backing up a database. If the floating-point formats on the machines are different but you have not used FLOAT or DOUBLE data types in your tables then the procedure is the same: just copy the relevant files. If the formats are different and your tables contain floating-point data, you have to use `mysqldump' and `mysqlimport' to move those tables.

A performance tip is to switch off auto-commit mode when you import data into your database, assuming your tablespace has enough space for the big rollback segment the big import transaction will generate. Do the commit only after importing a whole table or a segment of a table.

7.5.8 InnoDB Transaction Model

In the InnoDB transaction model the goal has been to combine the best properties of a multi-versioning database to traditional two-phase locking. InnoDB does locking on row level and runs queries by default as non-locking consistent reads, in the style of Oracle. The lock table in InnoDB is stored so space-efficiently that lock escalation is not needed: typically several users are allowed to lock every row in the database, or any random subset of the rows, without InnoDB running out of memory.

In InnoDB all user activity happens inside transactions. If the autocommit mode is used in MySQL, then each SQL statement will form a single transaction. MySQL always starts a new connection with the autocommit mode switched on.

If the autocommit mode is switched off with SET AUTOCOMMIT = 0, then we can think that a user always has a transaction open. If he issues the SQL COMMIT or ROLLBACK statement, it ends the current transaction, and a new starts. Both statements will release all InnoDB locks that were set during the current transaction. A COMMIT means that the changes made in the current transaction are made permanent and become visible to other users. A ROLLBACK, on the other hand, cancels all modifications made by the current transaction.

If the connection has AUTOCOMMIT = 1, then the user can still perform a multi-statement transaction by starting it with BEGIN and ending it with COMMIT or ROLLBACK.

In terms of the SQL-1992 transaction isolation levels, the InnoDB default is REPEATABLE READ. Starting from version 4.0.5, InnoDB offers all 4 different transaction isolation levels described by the SQL-1992 standard. You can set the default isolation level for all connections in the [mysqld] section of `my.cnf':

transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED
                         | REPEATABLE-READ | SERIALIZABLE}

A user can change the isolation level of a single session or all new incoming connections with the

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
                       {READ UNCOMMITTED | READ COMMITTED
                        | REPEATABLE READ | SERIALIZABLE}

SQL statement. Note that there are no hyphens in level names in the SQL syntax. If you specify the keyword GLOBAL in the above statement, it will determine the initial isolation level of new incoming connections, but will not change the isolation level of old connections. Any user is free to change the isolation level of his session, even in the middle of a transaction. In versions < 3.23.50 SET TRANSACTION had no effect on InnoDB tables. In versions < 4.0.5 only REPEATABLE READ and SERIALIZABLE were available.

You can query the global and session transaction isolation levels with:

SELECT @@global.tx_isolation;
SELECT @@tx_isolation;

In row level locking InnoDB uses so-called next-key locking. That means that besides index records, InnoDB can also lock the 'gap' before an index record to block insertions by other users immediately before the index record. A next-key lock means a lock which locks an index record and the gap before it. A gap lock means a lock which only locks a gap before some index record.

A detailed description of each isolation level in InnoDB:

7.5.8.1 Consistent Read

A consistent read means that InnoDB uses its multi-versioning to present to a query a snapshot of the database at a point in time. The query will see the changes made by exactly those transactions that committed before that point of time, and no changes made by later or uncommitted transactions. The exception to this rule is that the query will see the changes made by the transaction itself which issues the query.

If you are running with the default REPEATABLE READ isolation level, then all consistent reads within the same transaction read the snapshot established by the first such read in that transaction. You can get a fresher snapshot for your queries by committing the current transaction and after that issuing new queries.

Consistent read is the default mode in which InnoDB processes SELECT statements in READ COMMITTED and REPEATABLE READ isolation levels. A consistent read does not set any locks on the tables it accesses, and therefore other users are free to modify those tables at the same time a consistent read is being performed on the table.

7.5.8.2 Locking Reads

A consistent read is not convenient in some circumstances. Suppose you want to add a new row into your table CHILD, and make sure that the child already has a parent in table PARENT.

Suppose you use a consistent read to read the table PARENT and indeed see the parent of the child in the table. Can you now safely add the child row to table CHILD? No, because it may happen that meanwhile some other user has deleted the parent row from the table PARENT, and you are not aware of that.

The solution is to perform the SELECT in a locking mode, LOCK IN SHARE MODE.

SELECT * FROM PARENT WHERE NAME = 'Jones' LOCK IN SHARE MODE;

Performing a read in share mode means that we read the latest available data, and set a shared mode lock on the rows we read. If the latest data belongs to a yet uncommitted transaction of another user, we will wait until that transaction commits. A shared mode lock prevents others from updating or deleting the row we have read. After we see that the above query returns the parent 'Jones', we can safely add his child to table CHILD, and commit our transaction. This example shows how to implement referential integrity in your application code.

Let us look at another example: we have an integer counter field in a table CHILD_CODES which we use to assign a unique identifier to each child we add to table CHILD. Obviously, using a consistent read or a shared mode read to read the present value of the counter is not a good idea, since then two users of the database may see the same value for the counter, and we will get a duplicate key error when we add the two children with the same identifier to the table.

In this case there are two good ways to implement the reading and incrementing of the counter: (1) update the counter first by incrementing it by 1 and only after that read it, or (2) read the counter first with a lock mode FOR UPDATE, and increment after that:

SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;

A SELECT ... FOR UPDATE will read the latest available data setting exclusive locks on each row it reads. Thus it sets the same locks a searched SQL UPDATE would set on the rows.

7.5.8.3 Next-key Locking: Avoiding the Phantom Problem

In row level locking InnoDB uses an algorithm called next-key locking. InnoDB does the row level locking so that when it searches or scans an index of a table, it sets shared or exclusive locks on the index records in encounters. Thus the row level locks are more precisely called index record locks.

The locks InnoDB sets on index records also affect the 'gap' before that index record. If a user has a shared or exclusive lock on record R in an index, then another user cannot insert a new index record immediately before R in the index order. This locking of gaps is done to prevent the so-called phantom problem. Suppose I want to read and lock all children with identifier bigger than 100 from table CHILD, and update some field in the selected rows.

SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

Suppose there is an index on table CHILD on column ID. Our query will scan that index starting from the first record where ID is bigger than 100. Now, if the locks set on the index records would not lock out inserts made in the gaps, a new child might meanwhile be inserted to the table. If now I in my transaction execute

SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

again, I will see a new child in the result set the query returns. This is against the isolation principle of transactions: a transaction should be able to run so that the data it has read does not change during the transaction. If we regard a set of rows as a data item, then the new 'phantom' child would break this isolation principle.

When InnoDB scans an index it can also lock the gap after the last record in the index. Just that happens in the previous example: the locks set by InnoDB will prevent any insert to the table where ID would be bigger than 100.

You can use next-key locking to implement a uniqueness check in your application: if you read your data in share mode and do not see a duplicate for a row you are going to insert, then you can safely insert your row and know that the next-key lock set on the successor of your row during the read will prevent anyone meanwhile inserting a duplicate for your row. Thus the next-key locking allows you to 'lock' the non-existence of something in your table.

7.5.8.4 Locks Set by Different SQL Statements in InnoDB

7.5.8.5 Deadlock Detection and Rollback

InnoDB automatically detects a deadlock of transactions and rolls back a transaction or transactions to prevent the deadlock. Starting from version 4.0.5, InnoDB will try to pick small transactions to roll back. The size of a transaction is determined by the number of rows it has inserted, updated, or deleted. Previous to 4.0.5, InnoDB always rolled back the transaction whose lock request was the last one to build a deadlock, that is, a cycle in the waits-for graph of transactions.

InnoDB cannot detect deadlocks where a lock set by a MySQL LOCK TABLES statement is involved, or if a lock set in another storage engine than InnoDB is involved. You have to resolve these situations using innodb_lock_wait_timeout set in `my.cnf'.

When InnoDB performs a complete rollback of a transaction, all the locks of the transaction are released. However, if just a single SQL statement is rolled back as a result of an error, some of the locks set by the SQL statement may be preserved. This is because InnoDB stores row locks in a format where it cannot afterwards know which was set by which SQL statement.

7.5.8.6 An Example of How the Consistent Read Works in InnoDB

Suppose you are running on the default REPEATABLE READ isolation level. When you issue a consistent read, that is, an ordinary SELECT statement, InnoDB will give your transaction a timepoint according to which your query sees the database. Thus, if transaction B deletes a row and commits after your timepoint was assigned, then you will not see the row deleted. Similarly with inserts and updates.

You can advance your timepoint by committing your transaction and then doing another SELECT.

This is called multi-versioned concurrency control.

                  User A                 User B

              SET AUTOCOMMIT=0;      SET AUTOCOMMIT=0;
time
|             SELECT * FROM t;
|             empty set
|                                    INSERT INTO t VALUES (1, 2);
|
v             SELECT * FROM t;
              empty set
                                     COMMIT;

              SELECT * FROM t;
              empty set;

              COMMIT;

              SELECT * FROM t;
              ---------------------
              |    1    |    2    |
              ---------------------

Thus user A sees the row inserted by B only when B has committed the insert, and A has committed his own transaction so that the timepoint is advanced past the commit of B.

If you want to see the ``freshest'' state of the database, you should use a locking read:

SELECT * FROM t LOCK IN SHARE MODE;

7.5.8.7 How to cope with deadlocks?

Deadlocks are a classic problem in transactional databases, but they are not dangerous, unless they are so frequent that you cannot run certain transactions at all. Normally you have to write your applications so that they are always prepared to re-issue a transaction if it gets rolled back because of a deadlock.

InnoDB uses automatic row level locking. You can get deadlocks even in the case of transactions which just insert or delete a single row. That is because these operations are not really 'atomic': they automatically set locks on the (possibly several) index records of the row inserted/deleted.

You can cope with deadlocks and reduce the number of them with the following tricks:

7.5.8.8 Performance Tuning Tips

1. If the Unix `top' or the Windows `Task Manager' shows that the CPU usage percentage with your workload is less than 70%, your workload is probably disk-bound. Maybe you are making too many transaction commits, or the buffer pool is too small. Making the buffer pool bigger can help, but do not set it bigger than 80% of physical memory.

2. Wrap several modifications into one transaction. InnoDB must flush the log to disk at each transaction commit, if that transaction made modifications to the database. Since the rotation speed of a disk is typically at most 167 revolutions/second, that constrains the number of commits to the same 167/second if the disk does not fool the operating system.

3. If you can afford the loss of some latest committed transactions, you can set the `my.cnf' parameter innodb_flush_log_at_trx_commit to 0. InnoDB tries to flush the log once per second anyway, though the flush is not guaranteed.

4. Make your log files big, even as big as the buffer pool. When InnoDB has written the log files full, it has to write the modified contents of the buffer pool to disk in a checkpoint. Small log files will cause many unnecessary disk writes. The drawback in big log files is that recovery time will be longer.

5. Also the log buffer should be quite big, say 8 MB.

6. (Relevant from 3.23.39 up.) In some versions of Linux and Unix, flushing files to disk with the Unix fdatasync and other similar methods is surprisingly slow. The default method InnoDB uses is the fdatasync function. If you are not satisfied with the database write performance, you may try setting innodb_flush_method in `my.cnf' to O_DSYNC, though O_DSYNC seems to be slower on most systems.

7. In importing data to InnoDB, make sure that MySQL does not have autocommit=1 on. Then every insert requires a log flush to disk. Put before your plain SQL import file line

SET AUTOCOMMIT=0;

and after it

COMMIT;

If you use the `mysqldump' option --opt, you will get dump files which are fast to import also to an InnoDB table, even without wrapping them to the above SET AUTOCOMMIT=0; ... COMMIT; wrappers.

8. Beware of big rollbacks of mass inserts: InnoDB uses the insert buffer to save disk I/O in inserts, but in a corresponding rollback no such mechanism is used. A disk-bound rollback can take 30 times the time of the corresponding insert. Killing the database process will not help because the rollback will start again at the database startup. The only way to get rid of a runaway rollback is to increase the buffer pool so that the rollback becomes CPU-bound and runs fast, or delete the whole InnoDB database.

9. Beware also of other big disk-bound operations. Use DROP TABLE or TRUNCATE (from MySQL-4.0 up) to empty a table, not DELETE FROM yourtable.

10. Use the multi-line INSERT to reduce communication overhead between the client and the server if you need to insert many rows:

INSERT INTO yourtable VALUES (1, 2), (5, 5);

This tip is of course valid for inserts into any table type, not just InnoDB.

7.5.8.9 The InnoDB Monitor

Starting from version 3.23.41 InnoDB includes the InnoDB Monitor which prints information on the InnoDB internal state. When switched on, InnoDB Monitor will make the MySQL server `mysqld' to print data (note: the MySQL client will not print anything) to the standard output about once every 15 seconds. This data is useful in performance tuning. On Windows you must start mysqld-max from a MS-DOS prompt with the --standalone --console options to direct the output to the MS-DOS prompt window.

There is a separate innodb_lock_monitor which prints the same information as innodb_monitor plus information on locks set by each transaction.

The printed information includes data on:

You can start InnoDB Monitor through the following SQL command:

CREATE TABLE innodb_monitor(a int) type = innodb;

and stop it by

DROP TABLE innodb_monitor;

The CREATE TABLE syntax is just a way to pass a command to the InnoDB engine through the MySQL SQL parser: the created table is not relevant at all for InnoDB Monitor. If you shut down the database when the monitor is running, and you want to start the monitor again, you have to drop the table before you can issue a new CREATE TABLE to start the monitor. This syntax may change in a future release.

A sample output of the InnoDB Monitor:

================================
010809 18:45:06 INNODB MONITOR OUTPUT
================================
--------------------------
LOCKS HELD BY TRANSACTIONS
--------------------------
LOCK INFO:
Number of locks in the record hash table 1294
LOCKS FOR TRANSACTION ID 0 579342744
TABLE LOCK table test/mytable trx id 0 582333343 lock_mode IX

RECORD LOCKS space id 0 page no 12758 n bits 104 table test/mytable index
PRIMARY trx id 0 582333343 lock_mode X
Record lock, heap no 2 PHYSICAL RECORD: n_fields 74; 1-byte offs FALSE;
info bits 0
 0: len 4; hex 0001a801; asc ;; 1: len 6; hex 000022b5b39f; asc ";;
 2: len 7; hex 000002001e03ec; asc ;; 3: len 4; hex 00000001;
...
-----------------------------------------------
CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS
-----------------------------------------------
SYNC INFO:
Sorry, cannot give mutex list info in non-debug version!
Sorry, cannot give rw-lock list info in non-debug version!
-----------------------------------------------------
SYNC ARRAY INFO: reservation count 6041054, signal count 2913432
4a239430 waited for by thread 49627477 op. S-LOCK file NOT KNOWN line 0
Mut ex 0 sp 5530989 r 62038708 sys 2155035;
rws 0 8257574 8025336; rwx 0 1121090 1848344
-----------------------------------------------------
CURRENT PENDING FILE I/O'S
--------------------------
Pending normal aio reads:
Reserved slot, messages 40157658 4a4a40b8
Reserved slot, messages 40157658 4a477e28
...
Reserved slot, messages 40157658 4a4424a8
Reserved slot, messages 40157658 4a39ea38
Total of 36 reserved aio slots
Pending aio writes:
Total of 0 reserved aio slots
Pending insert buffer aio reads:
Total of 0 reserved aio slots
Pending log writes or reads:
Reserved slot, messages 40158c98 40157f98
Total of 1 reserved aio slots
Pending synchronous reads or writes:
Total of 0 reserved aio slots
-----------
BUFFER POOL
-----------
LRU list length 8034
Free list length 0
Flush list length 999
Buffer pool size in pages 8192
Pending reads 39
Pending writes: LRU 0, flush list 0, single page 0
Pages read 31383918, created 51310, written 2985115
----------------------------
END OF INNODB MONITOR OUTPUT
============================
010809 18:45:22 InnoDB starts purge
010809 18:45:22 InnoDB purged 0 pages

Some notes on the output:

7.5.9 Implementation of Multi-versioning

Since InnoDB is a multi-versioned database, it must keep information of old versions of rows in the tablespace. This information is stored in a data structure we call a rollback segment after an analogous data structure in Oracle.

InnoDB internally adds two fields to each row stored in the database. A 6-byte field tells the transaction identifier for the last transaction which inserted or updated the row. Also a deletion is internally treated as an update where a special bit in the row is set to mark it as deleted. Each row also contains a 7-byte field called the roll pointer. The roll pointer points to an undo log record written to the rollback segment. If the row was updated, then the undo log record contains the information necessary to rebuild the content of the row before it was updated.

InnoDB uses the information in the rollback segment to perform the undo operations needed in a transaction rollback. It also uses the information to build earlier versions of a row for a consistent read.

Undo logs in the rollback segment are divided into insert and update undo logs. Insert undo logs are only needed in transaction rollback and can be discarded as soon as the transaction commits. Update undo logs are used also in consistent reads, and they can be discarded only after there is no transaction present for which InnoDB has assigned a snapshot that in a consistent read could need the information in the update undo log to build an earlier version of a database row.

You must remember to commit your transactions regularly, also those transactions which only issue consistent reads. Otherwise InnoDB cannot discard data from the update undo logs, and the rollback segment may grow too big, filling up your tablespace.

The physical size of an undo log record in the rollback segment is typically smaller than the corresponding inserted or updated row. You can use this information to calculate the space need for your rollback segment.

In our multi-versioning scheme a row is not physically removed from the database immediately when you delete it with an SQL statement. Only when InnoDB can discard the update undo log record written for the deletion, it can also physically remove the corresponding row and its index records from the database. This removal operation is called a purge, and it is quite fast, usually taking the same order of time as the SQL statement which did the deletion.

7.5.10 Table and Index Structures

MySQL stores its data dictionary information of tables in `.frm' files in database directories. But every InnoDB type table also has its own entry in InnoDB internal data dictionaries inside the tablespace. When MySQL drops a table or a database, it has to delete both a `.frm' file or files, and the corresponding entries inside the InnoDB data dictionary. This is the reason why you cannot move InnoDB tables between databases simply by moving the `.frm' files, and why DROP DATABASE did not work for InnoDB type tables in MySQL versions <= 3.23.43.

Every InnoDB table has a special index called the clustered index where the data of the rows is stored. If you define a PRIMARY KEY on your table, then the index of the primary key will be the clustered index.

If you do not define a primary key for your table, InnoDB will internally generate a clustered index where the rows are ordered by the row id InnoDB assigns to the rows in such a table. The row id is a 6-byte field which monotonically increases as new rows are inserted. Thus the rows ordered by the row id will be physically in the insertion order.

Accessing a row through the clustered index is fast, because the row data will be on the same page where the index search leads us. In many databases the data is traditionally stored on a different page from the index record. If a table is large, the clustered index architecture often saves a disk I/O when compared to the traditional solution.

The records in non-clustered indexes (we also call them secondary indexes), in InnoDB contain the primary key value for the row. InnoDB uses this primary key value to search for the row from the clustered index. Note that if the primary key is long, the secondary indexes will use more space.

7.5.10.1 Physical Structure of an Index

All indexes in InnoDB are B-trees where the index records are stored in the leaf pages of the tree. The default size of an index page is 16 kB. When new records are inserted, InnoDB tries to leave 1 / 16 of the page free for future insertions and updates of the index records.

If index records are inserted in a sequential (ascending or descending) order, the resulting index pages will be about 15/16 full. If records are inserted in a random order, then the pages will be 1/2 - 15/16 full. If the fillfactor of an index page drops below 1/2, InnoDB will try to contract the index tree to free the page.

7.5.10.2 Insert Buffering

It is a common situation in a database application that the primary key is a unique identifier and new rows are inserted in the ascending order of the primary key. Thus the insertions to the clustered index do not require random reads from a disk.

On the other hand, secondary indexes are usually non-unique and insertions happen in a relatively random order into secondary indexes. This would cause a lot of random disk I/Os without a special mechanism used in InnoDB.

If an index record should be inserted to a non-unique secondary index, InnoDB checks if the secondary index page is already in the buffer pool. If that is the case, InnoDB will do the insertion directly to the index page. But, if the index page is not found from the buffer pool, InnoDB inserts the record to a special insert buffer structure. The insert buffer is kept so small that it entirely fits in the buffer pool, and insertions can be made to it very fast.

The insert buffer is periodically merged to the secondary index trees in the database. Often we can merge several insertions on the same page in of the index tree, and hence save disk I/Os. It has been measured that the insert buffer can speed up insertions to a table up to 15 times.

7.5.10.3 Adaptive Hash Indexes

If a database fits almost entirely in main memory, then the fastest way to perform queries on it is to use hash indexes. InnoDB has an automatic mechanism which monitors index searches made to the indexes defined for a table, and if InnoDB notices that queries could benefit from building of a hash index, such an index is automatically built.

But note that the hash index is always built based on an existing B-tree index on the table. InnoDB can build a hash index on a prefix of any length of the key defined for the B-tree, depending on what search pattern InnoDB observes on the B-tree index. A hash index can be partial: it is not required that the whole B-tree index is cached in the buffer pool. InnoDB will build hash indexes on demand to those pages of the index which are often accessed.

In a sense, through the adaptive hash index mechanism InnoDB adapts itself to ample main memory, coming closer to the architecture of main memory databases.

7.5.10.4 Physical Record Structure

7.5.10.5 How an Auto-increment Column Works in InnoDB

After a database startup, when a user first does an insert to a table T where an auto-increment column has been defined, and the user does not provide an explicit value for the column, then InnoDB executes SELECT MAX(auto-inc-column) FROM T, and assigns that value incremented by one to the column and the auto-increment counter of the table. We say that the auto-increment counter for table T has been initialised.

InnoDB follows the same procedure in initializing the auto-increment counter for a freshly created table.

Note that if the user specifies in an insert the value 0 to the auto-increment column, then InnoDB treats the row like the value would not have been specified.

After the auto-increment counter has been initialised, if a user inserts a row where he explicitly specifies the column value, and the value is bigger than the current counter value, then the counter is set to the specified column value. If the user does not explicitly specify a value, then InnoDB increments the counter by one and assigns its new value to the column.

The auto-increment mechanism, when assigning values from the counter, bypasses locking and transaction handling. Therefore you may also get gaps in the number sequence if you roll back transactions which have got numbers from the counter.

The behaviour of auto-increment is not defined if a user gives a negative value to the column or if the value becomes bigger than the maximum integer that can be stored in the specified integer type.

7.5.11 File Space Management and Disk I/O

7.5.11.1 Disk I/O

In disk I/O InnoDB uses asynchronous I/O. On Windows NT it uses the native asynchronous I/O provided by the operating system. On Unix, InnoDB uses simulated asynchronous I/O built into InnoDB: InnoDB creates a number of I/O threads to take care of I/O operations, such as read-ahead. In a future version we will add support for simulated aio on Windows NT and native aio on those versions of Unix which have one.

On Windows NT InnoDB uses non-buffered I/O. That means that the disk pages InnoDB reads or writes are not buffered in the operating system file cache. This saves some memory bandwidth.

Starting from 3.23.41 InnoDB uses a novel file flush technique called doublewrite. It adds safety to crash recovery after an operating system crash or a power outage, and improves performance on most Unix flavors by reducing the need for fsync operations.

Doublewrite means that InnoDB before writing pages to a datafile first writes them to a contiguous tablespace area called the doublewrite buffer. Only after the write and the flush to the doublewrite buffer has completed, InnoDB writes the pages to their proper positions in the datafile. If the operating system crashes in the middle of a page write, InnoDB will in recovery find a good copy of the page from the doublewrite buffer.

Starting from 3.23.41 you can also use a raw disk partition as a datafile, though this has not been tested yet. When you create a new datafile you have to put the keyword newraw immediately after the data file-size in innodb_data_file_path. The partition must be >= than you specify as the size. Note that 1M in InnoDB is 1024 x 1024 bytes, while in disk specifications 1 MB usually means 1000 000 bytes.

innodb_data_file_path=hdd1:5Gnewraw;hdd2:2Gnewraw

When you start the database again you must change the keyword to raw. Otherwise, InnoDB will write over your partition!

innodb_data_file_path=hdd1:5Graw;hdd2:2Graw

By using a raw disk you can on some Unixes perform unbuffered I/O.

There are two read-ahead heuristics in InnoDB: sequential read-ahead and random read-ahead. In sequential read-ahead InnoDB notices that the access pattern to a segment in the tablespace is sequential. Then InnoDB will post in advance a batch of reads of database pages to the I/O system. In random read-ahead InnoDB notices that some area in a tablespace seems to be in the process of being fully read into the buffer pool. Then InnoDB posts the remaining reads to the I/O system.

7.5.11.2 File Space Management

The datafiles you define in the configuration file form the tablespace of InnoDB. The files are simply catenated to form the tablespace, there is no striping in use. Currently you cannot directly instruct where the space is allocated for your tables, except by using the following fact: from a newly created tablespace InnoDB will allocate space starting from the low end.

The tablespace consists of database pages whose default size is 16 kB. The pages are grouped into extents of 64 consecutive pages. The 'files' inside a tablespace are called segments in InnoDB. The name of the rollback segment is somewhat misleading because it actually contains many segments in the tablespace.

For each index in InnoDB we allocate two segments: one is for non-leaf nodes of the B-tree, the other is for the leaf nodes. The idea here is to achieve better sequentiality for the leaf nodes, which contain the data.

When a segment grows inside the tablespace, InnoDB allocates the first 32 pages to it individually. After that InnoDB starts to allocate whole extents to the segment. InnoDB can add to a large segment up to 4 extents at a time to ensure good sequentiality of data.

Some pages in the tablespace contain bitmaps of other pages, and therefore a few extents in an InnoDB tablespace cannot be allocated to segments as a whole, but only as individual pages.

When you issue a query SHOW TABLE STATUS FROM ... LIKE ... to ask for available free space in the tablespace, InnoDB will report the extents which are definitely free in the tablespace. InnoDB always reserves some extents for clean-up and other internal purposes; these reserved extents are not included in the free space.

When you delete data from a table, InnoDB will contract the corresponding B-tree indexes. It depends on the pattern of deletes if that frees individual pages or extents to the tablespace, so that the freed space is available for other users. Dropping a table or deleting all rows from it is guaranteed to release the space to other users, but remember that deleted rows can be physically removed only in a purge operation after they are no longer needed in transaction rollback or consistent read.

7.5.11.3 Defragmenting a Table

If there are random insertions or deletions in the indexes of a table, the indexes may become fragmented. By fragmentation we mean that the physical ordering of the index pages on the disk is not close to the alphabetical ordering of the records on the pages, or that there are many unused pages in the 64-page blocks which were allocated to the index.

It can speed up index scans if you periodically use mysqldump to dump the table to a text file, drop the table, and reload it from the dump. Another way to do the defragmenting is to ALTER the table type to MyISAM and back to InnoDB again. Note that a MyISAM table must fit in a single file on your operating system.

If the insertions to and index are always ascending and records are deleted only from the end, then the file space management algorithm of InnoDB guarantees that fragmentation in the index will not occur.

7.5.12 Error Handling

The error handling in InnoDB is not always the same as specified in the ANSI SQL standards. According to the ANSI standard, any error during an SQL statement should cause the rollback of that statement. InnoDB sometimes rolls back only part of the statement, or the whole transaction. The following list specifies the error handling of InnoDB.

7.5.13 Restrictions on InnoDB Tables

7.5.14 InnoDB Change History

7.5.14.1 MySQL/InnoDB-4.1.0, April x, 2003

7.5.14.2 MySQL/InnoDB-3.23.56, March xx, 2003

7.5.14.3 MySQL/InnoDB-4.0.12, March xx, 2003

7.5.14.4 MySQL/InnoDB-4.0.11, February 25, 2003

7.5.14.5 MySQL/InnoDB-4.0.10, February 4, 2003

7.5.14.6 MySQL/InnoDB-3.23.55, January 24, 2003

7.5.14.7 MySQL/InnoDB-4.0.9, January 14, 2003

7.5.14.8 MySQL/InnoDB-4.0.8, January 7, 2003

7.5.14.9 MySQL/InnoDB-4.0.7, December 26, 2002

7.5.14.10 MySQL/InnoDB-4.0.6, December 19, 2002

7.5.14.11 MySQL/InnoDB-3.23.54, December 12, 2002

7.5.14.12 MySQL/InnoDB-4.0.5, November 18, 2002

7.5.14.13 MySQL/InnoDB-3.23.53, October 9, 2002

7.5.14.14 MySQL/InnoDB-4.0.4, October 2, 2002

7.5.14.15 MySQL/InnoDB-4.0.3, August 28, 2002

7.5.14.16 MySQL/InnoDB-3.23.52, August 16, 2002

7.5.14.17 MySQL/InnoDB-4.0.2, July 10, 2002

7.5.14.18 MySQL/InnoDB-3.23.51, June 12, 2002

7.5.14.19 MySQL/InnoDB-3.23.50, April 23, 2002

7.5.14.20 MySQL/InnoDB-3.23.49, February 17, 2002

7.5.14.21 MySQL/InnoDB-3.23.48, February 9, 2002

7.5.14.22 MySQL/InnoDB-3.23.47, December 28, 2001

7.5.14.23 MySQL/InnoDB-4.0.1, December 23, 2001

7.5.14.24 MySQL/InnoDB-3.23.46, November 30, 2001

7.5.14.25 MySQL/InnoDB-3.23.45, November 23, 2001

7.5.14.26 MySQL/InnoDB-3.23.44, November 2, 2001

7.5.14.27 MySQL/InnoDB-3.23.43, October 4, 2001

7.5.14.28 MySQL/InnoDB-3.23.42, September 9, 2001

7.5.14.29 MySQL/InnoDB-3.23.41, August 13, 2001

7.5.14.30 MySQL/InnoDB-3.23.40, July 16, 2001

7.5.14.31 MySQL/InnoDB-3.23.39, June 13, 2001

7.5.14.32 MySQL/InnoDB-3.23.38, May 12, 2001

7.5.15 InnoDB Contact Information

Contact information of Innobase Oy, producer of the InnoDB engine. Web site: http://www.innodb.com/. E-mail: Heikki.Tuuri@innodb.com

phone: 358-9-6969 3250 (office) 358-40-5617367 (mobile)
Innobase Oy Inc.
World Trade Center Helsinki
Aleksanterinkatu 17
P.O.Box 800
00101 Helsinki
Finland

7.6 BDB or BerkeleyDB Tables

7.6.1 Overview of BDB Tables

BerkeleyDB, available at http://www.sleepycat.com/ has provided MySQL with a transactional storage engine. Support for this storage engine is included in the MySQL source distribution starting from version 3.23.34 and is activated in the MySQL-Max binary. This storage engine is typically called BDB for short.

BDB tables may have a greater chance of surviving crashes and are also capable of COMMIT and ROLLBACK operations on transactions. The MySQL source distribution comes with a BDB distribution that has a couple of small patches to make it work more smoothly with MySQL. You can't use a non-patched BDB version with MySQL.

We at MySQL AB are working in close cooperation with Sleepycat to keep the quality of the MySQL/BDB interface high.

When it comes to supporting BDB tables, we are committed to help our users to locate the problem and help creating a reproducible test case for any problems involving BDB tables. Any such test case will be forwarded to Sleepycat who in turn will help us find and fix the problem. As this is a two-stage operation, any problems with BDB tables may take a little longer for us to fix than for other storage engines. However, as the BerkeleyDB code itself has been used by many other applications than MySQL, we don't envision any big problems with this. See section 1.4.1 Support Offered by MySQL AB.

7.6.2 Installing BDB

If you have downloaded a binary version of MySQL that includes support for BerkeleyDB, simply follow the instructions for installing a binary version of MySQL. See section 2.2.11 Installing a MySQL Binary Distribution. See section 4.7.5 mysqld-max, An Extended mysqld Server.

To compile MySQL with Berkeley DB support, download MySQL Version 3.23.34 or newer and configure MySQL with the --with-berkeley-db option. See section 2.3 Installing a MySQL Source Distribution.

cd /path/to/source/of/mysql-3.23.34
./configure --with-berkeley-db

Please refer to the manual provided with the BDB distribution for more updated information.

Even though Berkeley DB is in itself very tested and reliable, the MySQL interface is still considered gamma quality. We are actively improving and optimising it to get it stable very soon.

7.6.3 BDB startup options

If you are running with AUTOCOMMIT=0 then your changes in BDB tables will not be updated until you execute COMMIT. Instead of commit you can execute ROLLBACK to forget your changes. See section 6.7.1 BEGIN/COMMIT/ROLLBACK Syntax.

If you are running with AUTOCOMMIT=1 (the default), your changes will be committed immediately. You can start an extended transaction with the BEGIN WORK SQL command, after which your changes will not be committed until you execute COMMIT (or decide to ROLLBACK the changes).

The following options to mysqld can be used to change the behaviour of BDB tables:

Option Description
--bdb-home=directory Base directory for BDB tables. This should be the same directory you use for --datadir.
--bdb-lock-detect=# Berkeley lock detect. One of (DEFAULT, OLDEST, RANDOM, or YOUNGEST).
--bdb-logdir=directory Berkeley DB log file directory.
--bdb-no-sync Don't synchronously flush logs.
--bdb-no-recover Don't start Berkeley DB in recover mode.
--bdb-shared-data Start Berkeley DB in multi-process mode (Don't use DB_PRIVATE when initialising Berkeley DB)
--bdb-tmpdir=directory Berkeley DB temporary file directory.
--skip-bdb Disable usage of BDB tables.
-O bdb_max_lock=1000 Set the maximum number of locks possible. See section 4.5.6.4 SHOW VARIABLES.

If you use --skip-bdb, MySQL will not initialise the Berkeley DB library and this will save a lot of memory. Of course, you cannot use BDB tables if you are using this option. If you try to create a BDB table, MySQL will instead create a MyISAM table.

Normally you should start mysqld without --bdb-no-recover if you intend to use BDB tables. This may, however, give you problems when you try to start mysqld if the BDB log files are corrupted. See section 2.4.2 Problems Starting the MySQL Server.

With bdb_max_lock you can specify the maximum number of locks (10000 by default) you can have active on a BDB table. You should increase this if you get errors of type bdb: Lock table is out of available locks or Got error 12 from ... when you have do long transactions or when mysqld has to examine a lot of rows to calculate the query.

You may also want to change binlog_cache_size and max_binlog_cache_size if you are using big multi-line transactions. See section 6.7.1 BEGIN/COMMIT/ROLLBACK Syntax.

7.6.4 Characteristics of BDB tables:

7.6.5 Things we need to fix for BDB in the near future:

7.6.6 Operating systems supported by BDB

Currently we know that the BDB storage engine works with the following operating systems:

It doesn't work with the following operating systems:

Note: The above list is not complete; we will update it as we receive more information.

If you build MySQL with support for BDB tables and get the following error in the log file when you start mysqld:

bdb: architecture lacks fast mutexes: applications cannot be threaded
Can't init dtabases

This means that BDB tables are not supported for your architecture. In this case you must rebuild MySQL without BDB table support.

7.6.7 Restrictions on BDB Tables

Here follows the restrictions you have when using BDB tables:

7.6.8 Errors That May Occur When Using BDB Tables

8 MySQL APIs

This chapter describes the APIs available for MySQL, where to get them, and how to use them. The C API is the most extensively covered, as it was developed by the MySQL team, and is the basis for most of the other APIs.

8.1 MySQL C API

The C API code is distributed with MySQL. It is included in the mysqlclient library and allows C programs to access a database.

Many of the clients in the MySQL source distribution are written in C. If you are looking for examples that demonstrate how to use the C API, take a look at these clients. You can find these in the clients directory in the MySQL source distribution.

Most of the other client APIs (all except Connector/J) use the mysqlclient library to communicate with the MySQL server. This means that, for example, you can take advantage of many of the same environment variables that are used by other client programs, because they are referenced from the library. See section 4.8 MySQL Client-Side Scripts and Utilities, for a list of these variables.

The client has a maximum communication buffer size. The size of the buffer that is allocated initially (16K bytes) is automatically increased up to the maximum size (the maximum is 16M). Because buffer sizes are increased only as demand warrants, simply increasing the default maximum limit does not in itself cause more resources to be used. This size check is mostly a check for erroneous queries and communication packets.

The communication buffer must be large enough to contain a single SQL statement (for client-to-server traffic) and one row of returned data (for server-to-client traffic). Each thread's communication buffer is dynamically enlarged to handle any query or row up to the maximum limit. For example, if you have BLOB values that contain up to 16M of data, you must have a communication buffer limit of at least 16M (in both server and client). The client's default maximum is 16M, but the default maximum in the server is 1M. You can increase this by changing the value of the max_allowed_packet parameter when the server is started. See section 5.5.2 Tuning Server Parameters.

The MySQL server shrinks each communication buffer to net_buffer_length bytes after each query. For clients, the size of the buffer associated with a connection is not decreased until the connection is closed, at which time client memory is reclaimed.

For programming with threads, see section 8.1.14 How to Make a Threaded Client. For creating a stand-alone application which includes the "server" and "client" in the same program (and does not communicate with an external MySQL server), see section 8.1.15 libmysqld, the Embedded MySQL Server Library.

8.1.1 C API Datatypes

MYSQL
This structure represents a handle to one database connection. It is used for almost all MySQL functions.
MYSQL_RES
This structure represents the result of a query that returns rows (SELECT, SHOW, DESCRIBE, EXPLAIN). The information returned from a query is called the result set in the remainder of this section.
MYSQL_ROW
This is a type-safe representation of one row of data. It is currently implemented as an array of counted byte strings. (You cannot treat these as null-terminated strings if field values may contain binary data, because such values may contain null bytes internally.) Rows are obtained by calling mysql_fetch_row().
MYSQL_FIELD
This structure contains information about a field, such as the field's name, type, and size. Its members are described in more detail here. You may obtain the MYSQL_FIELD structures for each field by calling mysql_fetch_field() repeatedly. Field values are not part of this structure; they are contained in a MYSQL_ROW structure.
MYSQL_FIELD_OFFSET
This is a type-safe representation of an offset into a MySQL field list. (Used by mysql_field_seek().) Offsets are field numbers within a row, beginning at zero.
my_ulonglong
The type used for the number of rows and for mysql_affected_rows(), mysql_num_rows(), and mysql_insert_id(). This type provides a range of 0 to 1.84e19. On some systems, attempting to print a value of type my_ulonglong will not work. To print such a value, convert it to unsigned long and use a %lu print format. Example:
printf (Number of rows: %lu\n", (unsigned long) mysql_num_rows(result));

The MYSQL_FIELD structure contains the members listed here:

char * name
The name of the field, as a null-terminated string.
char * table
The name of the table containing this field, if it isn't a calculated field. For calculated fields, the table value is an empty string.
char * def
The default value of this field, as a null-terminated string. This is set only if you use mysql_list_fields().
enum enum_field_types type
The type of the field. The type value may be one of the following:
Type value Type description
FIELD_TYPE_TINY TINYINT field
FIELD_TYPE_SHORT SMALLINT field
FIELD_TYPE_LONG INTEGER field
FIELD_TYPE_INT24 MEDIUMINT field
FIELD_TYPE_LONGLONG BIGINT field
FIELD_TYPE_DECIMAL DECIMAL or NUMERIC field
FIELD_TYPE_FLOAT FLOAT field
FIELD_TYPE_DOUBLE DOUBLE or REAL field
FIELD_TYPE_TIMESTAMP TIMESTAMP field
FIELD_TYPE_DATE DATE field
FIELD_TYPE_TIME TIME field
FIELD_TYPE_DATETIME DATETIME field
FIELD_TYPE_YEAR YEAR field
FIELD_TYPE_STRING String (CHAR or VARCHAR) field
FIELD_TYPE_BLOB BLOB or TEXT field (use max_length to determine the maximum length)
FIELD_TYPE_SET SET field
FIELD_TYPE_ENUM ENUM field
FIELD_TYPE_NULL NULL-type field
FIELD_TYPE_CHAR Deprecated; use FIELD_TYPE_TINY instead
You can use the IS_NUM() macro to test whether a field has a numeric type. Pass the type value to IS_NUM() and it will evaluate to TRUE if the field is numeric:
if (IS_NUM(field->type))
    printf("Field is numeric\n");
unsigned int length
The width of the field, as specified in the table definition.
unsigned int max_length
The maximum width of the field for the result set (the length of the longest field value for the rows actually in the result set). If you use mysql_store_result() or mysql_list_fields(), this contains the maximum length for the field. If you use mysql_use_result(), the value of this variable is zero.
unsigned int flags
Different bit-flags for the field. The flags value may have zero or more of the following bits set:
Flag value Flag description
NOT_NULL_FLAG Field can't be NULL
PRI_KEY_FLAG Field is part of a primary key
UNIQUE_KEY_FLAG Field is part of a unique key
MULTIPLE_KEY_FLAG Field is part of a non-unique key
UNSIGNED_FLAG Field has the UNSIGNED attribute
ZEROFILL_FLAG Field has the ZEROFILL attribute
BINARY_FLAG Field has the BINARY attribute
AUTO_INCREMENT_FLAG Field has the AUTO_INCREMENT attribute
ENUM_FLAG Field is an ENUM (deprecated)
SET_FLAG Field is a SET (deprecated)
BLOB_FLAG Field is a BLOB or TEXT (deprecated)
TIMESTAMP_FLAG Field is a TIMESTAMP (deprecated)
Use of the BLOB_FLAG, ENUM_FLAG, SET_FLAG, and TIMESTAMP_FLAG flags is deprecated because they indicate the type of a field rather than an attribute of its type. It is preferable to test field->type against FIELD_TYPE_BLOB, FIELD_TYPE_ENUM, FIELD_TYPE_SET, or FIELD_TYPE_TIMESTAMP instead. The following example illustrates a typical use of the flags value:
if (field->flags & NOT_NULL_FLAG)
    printf("Field can't be null\n");
You may use the following convenience macros to determine the boolean status of the flags value:
Flag status Description
IS_NOT_NULL(flags) True if this field is defined as NOT NULL
IS_PRI_KEY(flags) True if this field is a primary key
IS_BLOB(flags) True if this field is a BLOB or TEXT (deprecated; test field->type instead)
unsigned int decimals
The number of decimals for numeric fields.

8.1.2 C API Function Overview

The functions available in the C API are listed here and are described in greater detail in a later section. See section 8.1.3 C API Function Descriptions.

Function Description
mysql_affected_rows() Returns the number of rows changed/deleted/inserted by the last UPDATE, DELETE, or INSERT query.
mysql_change_user() Changes user and database on an open connection.
mysql_character_set_name() Returns the name of the default character set for the connection.
mysql_close() Closes a server connection.
mysql_connect() Connects to a MySQL server. This function is deprecated; use mysql_real_connect() instead.
mysql_create_db() Creates a database. This function is deprecated; use the SQL command CREATE DATABASE instead.
mysql_data_seek() Seeks to an arbitrary row in a query result set.
mysql_debug() Does a DBUG_PUSH with the given string.
mysql_drop_db() Drops a database. This function is deprecated; use the SQL command DROP DATABASE instead.
mysql_dump_debug_info() Makes the server write debug information to the log.
mysql_eof() Determines whether the last row of a result set has been read. This function is deprecated; mysql_errno() or mysql_error() may be used instead.
mysql_errno() Returns the error number for the most recently invoked MySQL function.
mysql_error() Returns the error message for the most recently invoked MySQL function.
mysql_escape_string() Escapes special characters in a string for use in a SQL statement.
mysql_fetch_field() Returns the type of the next table field.
mysql_fetch_field_direct() Returns the type of a table field, given a field number.
mysql_fetch_fields() Returns an array of all field structures.
mysql_fetch_lengths() Returns the lengths of all columns in the current row.
mysql_fetch_row() Fetches the next row from the result set.
mysql_field_seek() Puts the column cursor on a specified column.
mysql_field_count() Returns the number of result columns for the most recent query.
mysql_field_tell() Returns the position of the field cursor used for the last mysql_fetch_field().
mysql_free_result() Frees memory used by a result set.
mysql_get_client_info() Returns client version information.
mysql_get_host_info() Returns a string describing the connection.
mysql_get_server_version() Returns version number of server as an integer (new in 4.1).
mysql_get_proto_info() Returns the protocol version used by the connection.
mysql_get_server_info() Returns the server version number.
mysql_info() Returns information about the most recently executed query.
mysql_init() Gets or initialises a MYSQL structure.
mysql_insert_id() Returns the ID generated for an AUTO_INCREMENT column by the previous query.
mysql_kill() Kills a given thread.
mysql_list_dbs() Returns database names matching a simple regular expression.
mysql_list_fields() Returns field names matching a simple regular expression.
mysql_list_processes() Returns a list of the current server threads.
mysql_list_tables() Returns table names matching a simple regular expression.
mysql_num_fields() Returns the number of columns in a result set.
mysql_num_rows() Returns the number of rows in a result set.
mysql_options() Sets connect options for mysql_connect().
mysql_ping() Checks whether the connection to the server is working, reconnecting as necessary.
mysql_query() Executes a SQL query specified as a null-terminated string.
mysql_real_connect() Connects to a MySQL server.
mysql_real_escape_string() Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection.
mysql_real_query() Executes a SQL query specified as a counted string.
mysql_reload() Tells the server to reload the grant tables.
mysql_row_seek() Seeks to a row in a result set, using value returned from mysql_row_tell().
mysql_row_tell() Returns the row cursor position.
mysql_select_db() Selects a database.
mysql_shutdown() Shuts down the database server.
mysql_stat() Returns the server status as a string.
mysql_store_result() Retrieves a complete result set to the client.
mysql_thread_id() Returns the current thread ID.
mysql_thread_safe() Returns 1 if the clients are compiled as thread-safe.
mysql_use_result() Initiates a row-by-row result set retrieval.
mysql_commit() Commits the transaction (new in 4.1).
mysql_rollback() Rolls back the transaction (new in 4.1).
mysql_autocommit() Toggles autocommit mode on/off (new in 4.1).
mysql_more_results() Checks whether any more results exists (new in 4.1).
mysql_next_result() Returns/Initiates the next result in multi-query executions (new in 4.1).

To connect to the server, call mysql_init() to initialise a connection handler, then call mysql_real_connect() with that handler (along with other information such as the hostname, user name, and password). Upon connection, mysql_real_connect() sets the reconnect flag (part of the MYSQL structure) to a value of 1. This flag indicates, in the event that a query cannot be performed because of a lost connection, to try reconnecting to the server before giving up. When you are done with the connection, call mysql_close() to terminate it.

While a connection is active, the client may send SQL queries to the server using mysql_query() or mysql_real_query(). The difference between the two is that mysql_query() expects the query to be specified as a null-terminated string whereas mysql_real_query() expects a counted string. If the string contains binary data (which may include null bytes), you must use mysql_real_query().

For each non-SELECT query (for example, INSERT, UPDATE, DELETE), you can find out how many rows were changed (affected) by calling mysql_affected_rows().

For SELECT queries, you retrieve the selected rows as a result set. (Note that some statements are SELECT-like in that they return rows. These include SHOW, DESCRIBE, and EXPLAIN. They should be treated the same way as SELECT statements.)

There are two ways for a client to process result sets. One way is to retrieve the entire result set all at once by calling mysql_store_result(). This function acquires from the server all the rows returned by the query and stores them in the client. The second way is for the client to initiate a row-by-row result set retrieval by calling mysql_use_result(). This function initialises the retrieval, but does not actually get any rows from the server.

In both cases, you access rows by calling mysql_fetch_row(). With mysql_store_result(), mysql_fetch_row() accesses rows that have already been fetched from the server. With mysql_use_result(), mysql_fetch_row() actually retrieves the row from the server. Information about the size of the data in each row is available by calling mysql_fetch_lengths().

After you are done with a result set, call mysql_free_result() to free the memory used for it.

The two retrieval mechanisms are complementary. Client programs should choose the approach that is most appropriate for their requirements. In practice, clients tend to use mysql_store_result() more commonly.

An advantage of mysql_store_result() is that because the rows have all been fetched to the client, you not only can access rows sequentially, you can move back and forth in the result set using mysql_data_seek() or mysql_row_seek() to change the current row position within the result set. You can also find out how many rows there are by calling mysql_num_rows(). On the other hand, the memory requirements for mysql_store_result() may be very high for large result sets and you are more likely to encounter out-of-memory conditions.

An advantage of mysql_use_result() is that the client requires less memory for the result set because it maintains only one row at a time (and because there is less allocation overhead, mysql_use_result() can be faster). Disadvantages are that you must process each row quickly to avoid tying up the server, you don't have random access to rows within the result set (you can only access rows sequentially), and you don't know how many rows are in the result set until you have retrieved them all. Furthermore, you must retrieve all the rows even if you determine in mid-retrieval that you've found the information you were looking for.

The API makes it possible for clients to respond appropriately to queries (retrieving rows only as necessary) without knowing whether or not the query is a SELECT. You can do this by calling mysql_store_result() after each mysql_query() (or mysql_real_query()). If the result set call succeeds, the query was a SELECT and you can read the rows. If the result set call fails, call mysql_field_count() to determine whether a result was actually to be expected. If mysql_field_count() returns zero, the query returned no data (indicating that it was an INSERT, UPDATE, DELETE, etc.), and was not expected to return rows. If mysql_field_count() is non-zero, the query should have returned rows, but didn't. This indicates that the query was a SELECT that failed. See the description for mysql_field_count() for an example of how this can be done.

Both mysql_store_result() and mysql_use_result() allow you to obtain information about the fields that make up the result set (the number of fields, their names and types, etc.). You can access field information sequentially within the row by calling mysql_fetch_field() repeatedly, or by field number within the row by calling mysql_fetch_field_direct(). The current field cursor position may be changed by calling mysql_field_seek(). Setting the field cursor affects subsequent calls to mysql_fetch_field(). You can also get information for fields all at once by calling mysql_fetch_fields().

For detecting and reporting errors, MySQL provides access to error information by means of the mysql_errno() and mysql_error() functions. These return the error code or error message for the most recently invoked function that can succeed or fail, allowing you to determine when an error occurred and what it was.

8.1.3 C API Function Descriptions

In the descriptions here, a parameter or return value of NULL means NULL in the sense of the C programming language, not a MySQL NULL value.

Functions that return a value generally return a pointer or an integer. Unless specified otherwise, functions returning a pointer return a non-NULL value to indicate success or a NULL value to indicate an error, and functions returning an integer return zero to indicate success or non-zero to indicate an error. Note that ``non-zero'' means just that. Unless the function description says otherwise, do not test against a value other than zero:

if (result)                   /* correct */
    ... error ...

if (result < 0)               /* incorrect */
    ... error ...

if (result == -1)             /* incorrect */
    ... error ...

When a function returns an error, the Errors subsection of the function description lists the possible types of errors. You can find out which of these occurred by calling mysql_errno(). A string representation of the error may be obtained by calling mysql_error().

8.1.3.1 mysql_affected_rows()

my_ulonglong mysql_affected_rows(MYSQL *mysql)

8.1.3.2 Description

Returns the number of rows changed by the last UPDATE, deleted by the last DELETE or inserted by the last INSERT statement. May be called immediately after mysql_query() for UPDATE, DELETE, or INSERT statements. For SELECT statements, mysql_affected_rows() works like mysql_num_rows().

8.1.3.3 Return Values

An integer greater than zero indicates the number of rows affected or retrieved. Zero indicates that no records where updated for an UPDATE statement, no rows matched the WHERE clause in the query or that no query has yet been executed. -1 indicates that the query returned an error or that, for a SELECT query, mysql_affected_rows() was called prior to calling mysql_store_result().

8.1.3.4 Errors

None.

8.1.3.5 Example

mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10");
printf("%ld products updated",(long) mysql_affected_rows(&mysql));

If one specifies the flag CLIENT_FOUND_ROWS when connecting to mysqld, mysql_affected_rows() will return the number of rows matched by the WHERE statement for UPDATE statements.

Note that when one uses a REPLACE command, mysql_affected_rows() will return 2 if the new row replaced and old row. This is because in this case one row was inserted after the duplicate was deleted.

8.1.3.6 mysql_change_user()

my_bool mysql_change_user(MYSQL *mysql, const char *user, const char *password, const char *db)

8.1.3.7 Description

Changes the user and causes the database specified by db to become the default (current) database on the connection specified by mysql. In subsequent queries, this database is the default for table references that do not include an explicit database specifier.

This function was introduced in MySQL Version 3.23.3.

mysql_change_user() fails unless the connected user can be authenticated or if he doesn't have permission to use the database. In this case the user and database are not changed

The db parameter may be set to NULL if you don't want to have a default database.

Starting from MySQL 4.0.6 this command will always ROLLBACK any active transactions, close all temporary tables, unlock all locked tables and reset the state as if one had done a new connect. This will happen even if the user didn't change.

8.1.3.8 Return Values

Zero for success. Non-zero if an error occurred.

8.1.3.9 Errors

The same that you can get from mysql_real_connect().

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.
ER_UNKNOWN_COM_ERROR
The MySQL server doesn't implement this command (probably an old server)
ER_ACCESS_DENIED_ERROR
The user or password was wrong.
ER_BAD_DB_ERROR
The database didn't exist.
ER_DBACCESS_DENIED_ERROR
The user did not have access rights to the database.
ER_WRONG_DB_NAME
The database name was too long.

8.1.3.10 Example

if (mysql_change_user(&mysql, "user", "password", "new_database"))
{
   fprintf(stderr, "Failed to change user.  Error: %s\n",
           mysql_error(&mysql));
}

8.1.3.11 mysql_character_set_name()

const char *mysql_character_set_name(MYSQL *mysql)

8.1.3.12 Description

Returns the default character set for the current connection.

8.1.3.13 Return Values

The default character set

8.1.3.14 Errors

None.

8.1.3.15 mysql_close()

void mysql_close(MYSQL *mysql)

8.1.3.16 Description

Closes a previously opened connection. mysql_close() also deallocates the connection handle pointed to by mysql if the handle was allocated automatically by mysql_init() or mysql_connect().

8.1.3.17 Return Values

None.

8.1.3.18 Errors

None.

8.1.3.19 mysql_connect()

MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)

8.1.3.20 Description

This function is deprecated. It is preferable to use mysql_real_connect() instead.

mysql_connect() attempts to establish a connection to a MySQL database engine running on host. mysql_connect() must complete successfully before you can execute any of the other API functions, with the exception of mysql_get_client_info().

The meanings of the parameters are the same as for the corresponding parameters for mysql_real_connect() with the difference that the connection parameter may be NULL. In this case the C API allocates memory for the connection structure automatically and frees it when you call mysql_close(). The disadvantage of this approach is that you can't retrieve an error message if the connection fails. (To get error information from mysql_errno() or mysql_error(), you must provide a valid MYSQL pointer.)

8.1.3.21 Return Values

Same as for mysql_real_connect().

8.1.3.22 Errors

Same as for mysql_real_connect().

8.1.3.23 mysql_create_db()

int mysql_create_db(MYSQL *mysql, const char *db)

8.1.3.24 Description

Creates the database named by the db parameter.

This function is deprecated. It is preferable to use mysql_query() to issue a SQL CREATE DATABASE statement instead.

8.1.3.25 Return Values

Zero if the database was created successfully. Non-zero if an error occurred.

8.1.3.26 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.27 Example

if(mysql_create_db(&mysql, "my_database"))
{
   fprintf(stderr, "Failed to create new database.  Error: %s\n",
           mysql_error(&mysql));
}

8.1.3.28 mysql_data_seek()

void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset)

8.1.3.29 Description

Seeks to an arbitrary row in a query result set. This requires that the result set structure contains the entire result of the query, so mysql_data_seek() may be used in conjunction only with mysql_store_result(), not with mysql_use_result().

The offset should be a value in the range from 0 to mysql_num_rows(result)-1.

8.1.3.30 Return Values

None.

8.1.3.31 Errors

None.

8.1.3.32 mysql_debug()

void mysql_debug(const char *debug)

8.1.3.33 Description

Does a DBUG_PUSH with the given string. mysql_debug() uses the Fred Fish debug library. To use this function, you must compile the client library to support debugging. See section E.1 Debugging a MySQL server. See section E.2 Debugging a MySQL client.

8.1.3.34 Return Values

None.

8.1.3.35 Errors

None.

8.1.3.36 Example

The call shown here causes the client library to generate a trace file in `/tmp/client.trace' on the client machine:

mysql_debug("d:t:O,/tmp/client.trace");

8.1.3.37 mysql_drop_db()

int mysql_drop_db(MYSQL *mysql, const char *db)

8.1.3.38 Description

Drops the database named by the db parameter.

This function is deprecated. It is preferable to use mysql_query() to issue a SQL DROP DATABASE statement instead.

8.1.3.39 Return Values

Zero if the database was dropped successfully. Non-zero if an error occurred.

8.1.3.40 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.41 Example

if(mysql_drop_db(&mysql, "my_database"))
  fprintf(stderr, "Failed to drop the database: Error: %s\n",
          mysql_error(&mysql));

8.1.3.42 mysql_dump_debug_info()

int mysql_dump_debug_info(MYSQL *mysql)

8.1.3.43 Description

Instructs the server to write some debug information to the log. For this to work, the connected user must have the SUPER privilege.

8.1.3.44 Return Values

Zero if the command was successful. Non-zero if an error occurred.

8.1.3.45 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.46 mysql_eof()

my_bool mysql_eof(MYSQL_RES *result)

8.1.3.47 Description

This function is deprecated. mysql_errno() or mysql_error() may be used instead.

mysql_eof() determines whether the last row of a result set has been read.

If you acquire a result set from a successful call to mysql_store_result(), the client receives the entire set in one operation. In this case, a NULL return from mysql_fetch_row() always means the end of the result set has been reached and it is unnecessary to call mysql_eof(). When used with mysql_store_result(), mysql_eof() will always return true.

On the other hand, if you use mysql_use_result() to initiate a result set retrieval, the rows of the set are obtained from the server one by one as you call mysql_fetch_row() repeatedly. Because an error may occur on the connection during this process, a NULL return value from mysql_fetch_row() does not necessarily mean the end of the result set was reached normally. In this case, you can use mysql_eof() to determine what happened. mysql_eof() returns a non-zero value if the end of the result set was reached and zero if an error occurred.

Historically, mysql_eof() predates the standard MySQL error functions mysql_errno() and mysql_error(). Because those error functions provide the same information, their use is preferred over mysql_eof(), which is now deprecated. (In fact, they provide more information, because mysql_eof() returns only a boolean value whereas the error functions indicate a reason for the error when one occurs.)

8.1.3.48 Return Values

Zero if no error occurred. Non-zero if the end of the result set has been reached.

8.1.3.49 Errors

None.

8.1.3.50 Example

The following example shows how you might use mysql_eof():

mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
    // do something with data
}
if(!mysql_eof(result))  // mysql_fetch_row() failed due to an error
{
    fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}

However, you can achieve the same effect with the standard MySQL error functions:

mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
    // do something with data
}
if(mysql_errno(&mysql))  // mysql_fetch_row() failed due to an error
{
    fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}

8.1.3.51 mysql_errno()

unsigned int mysql_errno(MYSQL *mysql)

8.1.3.52 Description

For the connection specified by mysql, mysql_errno() returns the error code for the most recently invoked API function that can succeed or fail. A return value of zero means that no error occurred. Client error message numbers are listed in the MySQL `errmsg.h' header file. Server error message numbers are listed in `mysqld_error.h'. In the MySQL source distribution you can find a complete list of error messages and error numbers in the file `Docs/mysqld_error.txt'.

8.1.3.53 Return Values

An error code value. Zero if no error occurred.

8.1.3.54 Errors

None.

8.1.3.55 mysql_error()

char *mysql_error(MYSQL *mysql)

8.1.3.56 Description

For the connection specified by mysql, mysql_error() returns the error message for the most recently invoked API function that can succeed or fail. An empty string ("") is returned if no error occurred. This means the following two tests are equivalent:

if(mysql_errno(&mysql))
{
    // an error occurred
}

if(mysql_error(&mysql)[0] != '\0')
{
    // an error occurred
}

The language of the client error messages may be changed by recompiling the MySQL client library. Currently you can choose error messages in several different languages. See section 4.6.2 Non-English Error Messages.

8.1.3.57 Return Values

A character string that describes the error. An empty string if no error occurred.

8.1.3.58 Errors

None.

8.1.3.59 mysql_escape_string()

You should use mysql_real_escape_string() instead!

This function is identical to mysql_real_escape_string() except that mysql_real_escape_string() takes a connection handler as its first argument and escapes the string according to the current character set. mysql_escape_string() does not take a connection argument and does not respect the current charset setting.

8.1.3.60 mysql_fetch_field()

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

8.1.3.61 Description

Returns the definition of one column of a result set as a MYSQL_FIELD structure. Call this function repeatedly to retrieve information about all columns in the result set. mysql_fetch_field() returns NULL when no more fields are left.

mysql_fetch_field() is reset to return information about the first field each time you execute a new SELECT query. The field returned by mysql_fetch_field() is also affected by calls to mysql_field_seek().

If you've called mysql_query() to perform a SELECT on a table but have not called mysql_store_result(), MySQL returns the default blob length (8K bytes) if you call mysql_fetch_field() to ask for the length of a BLOB field. (The 8K size is chosen because MySQL doesn't know the maximum length for the BLOB. This should be made configurable sometime.) Once you've retrieved the result set, field->max_length contains the length of the largest value for this column in the specific query.

8.1.3.62 Return Values

The MYSQL_FIELD structure for the current column. NULL if no columns are left.

8.1.3.63 Errors

None.

8.1.3.64 Example

MYSQL_FIELD *field;

while((field = mysql_fetch_field(result)))
{
    printf("field name %s\n", field->name);
}

8.1.3.65 mysql_fetch_fields()

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)

8.1.3.66 Description

Returns an array of all MYSQL_FIELD structures for a result set. Each structure provides the field definition for one column of the result set.

8.1.3.67 Return Values

An array of MYSQL_FIELD structures for all columns of a result set.

8.1.3.68 Errors

None.

8.1.3.69 Example

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *fields;

num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
for(i = 0; i < num_fields; i++)
{
   printf("Field %u is %s\n", i, fields[i].name);
}

8.1.3.70 mysql_fetch_field_direct()

MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr)

8.1.3.71 Description

Given a field number fieldnr for a column within a result set, returns that column's field definition as a MYSQL_FIELD structure. You may use this function to retrieve the definition for an arbitrary column. The value of fieldnr should be in the range from 0 to mysql_num_fields(result)-1.

8.1.3.72 Return Values

The MYSQL_FIELD structure for the specified column.

8.1.3.73 Errors

None.

8.1.3.74 Example

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *field;

num_fields = mysql_num_fields(result);
for(i = 0; i < num_fields; i++)
{
    field = mysql_fetch_field_direct(result, i);
    printf("Field %u is %s\n", i, field->name);
}

8.1.3.75 mysql_fetch_lengths()

unsigned long *mysql_fetch_lengths(MYSQL_RES *result)

8.1.3.76 Description

Returns the lengths of the columns of the current row within a result set. If you plan to copy field values, this length information is also useful for optimisation, because you can avoid calling strlen(). In addition, if the result set contains binary data, you must use this function to determine the size of the data, because strlen() returns incorrect results for any field containing null characters.

The length for empty columns and for columns containing NULL values is zero. To see how to distinguish these two cases, see the description for mysql_fetch_row().

8.1.3.77 Return Values

An array of unsigned long integers representing the size of each column (not including any terminating null characters). NULL if an error occurred.

8.1.3.78 Errors

mysql_fetch_lengths() is valid only for the current row of the result set. It returns NULL if you call it before calling mysql_fetch_row() or after retrieving all rows in the result.

8.1.3.79 Example

MYSQL_ROW row;
unsigned long *lengths;
unsigned int num_fields;
unsigned int i;

row = mysql_fetch_row(result);
if (row)
{
    num_fields = mysql_num_fields(result);
    lengths = mysql_fetch_lengths(result);
    for(i = 0; i < num_fields; i++)
    {
         printf("Column %u is %lu bytes in length.\n", i, lengths[i]);
    }
}

8.1.3.80 mysql_fetch_row()

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

8.1.3.81 Description

Retrieves the next row of a result set. When used after mysql_store_result(), mysql_fetch_row() returns NULL when there are no more rows to retrieve. When used after mysql_use_result(), mysql_fetch_row() returns NULL when there are no more rows to retrieve or if an error occurred.

The number of values in the row is given by mysql_num_fields(result). If row holds the return value from a call to mysql_fetch_row(), pointers to the values are accessed as row[0] to row[mysql_num_fields(result)-1]. NULL values in the row are indicated by NULL pointers.

The lengths of the field values in the row may be obtained by calling mysql_fetch_lengths(). Empty fields and fields containing NULL both have length 0; you can distinguish these by checking the pointer for the field value. If the pointer is NULL, the field is NULL; otherwise, the field is empty.

8.1.3.82 Return Values

A MYSQL_ROW structure for the next row. NULL if there are no more rows to retrieve or if an error occurred.

8.1.3.83 Errors

CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.84 Example

MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;

num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
   unsigned long *lengths;
   lengths = mysql_fetch_lengths(result);
   for(i = 0; i < num_fields; i++)
   {
       printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
   }
   printf("\n");
}

8.1.3.85 mysql_field_count()

unsigned int mysql_field_count(MYSQL *mysql)

If you are using a version of MySQL earlier than Version 3.22.24, you should use unsigned int mysql_num_fields(MYSQL *mysql) instead.

8.1.3.86 Description

Returns the number of columns for the most recent query on the connection.

The normal use of this function is when mysql_store_result() returned NULL (and thus you have no result set pointer). In this case, you can call mysql_field_count() to determine whether mysql_store_result() should have produced a non-empty result. This allows the client program to take proper action without knowing whether the query was a SELECT (or SELECT-like) statement. The example shown here illustrates how this may be done.

See section 8.1.12.1 Why Is It that After mysql_query() Returns Success, mysql_store_result() Sometimes Returns NULL?.

8.1.3.87 Return Values

An unsigned integer representing the number of fields in a result set.

8.1.3.88 Errors

None.

8.1.3.89 Example

MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;

if (mysql_query(&mysql,query_string))
{
    // error
}
else // query succeeded, process any data returned by it
{
    result = mysql_store_result(&mysql);
    if (result)  // there are rows
    {
        num_fields = mysql_num_fields(result);
        // retrieve rows, then call mysql_free_result(result)
    }
    else  // mysql_store_result() returned nothing; should it have?
    {
        if(mysql_field_count(&mysql) == 0)
        {
            // query does not return data
            // (it was not a SELECT)
            num_rows = mysql_affected_rows(&mysql);
        }
        else // mysql_store_result() should have returned data
        {
            fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
        }
    }
}

An alternative is to replace the mysql_field_count(&mysql) call with mysql_errno(&mysql). In this case, you are checking directly for an error from mysql_store_result() rather than inferring from the value of mysql_field_count() whether the statement was a SELECT.

8.1.3.90 mysql_field_seek()

MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset)

8.1.3.91 Description

Sets the field cursor to the given offset. The next call to mysql_fetch_field() will retrieve the field definition of the column associated with that offset.

To seek to the beginning of a row, pass an offset value of zero.

8.1.3.92 Return Values

The previous value of the field cursor.

8.1.3.93 Errors

None.

8.1.3.94 mysql_field_tell()

MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result)

8.1.3.95 Description

Returns the position of the field cursor used for the last mysql_fetch_field(). This value can be used as an argument to mysql_field_seek().

8.1.3.96 Return Values

The current offset of the field cursor.

8.1.3.97 Errors

None.

8.1.3.98 mysql_free_result()

void mysql_free_result(MYSQL_RES *result)

8.1.3.99 Description

Frees the memory allocated for a result set by mysql_store_result(), mysql_use_result(), mysql_list_dbs(), etc. When you are done with a result set, you must free the memory it uses by calling mysql_free_result().

8.1.3.100 Return Values

None.

8.1.3.101 Errors

None.

8.1.3.102 mysql_get_client_info()

char *mysql_get_client_info(void)

8.1.3.103 Description

Returns a string that represents the client library version.

8.1.3.104 Return Values

A character string that represents the MySQL client library version.

8.1.3.105 Errors

None.

8.1.3.106 mysql_get_server_version()

unsigned long mysql_get_server_version(MYSQL *mysql)

8.1.3.107 Description

Returns version number of server as an integer (new in 4.1).

8.1.3.108 Return Values

A number that represents the MySQL server version in format:

main_version*10000 + minor_version *100 + sub_version

For example, 4.1.0 is returned as 40100.

This is useful to quickly determine the version of the server in a client program to know if some capability exits.

8.1.3.109 Errors

None.

8.1.3.110 mysql_get_host_info()

char *mysql_get_host_info(MYSQL *mysql)

8.1.3.111 Description

Returns a string describing the type of connection in use, including the server host name.

8.1.3.112 Return Values

A character string representing the server host name and the connection type.

8.1.3.113 Errors

None.

8.1.3.114 mysql_get_proto_info()

unsigned int mysql_get_proto_info(MYSQL *mysql)

8.1.3.115 Description

Returns the protocol version used by current connection.

8.1.3.116 Return Values

An unsigned integer representing the protocol version used by the current connection.

8.1.3.117 Errors

None.

8.1.3.118 mysql_get_server_info()

char *mysql_get_server_info(MYSQL *mysql)

8.1.3.119 Description

Returns a string that represents the server version number.

8.1.3.120 Return Values

A character string that represents the server version number.

8.1.3.121 Errors

None.

8.1.3.122 mysql_info()

char *mysql_info(MYSQL *mysql)

8.1.3.123 Description

Retrieves a string providing information about the most recently executed query, but only for the statements listed here. For other statements, mysql_info() returns NULL. The format of the string varies depending on the type of query, as described here. The numbers are illustrative only; the string will contain values appropriate for the query.

INSERT INTO ... SELECT ...
String format: Records: 100 Duplicates: 0 Warnings: 0
INSERT INTO ... VALUES (...),(...),(...)...
String format: Records: 3 Duplicates: 0 Warnings: 0
LOAD DATA INFILE ...
String format: Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
ALTER TABLE
String format: Records: 3 Duplicates: 0 Warnings: 0
UPDATE
String format: Rows matched: 40 Changed: 40 Warnings: 0

Note that mysql_info() returns a non-NULL value for the INSERT ... VALUES statement only if multiple value lists are specified in the statement.

8.1.3.124 Return Values

A character string representing additional information about the most recently executed query. NULL if no information is available for the query.

8.1.3.125 Errors

None.

8.1.3.126 mysql_init()

MYSQL *mysql_init(MYSQL *mysql)

8.1.3.127 Description

Allocates or initialises a MYSQL object suitable for mysql_real_connect(). If mysql is a NULL pointer, the function allocates, initialises, and returns a new object. Otherwise, the object is initialised and the address of the object is returned. If mysql_init() allocates a new object, it will be freed when mysql_close() is called to close the connection.

8.1.3.128 Return Values

An initialised MYSQL* handle. NULL if there was insufficient memory to allocate a new object.

8.1.3.129 Errors

In case of insufficient memory, NULL is returned.

8.1.3.130 mysql_insert_id()

my_ulonglong mysql_insert_id(MYSQL *mysql)

8.1.3.131 Description

Returns the ID generated for an AUTO_INCREMENT column by the previous query. Use this function after you have performed an INSERT query into a table that contains an AUTO_INCREMENT field.

Note that mysql_insert_id() returns 0 if the previous query does not generate an AUTO_INCREMENT value. If you need to save the value for later, be sure to call mysql_insert_id() immediately after the query that generates the value.

mysql_insert_id() is updated after INSERT and UPDATE statements that generate an AUTO_INCREMENT value or that set a column value to LAST_INSERT_ID(expr). See section 6.3.6.2 Miscellaneous Functions.

Also note that the value of the SQL LAST_INSERT_ID() function always contains the most recently generated AUTO_INCREMENT value, and is not reset between queries because the value of that function is maintained in the server.

8.1.3.132 Return Values

The value of the AUTO_INCREMENT field that was updated by the previous query. Returns zero if there was no previous query on the connection or if the query did not update an AUTO_INCREMENT value.

8.1.3.133 Errors

None.

8.1.3.134 mysql_kill()

int mysql_kill(MYSQL *mysql, unsigned long pid)

8.1.3.135 Description

Asks the server to kill the thread specified by pid.

8.1.3.136 Return Values

Zero for success. Non-zero if an error occurred.

8.1.3.137 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.138 mysql_list_dbs()

MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild)

8.1.3.139 Description

Returns a result set consisting of database names on the server that match the simple regular expression specified by the wild parameter. wild may contain the wildcard characters `%' or `_', or may be a NULL pointer to match all databases. Calling mysql_list_dbs() is similar to executing the query SHOW databases [LIKE wild].

You must free the result set with mysql_free_result().

8.1.3.140 Return Values

A MYSQL_RES result set for success. NULL if an error occurred.

8.1.3.141 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_OUT_OF_MEMORY
Out of memory.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.142 mysql_list_fields()

MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)

8.1.3.143 Description

Returns a result set consisting of field names in the given table that match the simple regular expression specified by the wild parameter. wild may contain the wildcard characters `%' or `_', or may be a NULL pointer to match all fields. Calling mysql_list_fields() is similar to executing the query SHOW COLUMNS FROM tbl_name [LIKE wild].

Note that it's recommended that you use SHOW COLUMNS FROM tbl_name instead of mysql_list_fields().

You must free the result set with mysql_free_result().

8.1.3.144 Return Values

A MYSQL_RES result set for success. NULL if an error occurred.

8.1.3.145 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.146 mysql_list_processes()

MYSQL_RES *mysql_list_processes(MYSQL *mysql)

8.1.3.147 Description

Returns a result set describing the current server threads. This is the same kind of information as that reported by mysqladmin processlist or a SHOW PROCESSLIST query.

You must free the result set with mysql_free_result().

8.1.3.148 Return Values

A MYSQL_RES result set for success. NULL if an error occurred.

8.1.3.149 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.150 mysql_list_tables()

MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild)

8.1.3.151 Description

Returns a result set consisting of table names in the current database that match the simple regular expression specified by the wild parameter. wild may contain the wildcard characters `%' or `_', or may be a NULL pointer to match all tables. Calling mysql_list_tables() is similar to executing the query SHOW tables [LIKE wild].

You must free the result set with mysql_free_result().

8.1.3.152 Return Values

A MYSQL_RES result set for success. NULL if an error occurred.

8.1.3.153 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.154 mysql_num_fields()

unsigned int mysql_num_fields(MYSQL_RES *result)

or

unsigned int mysql_num_fields(MYSQL *mysql)

The second form doesn't work on MySQL Version 3.22.24 or newer. To pass a MYSQL* argument, you must use unsigned int mysql_field_count(MYSQL *mysql) instead.

8.1.3.155 Description

Returns the number of columns in a result set.

Note that you can get the number of columns either from a pointer to a result set or to a connection handle. You would use the connection handle if mysql_store_result() or mysql_use_result() returned NULL (and thus you have no result set pointer). In this case, you can call mysql_field_count() to determine whether mysql_store_result() should have produced a non-empty result. This allows the client program to take proper action without knowing whether or not the query was a SELECT (or SELECT-like) statement. The example shown here illustrates how this may be done.

See section 8.1.12.1 Why Is It that After mysql_query() Returns Success, mysql_store_result() Sometimes Returns NULL?.

8.1.3.156 Return Values

An unsigned integer representing the number of fields in a result set.

8.1.3.157 Errors

None.

8.1.3.158 Example

MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;

if (mysql_query(&mysql,query_string))
{
    // error
}
else // query succeeded, process any data returned by it
{
    result = mysql_store_result(&mysql);
    if (result)  // there are rows
    {
        num_fields = mysql_num_fields(result);
        // retrieve rows, then call mysql_free_result(result)
    }
    else  // mysql_store_result() returned nothing; should it have?
    {
        if (mysql_errno(&mysql))
	{
           fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
	}
        else if (mysql_field_count(&mysql) == 0)
        {
            // query does not return data
            // (it was not a SELECT)
            num_rows = mysql_affected_rows(&mysql);
        }
    }
}

An alternative (if you know that your query should have returned a result set) is to replace the mysql_errno(&mysql) call with a check if mysql_field_count(&mysql) is = 0. This will only happen if something went wrong.

8.1.3.159 mysql_num_rows()

my_ulonglong mysql_num_rows(MYSQL_RES *result)

8.1.3.160 Description

Returns the number of rows in the result set.

The use of mysql_num_rows() depends on whether you use mysql_store_result() or mysql_use_result() to return the result set. If you use mysql_store_result(), mysql_num_rows() may be called immediately. If you use mysql_use_result(), mysql_num_rows() will not return the correct value until all the rows in the result set have been retrieved.

8.1.3.161 Return Values

The number of rows in the result set.

8.1.3.162 Errors

None.

8.1.3.163 mysql_options()

int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)

8.1.3.164 Description

Can be used to set extra connect options and affect behaviour for a connection. This function may be called multiple times to set several options.

mysql_options() should be called after mysql_init() and before mysql_connect() or mysql_real_connect().

The option argument is the option that you want to set; the arg argument is the value for the option. If the option is an integer, then arg should point to the value of the integer.

Possible options values:

Option Argument type Function
MYSQL_OPT_CONNECT_TIMEOUT unsigned int * Connect timeout in seconds.
MYSQL_OPT_COMPRESS Not used Use the compressed client/server protocol.
MYSQL_OPT_LOCAL_INFILE optional pointer to uint If no pointer is given or if pointer points to an unsigned int != 0 the command LOAD LOCAL INFILE is enabled.
MYSQL_OPT_NAMED_PIPE Not used Use named pipes to connect to a MySQL server on NT.
MYSQL_INIT_COMMAND char * Command to execute when connecting to the MySQL server. Will automatically be re-executed when reconnecting.
MYSQL_READ_DEFAULT_FILE char * Read options from the named option file instead of from `my.cnf'.
MYSQL_READ_DEFAULT_GROUP char * Read options from the named group from `my.cnf' or the file specified with MYSQL_READ_DEFAULT_FILE.

Note that the group client is always read if you use MYSQL_READ_DEFAULT_FILE or MYSQL_READ_DEFAULT_GROUP.

The specified group in the option file may contain the following options:

Option Description
connect-timeout Connect timeout in seconds. On Linux this timeout is also used for waiting for the first answer from the server.
compress Use the compressed client/server protocol.
database Connect to this database if no database was specified in the connect command.
debug Debug options.
disable-local-infile Disable use of LOAD DATA LOCAL.
host Default host name.
init-command Command to execute when connecting to MySQL server. Will automatically be re-executed when reconnecting.
interactive-timeout Same as specifying CLIENT_INTERACTIVE to mysql_real_connect(). See section 8.1.3.175 mysql_real_connect().
local-infile[=(0|1)] If no argument or argument != 0 then enable use of LOAD DATA LOCAL.
max_allowed_packet Max size of packet client can read from server.
password Default password.
pipe Use named pipes to connect to a MySQL server on NT.
protocol=(TCP | SOCKET | PIPE | MEMORY) Which protocol to use when connecting to server (New in 4.1)
port Default port number.
return-found-rows Tell mysql_info() to return found rows instead of updated rows when using UPDATE.
shared-memory-base-name=name Shared memory name to use to connect to server (default is "MySQL"). New in MySQL 4.1.
socket Default socket number.
user Default user.

Note that timeout has been replaced by connect-timeout, but timeout will still work for a while.

For more information about option files, see section 4.1.2 `my.cnf' Option Files.

8.1.3.165 Return Values

Zero for success. Non-zero if you used an unknown option.

8.1.3.166 Example

MYSQL mysql;

mysql_init(&mysql);
mysql_options(&mysql,MYSQL_OPT_COMPRESS,0);
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"odbc");
if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
    fprintf(stderr, "Failed to connect to database: Error: %s\n",
          mysql_error(&mysql));
}

The above requests the client to use the compressed client/server protocol and read the additional options from the odbc section in the `my.cnf' file.

8.1.3.167 mysql_ping()

int mysql_ping(MYSQL *mysql)

8.1.3.168 Description

Checks whether the connection to the server is working. If it has gone down, an automatic reconnection is attempted.

This function can be used by clients that remain idle for a long while, to check whether the server has closed the connection and reconnect if necessary.

8.1.3.169 Return Values

Zero if the server is alive. Non-zero if an error occurred.

8.1.3.170 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.171 mysql_query()

int mysql_query(MYSQL *mysql, const char *query)

8.1.3.172 Description

Executes the SQL query pointed to by the null-terminated string query. The query must consist of a single SQL statement. You should not add a terminating semicolon (`;') or \g to the statement.

mysql_query() cannot be used for queries that contain binary data; you should use mysql_real_query() instead. (Binary data may contain the `\0' character, which mysql_query() interprets as the end of the query string.)

If you want to know if the query should return a result set or not, you can use mysql_field_count() to check for this. See section 8.1.3.85 mysql_field_count().

8.1.3.173 Return Values

Zero if the query was successful. Non-zero if an error occurred.

8.1.3.174 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.175 mysql_real_connect()

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned int client_flag)

8.1.3.176 Description

mysql_real_connect() attempts to establish a connection to a MySQL database engine running on host. mysql_real_connect() must complete successfully before you can execute any of the other API functions, with the exception of mysql_get_client_info().

The parameters are specified as follows:

8.1.3.177 Return Values

A MYSQL* connection handle if the connection was successful, NULL if the connection was unsuccessful. For a successful connection, the return value is the same as the value of the first parameter.

8.1.3.178 Errors

CR_CONN_HOST_ERROR
Failed to connect to the MySQL server.
CR_CONNECTION_ERROR
Failed to connect to the local MySQL server.
CR_IPSOCK_ERROR
Failed to create an IP socket.
CR_OUT_OF_MEMORY
Out of memory.
CR_SOCKET_CREATE_ERROR
Failed to create a Unix socket.
CR_UNKNOWN_HOST
Failed to find the IP address for the hostname.
CR_VERSION_ERROR
A protocol mismatch resulted from attempting to connect to a server with a client library that uses a different protocol version. This can happen if you use a very old client library to connect to a new server that wasn't started with the --old-protocol option.
CR_NAMEDPIPEOPEN_ERROR
Failed to create a named pipe on Windows.
CR_NAMEDPIPEWAIT_ERROR
Failed to wait for a named pipe on Windows.
CR_NAMEDPIPESETSTATE_ERROR
Failed to get a pipe handler on Windows.
CR_SERVER_LOST
If connect_timeout > 0 and it took longer then connect_timeout seconds to connect to the server or if the server died while executing the init-command.

8.1.3.179 Example

MYSQL mysql;

mysql_init(&mysql);
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"your_prog_name");
if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
    fprintf(stderr, "Failed to connect to database: Error: %s\n",
          mysql_error(&mysql));
}

By using mysql_options() the MySQL library will read the [client] and [your_prog_name] sections in the `my.cnf' file which will ensure that your program will work, even if someone has set up MySQL in some non-standard way.

Note that upon connection, mysql_real_connect() sets the reconnect flag (part of the MYSQL structure) to a value of 1. This flag indicates, in the event that a query cannot be performed because of a lost connection, to try reconnecting to the server before giving up.

8.1.3.180 mysql_real_escape_string()

unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length)

8.1.3.181 Description

This function is used to create a legal SQL string that you can use in a SQL statement. See section 6.1.1.1 Strings.

The string in from is encoded to an escaped SQL string, taking into account the current character set of the connection. The result is placed in to and a terminating null byte is appended. Characters encoded are NUL (ASCII 0), `\n', `\r', `\', `'', `"', and Control-Z (see section 6.1.1 Literals: How to Write Strings and Numbers). (Strictly speaking, MySQL requires only that backslash and the quote character used to quote the string in the query be escaped. This function quotes the other characters to make them easier to read in log files.)

The string pointed to by from must be length bytes long. You must allocate the to buffer to be at least length*2+1 bytes long. (In the worst case, each character may need to be encoded as using two bytes, and you need room for the terminating null byte.) When mysql_real_escape_string() returns, the contents of to will be a null-terminated string. The return value is the length of the encoded string, not including the terminating null character.

8.1.3.182 Example

char query[1000],*end;

end = strmov(query,"INSERT INTO test_table values(");
*end++ = '\'';
end += mysql_real_escape_string(&mysql, end,"What's this",11);
*end++ = '\'';
*end++ = ',';
*end++ = '\'';
end += mysql_real_escape_string(&mysql, end,"binary data: \0\r\n",16);
*end++ = '\'';
*end++ = ')';

if (mysql_real_query(&mysql,query,(unsigned int) (end - query)))
{
   fprintf(stderr, "Failed to insert row, Error: %s\n",
           mysql_error(&mysql));
}

The strmov() function used in the example is included in the mysqlclient library and works like strcpy() but returns a pointer to the terminating null of the first parameter.

8.1.3.183 Return Values

The length of the value placed into to, not including the terminating null character.

8.1.3.184 Errors

None.

8.1.3.185 mysql_real_query()

int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)

8.1.3.186 Description

Executes the SQL query pointed to by query, which should be a string length bytes long. The query must consist of a single SQL statement. You should not add a terminating semicolon (`;') or \g to the statement.

You must use mysql_real_query() rather than mysql_query() for queries that contain binary data, because binary data may contain the `\0' character. In addition, mysql_real_query() is faster than mysql_query() because it does not call strlen() on the query string.

If you want to know if the query should return a result set or not, you can use mysql_field_count() to check for this. See section 8.1.3.85 mysql_field_count().

8.1.3.187 Return Values

Zero if the query was successful. Non-zero if an error occurred.

8.1.3.188 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.189 mysql_reload()

int mysql_reload(MYSQL *mysql)

8.1.3.190 Description

Asks the MySQL server to reload the grant tables. The connected user must have the RELOAD privilege.

This function is deprecated. It is preferable to use mysql_query() to issue a SQL FLUSH PRIVILEGES statement instead.

8.1.3.191 Return Values

Zero for success. Non-zero if an error occurred.

8.1.3.192 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.193 mysql_row_seek()

MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset)

8.1.3.194 Description

Sets the row cursor to an arbitrary row in a query result set. This requires that the result set structure contains the entire result of the query, so mysql_row_seek() may be used in conjunction only with mysql_store_result(), not with mysql_use_result().

The offset should be a value returned from a call to mysql_row_tell() or to mysql_row_seek(). This value is not simply a row number; if you want to seek to a row within a result set using a row number, use mysql_data_seek() instead.

8.1.3.195 Return Values

The previous value of the row cursor. This value may be passed to a subsequent call to mysql_row_seek().

8.1.3.196 Errors

None.

8.1.3.197 mysql_row_tell()

MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result)

8.1.3.198 Description

Returns the current position of the row cursor for the last mysql_fetch_row(). This value can be used as an argument to mysql_row_seek().

You should use mysql_row_tell() only after mysql_store_result(), not after mysql_use_result().

8.1.3.199 Return Values

The current offset of the row cursor.

8.1.3.200 Errors

None.

8.1.3.201 mysql_select_db()

int mysql_select_db(MYSQL *mysql, const char *db)

8.1.3.202 Description

Causes the database specified by db to become the default (current) database on the connection specified by mysql. In subsequent queries, this database is the default for table references that do not include an explicit database specifier.

mysql_select_db() fails unless the connected user can be authenticated as having permission to use the database.

8.1.3.203 Return Values

Zero for success. Non-zero if an error occurred.

8.1.3.204 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.205 mysql_shutdown()

int mysql_shutdown(MYSQL *mysql)

8.1.3.206 Description

Asks the database server to shut down. The connected user must have SHUTDOWN privileges.

8.1.3.207 Return Values

Zero for success. Non-zero if an error occurred.

8.1.3.208 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.209 mysql_stat()

char *mysql_stat(MYSQL *mysql)

8.1.3.210 Description

Returns a character string containing information similar to that provided by the mysqladmin status command. This includes uptime in seconds and the number of running threads, questions, reloads, and open tables.

8.1.3.211 Return Values

A character string describing the server status. NULL if an error occurred.

8.1.3.212 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.213 mysql_store_result()

MYSQL_RES *mysql_store_result(MYSQL *mysql)

8.1.3.214 Description

You must call mysql_store_result() or mysql_use_result() for every query that successfully retrieves data (SELECT, SHOW, DESCRIBE, EXPLAIN).

You don't have to call mysql_store_result() or mysql_use_result() for other queries, but it will not do any harm or cause any notable performance if you call mysql_store_result() in all cases. You can detect if the query didn't have a result set by checking if mysql_store_result() returns 0 (more about this later one).

If you want to know if the query should return a result set or not, you can use mysql_field_count() to check for this. See section 8.1.3.85 mysql_field_count().

mysql_store_result() reads the entire result of a query to the client, allocates a MYSQL_RES structure, and places the result into this structure.

mysql_store_result() returns a null pointer if the query didn't return a result set (if the query was, for example, an INSERT statement).

mysql_store_result() also returns a null pointer if reading of the result set failed. You can check if you got an error by checking if mysql_error() doesn't return a null pointer, if mysql_errno() returns <> 0, or if mysql_field_count() returns <> 0.

An empty result set is returned if there are no rows returned. (An empty result set differs from a null pointer as a return value.)

Once you have called mysql_store_result() and got a result back that isn't a null pointer, you may call mysql_num_rows() to find out how many rows are in the result set.

You can call mysql_fetch_row() to fetch rows from the result set, or mysql_row_seek() and mysql_row_tell() to obtain or set the current row position within the result set.

You must call mysql_free_result() once you are done with the result set.

See section 8.1.12.1 Why Is It that After mysql_query() Returns Success, mysql_store_result() Sometimes Returns NULL?.

8.1.3.215 Return Values

A MYSQL_RES result structure with the results. NULL if an error occurred.

8.1.3.216 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_OUT_OF_MEMORY
Out of memory.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.217 mysql_thread_id()

unsigned long mysql_thread_id(MYSQL *mysql)

8.1.3.218 Description

Returns the thread ID of the current connection. This value can be used as an argument to mysql_kill() to kill the thread.

If the connection is lost and you reconnect with mysql_ping(), the thread ID will change. This means you should not get the thread ID and store it for later. You should get it when you need it.

8.1.3.219 Return Values

The thread ID of the current connection.

8.1.3.220 Errors

None.

8.1.3.221 mysql_use_result()

MYSQL_RES *mysql_use_result(MYSQL *mysql)

8.1.3.222 Description

You must call mysql_store_result() or mysql_use_result() for every query that successfully retrieves data (SELECT, SHOW, DESCRIBE, EXPLAIN).

mysql_use_result() initiates a result set retrieval but does not actually read the result set into the client like mysql_store_result() does. Instead, each row must be retrieved individually by making calls to mysql_fetch_row(). This reads the result of a query directly from the server without storing it in a temporary table or local buffer, which is somewhat faster and uses much less memory than mysql_store_result(). The client will only allocate memory for the current row and a communication buffer that may grow up to max_allowed_packet bytes.

On the other hand, you shouldn't use mysql_use_result() if you are doing a lot of processing for each row on the client side, or if the output is sent to a screen on which the user may type a ^S (stop scroll). This will tie up the server and prevent other threads from updating any tables from which the data is being fetched.

When using mysql_use_result(), you must execute mysql_fetch_row() until a NULL value is returned, otherwise, the unfetched rows will be returned as part of the result set for your next query. The C API will give the error Commands out of sync; you can't run this command now if you forget to do this!

You may not use mysql_data_seek(), mysql_row_seek(), mysql_row_tell(), mysql_num_rows(), or mysql_affected_rows() with a result returned from mysql_use_result(), nor may you issue other queries until the mysql_use_result() has finished. (However, after you have fetched all the rows, mysql_num_rows() will accurately return the number of rows fetched.)

You must call mysql_free_result() once you are done with the result set.

8.1.3.223 Return Values

A MYSQL_RES result structure. NULL if an error occurred.

8.1.3.224 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_OUT_OF_MEMORY
Out of memory.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.3.225 mysql_commit()

my_bool mysql_commit(MYSQL *mysql)

8.1.3.226 Description

Commits the current transaction. Available from MySQL 4.1

8.1.3.227 Return Values

Zero if successful. Non-zero if an error occured.

8.1.3.228 Errors

None

8.1.3.229 mysql_rollback()

my_bool mysql_rollback(MYSQL *mysql)

8.1.3.230 Description

Rollbacks the current transaction. Available from MySQL 4.1

8.1.3.231 Return Values

Zero if successful. Non-zero if an error occured.

8.1.3.232 Errors

None.

8.1.3.233 mysql_autocommit()

my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)

8.1.3.234 Description

Sets autocommit mode on/off. If the mode is 1, set autocommit mode to on; in case of 0, set to off. Available from MySQL 4.1

8.1.3.235 Return Values

Zero if successful. Non-zero if an error occured

8.1.3.236 Errors

None.

8.1.3.237 mysql_more_results()

my_bool mysql_more_results(MYSQL *mysql)

8.1.3.238 Description

Returns true if more results exists from the currently executed query, and the application must call mysql_next_result() to fetch the results. Available from MySQL 4.1

8.1.3.239 Return Values

TRUE if more results exists. FALSE if no more results exists.

8.1.3.240 Errors

None.

8.1.3.241 mysql_next_result()

int mysql_next_result(MYSQL *mysql)

8.1.3.242 Description

If more query results exists, then mysql_next_result() reads the next query results and returns the status back to application. Available from MySQL 4.1

8.1.3.243 Return Values

Zero if successful. Non-zero if an error occured

8.1.3.244 Errors

None.

8.1.4 C API Prepared Statements

From MySQL 4.1, you can also make use of the prepared statements using the statement handler 'MYSQL_STMT', which supports multiple query executions along with input and output binding.

Prepared execution is an efficient way to execute a statement more than once. The statement is first parsed, or prepared. This is executed one or more times at a later time using the statement handle that is returned during the prepare.

Another advantage of prepared statements is that it uses a binary protocol which makes the data tranfer between client and server in a more efficient way than the old MySQL protocol.

Prepared execution is faster than direct execution for statements executed more than once, primarly becuase the query is parsed only once; In the case of direct execution, the query is parsed every time. Prepared execution also can provide a reduction in the network traffic becuase during the execute call, it only sends the data for the parameters.

8.1.5 C API Prepared Statements DataTypes

Prepared statements mainly uses the following two MYSQL_STMT and MYSQL_BIND structures:

MYSQL_STMT
This structure represents a statement handle to prepared statements.It is used for all statement related functions. The statement is initialized when the query is prepared using mysql_prepare(). One connection can have 'n' statement handles, and the limit depends up on the system resources.
MYSQL_BIND
This structure is used in order to bind parameter buffers(mysql_bind_param()) inorder to the parameters data to mysql_execute() call; as well as to bind row buffers(mysql_bind_result()) to fetch the result set data using mysql_fetch(). The MYSQL_BIND structure contains the members listed here:
enum enum_field_types buffer_type [input]
The type of the buffer. The type value must be one of the following:
  • MYSQL_TYPE_TINY
  • MYSQL_TYPE_SHORT
  • MYSQL_TYPE_LONG
  • MYSQL_TYPE_LONGLONG
  • MYSQL_TYPE_FLOAT
  • MYSQL_TYPE_DOUBLE
  • MYSQL_TYPE_TIME
  • MYSQL_TYPE_DATE
  • MYSQL_TYPE_DATETIME
  • MYSQL_TYPE_TIMESTAMP
  • MYSQL_TYPE_STRING
  • MYSQL_TYPE_VAR_STRING
  • MYSQL_TYPE_TINY_BLOB
  • MYSQL_TYPE_MEDIUM_BLOB
  • MYSQL_TYPE_LONG_BLOB
  • MYSQL_TYPE_BLOB
void *buffer [input/output]
A pointer to a buffer for the parameters data in case if it is used to supply parameters data or pointer to a buffer in which to return the data when the structure is used for result set bind.
unsigned long buffer_length [input]
Length of the *buffer in bytes. For character and binary C data, the buffer_length specifies the length of the *buffer to be used as a parameter data in case if it is used with mysql_bind_param() or to return that many bytes when fetching results when this is used with mysql_bind_result().
long *length [input/output]
Pointer to the buffer for the parameter's length. When the structure is used as a input parameter data binding, then this argument points to a buffer that, when mysql_execute() is called, contains the length of the parameter value stored in *buffer. This is ignored except for character or binary C data. If the length is a null pointer, then the protocol assumes that all character and binary data are null terminated. When this structure is used in output binding, then mysql_fetch() return the the length of the data that is returned.
bool *is_null [input/output]
Indicates if the parameter data is NULL or fetched data is NULL.
MYSQL_TIME
This structure is used to send and receive DATE, TIME and TIMESTAMP data directly to/from server. The MYSQL_TIME structure contains the members listed here:
Member Type Description
year unsigned int Year.
month unsigned int Month of the year.
day unsigned int Day of the month.
hour unsigned int Hour of the day(TIME).
minute unsigned int Minute of the hour.
second unsigned int Second of the minute.
neg my_bool A boolean flag to indicate if the time is negative.
second_part unsigned long Fraction part of the second(not yet used)

8.1.6 C API Prepared Statements Function Overview

The functions available in the prepared statements are listed here and are described in greater detail in the later section. See section 8.1.7 C API Prepared Statement Function Descriptions.

Function Description
mysql_prepare() Prepares an SQL string for execution.
mysql_param_count() Returns the number of parameters in a prepared SQL statement.
mysql_prepare_result() Returns prepared statement meta information in the form of resultset.
mysql_bind_param() Binds a buffer to parameter markers in a prepared SQL statement.
mysql_execute() Executes the prepared statement.
mysql_stmt_affected_rows() Returns the number of rows changes/deleted/inserted by the last UPDATE, DELETE, or INSERT query.
mysql_bind_result() Binds application data buffers to columns in the resultset.
mysql_stmt_store_result() Retrieves the complete result set to the client.
mysql_fetch() Fetches the next rowset of data from the result set and returns data for all bound columns.
mysql_stmt_close() Frees memory used by prepared statement.
mysql_stmt_errno() Returns the error number for the last statement execution.
mysql_stmt_error() Returns the error message for the last statement execution.
mysql_send_long_data() Sends long data in chunks to server.

Call mysql_prepare() to prepare and initialize the statement handle, then call mysql_bind_param() to supply the parameters data, and then call mysql_execute() to execute the query. You can repeat the mysql_execute() by changing parameter values from the respective buffer supplied through mysql_bind_param().

In case if the query is a SELECT statement or any other query which results in a resultset, then mysql_prepare() will also return the result set meta data information in the form of MYSQL_RES result set through mysql_prepare_result().

You can supply the result buffers using mysql_bind_result(), so that the mysql_fetch() will automatically returns data to this buffers. This is row by row fetching.

You can also send the text or binary data in chunks to server using mysql_send_long_data(), by specifying the option is_long_data=1 or length=MYSQL_LONG_DATA or -2 in the MYSQL_BIND structure supplied with mysql_bind_param().

Once the statement execution is over, it must be freed using mysql_stmt_close so that it frees all the alloced resources for the statement handle.

8.1.6.1 Execution Steps:

To prepare and execute a statement, the application:

You can get the statement error code and message using mysql_stmt_errno() and mysql_stmt_error() respectively.

8.1.7 C API Prepared Statement Function Descriptions

You need to use the following functions when you want to prepare and execute the queries.

8.1.7.1 mysql_prepare()

MYSQL_STMT * mysql_prepare(MYSQL *mysql, const char *query, unsigned long length)

8.1.7.2 Description

Prepares the SQL query pointed to by the null-terminated string 'query'. The query must consist of a single SQL statement. You should not add a terminating semicolon (`;`) or \g to the statement.

The application can include one or more parameter markers in the SQL statement. To include a parameter marker, the appication embeds a question mark (?) into the SQL string at the appropriate position.

The markers are legal only in certain places in SQL statements. For example, they are not allowed in the select list(the list of columns to be returned by a SELECT statement), nor are they allowed as both operands of a binary operator such as the equal sign (=), becuase it would be impossible to determine the parameter type. In general, parameters are legal only in Data Manipulation Languange(DML) statements, and not in Data Defination Language(DDL) statements.

The parameter markers are then bound to application variables using mysql_bind_param().

8.1.7.3 Return Values

MYSQL_STMT if the prepare was successful. NULL if an error occured.

8.1.7.4 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order
CR_OUT_OF_MEMORY
Out of memory
CR_SERVER_GONE_ERROR
The MySQL server has gone away
CR_SERVER_LOST
The connection to the server was lost during the query
CR_UNKNOWN_ERROR
An unkown error occured

If the prepare is not successful, i.e. when mysql_prepare() returned a NULL statement, errors can be obtained by calling mysql_error().

8.1.7.5 Example

For the usage of mysql_prepare() refer to the Example from section 8.1.7.21 mysql_execute().

8.1.7.6 mysql_param_count()

unsigned int mysql_param_count(MYSQL_STMT *stmt)

8.1.7.7 Description

Returns the number of parameter markers present from the prepared query.

8.1.7.8 Return Values

An unsigned integer representing the number of parameters in a statement.

8.1.7.9 Errors

None

8.1.7.10 Example

For the usage of mysql_param_count() refer to the Example from section 8.1.7.21 mysql_execute().

8.1.7.11 mysql_prepare_result()

MYSQL_RES *mysql_prepare_result(MYSQL_STMT *stmt)

8.1.7.12 Description

If the mysql_prepare() resulted in a result set query, then mysql_prepare_result() returns the result set meta data in the form of MYSQL_RES structure; which can further be used to process the meta information such as total number of fields and individual field information. This resulted result set can be passed as an argument to any of the field based APIs in order to process the result set meta data information such as:

8.1.7.13 Return Values

A MYSQL_RES result structure. NULL if no meta information exists from the prepared query.

8.1.7.14 Errors

CR_OUT_OF_MEMORY
Out of memory
CR_UNKNOWN_ERROR
An unknown error occured

8.1.7.15 Example

For the usage of mysql_prepare_result() refer to the Example from section 8.1.7.40 mysql_fetch()

8.1.7.16 mysql_bind_param()

int mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)

8.1.7.17 Description

mysql_bind_param is used to bind data for the parameter markers in the SQL statement from mysql_prepare. It uses the structure MYSQL_BIND to supply the data. The supported buffer types are:

8.1.7.18 Return Values

Zero if the bind was successful. Non-zero if an error occured.

8.1.7.19 Errors

CR_NO_PREPARE_STMT
No prepared statement exists
CR_NO_PARAMETERS_EXISTS
No parameters exists to bind
CR_INVALID_BUFFER_USE
Indicates if the bind is to supply the long data in chunks and if the buffer type is non string or binary
CR_UNSUPPORTED_PARAM_TYPE
The conversion is not supported, possibly the buffer_type is illegal or its not from the above list of supported types.
CR_OUT_OF_MEMOR
Out of memory
CR_UNKNOWN_ERROR
An unknown error occured

8.1.7.20 Example

For the usage of mysql_bind_param() refer to the Example from section 8.1.7.21 mysql_execute().

8.1.7.21 mysql_execute()

int mysql_execute(MYSQL_STMT *stmt.

8.1.7.22 Description

mysql_execute() executes the prepared query associated with the statement handle. The parameter marker values will be sent to server during this call, so that server replaces markers with this newly supplied data.

If the statement is UPDATE,DELETE,or INSERT, the total number of changed/deletd/inserted values can be found by calling mysql_stmt_affected_rows. If this is a result set query, then one must call mysql_fetch() to fetch the data prior to calling any other calls which results in query processing. For more information on how to fetch the statement binary data, refer to section 8.1.7.40 mysql_fetch().

8.1.7.23 Return Values

mysql_execute() returns the following return values:

Return Value Description
0 Successful
1 Error occured. Error code and message can be obtained by calling mysql_stmt_errno() and mysql_stmt_error().

8.1.7.24 Errors

CR_NO_PREPARE_QUERY
No query prepared prior to execution
CR_ALL_PARAMS_NOT_BOUND
Not all parameters data is supplied
CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_OUT_OF_MEMORY
Out of memory.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.7.25 Example

The following example explains the uasage of mysql_prepare, mysql_param_count, mysql_bind_param, mysql_execute and mysql_stmt_affected_rows().


MYSQL_BIND   bind[3];
MYSQL_STMT   *stmt;
ulonglong    affected_rows;
long         length;
unsigned int param_count;
int          int_data;
short        small_data;
char         str_data[50], query[255];
my_bool      is_null;

  /* Set autocommit mode to true */
  mysql_autocommit(mysql, 1);
  
  if (mysql_query(mysql,"DROP TABLE IF EXISTS test_table"))
  {
    fprintf(stderr, "\n drop table failed");
    fprintf(stderr, "\n %s", mysql_error(mysql));
    exit(0);
  }
  if (mysql_query(mysql,"CREATE TABLE test_table(col1 int, col2 varchar(50), \
                                                 col3 smallint,\
                                                 col4 timestamp(14))"))
  {
    fprintf(stderr, "\n create table failed");
    fprintf(stderr, "\n %s", mysql_error(mysql));
    exit(0);
  }
  
  /* Prepare a insert query with 3 parameters */
  strmov(query, "INSERT INTO test_table(col1,col2,col3) values(?,?,?)");
  if(!(stmt = mysql_prepare(mysql, query, strlen(query))))
  {
    fprintf(stderr, "\n prepare, insert failed");
    fprintf(stderr, "\n %s", mysql_error(mysql));
    exit(0);
  }
  fprintf(stdout, "\n prepare, insert successful");

  /* Get the parameter count from the statement */
  param_count= mysql_param_count(stmt);

  fprintf(stdout, "\n total parameters in insert: %d", param_count);
  if (param_count != 3) /* validate parameter count */
  {
    fprintf(stderr, "\n invalid parameter count returned by MySQL");
    exit(0);
  }

  /* Bind the data for the parameters */

  /* INTEGER PART */
  bind[0].buffer_type= MYSQL_TYPE_LONG;
  bind[0].buffer= (char *)&int_data;
  bind[0].is_null= 0;
  bind[0].length= 0;

  /* STRING PART */
  bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
  bind[1].buffer= (char *)str_data;
  bind[1].buffer_length= sizeof(str_data);
  bind[1].is_null= 0;
  bind[1].length= 0;

  /* SMALLINT PART */
  bind[2].buffer_type= MYSQL_TYPE_SHORT;
  bind[2].buffer= (char *)&small_data;
  bind[2].is_null= &is_null;
  bind[2].length= 0;
  is_null= 0;

  /* Bind the buffers */
  if (mysql_bind_param(stmt, bind))
  {
    fprintf(stderr, "\n param bind failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }

  /* Specify the data */
  int_data= 10;             /* integer */
  strcpy(str_data,"MySQL"); /* string  */

  /* INSERT SMALLINT data as NULL */
  is_null= 1;

  /* Execute the insert statement - 1*/
  if (mysql_execute(stmt))
  {
    fprintf(stderr, "\n execute 1 failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    fprintf(stderr, "\n send a bug report to bugs@lists.mysql.com, by asking why this is not working ?");
    exit(0);
  }
    
  /* Get the total rows affected */   
  affected_rows= mysql_stmt_affected_rows(stmt);

  fprintf(stdout, "\n total affected rows: %lld", affected_rows);
  if (affected_rows != 1) /* validate affected rows */
  {
    fprintf(stderr, "\n invalid affected rows by MySQL");
    exit(0);
  }

  /* Re-execute the insert, by changing the values */
  int_data= 1000;             
  strcpy(str_data,"The most popular open source database"); 
  small_data= 1000;         /* smallint */
  is_null= 0;               /* reset NULL */
 
  /* Execute the insert statement - 2*/
  if (mysql_execute(stmt))
  {
    fprintf(stderr, "\n execute 2 failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }
    
  /* Get the total rows affected */   
  affected_rows= mysql_stmt_affected_rows(stmt);

  fprintf(stdout, "\n total affected rows: %lld", affected_rows);
  if (affected_rows != 1) /* validate affected rows */
  {
    fprintf(stderr, "\n invalid affected rows by MySQL");
    exit(0);
  }

  /* Close the statement */
  if (mysql_stmt_close(stmt))
  {
    fprintf(stderr, "\n failed while closing the statement");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }
  
  /* DROP THE TABLE */
  if (mysql_query(mysql,"DROP TABLE test_table"))
  {
    fprintf(stderr, "\n drop table failed");
    fprintf(stderr, "\n %s", mysql_error(mysql));
    exit(0);
  }
  fprintf(stdout, "Success, MySQL prepared statements are working!!!");

8.1.7.26 mysql_stmt_affected_rows()

ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)

8.1.7.27 Description

Returns total number of rows changed by the last execute statement. May be called immediatlely after mysql_execute() for UPDATE,DELETE,or INSERT statements.For SELECT statements, mysql_stmt_affected rows works like mysql_num_rows().

8.1.7.28 Return Values

An integer greater than zero indicates the number of rows affected or retrieved. Zero indicates that no records where updated for an UPDATE statement, no rows matched the WHERE clause in the query or that no query has yet been executed. -1 indicates that the query returned an error or that, for a SELECT query, mysql_stmt_affected_rows() was called prior to calling mysql_fetch().

8.1.7.29 Errors

None.

8.1.7.30 Example

For the usage of mysql_stmt_affected_rows() refer to the Example from section 8.1.7.21 mysql_execute().

8.1.7.31 mysql_bind_result()

my_bool mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)

8.1.7.32 Description

mysql_bind_result() is used to associate, or bind, columns in the resultset to data buffers and length buffers. When mysql_fetch() is called to fetch data, the MySQL client protocol returns the data for the bound columns in the specified buffers.

Note that all columns must be bound prior to calling mysql_fetch() in case of fetching the data to buffers; else mysql_fetch() simply ignores the data fetch; also the buffers should be sufficient enough to hold the data as the protocol doesn't return the data in chunks.

A column can be bound or rebound at any time, even after data has been fetched from the result set. The new binding takes effect the next time mysql_fetch() is called. For example, suppose an application binds the columns in a result set and calls mysql_fetch(). The mysql protocol returns data in the bound buffers. Now suppose the application binds the columns to a different set of buffers, then the protocol does not place the data for the just fetched row in the newly bound buffers. Instead, it does when the next mysql_fetch() is called.

To bind a column, an application calls mysql_bind_result() and passes the type, address, and the address of the length buffer. The supported buffer types are:

8.1.7.33 Return Values

Zero if the bind was successful. Non-zero if an error occured.

8.1.7.34 Errors

CR_NO_PREPARE_STMT
No prepared statement exists
CR_UNSUPPORTED_PARAM_TYPE
The conversion is not supported, possibly the buffer_type is illegal or its not from the list of supported types.
CR_OUT_OF_MEMOR
Out of memory
CR_UNKNOWN_ERROR
An unknown error occured

8.1.7.35 Example

For the usage of mysql_bind_result() refer to the Example from section 8.1.7.40 mysql_fetch()

8.1.7.36 mysql_stmt_store_result()

int mysql_stmt_store_result(MYSQL_STMT *stmt)

8.1.7.37 Description

You must call mysql_stmt_store_result() for every query that successfully retrieves data(SELECT,SHOW,DESCRIBE,EXPLAIN), and only if you want to buffer the complete result set by the client, so that the subsequent mysql_fetch() call returns buffered data.

You don't have to call mysql_stmt_store_result() for other queries, but it will not harm or cause any notable performance in all cases.You can detect if the query didn't have a result set by checking if mysql_prepare_result() returns 0. For more information refer to section 8.1.7.11 mysql_prepare_result().

8.1.7.38 Return Values

Zero if the results are buffered successfully or Non Zero in case of an error.

8.1.7.39 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_OUT_OF_MEMORY
Out of memory.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.

8.1.7.40 mysql_fetch()

int mysql_fetch(MYSQL_STMT *stmt)

8.1.7.41 Description

mysql_fetch() returns the next rowset in the result set. It can be called only while the result set exists i.e. after a call to mysql_execute() that creates a result set or after mysql_stmt_store_result(), which is called after mysql_execute() to buffer the entire resultset.

If row buffers are bound using mysql_bind_result(), it returns the data in those buffers for all the columns in the current row set and the lengths are returned to the length pointer.

Note that, all columns must be bound by the application.

If the data fetched is a NULL data, then the is_null value from MYSQL_BIND contains TRUE, 1, else the data and its length is returned to *buffer and *length variables based on the buffer type specified by the application. All numeric, float and double types have the fixed length(in bytes) as listed below:

Type Length
MYSQL_TYPE_TINY 1
MYSQL_TYPE_SHORT 2
MYSQL_TYPE_LONG 4
MYSQL_TYPE_FLOAT 4
MYSQL_TYPE_LONGLONG 8
MYSQL_TYPE_DOUBLE 8
MYSQL_TYPE_TIME sizeof(MYSQL_TIME)
MYSQL_TYPE_DATE sizeof(MYSQL_TIME)
MYSQL_TYPE_DATETIME sizeof(MYSQL_TIME)
MYSQL_TYPE_TIMESTAMP sizeof(MYSQL_TIME)
MYSQL_TYPE_STRING data length
MYSQL_TYPE_VAR_STRING data_length
MYSQL_TYPE_BLOB data_length
MYSQL_TYPE_TINY_BLOB data_length
MYSQL_TYPE_MEDIUM_BLOB data_length
MYSQL_TYPE_LONG_BLOB data_length


where *data_length is nothing but the 'Actual length of the data'.

8.1.7.42 Return Values

Return Value Description
0 Successful, the data has been fetched to application data buffers.
1 Error occured. Error code and message can be obtained by calling mysql_stmt_errno() and mysql_stmt_error().
100, MYSQL_NO_DATA No more rows/data exists

8.1.7.43 Errors

CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_OUT_OF_MEMORY
Out of memory.
CR_SERVER_GONE_ERROR
The MySQL server has gone away.
CR_SERVER_LOST
The connection to the server was lost during the query.
CR_UNKNOWN_ERROR
An unknown error occurred.
CR_UNSUPPORTED_PARAM_TYPE
If the buffer type is MYSQL_TYPE_DATE,DATETIME,TIME,or TIMESTAMP; and if the field type is not DATE, TIME, DATETIME or TIMESTAMP.
All other unsupported conversion errors are returned from mysql_bind_result().

8.1.7.44 Example

The following example explains the usage of mysql_prepare_result, mysql_bind_result(), and mysql_fetch()

  
MYSQL_STMT *stmt;  
MYSQL_BIND bind[2];
MYSQL_RES  *result;
int        int_data;
long       int_length, str_length;
char       str_data[50];
my_bool    is_null[2];

  query= "SELECT col1, col2 FROM test_table WHERE col1= 10)");
  if (!(stmt= mysql_prepare(&mysql, query, strlen(query)))
  {
    fprintf(stderr, "\n prepare failed");
    fprintf(stderr, "\n %s", mysql_error(&stmt));
    exit(0);
  }

  /* Get the fields meta information */
  if (!(result= mysql_prepare_result(stmt)))
  {
    fprintf(stderr, "\n prepare_result failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }

  fprintf(stdout, "Total fields: %ld", mysql_num_fields(result));

  if (mysql_num_fields(result) != 2)
  {
    fprintf(stderr, "\n prepare returned invalid field count");
    exit(0);
  }

  /* Execute the SELECT query */
  if (mysql_execute(stmt))
  {
    fprintf(stderr, "\n execute failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));  
    exit(0);
  }

  /* Bind the result data buffers */
  bind[0].buffer_type= MYSQL_TYPE_LONG;
  bind[0].buffer= (char *)&int_data;
  bind[0].is_null= &is_null[0];
  bind[0].length= &int_length;

  bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
  bind[1].buffer= (void *)str_data;
  bind[1].is_null= &is_null[1];
  bind[1].length= &str_length;

  if (mysql_bind_result(stmt, bind))
  {
    fprintf(stderr, "\n bind_result failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }  

  /* Now fetch data to buffers */
  if (mysql_fetch(stmt))
  {
    fprintf(stderr, "\n fetch failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }  
  
  if (is_null[0])
    fprintf(stdout, "\n Col1 data is NULL");
  else
    fprintf(stdout, "\n Col1: %d, length: %ld", int_data, int_length);
   
   if (is_null[1])
     fprintf(stdout, "\n Col2 data is NULL");
   else
    fprintf(stdout, "\n Col2: %s, length: %ld", str_data, str_length);

   
  /* call mysql_fetch again */
  if (mysql_fetch(stmt) |= MYSQL_NO_DATA)
  {
    fprintf(stderr, "\n fetch return more than one row);
    exit(0);
  }  

  /* Free the prepare result meta information */
  mysql_free_result(result);

  /* Free the statement handle */
  if (mysql_stmt_free(stmt))
  {
    fprintf(stderr, "\n failed to free the statement handle);
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }  
 

8.1.7.45 mysql_send_long_data()

int mysql_send_long_data(MYSQL_STMT *stmt, unsigned int parameter_number, const char *data, ulong length)

8.1.7.46 Description

Allows an application to send the data in pieces or chunks to server. This function can be used to send character or binary data values in parts to a column(it must be a text or blob) with a character or binary data type.

The data is a pointer to buffer containing the actual data for the parameter represendted by parameter_number. The length indicates the amount of data to be sent in bytes.

8.1.7.47 Return Values

Zero if the data is sent successfully to server. Non-zero if an error occured.

8.1.7.48 Errors

CR_INVALID_PARAMETER_NO
Invalid parameter number
CR_COMMANDS_OUT_OF_SYNC
Commands were executed in an improper order.
CR_SERVER_GONE_ERROR
The MySQL server has gone away
CR_OUT_OF_MEMOR
Out of memory
CR_UNKNOWN_ERROR
An unknown error occured

8.1.7.49 Example

The following example explains how to send the data in chunks to text column:

  
MYSQL_BIND bind[1];
long       length;

  query= "INSERT INTO test_long_data(text_column) VALUES(?)");
  if (!mysql_prepare(&mysql, query, strlen(query))
  {
    fprintf(stderr, "\n prepare failed");
    fprintf(stderr, "\n %s", mysql_error(&stmt));
    exit(0);
  }
   memset(bind, 0, sizeof(bind));
   bind[0].buffer_type= MYSQL_TYPE_STRING;
   bind[0].length= &length;
   bind[0].is_null= 0;

  /* Bind the buffers */
  if (mysql_bind_param(stmt, bind))
  {
    fprintf(stderr, "\n param bind failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }

   /* Supply data in chunks to server */
   if (!mysql_send_long_data(stmt,1,"MySQL",5))
  {
    fprintf(stderr, "\n send_long_data failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }

   /* Supply the next piece of data */
   if (mysql_send_long_data(stmt,1," - The most popular open source database",40))
  {
    fprintf(stderr, "\n send_long_data failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }

   /* Now, execute the query */
   if (mysql_execute(stmt))
  {
    fprintf(stderr, "\n mysql_execute failed");
    fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
    exit(0);
  }

   This inserts the data, "MySQL - The most popular open source database" 
   to the field 'text_column'.  

8.1.7.50 mysql_stmt_close()

my_bool mysql_stmt_close(MYSQL_STMT *)

8.1.7.51 Description

Closes the prepared statement. mysql_stmt_close() also deallocates the statement handle pointed to by stmt.

If the current query results are pending or un-read; this cancels the query results; so that next call can be executed.

8.1.7.52 Return Values

Zero if the statement was freed successfully. Non-zero if an error occured.

8.1.7.53 Errors

CR_SERVER_GONE_ERROR
The MySQL server has gone away
CR_UNKNOWN_ERROR
An unkown error occured

8.1.7.54 Example

For the usage of mysql_stmt_close() refer to the Example from section 8.1.7.21 mysql_execute().

8.1.7.55 mysql_stmt_errno()

unsigned int mysql_stmt_errno(MYSQL_STMT *stmt)

8.1.7.56 Description

For the statement specified by stmt, mysql_stmt_errno() returns the error code for the most recently invoked statement API function that can succeed or fail. A return value of zero means that no error occured. Client error message numbers are listed in the MySQL errmsg.h header file. Server error message numbers are listed in mysqld_error.h. In the MySQL source distribution you can find a complete list of error messages and error numbers in the file Docs/mysqld_error.txt

8.1.7.57 Return Values

An error code value. Zero if no error occured.

8.1.7.58 Errors

None

8.1.7.59 mysql_stmt_error()

char *mysql_stmt_error(MYSQL_STMT *stmt)

8.1.7.60 Description

For the statement specified by stmt, mysql_stmt_error() returns the error message for the most recently invoked statement API that can succeed or fail. An empty string ("") is returned if no error occured. This means the following two sets are equivalent:


if (mysql_stmt_errno(stmt))
{
  // an error occured
}

if (mysql_stmt_error(stmt))
{
  // an error occured
}

The language of the client error messages many be changed by recompiling the MySQL client library. Currently you can choose error messages in several different languages.

8.1.7.61 Return Values

A character string that describes the error. An empry string if no error occured.

8.1.7.62 Errors

None

8.1.8 C API Handling multiple query executions

From version 4.1, MySQL supports the multi query execution in a single command. In order to do this, you must set the client flag CLIENT_MULTI_QUERIES option when opening the connection.

By default mysql_query() or mysql_real_query() returns only the first query status and the subsequent queries status can be processed using mysql_more_results() and mysql_next_result().


  /* Connect to server with option CLIENT_MULTI_QUERIES */
  mysql_real_query(..., CLIENT_MULTI_QUERIES);

  /* Now execute multiple queries */
  mysql_query(mysql,"DROP TABLE IF EXISTS test_table;\
                     CREATE TABLE test_table(id int);\
                     INSERT INTO test_table VALUES(10);\
                     UPDATE test_table SET id=20 WHERE id=10;\
                     SELECT * FROM test_table;\
                     DROP TABLE test_table";
  while (mysql_more_results(mysql))
  {
    /* Process all results */
    mysql_next_result(mysql);
    ...
    printf("total affected rows: %lld", mysql_affected_rows(mysql));
    ...
    if ((result= mysql_store_result(mysql))
    {
      /* Returned a result set, process it */
    }
  }

8.1.9 C API Handling DATE, TIME and TIMESTAMP

Using the new binary protocol from MySQL 4.1 and above, one can send and receive the DATE, TIME and TIMESTAMP data using the MYSQL_TIME structure.

MYSQL_TIME structure consites of the following members:

In order to send the data, one must use the prepared statements through mysql_prepare() and mysql_execute(); and must bind the parameter using type as MYSQL_TYPE_DATE inorder to process date value, MYSQL_TYPE_TIME for time and MYSQL_TYPE_DATETIME or MYSQL_TYPE_TIMESTAMP for datetime/timestamp using mysql_bind_param() when sending and mysql_bind_results() while receiving the data.

Here is a simple example; which inserts the DATE, TIME and TIMESTAMP data.


MYSQL_TIME  ts;
MYSQL_BIND  bind[3];
MYSQL_STMT  *stmt;
  
  strmov(query, "INSERT INTO test_table(date_field, time_field,
                                        timestamp_field) VALUES(?,?,?");

  stmt= mysql_prepare(mysql, query, strlen(query))); 

  /* setup input buffers for all 3 parameters */
  bind[0].buffer_type= MYSQL_TYPE_DATE;
  bind[0].buffer= (char *)&ts;
  bind[0].is_null= 0;
  bind[0].length= 0;
  ..
  bind[1]= bind[2]= bind[0];
  ..

  mysql_bind_param(stmt, bind);

  /* supply the data to be sent is the ts structure */
  ts.year= 2002;
  ts.month= 02;
  ts.day= 03;

  ts.hour= 10;
  ts.minute= 45;
  ts.second= 20;

  mysql_execute(stmt);
  .. 

8.1.10 C API Threaded Function Descriptions

You need to use the following functions when you want to create a threaded client. See section 8.1.14 How to Make a Threaded Client.

8.1.10.1 my_init()

void my_init(void)

8.1.10.2 Description

This function needs to be called once in the program before calling any MySQL function. This initialises some global variables that MySQL needs. If you are using a thread-safe client library, this will also call mysql_thread_init() for this thread.

This is automatically called by mysql_init(), mysql_server_init() and mysql_connect().

8.1.10.3 Return Values

None.

8.1.10.4 mysql_thread_init()

my_bool mysql_thread_init(void)

8.1.10.5 Description

This function needs to be called for each created thread to initialise thread-specific variables.

This is automatically called by my_init() and mysql_connect().

8.1.10.6 Return Values

None.

8.1.10.7 mysql_thread_end()

void mysql_thread_end(void)

8.1.10.8 Description

This function needs to be called before calling pthread_exit() to free memory allocated by mysql_thread_init().

Note that this function is not invoked automatically by the client library. It must be called explicitly to avoid a memory leak.

8.1.10.9 Return Values

None.

8.1.10.10 mysql_thread_safe()

unsigned int mysql_thread_safe(void)

8.1.10.11 Description

This function indicates whether the client is compiled as thread-safe.

8.1.10.12 Return Values

1 is the client is thread-safe, 0 otherwise.

8.1.11 C API Embedded Server Function Descriptions

You must use the following functions if you want to allow your application to be linked against the embedded MySQL server library. See section 8.1.15 libmysqld, the Embedded MySQL Server Library.

If the program is linked with -lmysqlclient instead of -lmysqld, these functions do nothing. This makes it possible to choose between using the embedded MySQL server and a stand-alone server without modifying any code.

8.1.11.1 mysql_server_init()

int mysql_server_init(int argc, char **argv, char **groups)

8.1.11.2 Description

This function must be called once in the program using the embedded server before calling any other MySQL function. It starts up the server and initialises any subsystems (mysys, InnoDB, etc.) that the server uses. If this function is not called, the program will crash. If you are using the DBUG package that comes with MySQL, you should call this after you have called MY_INIT().

The argc and argv arguments are analogous to the arguments to main(). The first element of argv is ignored (it typically contains the program name). For convenience, argc may be 0 (zero) if there are no command-line arguments for the server. mysql_server_init() makes a copy of the arguments so it's safe to destroy argv or groups after the call.

The NULL-terminated list of strings in groups selects which groups in the option files will be active. See section 4.1.2 `my.cnf' Option Files. For convenience, groups may be NULL, in which case the [server] and [emedded] groups will be active.

8.1.11.3 Example

#include <mysql.h>
#include <stdlib.h>

static char *server_args[] = {
  "this_program",       /* this string is not used */
  "--datadir=.",
  "--key_buffer_size=32M"
};
static char *server_groups[] = {
  "embedded",
  "server",
  "this_program_SERVER",
  (char *)NULL
};

int main(void) {
  mysql_server_init(sizeof(server_args) / sizeof(char *),
                    server_args, server_groups);

  /* Use any MySQL API functions here */

  mysql_server_end();

  return EXIT_SUCCESS;
}

8.1.11.4 Return Values

0 if okay, 1 if an error occurred.

8.1.11.5 mysql_server_end()

void mysql_server_end(void)

8.1.11.6 Description

This function must be called once in the program after all other MySQL functions. It shuts down the embedded server.

8.1.11.7 Return Values

None.

8.1.12 Common questions and problems when using the C API

8.1.12.1 Why Is It that After mysql_query() Returns Success, mysql_store_result() Sometimes Returns NULL?

It is possible for mysql_store_result() to return NULL following a successful call to mysql_query(). When this happens, it means one of the following conditions occurred:

You can always check whether the statement should have produced a non-empty result by calling mysql_field_count(). If mysql_field_count() returns zero, the result is empty and the last query was a statement that does not return values (for example, an INSERT or a DELETE). If mysql_field_count() returns a non-zero value, the statement should have produced a non-empty result. See the description of the mysql_field_count() function for an example.

You can test for an error by calling mysql_error() or mysql_errno().

8.1.12.2 What Results Can I Get From a Query?

In addition to the result set returned by a query, you can also get the following information:

8.1.12.3 How Can I Get the Unique ID for the Last Inserted Row?

If you insert a record in a table containing a column that has the AUTO_INCREMENT attribute, you can get the most recently generated ID by calling the mysql_insert_id() function.

You can also retrieve the ID by using the LAST_INSERT_ID() function in a query string that you pass to mysql_query().

You can check if an AUTO_INCREMENT index is used by executing the following code. This also checks if the query was an INSERT with an AUTO_INCREMENT index:

if (mysql_error(&mysql)[0] == 0 &&
    mysql_num_fields(result) == 0 &&
    mysql_insert_id(&mysql) != 0)
{
    used_id = mysql_insert_id(&mysql);
}

The most recently generated ID is maintained in the server on a per-connection basis. It will not be changed by another client. It will not even be changed if you update another AUTO_INCREMENT column with a non-magic value (that is, a value that is not NULL and not 0).

If you want to use the ID that was generated for one table and insert it into a second table, you can use SQL statements like this:

INSERT INTO foo (auto,text)
    VALUES(NULL,'text');              # generate ID by inserting NULL
INSERT INTO foo2 (id,text)
    VALUES(LAST_INSERT_ID(),'text');  # use ID in second table

8.1.12.4 Problems Linking with the C API

When linking with the C API, the following errors may occur on some systems:

gcc -g -o client test.o -L/usr/local/lib/mysql -lmysqlclient -lsocket -lnsl

Undefined        first referenced
 symbol          in file
floor            /usr/local/lib/mysql/libmysqlclient.a(password.o)
ld: fatal: Symbol referencing errors. No output written to client

If this happens on your system, you must include the math library by adding -lm to the end of the compile/link line.

8.1.13 Building Client Programs

If you compile MySQL clients that you've written yourself or that you obtain from a third-party, they must be linked using the -lmysqlclient -lz option on the link command. You may also need to specify a -L option to tell the linker where to find the library. For example, if the library is installed in `/usr/local/mysql/lib', use -L/usr/local/mysql/lib -lmysqlclient -lz on the link command.

For clients that use MySQL header files, you may need to specify a -I option when you compile them (for example, -I/usr/local/mysql/include), so the compiler can find the header files.

To make the above simpler on Unix we have provied the mysql_config script for you. See section 4.8.9 mysql_config, Get compile options for compiling clients.

You can use this to compile a MySQL client by as follows:

CFG=/usr/local/mysql/bin/mysql_config
sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"

The sh -c is need to get the shell to not threat the output from mysql_config as one word.

8.1.14 How to Make a Threaded Client

The client library is almost thread-safe. The biggest problem is that the subroutines in `net.c' that read from sockets are not interrupt safe. This was done with the thought that you might want to have your own alarm that can break a long read to a server. If you install interrupt handlers for the SIGPIPE interrupt, the socket handling should be thread-safe.

In the older binaries we distribute on our web site (http://www.mysql.com/), the client libraries are not normally compiled with the thread-safe option (the Windows binaries are by default compiled to be thread-safe). Newer binary distributions should have both a normal and a thread-safe client library.

To get a threaded client where you can interrupt the client from other threads and set timeouts when talking with the MySQL server, you should use the -lmysys, -lmystrings, and -ldbug libraries and the net_serv.o code that the server uses.

If you don't need interrupts or timeouts, you can just compile a thread-safe client library (mysqlclient_r) and use this. See section 8.1 MySQL C API. In this case you don't have to worry about the net_serv.o object file or the other MySQL libraries.

When using a threaded client and you want to use timeouts and interrupts, you can make great use of the routines in the `thr_alarm.c' file. If you are using routines from the mysys library, the only thing you must remember is to call my_init() first! See section 8.1.10 C API Threaded Function Descriptions.

All functions except mysql_real_connect() are by default thread-safe. The following notes describe how to compile a thread-safe client library and use it in a thread-safe manner. (The notes below for mysql_real_connect() actually apply to mysql_connect() as well, but because mysql_connect() is deprecated, you should be using mysql_real_connect() anyway.)

To make mysql_real_connect() thread-safe, you must recompile the client library with this command:

shell> ./configure --enable-thread-safe-client

This will create a thread-safe client library libmysqlclient_r. (Assuming your OS has a thread-safe gethostbyname_r() function.) This library is thread-safe per connection. You can let two threads share the same connection with the following caveats:

You need to know the following if you have a thread that is calling MySQL functions which did not create the connection to the MySQL database:

When you call mysql_init() or mysql_connect(), MySQL will create a thread-specific variable for the thread that is used by the debug library (among other things).

If you call a MySQL function, before the thread has called mysql_init() or mysql_connect(), the thread will not have the necessary thread-specific variables in place and you are likely to end up with a core dump sooner or later.

The get things to work smoothly you have to do the following:

  1. Call my_init() at the start of your program if it calls any other MySQL function before calling mysql_real_connect().
  2. Call mysql_thread_init() in the thread handler before calling any MySQL function.
  3. In the thread, call mysql_thread_end() before calling pthread_exit(). This will free the memory used by MySQL thread-specific variables.

You may get some errors because of undefined symbols when linking your client with libmysqlclient_r. In most cases this is because you haven't included the thread libraries on the link/compile line.

8.1.15 libmysqld, the Embedded MySQL Server Library

8.1.15.1 Overview of the Embedded MySQL Server Library

The embedded MySQL server library makes it possible to run a full-featured MySQL server inside the client application. The main benefits are increased speed and more simple management for embedded applications.

The API is identical for the embedded MySQL version and the client/server version. To change an old threaded application to use the embedded library, you normally only have to add calls to the following functions:

Function When to call
mysql_server_init() Should be called before any other MySQL function is called, preferably early in the main() function.
mysql_server_end() Should be called before your program exits.
mysql_thread_init() Should be called in each thread you create that will access MySQL.
mysql_thread_end() Should be called before calling pthread_exit()

Then you must link your code with `libmysqld.a' instead of `libmysqlclient.a'.

The above mysql_server_xxx functions are also included in `libmysqlclient.a' to allow you to change between the embedded and the client/server version by just linking your application with the right library. See section 8.1.11.1 mysql_server_init().

8.1.15.2 Compiling Programs with libmysqld

To get a libmysqld library you should configure MySQL with the --with-embedded-server option.

When you link your program with libmysqld, you must also include the system-specific pthread libraries and some libraries that the MySQL server uses. You can get the full list of libraries by executing mysql_config --libmysqld-libs.

The correct flags for compiling and linking a threaded program must be used, even if you do not directly call any thread functions in your code.

8.1.15.3 Restrictions when using the Embedded MySQL Server

The embedded server has the following limitations:

Some of these limitations can be changed by editing the `mysql_embed.h' include file and recompiling MySQL.

8.1.15.4 Using Option Files with the Embedded Server

The following is the recommended way to use option files to make it easy to switch between a client/server application and one where MySQL is embedded. See section 4.1.2 `my.cnf' Option Files.

8.1.15.5 Things left to do in Embedded Server (TODO)

8.1.15.6 A Simple Embedded Server Example

This example program and makefile should work without any changes on a Linux or FreeBSD system. For other operating systems, minor changes will be needed. This example is designed to give enough details to understand the problem, without the clutter that is a necessary part of a real application.

To try out the example, create an `test_libmysqld' directory at the same level as the mysql-4.0 source directory. Save the `test_libmysqld.c' source and the `GNUmakefile' in the directory, and run GNU `make' from inside the `test_libmysqld' directory.

`test_libmysqld.c'

/*
 * A simple example client, using the embedded MySQL server library
 */

#include <mysql.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

MYSQL *db_connect(const char *dbname);
void db_disconnect(MYSQL *db);
void db_do_query(MYSQL *db, const char *query);

const char *server_groups[] = {
  "test_libmysqld_SERVER", "embedded", "server", NULL
};

int
main(int argc, char **argv)
{
  MYSQL *one, *two;

  /* mysql_server_init() must be called before any other mysql
   * functions.
   *
   * You can use mysql_server_init(0, NULL, NULL), and it will
   * initialise the server using groups = {
   *   "server", "embedded", NULL
   *  }.
   *
   * In your $HOME/.my.cnf file, you probably want to put:

[test_libmysqld_SERVER]
language = /path/to/source/of/mysql/sql/share/english

   * You could, of course, modify argc and argv before passing
   * them to this function.  Or you could create new ones in any
   * way you like.  But all of the arguments in argv (except for
   * argv[0], which is the program name) should be valid options
   * for the MySQL server.
   *
   * If you link this client against the normal mysqlclient
   * library, this function is just a stub that does nothing.
   */
  mysql_server_init(argc, argv, (char **)server_groups);

  one = db_connect("test");
  two = db_connect(NULL);

  db_do_query(one, "SHOW TABLE STATUS");
  db_do_query(two, "SHOW DATABASES");

  mysql_close(two);
  mysql_close(one);

  /* This must be called after all other mysql functions */
  mysql_server_end();

  exit(EXIT_SUCCESS);
}

static void
die(MYSQL *db, char *fmt, ...)
{
  va_list ap;
  va_start(ap, fmt);
  vfprintf(stderr, fmt, ap);
  va_end(ap);
  (void)putc('\n', stderr);
  if (db)
    db_disconnect(db);
  exit(EXIT_FAILURE);
}

MYSQL *
db_connect(const char *dbname)
{
  MYSQL *db = mysql_init(NULL);
  if (!db)
    die(db, "mysql_init failed: no memory");
  /*
   * Notice that the client and server use separate group names.
   * This is critical, because the server will not accept the
   * client's options, and vice versa.
   */
  mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test_libmysqld_CLIENT");
  if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0))
    die(db, "mysql_real_connect failed: %s", mysql_error(db));

  return db;
}

void
db_disconnect(MYSQL *db)
{
  mysql_close(db);
}

void
db_do_query(MYSQL *db, const char *query)
{
  if (mysql_query(db, query) != 0)
    goto err;

  if (mysql_field_count(db) > 0)
  {
    MYSQL_RES   *res;
    MYSQL_ROW    row, end_row;
    int num_fields;

    if (!(res = mysql_store_result(db)))
      goto err;
    num_fields = mysql_num_fields(res);
    while ((row = mysql_fetch_row(res)))
    {
      (void)fputs(">> ", stdout);
      for (end_row = row + num_fields; row < end_row; ++row)
        (void)printf("%s\t", row ? (char*)*row : "NULL");
      (void)fputc('\n', stdout);
    }
    (void)fputc('\n', stdout);
  }
  else
    (void)printf("Affected rows: %lld\n", mysql_affected_rows(db));

  mysql_free_result(res);

  return;

err:
  die(db, "db_do_query failed: %s [%s]", mysql_error(db), query);
}

`GNUmakefile'

# This assumes the MySQL software is installed in /usr/local/mysql
inc      := /usr/local/mysql/include/mysql
lib      := /usr/local/mysql/lib

# If you have not installed the MySQL software yet, try this instead
#inc      := $(HOME)/mysql-4.0/include
#lib      := $(HOME)/mysql-4.0/libmysqld

CC       := gcc
CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT
CFLAGS   := -g -W -Wall
LDFLAGS  := -static
# You can change -lmysqld to -lmysqlclient to use the
# client/server library
LDLIBS    = -L$(lib) -lmysqld -lz -lm -lcrypt

ifneq (,$(shell grep FreeBSD /COPYRIGHT 2>/dev/null))
# FreeBSD
LDFLAGS += -pthread
else
# Assume Linux
LDLIBS += -lpthread
endif

# This works for simple one-file test programs
sources := $(wildcard *.c)
objects := $(patsubst %c,%o,$(sources))
targets := $(basename $(sources))

all: $(targets)

clean:
	rm -f $(targets) $(objects) *.core

8.1.15.7 Licensing the Embedded Server

The MySQL source code is covered by the GNU GPL license (see section H GNU General Public License). One result of this is that any program which includes, by linking with libmysqld, the MySQL source code must be released as free software (under a license compatible with the GPL).

We encourage everyone to promote free software by releasing code under the GPL or a compatible license. For those who are not able to do this, another option is to purchase a commercial licence for the MySQL code from MySQL AB. For details, please see section 1.4.3 MySQL Licenses.

8.2 MySQL ODBC Support

MySQL provides support for ODBC by means of the MyODBC program. This chapter will teach you how to install MyODBC, and how to use it. Here, you will also find a list of common programs that are known to work with MyODBC.

8.2.1 How To Install MyODBC

MyODBC 2.50 is a 32-bit ODBC 2.50 specification level 0 (with level 1 and level 2 features) driver for connecting an ODBC-aware application to MySQL. MyODBC works on Windows 9x/Me/NT/2000/XP and most Unix platforms. MyODBC 3.51 is an enhanced version with ODBC 3.5x specification level 1 (complete core API + level 2 features).

MyODBC is Open Source, and you can find the newest version at http://www.mysql.com/downloads/api-myodbc.html. Please note that the 2.50.x versions are LGPL licensed, whereas the 3.51.x versions are GPL licensed.

If you have problem with MyODBC and your program also works with OLEDB, you should try the OLEDB driver.

Normally you only need to install MyODBC on Windows machines. You only need MyODBC for Unix if you have a program like ColdFusion that is running on the Unix machine and uses ODBC to connect to the databases.

If you want to install MyODBC on a Unix box, you will also need an ODBC manager. MyODBC is known to work with most of the Unix ODBC managers.

To install MyODBC on Windows, you should download the appropriate MyODBC `.zip' file, unpack it with WinZIP or some similar program, and execute the `SETUP.EXE' file.

On Windows/NT/XP you may get the following error when trying to install MyODBC:

An error occurred while copying C:\WINDOWS\SYSTEM\MFC30.DLL. Restart
Windows and try installing again (before running any applications which
use ODBC)

The problem in this case is that some other program is using ODBC and because of how Windows is designed, you may not in this case be able to install a new ODBC drivers with Microsoft's ODBC setup program. In most cases you can continue by just pressing Ignore to copy the rest of the MyODBC files and the final installation should still work. If this doesn't work, the solution is to reboot your computer in ``safe mode`` (Choose this by pressing F8 just before your machine starts Windows during rebooting), install MyODBC, and reboot to normal mode.

Notice that there are other configuration options on the screen of MySQL (trace, don't prompt on connect, etc) that you can try if you run into problems.

8.2.2 How to Fill in the Various Fields in the ODBC Administrator Program

There are three possibilities for specifying the server name on Windows95:

Example of how to fill in the ODBC setup:

Windows DSN name:   test
Description:        This is my test database
MySql Database:     test
Server:             194.216.84.21
User:               monty
Password:           my_password
Port:

The value for the Windows DSN name field is any name that is unique in your Windows ODBC setup.

You don't have to specify values for the Server, User, Password, or Port fields in the ODBC setup screen. However, if you do, the values will be used as the defaults later when you attempt to make a connection. You have the option of changing the values at that time.

If the port number is not given, the default port (3306) is used.

If you specify the option Read options from C:\my.cnf, the groups client and odbc will be read from the `C:\my.cnf' file. You can use all options that are usable by mysql_options(). See section 8.1.3.163 mysql_options().

8.2.3 Connect parameters for MyODBC

One can specify the following parameters for MyODBC on the [Servername] section of an `ODBC.INI' file or through the InConnectionString argument in the SQLDriverConnect() call.

Parameter Default value Comment
user ODBC (on Windows) The username used to connect to MySQL.
server localhost The hostname of the MySQL server.
database The default database.
option 0 A integer by which you can specify how MyODBC should work. See below.
port 3306 The TCP/IP port to use if server is not localhost.
stmt A statement that will be executed when connecting to MySQL.
password The password for the server user combination.
socket The socket or Windows pipe to connect to.

The option argument is used to tell MyODBC that the client isn't 100% ODBC compliant. On Windows, one normally sets the option flag by toggling the different options on the connection screen but one can also set this in the opton argument. The following options are listed in the same order as they appear in the MyODBC connect screen:

Bit Description
1 The client can't handle that MyODBC returns the real width of a column.
2 The client can't handle that MySQL returns the true value of affected rows. If this flag is set then MySQL returns 'found rows' instead. One must have MySQL 3.21.14 or newer to get this to work.
4 Make a debug log in c:\myodbc.log. This is the same as putting MYSQL_DEBUG=d:t:O,c::\myodbc.log in `AUTOEXEC.BAT'
8 Don't set any packet limit for results and parameters.
16 Don't prompt for questions even if driver would like to prompt
32 Simulate a ODBC 1.0 driver in some context.
64 Ignore use of database name in 'database.table.column'.
128 Force use of ODBC manager cursors (experimental).
256 Disable the use of extended fetch (experimental).
512 Pad CHAR fields to full column length.
1024 SQLDescribeCol() will return fully qualifed column names
2048 Use the compressed server/client protocol
4096 Tell server to ignore space after function name and before '(' (needed by PowerBuilder). This will make all function names keywords!
8192 Connect with named pipes to a mysqld server running on NT.
16384 Change LONGLONG columns to INT columns (some applications can't handle LONGLONG).
32768 Return 'user' as Table_qualifier and Table_owner from SQLTables (experimental)
65536 Read parameters from the client and odbc groups from `my.cnf'
131072 Add some extra safety checks (should not bee needed but...)

If you want to have many options, you should add the above flags! For example setting option to 12 (4+8) gives you debugging without package limits!

The default `MYODBC.DLL' is compiled for optimal performance. If you want to debug MyODBC (for example to enable tracing), you should instead use `MYODBCD.DLL'. To install this file, copy `MYODBCD.DLL' over the installed `MYODBC.DLL' file.

8.2.4 How to Report Problems with MyODBC

MyODBC has been tested with Access, Admndemo.exe, C++-Builder, Borland Builder 4, Centura Team Developer (formerly Gupta SQL/Windows), ColdFusion (on Solaris and NT with svc pack 5), Crystal Reports, DataJunction, Delphi, ERwin, Excel, iHTML, FileMaker Pro, FoxPro, Notes 4.5/4.6, SBSS, Perl DBD-ODBC, Paradox, Powerbuilder, Powerdesigner 32 bit, VC++, and Visual Basic.

If you know of any other applications that work with MyODBC, please send mail to myodbc@lists.mysql.com about this!

With some programs you may get an error like: Another user has modifies the record that you have modified. In most cases this can be solved by doing one of the following things:

If the above doesn't help, you should do a MyODBC trace file and try to figure out why things go wrong.

8.2.5 Programs Known to Work with MyODBC

Most programs should work with MyODBC, but for each of those listed here, we have tested it ourselves or received confirmation from some user that it works:

Program
Comment
Access
To make Access work:
ADO
When you are coding with the ADO API and MyODBC you need to put attention in some default properties that aren't supported by the MySQL server. For example, using the CursorLocation Property as adUseServer will return for the RecordCount Property a result of -1. To have the right value, you need to set this property to adUseClient, like is showing in the VB code here:
Dim myconn As New ADODB.Connection
Dim myrs As New Recordset
Dim mySQL As String
Dim myrows As Long

myconn.Open "DSN=MyODBCsample"
mySQL = "SELECT * from user"
myrs.Source = mySQL
Set myrs.ActiveConnection = myconn
myrs.CursorLocation = adUseClient
myrs.Open
myrows = myrs.RecordCount

myrs.Close
myconn.Close
Another workaround is to use a SELECT COUNT(*) statement for a similar query to get the correct row count.
Active server pages (ASP)
You should use the option flag Return matching rows.
BDE applications
To get these to work, you should set the option flags Don't optimize column widths and Return matching rows.
Borland Builder 4
When you start a query you can use the property Active or use the method Open. Note that Active will start by automatically issuing a SELECT * FROM ... query that may not be a good thing if your tables are big!
ColdFusion (On Unix)
The following information is taken from the ColdFusion documentation: Use the following information to configure ColdFusion Server for Linux to use the unixODBC driver with MyODBC for MySQL data sources. Allaire has verified that MyODBC Version 2.50.26 works with MySQL Version 3.22.27 and ColdFusion for Linux. (Any newer version should also work.) You can download MyODBC at http://www.mysql.com/downloads/api-myodbc.html ColdFusion Version 4.5.1 allows you to us the ColdFusion Administrator to add the MySQL data source. However, the driver is not included with ColdFusion Version 4.5.1. Before the MySQL driver will appear in the ODBC datasources drop-down list, you must build and copy the MyODBC driver to `/opt/coldfusion/lib/libmyodbc.so'. The Contrib directory contains the program `mydsn-xxx.zip' which allows you to build and remove the DSN registry file for the MyODBC driver on Coldfusion applications.
DataJunction
You have to change it to output VARCHAR rather than ENUM, as it exports the latter in a manner that causes MySQL grief.
Excel
Works. A few tips:
Word
To retrieve data from MySQL to Word/Excel documents, you need to use the MyODBC driver and the Add-in Microsoft Query help. For example, create a db with a table containing 2 columns of text:
odbcadmin
Test program for ODBC.
Delphi
You must use BDE Version 3.2 or newer. Set the Don't optimize column width option field when connecting to MySQL. Also, here is some potentially useful Delphi code that sets up both an ODBC entry and a BDE entry for MyODBC (the BDE entry requires a BDE Alias Editor that is free at a Delphi Super Page near you. (Thanks to Bryan Brunton bryan@flesherfab.com for this):
fReg:= TRegistry.Create;
  fReg.OpenKey('\Software\ODBC\ODBC.INI\DocumentsFab', True);
  fReg.WriteString('Database', 'Documents');
  fReg.WriteString('Description', ' ');
  fReg.WriteString('Driver', 'C:\WINNT\System32\myodbc.dll');
  fReg.WriteString('Flag', '1');
  fReg.WriteString('Password', '');
  fReg.WriteString('Port', ' ');
  fReg.WriteString('Server', 'xmark');
  fReg.WriteString('User', 'winuser');
  fReg.OpenKey('\Software\ODBC\ODBC.INI\ODBC Data Sources', True);
  fReg.WriteString('DocumentsFab', 'MySQL');
  fReg.CloseKey;
  fReg.Free;

  Memo1.Lines.Add('DATABASE NAME=');
  Memo1.Lines.Add('USER NAME=');
  Memo1.Lines.Add('ODBC DSN=DocumentsFab');
  Memo1.Lines.Add('OPEN MODE=READ/WRITE');
  Memo1.Lines.Add('BATCH COUNT=200');
  Memo1.Lines.Add('LANGDRIVER=');
  Memo1.Lines.Add('MAX ROWS=-1');
  Memo1.Lines.Add('SCHEMA CACHE DIR=');
  Memo1.Lines.Add('SCHEMA CACHE SIZE=8');
  Memo1.Lines.Add('SCHEMA CACHE TIME=-1');
  Memo1.Lines.Add('SQLPASSTHRU MODE=SHARED AUTOCOMMIT');
  Memo1.Lines.Add('SQLQRYMODE=');
  Memo1.Lines.Add('ENABLE SCHEMA CACHE=FALSE');
  Memo1.Lines.Add('ENABLE BCD=FALSE');
  Memo1.Lines.Add('ROWSET SIZE=20');
  Memo1.Lines.Add('BLOBS TO CACHE=64');
  Memo1.Lines.Add('BLOB SIZE=32');

  AliasEditor.Add('DocumentsFab','MySQL',Memo1.Lines);
C++ Builder
Tested with BDE Version 3.0. The only known problem is that when the table schema changes, query fields are not updated. BDE, however, does not seem to recognise primary keys, only the index PRIMARY, though this has not been a problem.
Vision
You should use the option flag Return matching rows.
Visual Basic
To be able to update a table, you must define a primary key for the table. Visual Basic with ADO can't handle big integers. This means that some queries like SHOW PROCESSLIST will not work properly. The fix is to set the option OPTION=16384 in the ODBC connect string or to set the Change BIGINT columns to INT option in the MyODBC connect screen. You may also want to set the Return matching rows option.
VisualInterDev
If you get the error [Microsoft][ODBC Driver Manager] Driver does not support this parameter the reason may be that you have a BIGINT in your result. Try setting the Change BIGINT columns to INT option in the MyODBC connect screen.
Visual Objects
You should use the option flag Don't optimize column widths.

8.2.6 How to Get the Value of an AUTO_INCREMENT Column in ODBC

A common problem is how to get the value of an automatically generated ID from an INSERT. With ODBC, you can do something like this (assuming that auto is an AUTO_INCREMENT field):

INSERT INTO foo (auto,text) VALUES(NULL,'text');
SELECT LAST_INSERT_ID();

Or, if you are just going to insert the ID into another table, you can do this:

INSERT INTO foo (auto,text) VALUES(NULL,'text');
INSERT INTO foo2 (id,text) VALUES(LAST_INSERT_ID(),'text');

See section 8.1.12.3 How Can I Get the Unique ID for the Last Inserted Row?.

For the benefit of some ODBC applications (at least Delphi and Access), the following query can be used to find a newly inserted row:

SELECT * FROM tbl_name WHERE auto IS NULL;

8.2.7 Reporting Problems with MyODBC

If you encounter difficulties with MyODBC, you should start by making a log file from the ODBC manager (the log you get when requesting logs from ODBCADMIN) and a MyODBC log.

To get a MyODBC log, you need to do the following:

  1. Ensure that you are using `myodbcd.dll' and not `myodbc.dll'. The easiest way to do this is to get `myodbcd.dll' from the MyODBC distribution and copy it over the `myodbc.dll', which is probably in your `C:\windows\system32' or `C:\winnt\system32' directory. Note that you probably want to restore the old myodbc.dll file when you have finished testing, as this is a lot faster than `myodbcd.dll'.
  2. Tag the `Trace MyODBC' option flag in the MyODBC connect/configure screen. The log will be written to file `C:\myodbc.log'. If the trace option is not remembered when you are going back to the above screen, it means that you are not using the myodbcd.dll driver (see the item above).
  3. Start your application and try to get it to fail.

Check the MyODBC trace file, to find out what could be wrong. You should be able to find out the issued queries by searching after the string >mysql_real_query in the `myodbc.log' file.

You should also try duplicating the queries in the mysql monitor or admndemo to find out if the error is MyODBC or MySQL.

If you find out something is wrong, please only send the relevant rows (max 40 rows) to myodbc@lists.mysql.com. Please never send the whole MyODBC or ODBC log file!

If you are unable to find out what's wrong, the last option is to make an archive (tar or zip) that contains a MyODBC trace file, the ODBC log file, and a README file that explains the problem. You can send this to ftp://support.mysql.com/pub/mysql/secret/. Only we at MySQL AB will have access to the files you upload, and we will be very discrete with the data!

If you can create a program that also shows this problem, please upload this too!

If the program works with some other SQL server, you should make an ODBC log file where you do exactly the same thing in the other SQL server.

Remember that the more information you can supply to us, the more likely it is that we can fix the problem!

8.3 MySQL Java Connectivity (JDBC)

There are 2 supported JDBC drivers for MySQL:

For documentation, consult any JDBC documentation, plus each driver's own documentation for MySQL-specific features.

8.4 MySQL PHP API

PHP is a server-side, HTML-embedded scripting language that may be used to create dynamic web pages. It contains support for accessing several databases, including MySQL. PHP may be run as a separate program or compiled as a module for use with the Apache web server.

The distribution and documentation are available at the PHP web site (http://www.php.net/).

8.4.1 Common Problems with MySQL and PHP

8.5 MySQL Perl API

This section documents the Perl DBI interface. The former interface was called mysqlperl. DBI/DBD now is the recommended Perl interface, so mysqlperl is obsolete and is not documented here.

8.5.1 DBI with DBD::mysql

DBI is a generic interface for many databases. That means that you can write a script that works with many different database engines without change. You need a DataBase Driver (DBD) defined for each database type. For MySQL, this driver is called DBD::mysql.

For more information on the Perl5 DBI, please visit the DBI web page and read the documentation:

http://dbi.perl.org/

For more information on Object Oriented Programming (OOP) as defined in Perl5, see the Perl OOP page:

http://language.perl.com/info/documentation.html

Note that if you want to use transactions with Perl, you need to have Msql-Mysql-modules version 1.2216 or newer.

The recommended Perl module is DBD-mysql-2.1022 or newer.

Installation instructions for MySQL Perl support are given in section 2.7 Perl Installation Comments.

If you have the MySQL module installed, you can find information about specific MySQL functionallity with one of the following command

shell> perldoc DBD/mysql
shell> perldoc mysql

8.5.2 The DBI Interface

Portable DBI Methods

Method Description
connect Establishes a connection to a database server.
disconnect Disconnects from the database server.
prepare Prepares a SQL statement for execution.
execute Executes prepared statements.
do Prepares and executes a SQL statement.
quote Quotes string or BLOB values to be inserted.
fetchrow_array Fetches the next row as an array of fields.
fetchrow_arrayref Fetches next row as a reference array of fields.
fetchrow_hashref Fetches next row as a reference to a hashtable.
fetchall_arrayref Fetches all data as an array of arrays.
finish Finishes a statement and lets the system free resources.
rows Returns the number of rows affected.
data_sources Returns an array of databases available on localhost.
ChopBlanks Controls whether fetchrow_* methods trim spaces.
NUM_OF_PARAMS The number of placeholders in the prepared statement.
NULLABLE Which columns can be NULL.
trace Perform tracing for debugging.

MySQL-specific Methods

Method Description
insertid The latest AUTO_INCREMENT value.
is_blob Which columns are BLOB values.
is_key Which columns are keys.
is_num Which columns are numeric.
is_pri_key Which columns are primary keys.
is_not_null Which columns CANNOT be NULL. See NULLABLE.
length Maximum possible column sizes.
max_length Maximum column sizes actually present in result.
NAME Column names.
NUM_OF_FIELDS Number of fields returned.
table Table names in returned set.
type All column types.

The Perl methods are described in more detail in the following sections. Variables used for method return values have these meanings:

$dbh
Database handle
$sth
Statement handle
$rc
Return code (often a status)
$rv
Return value (often a row count)

Portable DBI Methods

connect($data_source, $username, $password)
Use the connect method to make a database connection to the data source. The $data_source value should begin with DBI:driver_name:. Example uses of connect with the DBD::mysql driver:
$dbh = DBI->connect("DBI:mysql:$database", $user, $password);
$dbh = DBI->connect("DBI:mysql:$database:$hostname",
                    $user, $password);
$dbh = DBI->connect("DBI:mysql:$database:$hostname:$port",
                    $user, $password);
If the user name and/or password are undefined, DBI uses the values of the DBI_USER and DBI_PASS environment variables, respectively. If you don't specify a hostname, it defaults to 'localhost'. If you don't specify a port number, it defaults to the default MySQL port (3306). As of Msql-Mysql-modules Version 1.2009, the $data_source value allows certain modifiers:
mysql_read_default_file=file_name
Read `filename' as an option file. For information on option files, see section 4.1.2 `my.cnf' Option Files.
mysql_read_default_group=group_name
The default group when reading an option file is normally the [client] group. By specifying the mysql_read_default_group option, the default group becomes the [group_name] group.
mysql_compression=1
Use compressed communication between the client and server (MySQL Version 3.22.3 or later).
mysql_socket=/path/to/socket
Specify the pathname of the Unix socket that is used to connect to the server (MySQL Version 3.21.15 or later).
Multiple modifiers may be given; each must be preceded by a semicolon. For example, if you want to avoid hardcoding the user name and password into a DBI script, you can take them from the user's `~/.my.cnf' option file instead by writing your connect call like this:
$dbh = DBI->connect("DBI:mysql:$database"
                . ";mysql_read_default_file=$ENV{HOME}/.my.cnf",
                $user, $password);
This call will read options defined for the [client] group in the option file. If you wanted to do the same thing but use options specified for the [perl] group as well, you could use this:
$dbh = DBI->connect("DBI:mysql:$database"
                . ";mysql_read_default_file=$ENV{HOME}/.my.cnf"
                . ";mysql_read_default_group=perl",
                $user, $password);
disconnect
The disconnect method disconnects the database handle from the database. This is typically called right before you exit from the program. Example:
$rc = $dbh->disconnect;
prepare($statement)
Prepares a SQL statement for execution by the database engine and returns a statement handle ($sth), which you can use to invoke the execute method. Typically you handle SELECT statements (and SELECT-like statements such as SHOW, DESCRIBE, and EXPLAIN) by means of prepare and execute. Example:
$sth = $dbh->prepare($statement)
    or die "Can't prepare $statement: $dbh->errstr\n";
If you want to read big results to your client you can tell Perl to use mysql_use_result() with:
my $sth = $dbh->prepare($statement { "mysql_use_result" => 1});
execute
The execute method executes a prepared statement. For non-SELECT statements, execute returns the number of rows affected. If no rows are affected, execute returns "0E0", which Perl treats as zero but regards as true. If an error occurs, execute returns undef. For SELECT statements, execute only starts the SQL query in the database; you need to use one of the fetch_* methods described here to retrieve the data. Example:
$rv = $sth->execute
          or die "can't execute the query: $sth->errstr;
do($statement)
The do method prepares and executes a SQL statement and returns the number of rows affected. If no rows are affected, do returns "0E0", which Perl treats as zero but regards as true. This method is generally used for non-SELECT statements that cannot be prepared in advance (due to driver limitations) or that do not need to be executed more than once (inserts, deletes, etc.). Example:
$rv = $dbh->do($statement)
        or die "Can't execute $statement: $dbh- >errstr\n";
Generally the 'do' statement is much faster (and is preferable) than prepare/execute for statements that don't contain parameters.
quote($string)
The quote method is used to "escape" any special characters contained in the string and to add the required outer quotation marks. Example:
$sql = $dbh->quote($string)
fetchrow_array
This method fetches the next row of data and returns it as an array of field values. Example:
while(@row = $sth->fetchrow_array) {
        print qw($row[0]\t$row[1]\t$row[2]\n);
}
fetchrow_arrayref
This method fetches the next row of data and returns it as a reference to an array of field values. Example:
while($row_ref = $sth->fetchrow_arrayref) {
        print qw($row_ref->[0]\t$row_ref->[1]\t$row_ref->[2]\n);
}
fetchrow_hashref
This method fetches a row of data and returns a reference to a hash table containing field name/value pairs. This method is not nearly as efficient as using array references as demonstrated above. Example:
while($hash_ref = $sth->fetchrow_hashref) {
        print qw($hash_ref->{firstname}\t$hash_ref->{lastname}\t\
                $hash_ref->{title}\n);
}
fetchall_arrayref
This method is used to get all the data (rows) to be returned from the SQL statement. It returns a reference to an array of references to arrays for each row. You access or print the data by using a nested loop. Example:
my $table = $sth->fetchall_arrayref
                or die "$sth->errstr\n";
my($i, $j);
for $i ( 0 .. $#{$table} ) {
        for $j ( 0 .. $#{$table->[$i]} ) {
                print "$table->[$i][$j]\t";
        }
        print "\n";
}
finish
Indicates that no more data will be fetched from this statement handle. You call this method to free up the statement handle and any system resources associated with it. Example:
$rc = $sth->finish;
rows
Returns the number of rows changed (updated, deleted, etc.) by the last command. This is usually used after a non-SELECT execute statement. Example:
$rv = $sth->rows;
NULLABLE
Returns a reference to an array of values that indicate whether columns may contain NULL values. The possible values for each array element are 0 or the empty string if the column cannot be NULL, 1 if it can, and 2 if the column's NULL status is unknown. Example:
$null_possible = $sth->{NULLABLE};
NUM_OF_FIELDS
This attribute indicates the number of fields returned by a SELECT or SHOW FIELDS statement. You may use this for checking whether a statement returned a result: A zero value indicates a non-SELECT statement like INSERT, DELETE, or UPDATE. Example:
$nr_of_fields = $sth->{NUM_OF_FIELDS};
data_sources($driver_name)
This method returns an array containing names of databases available to the MySQL server on the host 'localhost'. Example:
@dbs = DBI->data_sources("mysql");
ChopBlanks
This attribute determines whether the fetchrow_* methods will chop leading and trailing blanks from the returned values. Example:
$sth->{'ChopBlanks'} =1;
trace($trace_level)
trace($trace_level, $trace_filename)
The trace method enables or disables tracing. When invoked as a DBI class method, it affects tracing for all handles. When invoked as a database or statement handle method, it affects tracing for the given handle (and any future children of the handle). Setting $trace_level to 2 provides detailed trace information. Setting $trace_level to 0 disables tracing. Trace output goes to the standard error output by default. If $trace_filename is specified, the file is opened in append mode and output for all traced handles is written to that file. Example:
DBI->trace(2);                # trace everything
DBI->trace(2,"/tmp/dbi.out"); # trace everything to
                              # /tmp/dbi.out
$dth->trace(2);               # trace this database handle
$sth->trace(2);               # trace this statement handle
You can also enable DBI tracing by setting the DBI_TRACE environment variable. Setting it to a numeric value is equivalent to calling DBI->(value). Setting it to a pathname is equivalent to calling DBI->(2,value).

MySQL-specific Methods

The methods shown here are MySQL-specific and not part of the DBI standard. Several of them are now deprecated: is_blob, is_key, is_num, is_pri_key, is_not_null, length, max_length, and table. Where DBI-standard alternatives exist, they are noted here:

insertid
If you use the AUTO_INCREMENT feature of MySQL, the new auto-incremented values will be stored here. Example:
$new_id = $sth->{insertid};
As an alternative, you can use $dbh->{'mysql_insertid'}.
is_blob
Returns a reference to an array of boolean values; for each element of the array, a value of TRUE indicates that the respective column is a BLOB. Example:
$keys = $sth->{is_blob};
is_key
Returns a reference to an array of boolean values; for each element of the array, a value of TRUE indicates that the respective column is a key. Example:
$keys = $sth->{is_key};
is_num
Returns a reference to an array of boolean values; for each element of the array, a value of TRUE indicates that the respective column contains numeric values. Example:
$nums = $sth->{is_num};
is_pri_key
Returns a reference to an array of boolean values; for each element of the array, a value of TRUE indicates that the respective column is a primary key. Example:
$pri_keys = $sth->{is_pri_key};
is_not_null
Returns a reference to an array of boolean values; for each element of the array, a value of FALSE indicates that this column may contain NULL values. Example:
$not_nulls = $sth->{is_not_null};
is_not_null is deprecated; it is preferable to use the NULLABLE attribute (described above), because that is a DBI standard.
length
max_length
Each of these methods returns a reference to an array of column sizes. The length array indicates the maximum possible sizes that each column may be (as declared in the table description). The max_length array indicates the maximum sizes actually present in the result table. Example:
$lengths = $sth->{length};
$max_lengths = $sth->{max_length};
NAME
Returns a reference to an array of column names. Example:
$names = $sth->{NAME};
table
Returns a reference to an array of table names. Example:
$tables = $sth->{table};
type
Returns a reference to an array of column types. Example:
$types = $sth->{type};

8.5.3 More DBI/DBD Information

You can use the perldoc command to get more information about DBI.

perldoc DBI
perldoc DBI::FAQ
perldoc DBD::mysql

You can also use the pod2man, pod2html, etc., tools to translate to other formats.

You can find the latest DBI information at the DBI web page: http://dbi.perl.org/.

8.6 MySQL C++ API

MySQL Connector/C++ (or MySQL++) is the official MySQL API for C++. More information can be found at http://www.mysql.com/products/mysql++/.

8.6.1 Borland C++

You can compile the MySQL Windows source with Borland C++ 5.02. (The Windows source includes only projects for Microsoft VC++, for Borland C++ you have to do the project files yourself.)

One known problem with Borland C++ is that it uses a different structure alignment than VC++. This means that you will run into problems if you try to use the default libmysql.dll libraries (that was compiled with VC++) with Borland C++. You can do one of the following to avoid this problem.

8.7 MySQL Python API

MySQLdb provides MySQL support for Python, compliant with the Python DB API version 2.0. It can be found at http://sourceforge.net/projects/mysql-python/.

8.8 MySQL Tcl API

MySQLtcl is a simple API for accessing a MySQL database server from the Tcl programming language. It can be found at http://www.xdobry.de/mysqltcl/.

8.9 MySQL Eiffel wrapper

Eiffel MySQL is an interface to the MySQL database server using the Eiffel programming language, written by Michael Ravits. It can be found at http://efsa.sourceforge.net/archive/ravits/mysql.htm.

9 Extending MySQL

9.1 MySQL Internals

This chapter describes a lot of things that you need to know when working on the MySQL code. If you plan to contribute to MySQL development, want to have access to the bleeding-edge in-between versions code, or just want to keep track of development, follow the instructions in section 2.3.4 Installing from the Development Source Tree. If you are interested in MySQL internals, you should also subscribe to our internals mailing list. This list is relatively low traffic. For details on how to subscribe, please see section 1.7.1.1 The MySQL Mailing Lists. All developers at MySQL AB are on the internals list and we help other people who are working on the MySQL code. Feel free to use this list both to ask questions about the code and to send patches that you would like to contribute to the MySQL project!

9.1.1 MySQL Threads

The MySQL server creates the following threads:

mysqladmin processlist only shows the connection, INSERT DELAYED, and replication threads.

9.1.2 MySQL Test Suite

Until recently, our main full-coverage test suite was based on proprietary customer data and for that reason has not been publicly available. The only publicly available part of our testing process consisted of the crash-me test, a Perl DBI/DBD benchmark found in the sql-bench directory, and miscellaneous tests located in tests directory. The lack of a standardised publicly available test suite has made it difficult for our users, as well developers, to do regression tests on the MySQL code. To address this problem, we have created a new test system that is included in the source and binary distributions starting in Version 3.23.29.

The current set of test cases doesn't test everything in MySQL, but it should catch most obvious bugs in the SQL processing code, OS/library issues, and is quite thorough in testing replication. Our eventual goal is to have the tests cover 100% of the code. We welcome contributions to our test suite. You may especially want to contribute tests that examine the functionality critical to your system, as this will ensure that all future MySQL releases will work well with your applications.

9.1.2.1 Running the MySQL Test Suite

The test system consist of a test language interpreter (mysqltest), a shell script to run all tests(mysql-test-run), the actual test cases written in a special test language, and their expected results. To run the test suite on your system after a build, type make test or mysql-test/mysql-test-run from the source root. If you have installed a binary distribution, cd to the install root (eg. /usr/local/mysql), and do scripts/mysql-test-run. All tests should succeed. If not, you should try to find out why and report the problem if this is a bug in MySQL. See section 9.1.2.3 Reporting Bugs in the MySQL Test Suite.

If you have a copy of mysqld running on the machine where you want to run the test suite you do not have to stop it, as long as it is not using ports 9306 and 9307. If one of those ports is taken, you should edit mysql-test-run and change the values of the master and/or slave port to one that is available.

You can run one individual test case with mysql-test/mysql-test-run test_name.

If one test fails, you should test running mysql-test-run with the --force option to check if any other tests fails.

9.1.2.2 Extending the MySQL Test Suite

You can use the mysqltest language to write your own test cases. Unfortunately, we have not yet written full documentation for it - we plan to do this shortly. You can, however, look at our current test cases and use them as an example. The following points should help you get started:

9.1.2.3 Reporting Bugs in the MySQL Test Suite

If your MySQL version doesn't pass the test suite you should do the following:

9.2 Adding New Functions to MySQL

There are two ways to add new functions to MySQL:

Each method has advantages and disadvantages:

Whichever method you use to add new functions, they may be used just like native functions such as ABS() or SOUNDEX().

9.2.1 CREATE FUNCTION/DROP FUNCTION Syntax

CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|REAL|INTEGER}
       SONAME shared_library_name

DROP FUNCTION function_name

A user-definable function (UDF) is a way to extend MySQL with a new function that works like native (built in) MySQL functions such as ABS() and CONCAT().

AGGREGATE is a new option for MySQL Version 3.23. An AGGREGATE function works exactly like a native MySQL GROUP function like SUM or COUNT().

CREATE FUNCTION saves the function's name, type, and shared library name in the mysql.func system table. You must have the INSERT and DELETE privileges for the mysql database to create and drop functions.

All active functions are reloaded each time the server starts, unless you start mysqld with the --skip-grant-tables option. In this case, UDF initialisation is skipped and UDFs are unavailable. (An active function is one that has been loaded with CREATE FUNCTION and not removed with DROP FUNCTION.)

For instructions on writing user-definable functions, see section 9.2 Adding New Functions to MySQL. For the UDF mechanism to work, functions must be written in C or C++, your operating system must support dynamic loading and you must have compiled mysqld dynamically (not statically).

Note that to make AGGREGATE work, you must have a mysql.func table that contains the column type. If this is not the case, you should run the script mysql_fix_privilege_tables to get this fixed.

9.2.2 Adding a New User-definable Function

For the UDF mechanism to work, functions must be written in C or C++ and your operating system must support dynamic loading. The MySQL source distribution includes a file `sql/udf_example.cc' that defines 5 new functions. Consult this file to see how UDF calling conventions work.

For mysqld to be able to use UDF functions, you should configure MySQL with --with-mysqld-ldflags=-rdynamic The reason is that to on many platforms (including Linux) you can load a dynamic library (with dlopen()) from a static linked program, which you would get if you are using --with-mysqld-ldflags=-all-static If you want to use an UDF that needs to access symbols from mysqld (like the methaphone example in `sql/udf_example.cc' that uses default_charset_info), you must link the program with -rdynamic (see man dlopen).

For each function that you want to use in SQL statements, you should define corresponding C (or C++) functions. In the discussion below, the name ``xxx'' is used for an example function name. To distinquish between SQL and C/C++ usage, XXX() (uppercase) indicates a SQL function call, and xxx() (lowercase) indicates a C/C++ function call.

The C/C++ functions that you write to implement the interface for XXX() are:

xxx() (required)
The main function. This is where the function result is computed. The correspondence between the SQL type and return type of your C/C++ function is shown here:
SQL type C/C++ type
STRING char *
INTEGER long long
REAL double
xxx_init() (optional)
The initialisation function for xxx(). It can be used to:
xxx_deinit() (optional)
The deinitialisation function for xxx(). It should deallocate any memory allocated by the initialisation function.

When a SQL statement invokes XXX(), MySQL calls the initialisation function xxx_init() to let it perform any required setup, such as argument checking or memory allocation. If xxx_init() returns an error, the SQL statement is aborted with an error message and the main and deinitialisation functions are not called. Otherwise, the main function xxx() is called once for each row. After all rows have been processed, the deinitialisation function xxx_deinit() is called so it can perform any required cleanup.

For aggregate functions (like SUM()), you must also provide the following functions:

xxx_reset() (required)
Reset sum and insert the argument as the initial value for a new group.
xxx_add() (required)
Add the argument to the old sum.

When using aggregate UDF functions MySQL works the following way:

  1. Call xxx_init() to let the aggregate function allocate the memory it will need to store results.
  2. Sort the table according to the GROUP BY expression.
  3. For the first row in a new group, call the xxx_reset() function.
  4. For each new row that belongs in the same group, call the xxx_add() function.
  5. When the group changes or after the last row has been processed, call xxx() to get the result for the aggregate.
  6. Repeat 3-5 until all rows has been processed
  7. Call xxx_deinit() to let the UDF free any memory it has allocated.

All functions must be thread-safe (not just the main function, but the initialisation and deinitialisation functions as well). This means that you are not allowed to allocate any global or static variables that change! If you need memory, you should allocate it in xxx_init() and free it in xxx_deinit().

9.2.2.1 UDF Calling Sequences for simple functions

The main function should be declared as shown here. Note that the return type and parameters differ, depending on whether you will declare the SQL function XXX() to return STRING, INTEGER, or REAL in the CREATE FUNCTION statement:

For STRING functions:

char *xxx(UDF_INIT *initid, UDF_ARGS *args,
          char *result, unsigned long *length,
          char *is_null, char *error);

For INTEGER functions:

long long xxx(UDF_INIT *initid, UDF_ARGS *args,
              char *is_null, char *error);

For REAL functions:

double xxx(UDF_INIT *initid, UDF_ARGS *args,
              char *is_null, char *error);

The initialisation and deinitialisation functions are declared like this:

my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);

void xxx_deinit(UDF_INIT *initid);

The initid parameter is passed to all three functions. It points to a UDF_INIT structure that is used to communicate information between functions. The UDF_INIT structure members are listed below. The initialisation function should fill in any members that it wishes to change. (To use the default for a member, leave it unchanged.):

my_bool maybe_null
xxx_init() should set maybe_null to 1 if xxx() can return NULL. The default value is 1 if any of the arguments are declared maybe_null.
unsigned int decimals
Number of decimals. The default value is the maximum number of decimals in the arguments passed to the main function. (For example, if the function is passed 1.34, 1.345, and 1.3, the default would be 3, because 1.345 has 3 decimals.
unsigned int max_length
The maximum length of the string result. The default value differs depending on the result type of the function. For string functions, the default is the length of the longest argument. For integer functions, the default is 21 digits. For real functions, the default is 13 plus the number of decimals indicated by initid->decimals. (For numeric functions, the length includes any sign or decimal point characters.) If you want to return a blob, you can set this to 65K or 16M; this memory is not allocated but used to decide which column type to use if there is a need to temporary store the data.
char *ptr
A pointer that the function can use for its own purposes. For example, functions can use initid->ptr to communicate allocated memory between functions. In xxx_init(), allocate the memory and assign it to this pointer:
initid->ptr = allocated_memory;
In xxx() and xxx_deinit(), refer to initid->ptr to use or deallocate the memory.

9.2.2.2 UDF Calling Sequences for aggregate functions

Here follows a description of the different functions you need to define when you want to create an aggregate UDF function.

char *xxx_reset(UDF_INIT *initid, UDF_ARGS *args,
                char *is_null, char *error);

This function is called when MySQL finds the first row in a new group. In the function you should reset any internal summary variables and then set the given argument as the first argument in the group.

In many cases this is implemented internally by reseting all variables and then calling xxx_add().

char *xxx_add(UDF_INIT *initid, UDF_ARGS *args,
              char *is_null, char *error);

This function is called for all rows that belongs to the same group, except for the first row. In this you should add the value in UDF_ARGS to your internal summary variable.

The xxx() function should be declared identical as when you define a simple UDF function. See section 9.2.2.1 UDF Calling Sequences for simple functions.

This function is called when all rows in the group has been processed. You should normally never access the args variable here but return your value based on your internal summary variables.

All argument processing in xxx_reset() and xxx_add() should be done identically as for normal UDF functions. See section 9.2.2.3 Argument Processing.

The return value handling in xxx() should be done identically as for a normal UDF. See section 9.2.2.4 Return Values and Error Handling.

The pointer argument to is_null and error is the same for all calls to xxx_reset(), xxx_add() and xxx(). You can use this to remember that you got an error or if the xxx() function should return NULL. Note that you should not store a string into *error! This is just a 1 byte flag!

is_null is reset for each group (before calling xxx_reset(). error is never reset.

If isnull or error are set after xxx() then MySQL will return NULL as the result for the group function.

9.2.2.3 Argument Processing

The args parameter points to a UDF_ARGS structure that has the members listed here:

unsigned int arg_count
The number of arguments. Check this value in the initialisation function if you want your function to be called with a particular number of arguments. For example:
if (args->arg_count != 2)
{
    strcpy(message,"XXX() requires two arguments");
    return 1;
}
enum Item_result *arg_type
The types for each argument. The possible type values are STRING_RESULT, INT_RESULT, and REAL_RESULT. To make sure that arguments are of a given type and return an error if they are not, check the arg_type array in the initialisation function. For example:
if (args->arg_type[0] != STRING_RESULT ||
    args->arg_type[1] != INT_RESULT)
{
    strcpy(message,"XXX() requires a string and an integer");
    return 1;
}
As an alternative to requiring your function's arguments to be of particular types, you can use the initialisation function to set the arg_type elements to the types you want. This causes MySQL to coerce arguments to those types for each call to xxx(). For example, to specify coercion of the first two arguments to string and integer, do this in xxx_init():
args->arg_type[0] = STRING_RESULT;
args->arg_type[1] = INT_RESULT;
char **args
args->args communicates information to the initialisation function about the general nature of the arguments your function was called with. For a constant argument i, args->args[i] points to the argument value. (See below for instructions on how to access the value properly.) For a non-constant argument, args->args[i] is 0. A constant argument is an expression that uses only constants, such as 3 or 4*7-2 or SIN(3.14). A non-constant argument is an expression that refers to values that may change from row to row, such as column names or functions that are called with non-constant arguments. For each invocation of the main function, args->args contains the actual arguments that are passed for the row currently being processed. Functions can refer to an argument i as follows:
unsigned long *lengths
For the initialisation function, the lengths array indicates the maximum string length for each argument. You should not change these. For each invocation of the main function, lengths contains the actual lengths of any string arguments that are passed for the row currently being processed. For arguments of types INT_RESULT or REAL_RESULT, lengths still contains the maximum length of the argument (as for the initialisation function).

9.2.2.4 Return Values and Error Handling

The initialisation function should return 0 if no error occurred and 1 otherwise. If an error occurs, xxx_init() should store a null-terminated error message in the message parameter. The message will be returned to the client. The message buffer is MYSQL_ERRMSG_SIZE characters long, but you should try to keep the message to less than 80 characters so that it fits the width of a standard terminal screen.

The return value of the main function xxx() is the function value, for long long and double functions. A string functions should return a pointer to the result and store the length of the string in the length arguments.

Set these to the contents and length of the return value. For example:

memcpy(result, "result string", 13);
*length = 13;

The result buffer that is passed to the calc function is 255 byte big. If your result fits in this, you don't have to worry about memory allocation for results.

If your string function needs to return a string longer than 255 bytes, you must allocate the space for it with malloc() in your xxx_init() function or your xxx() function and free it in your xxx_deinit() function. You can store the allocated memory in the ptr slot in the UDF_INIT structure for reuse by future xxx() calls. See section 9.2.2.1 UDF Calling Sequences for simple functions.

To indicate a return value of NULL in the main function, set is_null to 1:

*is_null = 1;

To indicate an error return in the main function, set the error parameter to 1:

*error = 1;

If xxx() sets *error to 1 for any row, the function value is NULL for the current row and for any subsequent rows processed by the statement in which XXX() was invoked. (xxx() will not even be called for subsequent rows.) Note: in MySQL versions prior to 3.22.10, you should set both *error and *is_null:

*error = 1;
*is_null = 1;

9.2.2.5 Compiling and Installing User-definable Functions

Files implementing UDFs must be compiled and installed on the host where the server runs. This process is described below for the example UDF file `udf_example.cc' that is included in the MySQL source distribution. This file contains the following functions:

A dynamically loadable file should be compiled as a sharable object file, using a command something like this:

shell> gcc -shared -o udf_example.so myfunc.cc

You can easily find out the correct compiler options for your system by running this command in the `sql' directory of your MySQL source tree:

shell> make udf_example.o

You should run a compile command similar to the one that make displays, except that you should remove the -c option near the end of the line and add -o udf_example.so to the end of the line. (On some systems, you may need to leave the -c on the command.)

Once you compile a shared object containing UDFs, you must install it and tell MySQL about it. Compiling a shared object from `udf_example.cc' produces a file named something like `udf_example.so' (the exact name may vary from platform to platform). Copy this file to some directory searched by ld, such as `/usr/lib'. On many systems, you can set the LD_LIBRARY or LD_LIBRARY_PATH environment variable to point at the directory where you have your UDF function files. The dlopen manual page tells you which variable you should use on your system. You should set this in mysql.server or safe_mysqld startup scripts and restart mysqld.

After the library is installed, notify mysqld about the new functions with these commands:

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION reverse_lookup
    ->        RETURNS STRING SONAME "udf_example.so";
mysql> CREATE AGGREGATE FUNCTION avgcost
    ->        RETURNS REAL SONAME "udf_example.so";

Functions can be deleted using DROP FUNCTION:

mysql> DROP FUNCTION metaphon;
mysql> DROP FUNCTION myfunc_double;
mysql> DROP FUNCTION myfunc_int;
mysql> DROP FUNCTION lookup;
mysql> DROP FUNCTION reverse_lookup;
mysql> DROP FUNCTION avgcost;

The CREATE FUNCTION and DROP FUNCTION statements update the system table func in the mysql database. The function's name, type and shared library name are saved in the table. You must have the INSERT and DELETE privileges for the mysql database to create and drop functions.

You should not use CREATE FUNCTION to add a function that has already been created. If you need to reinstall a function, you should remove it with DROP FUNCTION and then reinstall it with CREATE FUNCTION. You would need to do this, for example, if you recompile a new version of your function, so that mysqld gets the new version. Otherwise, the server will continue to use the old version.

Active functions are reloaded each time the server starts, unless you start mysqld with the --skip-grant-tables option. In this case, UDF initialisation is skipped and UDFs are unavailable. (An active function is one that has been loaded with CREATE FUNCTION and not removed with DROP FUNCTION.)

9.2.3 Adding a New Native Function

The procedure for adding a new native function is described here. Note that you cannot add native functions to a binary distribution because the procedure involves modifying MySQL source code. You must compile MySQL yourself from a source distribution. Also note that if you migrate to another version of MySQL (for example, when a new version is released), you will need to repeat the procedure with the new version.

To add a new native MySQL function, follow these steps:

  1. Add one line to `lex.h' that defines the function name in the sql_functions[] array.
  2. If the function prototype is simple (just takes zero, one, two or three arguments), you should in lex.h specify SYM(FUNC_ARG#) (where # is the number of arguments) as the second argument in the sql_functions[] array and add a function that creates a function object in `item_create.cc'. Take a look at "ABS" and create_funcs_abs() for an example of this. If the function prototype is complicated (for example takes a variable number of arguments), you should add two lines to `sql_yacc.yy'. One indicates the preprocessor symbol that yacc should define (this should be added at the beginning of the file). Then define the function parameters and add an ``item'' with these parameters to the simple_expr parsing rule. For an example, check all occurrences of ATAN in `sql_yacc.yy' to see how this is done.
  3. In `item_func.h', declare a class inheriting from Item_num_func or Item_str_func, depending on whether your function returns a number or a string.
  4. In `item_func.cc', add one of the following declarations, depending on whether you are defining a numeric or string function:
    double   Item_func_newname::val()
    longlong Item_func_newname::val_int()
    String  *Item_func_newname::Str(String *str)
    
    If you inherit your object from any of the standard items (like Item_num_func you probably only have to define one of the above functions and let the parent object take care of the other functions. For example, the Item_str_func class defines a val() function that executes atof() on the value returned by ::str().
  5. You should probably also define the following object function:
    void Item_func_newname::fix_length_and_dec()
    
    This function should at least calculate max_length based on the given arguments. max_length is the maximum number of characters the function may return. This function should also set maybe_null = 0 if the main function can't return a NULL value. The function can check if any of the function arguments can return NULL by checking the arguments maybe_null variable. You can take a look at Item_func_mod::fix_length_and_dec for a typical example of how to do this.

All functions must be thread-safe (in other words, don't use any global or static variables in the functions without protecting them with mutexes).

If you want to return NULL, from ::val(), ::val_int() or ::str() you should set null_value to 1 and return 0.

For ::str() object functions, there are some additional considerations to be aware of:

9.3 Adding New Procedures to MySQL

In MySQL, you can define a procedure in C++ that can access and modify the data in a query before it is sent to the client. The modification can be done on row-by-row or GROUP BY level.

We have created an example procedure in MySQL Version 3.23 to show you what can be done.

Additionally we recommend you to take a look at mylua. With this you can use the LUA language to load a procedure at runtime into mysqld.

9.3.1 Procedure Analyse

analyse([max elements,[max memory]])

This procedure is defined in the `sql/sql_analyse.cc'. This examines the result from your query and returns an analysis of the results:

SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])

9.3.2 Writing a Procedure

For the moment, the only documentation for this is the source.

You can find all information about procedures by examining the following files:

A Problems and Common Errors

This chapter lists some common problems and error messages that users have run into. You will learn how to figure out what the problem is, and what to do to solve it. You will also find proper solutions to some common problems.

A.1 How to Determine What Is Causing Problems

When you run into problems, the first thing you should do is to find out which program / piece of equipment is causing problems:

If after you have examined all other possibilities and you have concluded that it's the MySQL server or a MySQL client that is causing the problem, it's time to do a bug report for our mailing list or our support team. In the bug report, try to give a very detailed description of how the system is behaving and what you think is happening. You should also state why you think it's MySQL that is causing the problems. Take into consideration all the situations in this chapter. State any problems exactly how they appear when you examine your system. Use the 'cut and paste' method for any output and/or error messages from programs and/or log files!

Try to describe in detail which program is not working and all symptoms you see! We have in the past received many bug reports that just state "the system doesn't work". This doesn't provide us with any information about what could be the problem.

If a program fails, it's always useful to know:

When sending a bug report, you should of follow the outlines described in this manual. See section 1.7.1.2 Asking Questions or Reporting Bugs.

A.2 Common Errors When Using MySQL

This section lists some errors that users frequently get. You will find descriptions of the errors, and how to solve the problem here.

A.2.1 Access denied Error

See section 4.2.11 Causes of Access denied Errors. See section 4.2.6 How the Privilege System Works.

A.2.2 MySQL server has gone away Error

This section also covers the related Lost connection to server during query error.

The most common reason for the MySQL server has gone away error is that the server timed out and closed the connection. By default, the server closes the connection after 8 hours if nothing has happened. You can change the time limit by setting the wait_timeout variable when you start mysqld.

Another common reason to receive the MySQL server has gone away error is because you have issued a ``close'' on your MySQL connection and then tried to run a query on the closed connection.

If you have a script, you just have to issue the query again for the client to do an automatic reconnection.

You normally can get the following error codes in this case (which one you get is OS-dependent):

Error code Description
CR_SERVER_GONE_ERROR The client couldn't send a question to the server.
CR_SERVER_LOST The client didn't get an error when writing to the server, but it didn't get a full answer (or any answer) to the question.

You will also get this error if someone has kills the running thread with kill #threadid#.

You can check that the MySQL hasn't died by executing mysqladmin version and examining the uptime. If the problem is that mysqld crashed you should concentrate one finding the reason for the crash. You should in this case start by checking if issuing the query again will kill MySQL again. See section A.4.1 What To Do If MySQL Keeps Crashing.

You can also get these errors if you send a query to the server that is incorrect or too large. If mysqld gets a packet that is too large or out of order, it assumes that something has gone wrong with the client and closes the connection. If you need big queries (for example, if you are working with big BLOB columns), you can increase the query limit by starting mysqld with the -O max_allowed_packet=# option (default 1M). The extra memory is allocated on demand, so mysqld will allocate more memory only when you issue a big query or when mysqld must return a big result row!

You will also get a lost connection if you are sending a packet >= 16M if your client is older than 4.0.8 and your server is 4.0.8 and above, or the other way around.

If you want to make a bug report regarding this problem, be sure that you include the following information:

See section 1.7.1.2 Asking Questions or Reporting Bugs.

A.2.3 Can't connect to [local] MySQL server Error

A MySQL client on Unix can connect to the mysqld server in two different ways: Unix sockets, which connect through a file in the file system (default `/tmp/mysqld.sock') or TCP/IP, which connects through a port number. Unix sockets are faster than TCP/IP but can only be used when connecting to a server on the same computer. Unix sockets are used if you don't specify a hostname or if you specify the special hostname localhost.

On Windows, if the mysqld server is running on 9x/Me, you can connect only via TCP/IP. If the server is running on NT/2000/XP and mysqld is started with --enable-named-pipe, you can also connect with named pipes. The name of the named pipe is MySQL. If you don't give a hostname when connecting to mysqld, a MySQL client will first try to connect to the named pipe, and if this doesn't work it will connect to the TCP/IP port. You can force the use of named pipes on Windows by using . as the hostname.

The error (2002) Can't connect to ... normally means that there isn't a MySQL server running on the system or that you are using a wrong socket file or TCP/IP port when trying to connect to the mysqld server.

Start by checking (using ps or the task manager on Windows) that there is a process running named mysqld on your server! If there isn't any mysqld process, you should start one. See section 2.4.2 Problems Starting the MySQL Server.

If a mysqld process is running, you can check the server by trying these different connections (the port number and socket pathname might be different in your setup, of course):

shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h `hostname` version variables
shell> mysqladmin -h `hostname` --port=3306 version
shell> mysqladmin -h 'ip for your host' version
shell> mysqladmin --protocol=socket --socket=/tmp/mysql.sock version

Note the use of backquotes rather than forward quotes with the hostname command; these cause the output of hostname (that is, the current hostname) to be substituted into the mysqladmin command.

Here are some reasons the Can't connect to local MySQL server error might occur:

If you get the error message Can't connect to MySQL server on some_hostname, you can try the following things to find out what the problem is :

A.2.4 Host '...' is blocked Error

If you get an error like this:

Host 'hostname' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

this means that mysqld has gotten a lot (max_connect_errors) of connect requests from the host 'hostname' that have been interrupted in the middle. After max_connect_errors failed requests, mysqld assumes that something is wrong (like an attack from a cracker), and blocks the site from further connections until someone executes the command mysqladmin flush-hosts.

By default, mysqld blocks a host after 10 connection errors. You can easily adjust this by starting the server like this:

shell> safe_mysqld -O max_connect_errors=10000 &

Note that if you get this error message for a given host, you should first check that there isn't anything wrong with TCP/IP connections from that host. If your TCP/IP connections aren't working, it won't do you any good to increase the value of the max_connect_errors variable!

A.2.5 Too many connections Error

If you get the error Too many connections when you try to connect to MySQL, this means that there is already max_connections clients connected to the mysqld server.

If you need more connections than the default (100), then you should restart mysqld with a bigger value for the max_connections variable.

Note that mysqld actually allows (max_connections+1) clients to connect. The last connection is reserved for a user with the SUPER privilege. By not giving this privilege to normal users (they shouldn't need this), an administrator with this privilege can log in and use SHOW PROCESSLIST to find out what could be wrong. See section 4.5.6.6 SHOW PROCESSLIST.

The maximum number of connects MySQL is depending on how good the thread library is on a given platform. Linux or Solaris should be able to support 500-1000 simultaneous connections, depending on how much RAM you have and what your clients are doing.

A.2.6 Some non-transactional changed tables couldn't be rolled back Error

If you get the error/warning: Warning: Some non-transactional changed tables couldn't be rolled back when trying to do a ROLLBACK, this means that some of the tables you used in the transaction didn't support transactions. These non-transactional tables will not be affected by the ROLLBACK statement.

The most typical case when this happens is when you have tried to create a table of a type that is not supported by your mysqld binary. If mysqld doesn't support a table type (or if the table type is disabled by a startup option) , it will instead create the table type with the table type that is most resembles to the one you requested, probably MyISAM.

You can check the table type for a table by doing:

SHOW TABLE STATUS LIKE 'table_name'. See section 4.5.6.2 SHOW TABLE STATUS.

You can check the extensions your mysqld binary supports by doing:

show variables like 'have_%'. See section 4.5.6.4 SHOW VARIABLES.

A.2.7 Out of memory Error

If you issue a query and get something like the following error:

mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory

note that the error refers to the MySQL client mysql. The reason for this error is simply that the client does not have enough memory to store the whole result.

To remedy the problem, first check that your query is correct. Is it reasonable that it should return so many rows? If so, you can use mysql --quick, which uses mysql_use_result() to retrieve the result set. This places less of a load on the client (but more on the server).

A.2.8 Packet too large Error

When a MySQL client or the mysqld server gets a packet bigger than max_allowed_packet bytes, it issues a Packet too large error and closes the connection.

In MySQL 3.23 the biggest possible packet is 16M (due to limits in the client/server protocol). In MySQL 4.0.1 and up, this is only limited by the amount on memory you have on your server (up to a theoretical maximum of 2G).

A communication packet is a single SQL statement sent to the MySQL server or a single row that is sent to the client.

When a MySQL client or the mysqld server gets a packet bigger than max_allowed_packet bytes, it issues a Packet too large error and closes the connection. With some clients, you may also get Lost connection to MySQL server during query error if the communication packet is too big.

Note that both the client and the server has it's own max_allowed_packet variable. If you want to handle big packets, you have to increase this variable both in the client and in the server.

It's safe to increase this variable as memory is only allocated when needed; this variable is more a precaution to catch wrong packets between the client/server and also to ensure that you don't accidentally use big packets so that you run out of memory.

If you are using the mysql client, you may specify a bigger buffer by starting the client with mysql --set-variable=max_allowed_packet=8M. Other clients have different methods to set this variable. Please note that --set-variable is deprecated since MySQL 4.0, just use --max-allowed-packet=8M instead. You can use the option file to set max_allowed_packet to a larger size in mysqld. For example, if you are expecting to store the full length of a MEDIUMBLOB into a table, you'll need to start the server with the set-variable=max_allowed_packet=16M option.

You can also get strange problems with large packets if you are using big blobs, but you haven't given mysqld access to enough memory to handle the query. If you suspect this is the case, try adding ulimit -d 256000 to the beginning of the safe_mysqld script and restart mysqld.

A.2.9 Communication Errors / Aborted Connection

Starting with MySQL 3.23.40 you only get the Aborted connection error of you start mysqld with --warnings.

If you find errors like the following in your error log.

010301 14:38:23  Aborted connection 854 to db: 'users' user: 'josh'

See section 4.9.1 The Error Log.

This means that something of the following has happened:

When the above happens, the server variable Aborted_clients is incremented.

The server variable Aborted_connects is incremented when:

Note that the above could indicate that someone is trying to break into your database!

Other reasons for problems with Aborted clients / Aborted connections.

A.2.10 The table is full Error

There is a couple of different cases when you can get this error:

A.2.11 Can't create/write to file Error

If you get an error for some queries of type:

Can't create/write to file '\\sqla3fe_0.ism'.

this means that MySQL can't create a temporary file for the result set in the given temporary directory. (The above error is a typical error message on Windows, and the Unix error message is similar.) The fix is to start mysqld with --tmpdir=path or to add to your option file:

[mysqld]
tmpdir=C:/temp

assuming that the `c:\\temp' directory exists. See section 4.1.2 `my.cnf' Option Files.

Check also the error code that you get with perror. One reason may also be a disk full error;

shell> perror 28
Error code  28:  No space left on device

A.2.12 Commands out of sync Error in Client

If you get Commands out of sync; you can't run this command now in your client code, you are calling client functions in the wrong order!

This can happen, for example, if you are using mysql_use_result() and try to execute a new query before you have called mysql_free_result(). It can also happen if you try to execute two queries that return data without a mysql_use_result() or mysql_store_result() in between.

A.2.13 Ignoring user Error

If you get the following error:

Found wrong password for user: 'some_user@some_host'; ignoring user

this means that when mysqld was started or when it reloaded the permissions tables, it found an entry in the user table with an invalid password. As a result, the entry is simply ignored by the permission system.

Possible causes of and fixes for this problem:

A.2.14 Table 'xxx' doesn't exist Error

If you get the error Table 'xxx' doesn't exist or Can't find file: 'xxx' (errno: 2), this means that no table exists in the current database with the name xxx.

Note that as MySQL uses directories and files to store databases and tables, the database and table names are case-sensitive! (On Windows the databases and tables names are not case-sensitive, but all references to a given table within a query must use the same case!)

You can check which tables you have in the current database with SHOW TABLES. See section 4.5.6 SHOW Syntax.

A.2.15 Can't initialize character set xxx error

If you get an error like:

MySQL Connection Failed: Can't initialize character set xxx

This means one of the following things:

A.2.16 File Not Found

If you get ERROR '...' not found (errno: 23), Can't open file: ... (errno: 24), or any other error with errno 23 or errno 24 from MySQL, it means that you haven't allocated enough file descriptors for MySQL. You can use the perror utility to get a description of what the error number means:

shell> perror 23
File table overflow
shell> perror 24
Too many open files
shell> perror 11
Resource temporarily unavailable

The problem here is that mysqld is trying to keep open too many files simultaneously. You can either tell mysqld not to open so many files at once or increase the number of file descriptors available to mysqld.

To tell mysqld to keep open fewer files at a time, you can make the table cache smaller by using the -O table_cache=32 option to safe_mysqld (the default value is 64). Reducing the value of max_connections will also reduce the number of open files (the default value is 90).

To change the number of file descriptors available to mysqld, you can use the option --open-files-limit=# to safe_mysqld or -O open-files-limit=# to mysqld. See section 4.5.6.4 SHOW VARIABLES. The easiest way to do that is to add the option to your option file. See section 4.1.2 `my.cnf' Option Files. If you have an old mysqld version that doesn't support this, you can edit the safe_mysqld script. There is a commented-out line ulimit -n 256 in the script. You can remove the '#' character to uncomment this line, and change the number 256 to affect the number of file descriptors available to mysqld.

ulimit (and open-files-limit) can increase the number of file descriptors, but only up to the limit imposed by the operating system. There is also a 'hard' limit that can only be overrided if you start safe_mysqld or mysqld as root (just remember that you need to also use the --user=... option in this case). If you need to increase the OS limit on the number of file descriptors available to each process, consult the documentation for your operating system.

Note that if you run the tcsh shell, ulimit will not work! tcsh will also report incorrect values when you ask for the current limits! In this case you should start safe_mysqld with sh!

A.3 Installation Related Issues

A.3.1 Problems When Linking with the MySQL Client Library

If you are linking your program and you get errors for unreferenced symbols that start with mysql_, like the following:

/tmp/ccFKsdPa.o: In function `main':
/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

you should be able to solve this by adding -Lpath-to-the-mysql-library -lmysqlclient last on your link line.

If you get undefined reference errors for the uncompress or compress function, add -lz last on your link line and try again!

If you get undefined reference errors for functions that should exist on your system, like connect, check the man page for the function in question, for which libraries you should add to the link line!

If you get undefined reference errors for functions that don't exist on your system, like the following:

mf_format.o(.text+0x201): undefined reference to `__lxstat'

it usually means that your library is compiled on a system that is not 100% compatible with yours. In this case you should download the latest MySQL source distribution and compile this yourself. See section 2.3 Installing a MySQL Source Distribution.

If you are trying to run a program and you then get errors for unreferenced symbols that start with mysql_ or that the mysqlclient library can't be found, this means that your system can't find the share `libmysqlclient.so' library.

The fix for this is to tell your system to search after shared libraries where the library is located by one of the following methods:

Another way to solve this problem is to link your program statically, with -static, or by removing the dynamic MySQL libraries before linking your code. In the second case you should be sure that no other programs are using the dynamic libraries!

A.3.2 How to Run MySQL As a Normal User

The MySQL server mysqld can be started and run by any user. In order to change mysqld to run as a Unix user user_name, you must do the following:

  1. Stop the server if it's running (use mysqladmin shutdown).
  2. Change the database directories and files so that user_name has privileges to read and write files in them (you may need to do this as the Unix root user):
    shell> chown -R user_name /path/to/mysql/datadir
    
    If directories or files within the MySQL data directory are symlinks, you'll also need to follow those links and change the directories and files they point to. chown -R may not follow symlinks for you.
  3. Start the server as user user_name, or, if you are using MySQL Version 3.22 or later, start mysqld as the Unix root user and use the --user=user_name option. mysqld will switch to run as the Unix user user_name before accepting any connections.
  4. To start the server as the given user name automatically at system startup time, add a user line that specifies the user name to the [mysqld] group of the `/etc/my.cnf' option file or the `my.cnf' option file in the server's data directory. For example:
    [mysqld]
    user=user_name
    

At this point, your mysqld process should be running fine and dandy as the Unix user user_name. One thing hasn't changed, though: the contents of the permissions tables. By default (right after running the permissions table install script mysql_install_db), the MySQL user root is the only user with permission to access the mysql database or to create or drop databases. Unless you have changed those permissions, they still hold. This shouldn't stop you from accessing MySQL as the MySQL root user when you're logged in as a Unix user other than root; just specify the -u root option to the client program.

Note that accessing MySQL as root, by supplying -u root on the command-line, has nothing to do with MySQL running as the Unix root user, or, indeed, as another Unix user. The access permissions and user names of MySQL are completely separate from Unix user names. The only connection with Unix user names is that if you don't provide a -u option when you invoke a client program, the client will try to connect using your Unix login name as your MySQL user name.

If your Unix box itself isn't secured, you should probably at least put a password on the MySQL root users in the access tables. Otherwise, any user with an account on that machine can run mysql -u root db_name and do whatever he likes.

A.3.3 Problems with File Permissions

If you have problems with file permissions, for example, if mysql issues the following error message when you create a table:

ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)

then the environment variable UMASK might be set incorrectly when mysqld starts up. The default umask value is 0660. You can change this behaviour by starting safe_mysqld as follows:

shell> UMASK=384  # = 600 in octal
shell> export UMASK
shell> /path/to/safe_mysqld &

By default MySQL will create database and RAID directories with permission type 0700. You can modify this behaviour by setting the UMASK_DIR variable. If you set this, new directories are created with the combined UMASK and UMASK_DIR. For example, if you want to give group access to all new directories, you can do:

shell> UMASK_DIR=504  # = 770 in octal
shell> export UMASK_DIR
shell> /path/to/safe_mysqld &

In MySQL Version 3.23.25 and above, MySQL assumes that the value for UMASK and UMASK_DIR is in octal if it starts with a zero.

See section F Environment Variables.

A.4 Administration Related Issues

A.4.1 What To Do If MySQL Keeps Crashing

All MySQL versions are tested on many platforms before they are released. This doesn't mean that there aren't any bugs in MySQL, but it means if there are bugs, they are very few and can be hard to find. If you have a problem, it will always help if you try to find out exactly what crashes your system, as you will have a much better chance of getting this fixed quickly.

First, you should try to find out whether the problem is that the mysqld daemon dies or whether your problem has to do with your client. You can check how long your mysqld server has been up by executing mysqladmin version. If mysqld has died, you may find the reason for this in the file `mysql-data-directory/`hostname`.err'. See section 4.9.1 The Error Log.

Many crashes of MySQL are caused by corrupted index / data files. MySQL will update the data on disk, with the write() system call, after every SQL statement and before the client is notified about the result. (This is not true if you are running with delay_key_write, in which case only the data is written.) This means that the data is safe even if mysqld crashes, as the OS will ensure that the not flushed data is written to disk. You can force MySQL to sync everything to disk after every SQL command by starting mysqld with --flush.

The above means that normally you shouldn't get corrupted tables unless:

Because it is very difficult to know why something is crashing, first try to check whether things that work for others crash for you. Please try the following things:

A.4.2 How to Reset a Forgotten Root Password

If you never set a root password for MySQL, then the server will not require a password at all for connecting as root. It is recommended to always set a password for each user. See section 4.2.2 How to Make MySQL Secure Against Crackers.

If you have set a root password, but forgot what it was, you can set a new password with the following procedure:

  1. Take down the mysqld server by sending a kill (not kill -9) to the mysqld server. The pid is stored in a `.pid' file, which is normally in the MySQL database directory:
    shell> kill `cat /mysql-data-directory/hostname.pid`
    
    You must be either the Unix root user or the same user mysqld runs as to do this.
  2. Restart mysqld with the --skip-grant-tables option.
  3. Set a new password with the mysqladmin password command:
    shell> mysqladmin -u root password 'mynewpassword'
    
  4. Now you can either stop mysqld and restart it normally, or just load the privilege tables with:
    shell> mysqladmin -h hostname flush-privileges
    
  5. After this, you should be able to connect using the new password.

Alternatively, you can set the new password using the mysql client:

  1. Take down and restart mysqld with the --skip-grant-tables option as described above.
  2. Connect to the mysqld server with:
    shell> mysql -u root mysql
    
  3. Issue the following commands in the mysql client:
    mysql> UPDATE user SET Password=PASSWORD('mynewpassword')
        ->             WHERE User='root';
    mysql> FLUSH PRIVILEGES;
    
  4. After this, you should be able to connect using the new password.
  5. You can now stop mysqld and restart it normally.

A.4.3 How MySQL Handles a Full Disk

When a disk-full condition occurs, MySQL does the following:

To alleviate the problem, you can take the following actions:

Exceptions to the above behaveour is when you use REPAIR or OPTIMIZE or when the indexes are created in a batch after an LOAD DATA INFILE or after an ALTER TABLE statement.

All of the above commands may use big temporary files that left to themself would cause big problems for the rest of the system. If MySQL gets disk full while doing any of the above operations, it will remove the big temporary files and mark the table as crashed (except for ALTER TABLE, in which the old table will be left unchanged).

A.4.4 Where MySQL Stores Temporary Files

MySQL uses the value of the TMPDIR environment variable as the pathname of the directory in which to store temporary files. If you don't have TMPDIR set, MySQL uses the system default, which is normally `/tmp' or `/usr/tmp'. If the filesystem containing your temporary file directory is too small, you should edit safe_mysqld to set TMPDIR to point to a directory in a filesystem where you have enough space! You can also set the temporary directory using the --tmpdir option to mysqld.

MySQL creates all temporary files as hidden files. This ensures that the temporary files will be removed if mysqld is terminated. The disadvantage of using hidden files is that you will not see a big temporary file that fills up the filesystem in which the temporary file directory is located.

When sorting (ORDER BY or GROUP BY), MySQL normally uses one or two temporary files. The maximum disk-space needed is:

(length of what is sorted + sizeof(database pointer))
* number of matched rows
* 2

sizeof(database pointer) is usually 4, but may grow in the future for really big tables.

For some SELECT queries, MySQL also creates temporary SQL tables. These are not hidden and have names of the form `SQL_*'.

ALTER TABLE creates a temporary table in the same directory as the original table.

If you use MySQL 4.1 or later you can spread load between several physical disks by setting --tmpdir to a list of paths separated by colon : (semicolon ; on Windows). They will be used in round-robin fashion. Note: These paths should end up on different physical disks, not different partitions of the same disk.

A.4.5 How to Protect or Change the MySQL Socket File `/tmp/mysql.sock'

If you have problems with the fact that anyone can delete the MySQL communication socket `/tmp/mysql.sock', you can, on most versions of Unix, protect your `/tmp' filesystem by setting the sticky bit on it. Log in as root and do the following:

shell> chmod +t /tmp

This will protect your `/tmp' filesystem so that files can be deleted only by their owners or the superuser (root).

You can check if the sticky bit is set by executing ls -ld /tmp. If the last permission bit is t, the bit is set.

You can change the place where MySQL uses / puts the socket file the following ways:

You can test that the socket works with this command:

shell> mysqladmin --socket=/path/to/socket version

A.4.6 Time Zone Problems

If you have a problem with SELECT NOW() returning values in GMT and not your local time, you have to set the TZ environment variable to your current time zone. This should be done for the environment in which the server runs, for example, in safe_mysqld or mysql.server. See section F Environment Variables.

A.5 Query Related Issues

A.5.1 Case-Sensitivity in Searches

By default, MySQL searches are case-insensitive (although there are some character sets that are never case-insensitive, such as czech). That means that if you search with col_name LIKE 'a%', you will get all column values that start with A or a. If you want to make this search case-sensitive, use something like INSTR(col_name, "A")=1 to check a prefix. Or use STRCMP(col_name, "A") = 0 if the column value must be exactly "A".

Simple comparison operations (>=, >, = , < , <=, sorting and grouping) are based on each character's ``sort value''. Characters with the same sort value (like E, e and é) are treated as the same character!

In older MySQL versions LIKE comparisons were done on the uppercase value of each character (E == e but E <> é). In newer MySQL versions LIKE works just like the other comparison operators.

If you want a column always to be treated in case-sensitive fashion, declare it as BINARY. See section 6.5.3 CREATE TABLE Syntax.

If you are using Chinese data in the so-called big5 encoding, you want to make all character columns BINARY. This works because the sorting order of big5 encoding characters is based on the order of ASCII codes.

A.5.2 Problems Using DATE Columns

The format of a DATE value is 'YYYY-MM-DD'. According to ANSI SQL, no other format is allowed. You should use this format in UPDATE expressions and in the WHERE clause of SELECT statements. For example:

mysql> SELECT * FROM tbl_name WHERE date >= '1997-05-05';

As a convenience, MySQL automatically converts a date to a number if the date is used in a numeric context (and vice versa). It is also smart enough to allow a ``relaxed'' string form when updating and in a WHERE clause that compares a date to a TIMESTAMP, DATE, or a DATETIME column. (Relaxed form means that any punctuation character may be used as the separator between parts. For example, '1998-08-15' and '1998#08#15' are equivalent.) MySQL can also convert a string containing no separators (such as '19980815'), provided it makes sense as a date.

The special date '0000-00-00' can be stored and retrieved as '0000-00-00'. When using a '0000-00-00' date through MyODBC, it will automatically be converted to NULL in MyODBC Version 2.50.12 and above, because ODBC can't handle this kind of date.

Because MySQL performs the conversions described above, the following statements work:

mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
mysql> INSERT INTO tbl_name (idate) VALUES ('19970505');
mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05');
mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05');
mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00');

mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05';
mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT MOD(idate,100) FROM tbl_name WHERE idate >= 19970505;
mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';

However, the following will not work:

mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;

STRCMP() is a string function, so it converts idate to a string and performs a string comparison. It does not convert '19970505' to a date and perform a date comparison.

Note that MySQL does very limited checking whether the date is correct. If you store an incorrect date, such as '1998-2-31', the wrong date will be stored.

Because MySQL packs dates for storage, it can't store any given date as it would not fit onto the result buffer. The rules for accepting a date are:

If the date cannot be converted to any reasonable value, a 0 is stored in the DATE field, which will be retrieved as 0000-00-00. This is both a speed and convenience issue as we believe that the database's responsiblity is to retrieve the same date you stored (even if the data was not logically correct in all cases). We think it is up to the application to check the dates, and not the server.

A.5.3 Problems with NULL Values

The concept of the NULL value is a common source of confusion for newcomers to SQL, who often think that NULL is the same thing as an empty string "". This is not the case! For example, the following statements are completely different:

mysql> INSERT INTO my_table (phone) VALUES (NULL);
mysql> INSERT INTO my_table (phone) VALUES ("");

Both statements insert a value into the phone column, but the first inserts a NULL value and the second inserts an empty string. The meaning of the first can be regarded as ``phone number is not known'' and the meaning of the second can be regarded as ``she has no phone''.

In SQL, the NULL value is always false in comparison to any other value, even NULL. An expression that contains NULL always produces a NULL value unless otherwise indicated in the documentation for the operators and functions involved in the expression. All columns in the following example return NULL:

mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);

If you want to search for column values that are NULL, you cannot use the =NULL test. The following statement returns no rows, because expr = NULL is FALSE, for any expression:

mysql> SELECT * FROM my_table WHERE phone = NULL;

To look for NULL values, you must use the IS NULL test. The following shows how to find the NULL phone number and the empty phone number:

mysql> SELECT * FROM my_table WHERE phone IS NULL;
mysql> SELECT * FROM my_table WHERE phone = "";

Note that you can only add an index on a column that can have NULL values if you are using MySQL Version 3.23.2 or newer and are using the MyISAM or InnoDB table type. In earlier versions and with other table types, you must declare such columns NOT NULL. This also means you cannot then insert NULL into an indexed column.

When reading data with LOAD DATA INFILE, empty columns are updated with ''. If you want a NULL value in a column, you should use \N in the text file. The literal word 'NULL' may also be used under some circumstances. See section 6.4.9 LOAD DATA INFILE Syntax.

When using ORDER BY, NULL values are presented first. In versions prior to 4.0.2, if you sort in descending order using DESC, NULL values are presented last. When using GROUP BY, all NULL values are regarded as equal.

To help with NULL handling, you can use the IS NULL and IS NOT NULL operators and the IFNULL() function.

For some column types, NULL values are handled specially. If you insert NULL into the first TIMESTAMP column of a table, the current date and time is inserted. If you insert NULL into an AUTO_INCREMENT column, the next number in the sequence is inserted.

A.5.4 Problems with alias

You can use an alias to refer to a column in the GROUP BY, ORDER BY, or in the HAVING part. Aliases can also be used to give columns better names:

SELECT SQRT(a*b) as rt FROM table_name GROUP BY rt HAVING rt > 0;
SELECT id,COUNT(*) AS cnt FROM table_name GROUP BY id HAVING cnt > 0;
SELECT id AS "Customer identity" FROM table_name;

Note that ANSI SQL doesn't allow you to refer to an alias in a WHERE clause. This is because when the WHERE code is executed the column value may not yet be determined. For example, the following query is illegal:

SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;

The WHERE statement is executed to determine which rows should be included in the GROUP BY part while HAVING is used to decide which rows from the result set should be used.

A.5.5 Deleting Rows from Related Tables

As MySQL doesn't support subqueries (prior to Version 4.1), nor the use of more than one table in the DELETE statement (prior to Version 4.0), you should use the following approach to delete rows from 2 related tables:

  1. SELECT the rows based on some WHERE condition in the main table.
  2. DELETE the rows in the main table based on the same condition.
  3. DELETE FROM related_table WHERE related_column IN (selected_rows).

If the total number of characters in the query with related_column is more than 1,048,576 (the default value of max_allowed_packet, you should split it into smaller parts and execute multiple DELETE statements. You will probably get the fastest DELETE by only deleting 100-1000 related_column id's per query if the related_column is an index. If the related_column isn't an index, the speed is independent of the number of arguments in the IN clause.

A.5.6 Solving Problems with No Matching Rows

If you have a complicated query that has many tables and that doesn't return any rows, you should use the following procedure to find out what is wrong with your query:

  1. Test the query with EXPLAIN and check if you can find something that is obviously wrong. See section 5.2.1 EXPLAIN Syntax (Get Information About a SELECT).
  2. Select only those fields that are used in the WHERE clause.
  3. Remove one table at a time from the query until it returns some rows. If the tables are big, it's a good idea to use LIMIT 10 with the query.
  4. Do a SELECT for the column that should have matched a row against the table that was last removed from the query.
  5. If you are comparing FLOAT or DOUBLE columns with numbers that have decimals, you can't use '='. This problem is common in most computer languages because floating-point values are not exact values. In most cases, changing the FLOAT to a DOUBLE will fix this. See section A.5.7 Problems with Floating-Point Comparison.
  6. If you still can't figure out what's wrong, create a minimal test that can be run with mysql test < query.sql that shows your problems. You can create a test file with mysqldump --quick database tables > query.sql. Open the file in an editor, remove some insert lines (if there are too many of these), and add your select statement at the end of the file. Test that you still have your problem by doing:
    shell> mysqladmin create test2
    shell> mysql test2 < query.sql
    
    Post the test file using mysqlbug to mysql@lists.mysql.com.

A.5.7 Problems with Floating-Point Comparison

floating-point numbers cause confusion sometimes, because these numbers are not stored as exact values inside computer architecture. What one can see on the screen usually is not the exact value of the number.

Field types FLOAT, DOUBLE and DECIMAL are such.

CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2));
INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
(6, 0.00, 0.00), (6, -51.40, 0.00);

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

The result is correct. Although the first five records look like they shouldn't pass the comparison test, they may do so because the difference between the numbers show up around tenth decimal, or so depending on computer architecture.

The problem cannot be solved by using ROUND() (or similar function), because the result is still a floating-point number. Example:

mysql> SELECT i, ROUND(SUM(d1), 2) AS a, ROUND(SUM(d2), 2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+-------+
| i    | a      | b     |
+------+--------+-------+
|    1 |  21.40 | 21.40 |
|    2 |  76.80 | 76.80 |
|    3 |   7.40 |  7.40 |
|    4 |  15.40 | 15.40 |
|    5 |   7.20 |  7.20 |
|    6 | -51.40 |  0.00 |
+------+--------+-------+

This is what the numbers in column 'a' look like:

mysql> SELECT i, ROUND(SUM(d1), 2)*1.0000000000000000 AS a,
    -> ROUND(SUM(d2), 2) AS b FROM t1 GROUP BY i HAVING a <> b;
+------+----------------------+-------+
| i    | a                    | b     |
+------+----------------------+-------+
|    1 |  21.3999999999999986 | 21.40 |
|    2 |  76.7999999999999972 | 76.80 |
|    3 |   7.4000000000000004 |  7.40 |
|    4 |  15.4000000000000004 | 15.40 |
|    5 |   7.2000000000000002 |  7.20 |
|    6 | -51.3999999999999986 |  0.00 |
+------+----------------------+-------+

Depending on the computer architecture you may or may not see similar results. Each CPU may evaluate floating-point numbers differently. For example in some machines you may get 'right' results by multiplaying both arguments with 1, an example follows.

WARNING: NEVER TRUST THIS METHOD IN YOUR APPLICATION, THIS IS AN EXAMPLE OF A WRONG METHOD!!!

mysql> SELECT i, ROUND(SUM(d1), 2)*1 AS a, ROUND(SUM(d2), 2)*1 AS b
    -> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+

The reason why the above example seems to be working is that on the particular machine where the test was done, the CPU floating-point arithmetics happens to round the numbers to same, but there is no rule that any CPU should do so, so it cannot be trusted.

The correct way to do floating-point number comparison is to first decide on what is the wanted tolerance between the numbers and then do the comparison against the tolerance number. For example, if we agree on that floating-point numbers should be regarded the same, if they are same with precision of one of ten thousand (0.0001), the comparison should be done like this:

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) > 0.0001;
+------+--------+------+
| i    | a      | b    |
+------+--------+------+
|    6 | -51.40 | 0.00 |
+------+--------+------+
1 row in set (0.00 sec)

And vice versa, if we wanted to get rows where the numbers are the same, the test would be:

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) < 0.0001;
+------+-------+-------+
| i    | a     | b     |
+------+-------+-------+
|    1 | 21.40 | 21.40 |
|    2 | 76.80 | 76.80 |
|    3 |  7.40 |  7.40 |
|    4 | 15.40 | 15.40 |
|    5 |  7.20 |  7.20 |
+------+-------+-------+

A.6 Table Definition Related Issues

A.6.1 Problems with ALTER TABLE.

ALTER TABLE changes a table to the current character set. If you get a duplicate key error during ALTER TABLE, then the cause is either that the new character sets maps two keys to the same value or that the table is corrupted, in which case you should run REPAIR TABLE on the table.

If ALTER TABLE dies with an error like this:

Error on rename of './database/name.frm' to './database/B-a.frm' (Errcode: 17)

the problem may be that MySQL has crashed in a previous ALTER TABLE and there is an old table named `A-something' or `B-something' lying around. In this case, go to the MySQL data directory and delete all files that have names starting with A- or B-. (You may want to move them elsewhere instead of deleting them.)

ALTER TABLE works the following way:

If something goes wrong with the renaming operation, MySQL tries to undo the changes. If something goes seriously wrong (this shouldn't happen, of course), MySQL may leave the old table as `B-xxx', but a simple rename on the system level should get your data back.

A.6.2 How To Change the Order of Columns in a Table

The whole point of SQL is to abstract the application from the data storage format. You should always specify the order in which you wish to retrieve your data. For example:

SELECT col_name1, col_name2, col_name3 FROM tbl_name;

will return columns in the order col_name1, col_name2, col_name3, whereas:

SELECT col_name1, col_name3, col_name2 FROM tbl_name;

will return columns in the order col_name1, col_name3, col_name2.

If you want to change the order of columns anyway, you can do it as follows:

  1. Create a new table with the columns in the right order.
  2. Execute INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
  3. Drop or rename old_table.
  4. ALTER TABLE new_table RENAME old_table.

You should never, in an application, use SELECT * and retrieve the columns based on their position, because the order and position in which columns are returned cannot may not remain the same (if you add/move/delete columns). A simple change to your database structure would then cause your application to fail. Of course SELECT * is quite suitable for testing queries.

A.6.3 TEMPORARY TABLE problems

The following are a list of the limitations with TEMPORARY TABLES.

B Contributed Programs

Many users of MySQL have contributed very useful support tools and add-ons.

A list of some software available from the MySQL website (or any mirror) is shown here.

You can also visit our online listing of MySQL-related software at http://www.mysql.com/portal/software/. The community facilities there also allow for your input!

If you want to build MySQL support for the Perl DBI/DBD interface, you should fetch the Data-Dumper, DBI, and Msql-Mysql-modules files and install them. See section 2.7 Perl Installation Comments.

Note: The programs listed here can be freely downloaded and used. They are copyrighted by their respective owners. Please see individual product documentation for more details on licensing and terms. MySQL AB assumes no liability for the correctness of the information in this chapter or for the proper operation of the programs listed herein.

B.1 APIs

B.2 Converters

B.3 Utilities

C Credits

This appendix lists the developers, contributors, and supporters that have helped to make MySQL what it is today.

C.1 Developers at MySQL AB

These are the developers that are or have been employed by MySQL AB to work on the MySQL database software, roughly in the order they started to work with us. Following each developer is a small list of the tasks that the developer is responsible for, or the accomplishments they have made. All developers are involved in support.

Michael (Monty) Widenius
David Axmark
Jani Tolonen
Sinisa Milivojevic
Tonu Samuel (past developer)
Sasha Pachev
Matt Wagner
Miguel Solorzano
Timothy Smith (past developer)
Sergei Golubchik
Jeremy Cole
Indrek Siitan
Jorge del Conde
Venu Anuganti
Arjen Lentz
Alexander (Bar) Barkov, Alexey (Holyfoot) Botchkov, and Ramil Kalimullin
Oleksandr (Sanja) Byelkin
Aleksey (Walrus) Kishkin and Alexey (Ranger) Stroganov
Zak Greant
Carsten Pedersen
Lenz Grimmer
Peter Zaitsev
Alexander (Salle) Keremidarski
Per-Erik Martin
Jim Winstead
Mark Matthews
Peter Gulutzan

C.2 Contributors to MySQL

While MySQL AB owns all copyrights in the MySQL server and the MySQL manual, we wish to recognise those who have made contributions of one kind or another to the MySQL distribution. Contributors are listed here, in somewhat random order:

Paul DuBois
Ongoing help with making this manual correct and understandable. That includes rewriting Monty's and David's attempts at English into English as other people know it.
Gianmassimo Vigazzola qwerg@mbox.vol.it or qwerg@tin.it
The initial port to Win32/NT.
Kim Aldale
Helped to rewrite Monty's and David's early attempts at English into English.
Per Eric Olsson
For more or less constructive criticism and real testing of the dynamic record format.
Irena Pancirov irena@mail.yacc.it
Win32 port with Borland compiler. mysqlshutdown.exe and mysqlwatch.exe
David J. Hughes
For the effort to make a shareware SQL database. At TcX, the predecessor of MySQL AB, we started with mSQL, but found that it couldn't satisfy our purposes so instead we wrote a SQL interface to our application builder Unireg. mysqladmin and mysql client are programs that were largely influenced by their mSQL counterparts. We have put a lot of effort into making the MySQL syntax a superset of mSQL. Many of the API's ideas are borrowed from mSQL to make it easy to port free mSQL programs to the MySQL API. The MySQL software doesn't contain any code from mSQL. Two files in the distribution (`client/insert_test.c' and `client/select_test.c') are based on the corresponding (non-copyrighted) files in the mSQL distribution, but are modified as examples showing the changes necessary to convert code from mSQL to MySQL Server. (mSQL is copyrighted David J. Hughes.)
Fred Fish
For his excellent C debugging and trace library. Monty has made a number of smaller improvements to the library (speed and additional options).
Richard A. O'Keefe
For his public domain string library.
Henry Spencer
For his regex library, used in WHERE column REGEXP regexp.
Free Software Foundation
From whom we got an excellent compiler (gcc), the libc library (from which we have borrowed `strto.c' to get some code working in Linux), and the readline library (for the mysql client).
Free Software Foundation & The XEmacs development team
For a really great editor/environment used by almost everybody at MySQL AB/TcX/detron.
Patrick Lynch
For helping us acquire http://www.mysql.com/.
Fred Lindberg
For setting up qmail to handle the MySQL mailing list and for the incredible help we got in managing the MySQL mailing lists.
Igor Romanenko igor@frog.kiev.ua
mysqldump (previously msqldump, but ported and enhanced by Monty).
Yuri Dario
For keeping up and extending the MySQL OS/2 port.
Tim Bunce, Alligator Descartes
For the DBD (Perl) interface.
Tim Bunce
Author of mysqlhotcopy.
Andreas Koenig a.koenig@mind.de
For the Perl interface for MySQL Server.
Eugene Chan eugene@acenet.com.sg
For porting PHP for MySQL Server.
Michael J. Miller Jr. mke@terrapin.turbolift.com
For the first MySQL manual. And a lot of spelling/language fixes for the FAQ (that turned into the MySQL manual a long time ago).
Yan Cailin
First translator of the MySQL Reference Manual into simplified chinese in early 2000 on which the Big5 and HK coded (http://mysql.hitstar.com/) versions were based. Personal home page at linuxdb.yeah.net.
Giovanni Maruzzelli maruzz@matrice.it
For porting iODBC (Unix ODBC).
Chris Provenzano
Portable user level pthreads. From the copyright: This product includes software developed by Chris Provenzano, the University of California, Berkeley, and contributors. We are currently using version 1_60_beta6 patched by Monty (see `mit-pthreads/Changes-mysql').
Xavier Leroy Xavier.Leroy@inria.fr
The author of LinuxThreads (used by the MySQL Server on Linux).
Zarko Mocnik zarko.mocnik@dem.si
Sorting for Slovenian language and the `cset.tar.gz' module that makes it easier to add other character sets.
"TAMITO" tommy@valley.ne.jp
The _MB character set macros and the ujis and sjis character sets.
Joshua Chamas joshua@chamas.com
Base for concurrent insert, extended date syntax, debugging on NT, and answering on the MySQL mailing list.
Yves Carlier Yves.Carlier@rug.ac.be
mysqlaccess, a program to show the access rights for a user.
Rhys Jones rhys@wales.com (And GWE Technologies Limited)
For JDBC, a module to extract data from a MySQL Database with a Java client.
Dr Xiaokun Kelvin ZHU X.Zhu@brad.ac.uk
Further development of the JDBC driver and other MySQL-related Java tools.
James Cooper pixel@organic.com
For setting up a searchable mailing list archive at his site.
Rick Mehalick Rick_Mehalick@i-o.com
For xmysql, a graphical X client for MySQL Server.
Doug Sisk sisk@wix.com
For providing RPM packages of MySQL for RedHat Linux.
Diemand Alexander V. axeld@vial.ethz.ch
For providing RPM packages of MySQL for RedHat Linux-Alpha.
Antoni Pamies Olive toni@readysoft.es
For providing RPM versions of a lot of MySQL clients for Intel and SPARC.
Jay Bloodworth jay@pathways.sde.state.sc.us
For providing RPM versions for MySQL Version 3.21.
Jochen Wiedmann wiedmann@neckar-alb.de
For maintaining the Perl DBD::mysql module.
Therrien Gilbert gilbert@ican.net, Jean-Marc Pouyot jmp@scalaire.fr
French error messages.
Petr Snajdr, snajdr@pvt.net
Czech error messages.
Jaroslaw Lewandowski jotel@itnet.com.pl
Polish error messages.
Miguel Angel Fernandez Roiz
Spanish error messages.
Roy-Magne Mo rmo@www.hivolda.no
Norwegian error messages and testing of Version 3.21.#.
Timur I. Bakeyev root@timur.tatarstan.ru
Russian error messages.
brenno@dewinter.com & Filippo Grassilli phil@hyppo.com
Italian error messages.
Dirk Munzinger dirk@trinity.saar.de
German error messages.
Billik Stefan billik@sun.uniag.sk
Slovak error messages.
Stefan Saroiu tzoompy@cs.washington.edu
Romanian error messages.
Peter Feher
Hungarian error messages.
Roberto M. Serqueira
Portugise error messages.
Carsten H. Pedersen
Danish error messages.
Arjen G. Lentz
Dutch error messages, completing earlier partial translation (also work on consistency and spelling).
David Sacerdote davids@secnet.com
Ideas for secure checking of DNS hostnames.
Wei-Jou Chen jou@nematic.ieo.nctu.edu.tw
Some support for Chinese(BIG5) characters.
Wei He hewei@mail.ied.ac.cn
A lot of functionality for the Chinese(GBK) character set.
Zeev Suraski bourbon@netvision.net.il
FROM_UNIXTIME() time formatting, ENCRYPT() functions, and bison advisor. Active mailing list member.
Luuk de Boer luuk@wxs.nl
Ported (and extended) the benchmark suite to DBI/DBD. Have been of great help with crash-me and running benchmarks. Some new date functions. The mysql_setpermissions script.
Jay Flaherty fty@mediapulse.com
Big parts of the Perl DBI/DBD section in the manual.
Paul Southworth pauls@etext.org, Ray Loyzaga yar@cs.su.oz.au
Proof-reading of the Reference Manual.
Alexis Mikhailov root@medinf.chuvashia.su
User-definable functions (UDFs); CREATE FUNCTION and DROP FUNCTION.
Andreas F. Bobak bobak@relog.ch
The AGGREGATE extension to UDF functions.
Ross Wakelin R.Wakelin@march.co.uk
Help to set up InstallShield for MySQL-Win32.
Jethro Wright III jetman@li.net
The `libmysql.dll' library.
James Pereria jpereira@iafrica.com
Mysqlmanager, a Win32 GUI tool for administrating MySQL Server.
Curt Sampson cjs@portal.ca
Porting of MIT-pthreads to NetBSD/Alpha and NetBSD 1.3/i386.
Antony T. Curtis antony.curtis@olcs.net
Porting of the MySQL Database software to OS/2.
Martin Ramsch m.ramsch@computer.org
Examples in the MySQL Tutorial.
Steve Harvey
For making mysqlaccess more secure.
Konark IA-64 Centre of Persistent Systems Private Limited
http://www.pspl.co.in/konark/. Help with the Win64 port of the MySQL server.
Albert Chin-A-Young.
Configure updates for Tru64, large file support and better TCP wrappers support.
John Birrell
Emulation of pthread_mutex() for OS/2.
Benjamin Pflugmann
Extended MERGE tables to handle INSERTS. Active member on the MySQL mailing lists.
Guilhem Bichot
Fixed handling of exponents for DECIMAL. Author of mysql_tableinfo.
Jocelyn Fournier
Excellent spotting and reporting innumerable bugs (especially in the MySQL 4.1 subquery code).
Georg Richter
MySQL 4.1 testing and bug hunting. New PHP 5.0 mysqli extension (API) for use with MySQL 4.1 and up.
Marc Liyanage
Maintaining the Mac OS X packages and providing invaluable feedback on how to create Mac OS X PKGs.

Other contributors, bugfinders, and testers: James H. Thompson, Maurizio Menghini, Wojciech Tryc, Luca Berra, Zarko Mocnik, Wim Bonis, Elmar Haneke, jehamby@lightside, psmith@BayNetworks.com, duane@connect.com.au, Ted Deppner ted@psyber.com, Mike Simons, Jaakko Hyvatti.

And lots of bug report/patches from the folks on the mailing list.

A big tribute goes to those that help us answer questions on the mysql@lists.mysql.com mailing list:

Daniel Koch dkoch@amcity.com
Irix setup.
Luuk de Boer luuk@wxs.nl
Benchmark questions.
Tim Sailer tps@users.buoy.com
DBD-mysql questions.
Boyd Lynn Gerber gerberb@zenez.com
SCO-related questions.
Richard Mehalick RM186061@shellus.com
xmysql-related questions and basic installation questions.
Zeev Suraski bourbon@netvision.net.il
Apache module configuration questions (log & auth), PHP-related questions, SQL syntax-related questions and other general questions.
Francesc Guasch frankie@citel.upc.es
General questions.
Jonathan J Smith jsmith@wtp.net
Questions pertaining to OS-specifics with Linux, SQL syntax, and other things that might need some work.
David Sklar sklar@student.net
Using MySQL from PHP and Perl.
Alistair MacDonald A.MacDonald@uel.ac.uk
Not yet specified, but is flexible and can handle Linux and maybe HP-UX. Will try to get user to use mysqlbug.
John Lyon jlyon@imag.net
Questions about installing MySQL on Linux systems, using either `.rpm' files or compiling from source.
Lorvid Ltd. lorvid@WOLFENET.com
Simple billing/license/support/copyright issues.
Patrick Sherrill patrick@coconet.com
ODBC and VisualC++ interface questions.
Randy Harmon rjharmon@uptimecomputers.com
DBD, Linux, some SQL syntax questions.

C.3 Supporters to MySQL

While MySQL AB owns all copyrights in the MySQL server and the MySQL manual, we wish to recognise the following companies, which helped us finance the development of the MySQL server, such as by paying us for developing a new feature or giving us hardware for development of the MySQL server.

VA Linux / Andover.net
Funded replication.
NuSphere
Editing of the MySQL manual.
Stork Design studio
The MySQL web site in use between 1998-2000.
Intel
Contributed to development on Windows and Linux platforms.
Compaq
Contributed to Development on Linux/Alpha.
SWSoft
Development on the embedded mysqld version.
FutureQuest
--skip-show-database

D MySQL Change History

This appendix lists the changes from version to version in the MySQL source code.

We are now working actively on MySQL 4.1 & 5.0 and will only provide critical bug fixes for MySQL 4.0 and MySQL 3.23. We update this section as we add new features, so that everybody can follow the development.

Our TODO section contains what further plans we have for 4.1 & 5.0. See section 1.9 MySQL and The Future (The TODO).

Note that we tend to update the manual at the same time we make changes to MySQL. If you find a version listed here that you can't find on the MySQL download page (http://www.mysql.com/downloads/), this means that the version has not yet been released!

D.1 Changes in release 5.0.0 (Development)

Version 5.0 is for the moment only available on for MySQL developers. It will be publicly available as soon we are confident that the base for stored procedures is sound and working.

The following changelog shows what is already done in the 5.0 tree:

D.2 Changes in release 4.1.x (Alpha)

Version 4.1 of the MySQL server includes many enhancements and new features: This version is available from our public BitKeeper tree (sources) and will be available as a binary shortly.

For a full list of changes, please refer to the changelog sections for each individual 4.1.x release.

D.2.1 Changes in release 4.1.0

D.3 Changes in release 4.0.x (Production)

Version 4.0 of the MySQL server includes many enhancements and new features:

For a full list of changes, please refer to the changelog sections for each individual 4.0.x release.

D.3.1 Changes in release 4.0.13 (not released yet)

Functionality added or changed:

Bugs fixed:

D.3.2 Changes in release 4.0.12 (15 Mar 2003: Production)

Functionality added or changed:

Bugs fixed:

D.3.3 Changes in release 4.0.11 (20 Feb 2003)

Functionality added or changed:

Bugs fixed:

D.3.4 Changes in release 4.0.10 (29 Jan 2003)

Functionality added or changed:

Bugs fixed:

D.3.5 Changes in release 4.0.9 (09 Jan 2003)

Functionality added or changed:

Bugs fixed:

D.3.6 Changes in release 4.0.8 (07 Jan 2003)

Functionality added or changed:

Bugs fixed:

D.3.7 Changes in release 4.0.7 (20 Dec 2002)

Functionality added or changed:

Bugs fixed:

D.3.8 Changes in release 4.0.6 (14 Dec 2002: Gamma)

Functionality added or changed:

Bugs fixed:

D.3.9 Changes in release 4.0.5 (13 Nov 2002)

Functionality added or changed:

Bugs fixed:

D.3.10 Changes in release 4.0.4 (29 Sep 2002)

D.3.11 Changes in release 4.0.3 (26 Aug 2002: Beta)

D.3.12 Changes in release 4.0.2 (01 Jul 2002)

D.3.13 Changes in release 4.0.1 (23 Dec 2001)

D.3.14 Changes in release 4.0.0 (Oct 2001: Alpha)

D.4 Changes in release 3.23.x (Recent; still supported)

Please note that since release 4.0 is now production level, only critical fixes are done in the 3.23 release series. You are recommended to upgrade when possible, to take advantage of all speed and feature improvements in 4.0. See section 2.5.3 Upgrading From Version 3.23 to 4.0.

The 3.23 release has several major features that are not present in previous versions. We have added three new table types:

MyISAM
A new ISAM library which is tuned for SQL and supports large files.
InnoDB
A transaction-safe storage engine that supports row level locking, and many Oracle-like features.
BerkeleyDB or BDB
Uses the Berkeley DB library from Sleepycat Software to implement transaction-safe tables.

Note that only MyISAM is available in the standard binary distribution.

The 3.23 release also includes support for database replication between a master and many slaves, full-text indexing, and much more.

All new features are being developed in the 4.x version. Only bug fixes and minor enhancements to existing features will be added to 3.23.

The replication code and BerkeleyDB code is still not as tested and as the rest of the code, so we will probably need to do a couple of future releases of 3.23 with small fixes for this part of the code. As long as you don't use these features, you should be quite safe with MySQL 3.23!

Note that the above doesn't mean that replication or Berkeley DB don't work. We have done a lot of testing of all code, including replication and BDB without finding any problems. It only means that not as many users use this code as the rest of the code and because of this we are not yet 100% confident in this code.

D.4.1 Changes in release 3.23.57 (not released yet)

D.4.2 Changes in release 3.23.56 (13 Mar 2003)

D.4.3 Changes in release 3.23.55 (23 Jan 2003)

D.4.4 Changes in release 3.23.54 (05 Dec 2002)

D.4.5 Changes in release 3.23.53 (09 Oct 2002)

D.4.6 Changes in release 3.23.52 (14 Aug 2002)

D.4.7 Changes in release 3.23.51 (31 May 2002)

D.4.8 Changes in release 3.23.50 (21 Apr 2002)

D.4.9 Changes in release 3.23.49

D.4.10 Changes in release 3.23.48 (07 Feb 2002)

D.4.11 Changes in release 3.23.47 (27 Dec 2001)

D.4.12 Changes in release 3.23.46 (29 Nov 2001)

D.4.13 Changes in release 3.23.45 (22 Nov 2001)

D.4.14 Changes in release 3.23.44 (31 Oct 2001)

The following changes are for InnoDB tables:

D.4.15 Changes in release 3.23.43 (04 Oct 2001)

D.4.16 Changes in release 3.23.42 (08 Sep 2001)

D.4.17 Changes in release 3.23.41 (11 Aug 2001)

D.4.18 Changes in release 3.23.40

D.4.19 Changes in release 3.23.39 (12 Jun 2001)

D.4.20 Changes in release 3.23.38 (09 May 2001)

D.4.21 Changes in release 3.23.37 (17 Apr 2001)

D.4.22 Changes in release 3.23.36 (27 Mar 2001)

D.4.23 Changes in release 3.23.35 (15 Mar 2001)

D.4.24 Changes in release 3.23.34a

D.4.25 Changes in release 3.23.34 (10 Mar 2001)

D.4.26 Changes in release 3.23.33 (09 Feb 2001)

D.4.27 Changes in release 3.23.32 (22 Jan 2001: Production)

D.4.28 Changes in release 3.23.31 (17 Jan 2001)

D.4.29 Changes in release 3.23.30 (04 Jan 2001)

D.4.30 Changes in release 3.23.29 (16 Dec 2000)

D.4.31 Changes in release 3.23.28 (22 Nov 2000: Gamma)

D.4.32 Changes in release 3.23.27 (24 Oct 2000)

D.4.33 Changes in release 3.23.26 (18 Oct 2000)

D.4.34 Changes in release 3.23.25 (29 Sep 2000)

D.4.35 Changes in release 3.23.24 (08 Sep 2000)

D.4.36 Changes in release 3.23.23 (01 Sep 2000)

D.4.37 Changes in release 3.23.22 (31 Jul 2000)

D.4.38 Changes in release 3.23.21

D.4.39 Changes in release 3.23.20

D.4.40 Changes in release 3.23.19

D.4.41 Changes in release 3.23.18

D.4.42 Changes in release 3.23.17

D.4.43 Changes in release 3.23.16

D.4.44 Changes in release 3.23.15 (May 2000: Beta)

D.4.45 Changes in release 3.23.14

D.4.46 Changes in release 3.23.13

D.4.47 Changes in release 3.23.12 (07 Mar 2000)

D.4.48 Changes in release 3.23.11

D.4.49 Changes in release 3.23.10

D.4.50 Changes in release 3.23.9

D.4.51 Changes in release 3.23.8 (02 Jan 2000)

D.4.52 Changes in release 3.23.7 (10 Dec 1999)

D.4.53 Changes in release 3.23.6

D.4.54 Changes in release 3.23.5 (20 Oct 1999)

D.4.55 Changes in release 3.23.4 (28 Sep 1999)

D.4.56 Changes in release 3.23.3

D.4.57 Changes in release 3.23.2 (09 Aug 1999)

D.4.58 Changes in release 3.23.1

D.4.59 Changes in release 3.23.0 (05 Aug 1999: Alpha)

D.5 Changes in release 3.22.x (Old; discontinued)

The 3.22 version has faster and safer connect code than version 3.21, as well as a lot of new nice enhancements. As there aren't really any major changes, upgrading from 3.21 to 3.22 should be very easy and painless. See section 2.5.5 Upgrading from Version 3.21 to 3.22.

D.5.1 Changes in release 3.22.35

D.5.2 Changes in release 3.22.34

D.5.3 Changes in release 3.22.33

D.5.4 Changes in release 3.22.32 (14 Feb 2000)

D.5.5 Changes in release 3.22.31

D.5.6 Changes in release 3.22.30

D.5.7 Changes in release 3.22.29 (02 Jan 2000)

D.5.8 Changes in release 3.22.28 (20 Oct 1999)

D.5.9 Changes in release 3.22.27

D.5.10 Changes in release 3.22.26 (16 Sep 1999)

D.5.11 Changes in release 3.22.25

D.5.12 Changes in release 3.22.24 (05 Jul 1999)

D.5.13 Changes in release 3.22.23 (08 Jun 1999)

D.5.14 Changes in release 3.22.22 (30 Apr 1999)

D.5.15 Changes in release 3.22.21

D.5.16 Changes in release 3.22.20 (18 Mar 1999)

D.5.17 Changes in release 3.22.19 (Mar 1999: Production)

D.5.18 Changes in release 3.22.18

D.5.19 Changes in release 3.22.17

D.5.20 Changes in release 3.22.16 (Feb 1999: Gamma)

D.5.21 Changes in release 3.22.15

D.5.22 Changes in release 3.22.14

D.5.23 Changes in release 3.22.13

D.5.24 Changes in release 3.22.12

D.5.25 Changes in release 3.22.11

D.5.26 Changes in release 3.22.10

D.5.27 Changes in release 3.22.9

D.5.28 Changes in release 3.22.8

D.5.29 Changes in release 3.22.7 (Sep 1998: Beta)

D.5.30 Changes in release 3.22.6

D.5.31 Changes in release 3.22.5

D.5.32 Changes in release 3.22.4

D.5.33 Changes in release 3.22.3

D.5.34 Changes in release 3.22.2

D.5.35 Changes in release 3.22.1 (Jun 1998: Alpha)

D.5.36 Changes in release 3.22.0

D.6 Changes in release 3.21.x

Version 3.21 is quite old now, and should be avoided if possible. This information is kept here for historical purposes only.

D.6.1 Changes in release 3.21.33

D.6.2 Changes in release 3.21.32

D.6.3 Changes in release 3.21.31

D.6.4 Changes in release 3.21.30

D.6.5 Changes in release 3.21.29

D.6.6 Changes in release 3.21.28

D.6.7 Changes in release 3.21.27

D.6.8 Changes in release 3.21.26

D.6.9 Changes in release 3.21.25

D.6.10 Changes in release 3.21.24

D.6.11 Changes in release 3.21.23

D.6.12 Changes in release 3.21.22

D.6.13 Changes in release 3.21.21a

D.6.14 Changes in release 3.21.21

D.6.15 Changes in release 3.21.20

D.6.16 Changes in release 3.21.19

D.6.17 Changes in release 3.21.18

D.6.18 Changes in release 3.21.17

D.6.19 Changes in release 3.21.16

D.6.20 Changes in release 3.21.15

D.6.21 Changes in release 3.21.14b

D.6.22 Changes in release 3.21.14a

D.6.23 Changes in release 3.21.13

D.6.24 Changes in release 3.21.12

D.6.25 Changes in release 3.21.11

D.6.26 Changes in release 3.21.10

D.6.27 Changes in release 3.21.9

D.6.28 Changes in release 3.21.8

D.6.29 Changes in release 3.21.7

D.6.30 Changes in release 3.21.6

D.6.31 Changes in release 3.21.5

D.6.32 Changes in release 3.21.4

D.6.33 Changes in release 3.21.3

D.6.34 Changes in release 3.21.2

D.6.35 Changes in release 3.21.0

D.7 Changes in release 3.20.x

Version 3.20 is quite old now, and should be avoided if possible. This information is kept here for historical purposes only.

Changes from 3.20.18 to 3.20.32b are not documented here because the 3.21 release branched here. And the relevant changes are also documented as changes to the 3.21 version.

D.7.1 Changes in release 3.20.18

D.7.2 Changes in release 3.20.17

D.7.3 Changes in release 3.20.16

D.7.4 Changes in release 3.20.15

D.7.5 Changes in release 3.20.14

D.7.6 Changes in release 3.20.13

D.7.7 Changes in release 3.20.11

D.7.8 Changes in release 3.20.10

D.7.9 Changes in release 3.20.9

D.7.10 Changes in release 3.20.8

D.7.11 Changes in release 3.20.7

D.7.12 Changes in release 3.20.6

D.7.13 Changes in release 3.20.3

D.7.14 Changes in release 3.20.0

D.8 Changes in release 3.19.x

Version 3.19 is quite old now, and should be avoided if possible. This information is kept here for historical purposes only.

D.8.1 Changes in release 3.19.5

D.8.2 Changes in release 3.19.4

D.8.3 Changes in release 3.19.3

E Porting to Other Systems

This appendix will help you port MySQL to other operationg systems. Do check the list of currently supported operating systems first. See section 2.2.5 Operating Systems Supported by MySQL. If you have created a new port of MySQL, please let us know so that we can list it here and on our web site (http://www.mysql.com/), recommending it to other users.

Note: If you create a new port of MySQL, you are free to copy and distribute it under the GPL license, but it does not make you a copyright holder of MySQL.

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 earlier versions are not good enough) and on Linux we use LinuxThreads by Xavier Leroy, Xavier.Leroy@inria.fr.

The hard part of porting to a new Unix variant without good native thread support is probably to port MIT-pthreads. See `mit-pthreads/README' and Programming POSIX Threads (http://www.humanfactor.com/pthreads/).

The MySQL distribution includes a patched version of Provenzano's Pthreads from MIT (see the MIT Pthreads web page at http://www.mit.edu:8001/people/proven/pthreads.html). This can be used for some operating systems that do not have POSIX threads.

It is also possible to use another user level thread package named FSU Pthreads (see FSU Pthreads home page). This implementation is being used for the SCO port.

See the `thr_lock.c' and `thr_alarm.c' programs in the `mysys' directory for some tests/examples of these problems.

Both the server and the client need a working C++ compiler (we use gcc and have tried SPARCworks). Another compiler that is known to work is the Irix cc.

To compile only the client use ./configure --without-server.

There is currently no support for only compiling the server, nor is it likly to be added unless someone has a good reason for it.

If you want/need to change any `Makefile' or the configure script you must get Automake and Autoconf. We have used the automake-1.2 and autoconf-2.12 distributions.

All steps needed to remake everything from the most basic files.

/bin/rm */.deps/*.P
/bin/rm -f config.cache
aclocal
autoheader
aclocal
automake
autoconf
./configure --with-debug=full --prefix='your installation directory'

# The makefiles generated above need GNU make 3.75 or newer.
# (called gmake below)
gmake clean all install init-db

If you run into problems with a new port, you may have to do some debugging of MySQL! See section E.1 Debugging a MySQL server.

Note: before you start debugging mysqld, first get the test programs mysys/thr_alarm and mysys/thr_lock to work. This will ensure that your thread installation has even a remote chance to work!

E.1 Debugging a MySQL server

If you are using some functionality that is very new in MySQL, you can try to run mysqld with the --skip-new (which will disable all new, potentially unsafe functionality) or with --safe-mode which disables a lot of optimisation that may cause problems. See section A.4.1 What To Do If MySQL Keeps Crashing.

If mysqld doesn't want to start, you should check that you don't have any `my.cnf' files that interfere with your setup! You can check your `my.cnf' arguments with mysqld --print-defaults and avoid using them by starting with mysqld --no-defaults ....

If mysqld starts to eat up CPU or memory or if it ``hangs'', you can use mysqladmin processlist status to find out if someone is executing a query that takes a long time. It may be a good idea to run mysqladmin -i10 processlist status in some window if you are experiencing performance problems or problems when new clients can't connect.

The command mysqladmin debug will dump some information about locks in use, used memory and query usage to the mysql log file. This may help solve some problems. This command also provides some useful information even if you haven't compiled MySQL for debugging!

If the problem is that some tables are getting slower and slower you should try to optimise the table with OPTIMIZE TABLE or myisamchk. See section 4 Database Administration. You should also check the slow queries with EXPLAIN.

You should also read the OS-specific section in this manual for problems that may be unique to your environment. See section 2.6 Operating System Specific Notes.

E.1.1 Compiling MYSQL for Debugging

If you have some very specific problem, you can always try to debug MySQL. To do this you must configure MySQL with the --with-debug or the --with-debug=full option. You can check whether MySQL was compiled with debugging by doing: mysqld --help. If the --debug flag is listed with the options then you have debugging enabled. mysqladmin ver also lists the mysqld version as mysql ... --debug in this case.

If you are using gcc or egcs, the recommended configure line is:

CC=gcc CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors \
   -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \
   --with-debug --with-extra-charsets=complex

This will avoid problems with the libstdc++ library and with C++ exceptions (many compilers have problems with C++ exceptions in threaded code) and compile a MySQL version with support for all character sets.

If you suspect a memory overrun error, you can configure MySQL with --with-debug=full, which will install a memory allocation (SAFEMALLOC) checker. Running with SAFEMALLOC is however quite slow, so if you get performance problems you should start mysqld with the --skip-safemalloc option. This will disable the memory overrun checks for each call to malloc and free.

If mysqld stops crashing when you compile it with --with-debug, you have probably found a compiler bug or a timing bug within MySQL. In this case you can try to add -g to the CFLAGS and CXXFLAGS variables above and not use --with-debug. If mysqld now dies, you can at least attach to it with gdb or use gdb on the core file to find out what happened.

When you configure MySQL for debugging you automatically enable a lot of extra safety check functions that monitor the health of mysqld. If they find something ``unexpected,'' an entry will be written to stderr, which safe_mysqld directs to the error log! This also means that if you are having some unexpected problems with MySQL and are using a source distribution, the first thing you should do is to configure MySQL for debugging! (The second thing, of course, is to send mail to mysql@lists.mysql.com and ask for help. Please use the mysqlbug script for all bug reports or questions regarding the MySQL version you are using!

In the Windows MySQL distribution, mysqld.exe is by default compiled with support for trace files.

E.1.2 Creating Trace Files

If the mysqld server doesn't start or if you can cause the mysqld server to crash quickly, you can try to create a trace file to find the problem.

To do this you have to have a mysqld that is compiled for debugging. You can check this by executing mysqld -V. If the version number ends with -debug, it's compiled with support for trace files.

Start the mysqld server with a trace log in `/tmp/mysqld.trace' (or `C:\mysqld.trace' on Windows):

mysqld --debug

On Windows you should also use the --standalone flag to not start mysqld as a service:

In a DOS window do:

mysqld --debug --standalone

After this you can use the mysql.exe command-line tool in a second DOS window to reproduce the problem. You can take down the above mysqld server with mysqladmin shutdown.

Note that the trace file will get very big! If you want to have a smaller trace file, you can use something like:

mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace

which only prints information with the most interesting tags in `/tmp/mysqld.trace'.

If you make a bug report about this, please only send the lines from the trace file to the appropriate mailing list where something seems to go wrong! If you can't locate the wrong place, you can ftp the trace file, together with a full bug report, to ftp://support.mysql.com/pub/mysql/secret/ so that a MySQL developer can take a look a this.

The trace file is made with the DBUG package by Fred Fish. See section E.3 The DBUG Package.

E.1.3 Debugging mysqld under gdb

On most systems you can also start mysqld from gdb to get more information if mysqld crashes.

With some older gdb versions on Linux you must use run --one-thread if you want to be able to debug mysqld threads. In this case you can only have one thread active at a time. We recommend you to upgrade to gdb 5.1 ASAP as thread debugging works much better with this version!

When running mysqld under gdb, you should disable the stack trace with --skip-stack-trace to be able to catch segfaults within gdb.

It's very hard to debug MySQL under gdb if you do a lot of new connections the whole time as gdb doesn't free the memory for old threads. You can avoid this problem by starting mysqld with -O thread_cache_size= 'max_connections +1'. In most cases just using -O thread_cache_size=5' will help a lot!

If you want to get a core dump on Linux if mysqld dies with a SIGSEGV signal, you can start mysqld with the --core-file option. This core file can be used to make a backtrace that may help you find out why mysqld died:

shell> gdb mysqld core
gdb>   backtrace full
gdb>   exit

See section A.4.1 What To Do If MySQL Keeps Crashing.

If you are using gdb 4.17.x or above on Linux, you should install a `.gdb' file, with the following information, in your current directory:

set print sevenbit off
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
handle SIGWAITING nostop noprint
handle SIGLWP nostop noprint
handle SIGPIPE nostop
handle SIGALRM nostop
handle SIGHUP nostop
handle SIGTERM nostop noprint

If you have problems debugging threads with gdb, you should download gdb 5.x and try this instead. The new gdb version has very improved thread handling!

Here is an example how to debug mysqld:

shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Do this when mysqld crashes

Include the above output in a mail generated with mysqlbug and mail this to mysql@lists.mysql.com.

If mysqld hangs you can try to use some system tools like strace or /usr/proc/bin/pstack to examine where mysqld has hung.

strace /tmp/log libexec/mysqld

If you are using the Perl DBI interface, you can turn on debugging information by using the trace method or by setting the DBI_TRACE environment variable. See section 8.5.2 The DBI Interface.

E.1.4 Using a Stack Trace

On some operating systems, the error log will contain a stack trace if mysqld dies unexpectedly. You can use this to find out where (and maybe why) mysqld died. See section 4.9.1 The Error Log. To get a stack trace, you must not compile mysqld with the -fomit-frame-pointer option to gcc. See section E.1.1 Compiling MYSQL for Debugging.

If the error file contains something like the following:

mysqld got signal 11;
The manual section 'Debugging a MySQL server' tells you how to use a
stack trace and/or the core file to produce a readable backtrace that may
help in finding out why mysqld died
Attemping backtrace. You can use the following information to find out
where mysqld died.  If you see no messages after this, something went
terribly wrong
stack range sanity check, ok, backtrace follows
0x40077552
0x81281a0
0x8128f47
0x8127be0
0x8127995
0x8104947
0x80ff28f
0x810131b
0x80ee4bc
0x80c3c91
0x80c6b43
0x80c1fd9
0x80c1686

you can find where mysqld died by doing the following:

  1. Copy the above numbers to a file, for example `mysqld.stack'.
  2. Make a symbol file for the mysqld server:
    nm -n libexec/mysqld > /tmp/mysqld.sym
    
    Note that many MySQL binary distributions comes with the above file, named mysqld.sym.gz. In this case you must unpack this by doing:
    gunzip < bin/mysqld.sym.gz > /tmp/mysqld.sym
    
  3. Execute resolve_stack_dump -s /tmp/mysqld.sym -n mysqld.stack. This will print out where mysqld died. If this doesn't help you find out why mysqld died, you should make a bug report and include the output from the above command with the bug report. Note however that in most cases it will not help us to just have a stack trace to find the reason for the problem. To be able to locate the bug or provide a workaround, we would in most cases need to know the query that killed mysqld and preferable a test case so that we can repeat the problem! See section 1.7.1.3 How to Report Bugs or Problems.

E.1.5 Using Log Files to Find Cause of Errors in mysqld

Note that before starting mysqld with --log you should check all your tables with myisamchk. See section 4 Database Administration.

If mysqld dies or hangs, you should start mysqld with --log. When mysqld dies again, you can examine the end of the log file for the query that killed mysqld.

If you are using --log without a file name, the log is stored in the database directory as 'hostname'.log In most cases it's the last query in the log file that killed mysqld, but if possible you should verify this by restarting mysqld and executing the found query from the mysql command-line tools. If this works, you should also test all complicated queries that didn't complete.

You can also try the command EXPLAIN on all SELECT statements that takes a long time to ensure that mysqld is using indexes properly. See section 5.2.1 EXPLAIN Syntax (Get Information About a SELECT).

You can find the queries that take a long time to execute by starting mysqld with --log-slow-queries. See section 4.9.5 The Slow Query Log.

If you find the text mysqld restarted in the error log file (normally named `hostname.err') you have probably found a query that causes mysqld to fail. If this happens you should check all your tables with myisamchk (see section 4 Database Administration), and test the queries in the MySQL log files to see if one doesn't work. If you find such a query, try first upgrading to the newest MySQL version. If this doesn't help and you can't find anything in the mysql mail archive, you should report the bug to mysql@lists.mysql.com. Links to mail archives are available online at http://lists.mysql.com/.

If you have started mysqld with myisam-recover, MySQL will automatically check and try to repair MyISAM tables if they are marked as 'not closed properly' or 'crashed'. If this happens, MySQL will write an entry in the hostname.err file 'Warning: Checking table ...' which is followed by Warning: Repairing table if the table needs to be repaired. If you get a lot of these errors, without mysqld having died unexpectedly just before, then something is wrong and needs to be investigated further. See section 4.1.1 mysqld Command-line Options.

It's of course not a good sign if mysqld did died unexpectedly, but in this case one shouldn't investigate the Checking table... messages but instead try to find out why mysqld died.

E.1.6 Making a Test Case If You Experience Table Corruption

If you get corrupted tables or if mysqld always fails after some update commands, you can test if this bug is reproducible by doing the following:

You can also use the script mysql_find_rows to just execute some of the update statements if you want to narrow down the problem.

E.2 Debugging a MySQL client

To be able to debug a MySQL client with the integrated debug package, you should configure MySQL with --with-debug or --with-debug=full. See section 2.3.3 Typical configure Options.

Before running a client, you should set the MYSQL_DEBUG environment variable:

shell> MYSQL_DEBUG=d:t:O,/tmp/client.trace
shell> export MYSQL_DEBUG

This causes clients to generate a trace file in `/tmp/client.trace'.

If you have problems with your own client code, you should attempt to connect to the server and run your query using a client that is known to work. Do this by running mysql in debugging mode (assuming you have compiled MySQL with debugging on):

shell> mysql --debug=d:t:O,/tmp/client.trace

This will provide useful information in case you mail a bug report. See section 1.7.1.3 How to Report Bugs or Problems.

If your client crashes at some 'legal' looking code, you should check that your `mysql.h' include file matches your mysql library file. A very common mistake is to use an old `mysql.h' file from an old MySQL installation with new MySQL library.

E.3 The DBUG Package

The MySQL server and most MySQL clients are compiled with the DBUG package originally made by Fred Fish. When one has configured MySQL for debugging, this package makes it possible to get a trace file of what the program is debugging. See section E.1.2 Creating Trace Files.

One uses the debug package by invoking the program with the --debug="..." or the -#... option.

Most MySQL programs has a default debug string that will be used if you don't specify an option to --debug. The default trace file is usually /tmp/programname.trace on Unix and \programname.trace on Windows.

The debug control string is a sequence of colon separated fields as follows:

<field_1>:<field_2>:...:<field_N>

Each field consists of a mandatory flag character followed by an optional "," and comma-separated list of modifiers:

flag[,modifier,modifier,...,modifier]

The currently recognised flag characters are:

Flag Description
d Enable output from DBUG_<N> macros for the current state. May be followed by a list of keywords which selects output only for the DBUG macros with that keyword. An empty list of keywords implies output for all macros.
D Delay after each debugger output line. The argument is the number of tenths of seconds to delay, subject to machine capabilities. That is, -#D,20 is delay two seconds.
f Limit debugging and/or tracing, and profiling to the list of named functions. Note that a null list will disable all functions. The appropriate "d" or "t" flags must still be given, this flag only limits their actions if they are enabled.
F Identify the source file name for each line of debug or trace output.
i Identify the process with the pid or thread id for each line of debug or trace output.
g Enable profiling. Create a file called 'dbugmon.out' containing information that can be used to profile the program. May be followed by a list of keywords that select profiling only for the functions in that list. A null list implies that all functions are considered.
L Identify the source file line number for each line of debug or trace output.
n Print the current function nesting depth for each line of debug or trace output.
N Number each line of dbug output.
o Redirect the debugger output stream to the specified file. The default output is stderr.
O As o but the file is really flushed between each write. When needed the file is closed and reopened between each write.
p Limit debugger actions to specified processes. A process must be identified with the DBUG_PROCESS macro and match one in the list for debugger actions to occur.
P Print the current process name for each line of debug or trace output.
r When pushing a new state, do not inherit the previous state's function nesting level. Useful when the output is to start at the left margin.
S Do function _sanity(_file_,_line_) at each debugged function until _sanity() returns something that differs from 0. (Mostly used with safemalloc to find memory leaks)
t Enable function call/exit trace lines. May be followed by a list (containing only one modifier) giving a numeric maximum trace level, beyond which no output will occur for either debugging or tracing macros. The default is a compile time option.

Some examples of debug control strings which might appear on a shell command-line (the "-#" is typically used to introduce a control string to an application program) are:

-#d:t
-#d:f,main,subr1:F:L:t,20
-#d,input,output,files:n
-#d:t:i:O,\\mysqld.trace

In MySQL, common tags to print (with the d option) are: enter,exit,error,warning,info and loop.

E.4 Locking methods

Currently MySQL only supports table locking for ISAM/MyISAM and HEAP tables, page-level locking for BDB tables and row-level locking for InnoDB tables. See section 5.3.1 How MySQL Locks Tables. With MyISAM tables one can freely mix INSERT and SELECT without locks, if the INSERTs are non-conflicting (i.e. whenever they append to the end of the table file rather than filling freespace from deleted rows/data).

Starting in version 3.23.33, you can analyse the table lock contention on your system by checking Table_locks_waited and Table_locks_immediate environment variables.

To decide if you want to use a table type with row-level locking, you will want to look at what the application does and what the select/update pattern of the data is.

Pros for row locking:

Cons:

Table locks are superior to page level / row level locks in the following cases:

Other options than row / page level locking:

Versioning (like we use in MySQL for concurrent inserts) where you can have one writer at the same time as many readers. This means that the database/table supports different views for the data depending on when one started to access it. Other names for this are time travel, copy on write or copy on demand.

Copy on demand is in many case much better than page or row level locking; the worst case does, however, use much more memory than when using normal locks.

Instead of using row level locks one can use application level locks (like get_lock/release_lock in MySQL). This works of course only in well-behaved applications.

In many cases one can do an educated guess which locking type is best for the application, but generally it's very hard to say that a given lock type is better than another; everything depends on the application and different part of the application may require different lock types.

Here are some tips about locking in MySQL:

Most web applications do lots of selects, very few deletes, updates mainly on keys, and inserts in some specific tables. The base MySQL setup is very well tuned for this.

Concurrent users are not a problem if one doesn't mix updates with selects that need to examine many rows in the same table.

If one mixes inserts and deletes on the same table then INSERT DELAYED may be of great help.

One can also use LOCK TABLES to speed up things (many updates within a single lock is much faster than updates without locks). Splitting thing to different tables will also help.

If you get speed problems with the table locks in MySQL, you may be able to solve these by converting some of your tables to InnoDB or BDB tables. See section 7.5 InnoDB Tables. See section 7.6 BDB or BerkeleyDB Tables.

The optimisation section in the manual covers a lot of different aspects of how to tune applications. See section 5.2.12 Other Optimisation Tips.

E.5 Comments about RTS threads

I have tried to use the RTS thread packages with MySQL but stumbled on the following problems:

They use an old version of a lot of POSIX calls and it is very tedious to make wrappers for all functions. I am inclined to think that it would be easier to change the thread libraries to the newest POSIX specification.

Some wrappers are already written. See `mysys/my_pthread.c' for more info.

At least the following should be changed:

pthread_get_specific should use one argument. sigwait should take two arguments. A lot of functions (at least pthread_cond_wait, pthread_cond_timedwait) should return the error code on error. Now they return -1 and set errno.

Another problem is that user-level threads use the ALRM signal and this aborts a lot of functions (read, write, open...). MySQL should do a retry on interrupt on all of these but it is not that easy to verify it.

The biggest unsolved problem is the following:

To get thread-level alarms I changed `mysys/thr_alarm.c' to wait between alarms with pthread_cond_timedwait(), but this aborts with error EINTR. I tried to debug the thread library as to why this happens, but couldn't find any easy solution.

If someone wants to try MySQL with RTS threads I suggest the following:

E.6 Differences between different thread packages

MySQL is very dependent on the thread package used. So when choosing a good platform for MySQL, the thread package is very important.

There are at least three types of thread packages:

In some systems kernel threads are managed by integrating user level threads in the system libraries. In such cases, the thread switching can only be done by the thread library and the kernel isn't really ``thread aware''.

F Environment Variables

Here is a list of all the environment variables that are used directly or indirectly by MySQL. Most of these can also be found in other places in this manual.

Note that any options on the command-line will take precedence over values specified in configuration files and environment variables, and values in configuration files take precedence over values in environment variables.

In many cases it's preferable to use a configure file instead of environment variables to modify the behaviour of MySQL. See section 4.1.2 `my.cnf' Option Files.

Variable Description
CCX Set this to your C++ compiler when running configure.
CC Set this to your C compiler when running configure.
CFLAGS Flags for your C compiler when running configure.
CXXFLAGS Flags for your C++ compiler when running configure.
DBI_USER The default user name for Perl DBI.
DBI_TRACE Used when tracing Perl DBI.
HOME The default path for the mysql history file is `$HOME/.mysql_history'.
LD_RUN_PATH Used to specify where your `libmysqlclient.so' is.
MYSQL_DEBUG Debug-trace options when debugging.
MYSQL_HISTFILE The path to the mysql history file.
MYSQL_HOST Default host name used by the mysql command-line client.
MYSQL_PS1 Command prompt to use in the mysql command-line client. See section 4.8.2 mysql, The Command-line Tool.
MYSQL_PWD The default password when connecting to mysqld. Note that use of this is insecure!
MYSQL_TCP_PORT The default TCP/IP port.
MYSQL_UNIX_PORT The default socket; used for connections to localhost.
PATH Used by the shell to finds the MySQL programs.
TMPDIR The directory where temporary tables/files are created.
TZ This should be set to your local time zone. See section A.4.6 Time Zone Problems.
UMASK_DIR The user-directory creation mask when creating directories. Note that this is ANDed with UMASK!
UMASK The user-file creation mask when creating files.
USER The default user on Windows to use when connecting to mysqld.

G MySQL Regular Expressions

A regular expression (regex) is a powerful way of specifying a complex search.

MySQL uses Henry Spencer's implementation of regular expressions, which is aimed at conformance with POSIX 1003.2. MySQL uses the extended version.

This is a simplistic reference that skips the details. To get more exact information, see Henry Spencer's regex(7) manual page that is included in the source distribution. See section C Credits.

A regular expression describes a set of strings. The simplest regexp is one that has no special characters in it. For example, the regexp hello matches hello and nothing else.

Non-trivial regular expressions use certain special constructs so that they can match more than one string. For example, the regexp hello|word matches either the string hello or the string word.

As a more complex example, the regexp B[an]*s matches any of the strings Bananas, Baaaaas, Bs, and any other string starting with a B, ending with an s, and containing any number of a or n characters in between.

A regular expression may use any of the following special characters/constructs:

^
Match the beginning of a string.
mysql> SELECT "fo\nfo" REGEXP "^fo$";           -> 0
mysql> SELECT "fofo" REGEXP "^fo";              -> 1
$
Match the end of a string.
mysql> SELECT "fo\no" REGEXP "^fo\no$";         -> 1
mysql> SELECT "fo\no" REGEXP "^fo$";            -> 0
.
Match any character (including newline).
mysql> SELECT "fofo" REGEXP "^f.*";             -> 1
mysql> SELECT "fo\nfo" REGEXP "^f.*";           -> 1
a*
Match any sequence of zero or more a characters.
mysql> SELECT "Ban" REGEXP "^Ba*n";             -> 1
mysql> SELECT "Baaan" REGEXP "^Ba*n";           -> 1
mysql> SELECT "Bn" REGEXP "^Ba*n";              -> 1
a+
Match any sequence of one or more a characters.
mysql> SELECT "Ban" REGEXP "^Ba+n";             -> 1
mysql> SELECT "Bn" REGEXP "^Ba+n";              -> 0
a?
Match either zero or one a character.
mysql> SELECT "Bn" REGEXP "^Ba?n";              -> 1
mysql> SELECT "Ban" REGEXP "^Ba?n";             -> 1
mysql> SELECT "Baan" REGEXP "^Ba?n";            -> 0
de|abc
Match either of the sequences de or abc.
mysql> SELECT "pi" REGEXP "pi|apa";             -> 1
mysql> SELECT "axe" REGEXP "pi|apa";            -> 0
mysql> SELECT "apa" REGEXP "pi|apa";            -> 1
mysql> SELECT "apa" REGEXP "^(pi|apa)$";        -> 1
mysql> SELECT "pi" REGEXP "^(pi|apa)$";         -> 1
mysql> SELECT "pix" REGEXP "^(pi|apa)$";        -> 0
(abc)*
Match zero or more instances of the sequence abc.
mysql> SELECT "pi" REGEXP "^(pi)*$";            -> 1
mysql> SELECT "pip" REGEXP "^(pi)*$";           -> 0
mysql> SELECT "pipi" REGEXP "^(pi)*$";          -> 1
{1}
{2,3}
The is a more general way of writing regexps that match many occurrences of the previous atom.
a*
Can be written as a{0,}.
a+
Can be written as a{1,}.
a?
Can be written as a{0,1}.
To be more precise, an atom followed by a bound containing one integer i and no comma matches a sequence of exactly i matches of the atom. An atom followed by a bound containing one integer i and a comma matches a sequence of i or more matches of the atom. An atom followed by a bound containing two integers i and j matches a sequence of i through j (inclusive) matches of the atom. Both arguments must be in the range from 0 to RE_DUP_MAX (default 255), inclusive. If there are two arguments, the second must be greater than or equal to the first.
[a-dX]
[^a-dX]
Matches any character which is (or is not, if ^ is used) either a, b, c, d or X. To include a literal ] character, it must immediately follow the opening bracket [. To include a literal - character, it must be written first or last. So [0-9] matches any decimal digit. Any character that does not have a defined meaning inside a [] pair has no special meaning and matches only itself.
mysql> SELECT "aXbc" REGEXP "[a-dXYZ]";         -> 1
mysql> SELECT "aXbc" REGEXP "^[a-dXYZ]$";       -> 0
mysql> SELECT "aXbc" REGEXP "^[a-dXYZ]+$";      -> 1
mysql> SELECT "aXbc" REGEXP "^[^a-dXYZ]+$";     -> 0
mysql> SELECT "gheis" REGEXP "^[^a-dXYZ]+$";    -> 1
mysql> SELECT "gheisa" REGEXP "^[^a-dXYZ]+$";   -> 0
[[.characters.]]
The sequence of characters of that collating element. The sequence is a single element of the bracket expression's list. A bracket expression containing a multi-character collating element can thus match more than one character, for example, if the collating sequence includes a ch collating element, then the regular expression [[.ch.]]*c matches the first five characters of chchcc.
[=character_class=]
An equivalence class, standing for the sequences of characters of all collating elements equivalent to that one, including itself. For example, if o and (+) are the members of an equivalence class, then [[=o=]], [[=(+)=]], and [o(+)] are all synonymous. An equivalence class may not be an endpoint of a range.
[:character_class:]
Within a bracket expression, the name of a character class enclosed in [: and :] stands for the list of all characters belonging to that class. Standard character class names are:
Name Name Name
alnum digit punct
alpha graph space
blank lower upper
cntrl print xdigit
These stand for the character classes defined in the ctype(3) manual page. A locale may provide others. A character class may not be used as an endpoint of a range.
mysql> SELECT "justalnums" REGEXP "[[:alnum:]]+";       -> 1
mysql> SELECT "!!" REGEXP "[[:alnum:]]+";               -> 0
[[:<:]]
[[:>:]]
These match the null string at the beginning and end of a word respectively. A word is defined as a sequence of word characters which is neither preceded nor followed by word characters. A word character is an alnum character (as defined by ctype(3)) or an underscore (_).
mysql> SELECT "a word a" REGEXP "[[:<:]]word[[:>:]]";      -> 1
mysql> SELECT "a xword a" REGEXP "[[:<:]]word[[:>:]]";     -> 0
mysql> SELECT "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1

H GNU General Public License

Version 2, June 1991

Copyright © 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

H.1 Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

H.2 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The ``Program'', below, refers to any such program or work, and a ``work based on the Program'' means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) Each licensee is addressed as ``you''. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
  2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
  3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
    2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
    3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
  4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
    1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    2. Accompany it with a written offer, valid for at least three years, to give any third-party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
    The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
  5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
  7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
  8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
  9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
  11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

    9.4 NO WARRANTY

  12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

9.5 END OF TERMS AND CONDITIONS

H.3 How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.

one line to give the program's name and a brief idea of what it does.
Copyright (C) yyyy  name of author

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.

signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.

I GNU Lesser General Public License

Version 2.1, February 1999

Copyright © 1991, 1999 Free Software Foundation, Inc.
59 Temple Place -- Suite 330, Boston, MA 02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
as the successor of the GNU Library Public License, version 2, hence the
version number 2.1.]

I.1 Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.

This license, the Lesser General Public License, applies to some specially designated software--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.

When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.

To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.

For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.

We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.

To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.

Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.

Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.

When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.

We call this license the Lesser General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.

For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.

In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.

Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.

The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a ``work based on the library'' and a ``work that uses the library''. The former contains code derived from the library, whereas the latter must be combined with the library in order to run.

I.2 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called ``this License''). Each licensee is addressed as ``you''. A ``library'' means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The ``Library'', below, refers to any such software library or work which has been distributed under these terms. A ``work based on the Library'' means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) ``Source code'' for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
  2. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
  3. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
    1. The modified work must itself be a software library.
    2. You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
    3. You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
    4. If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
  4. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
  5. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
  6. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a ``work that uses the Library''. Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a ``work that uses the Library'' with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a ``work that uses the library''. The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a ``work that uses the Library'' uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether they are linked directly with the Library itself.
  7. As an exception to the Sections above, you may also combine or link a ``work that uses the Library'' with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
    1. Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable ``work that uses the Library'', as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
    2. Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at runtime a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
    3. Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
    4. If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
    5. Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
    For an executable, the required form of the ``work that uses the Library'' must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
  8. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
    1. Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
    2. Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
  9. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
  10. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
  11. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
  12. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
  13. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
  14. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
  15. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

    9.6 NO WARRANTY

  16. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  17. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

9.7 END OF TERMS AND CONDITIONS

I.3 How to Apply These Terms to Your New Libraries

If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).

To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found.

one line to give the library's name and an idea of what it does.
Copyright (C) year  name of author

This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
USA.

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the library, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the library
`Frob' (a library for tweaking knobs) written by James Random Hacker.

signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice

That's all there is to it!

SQL command, type and function index

  • ! (logical NOT)
  • != (not equal)
  • "
  • % (modulo)
  • % (wildcard character)
  • & (bitwise AND)
  • && (logical AND)
  • () (parentheses)
  • (Control-Z) \z
  • * (multiplication)
  • + (addition)
  • - (subtraction)
  • - (unary minus)
  • -p option
  • -password option
  • .my.cnf file, .my.cnf file, .my.cnf file, .my.cnf file, .my.cnf file, .my.cnf file, .my.cnf file
  • .mysql_history file
  • .pid (process ID) file
  • / (division)
  • /etc/passwd
  • `/etc/passwd'
  • < (less than)
  • <<
  • << (left shift)
  • <= (less than or equal)
  • <=> (Equal to)
  • <> (not equal)
  • = (equal)
  • > (greater than)
  • >= (greater than or equal)
  • >> (right shift)
  • \" (double quote)
  • \' (single quote)
  • \0 (ASCII 0)
  • \\ (escape)
  • \b (backspace)
  • \n (newline)
  • \r (carriage return)
  • \t (tab)
  • \z (Control-Z) ASCII(26)
  • ^ (bitwise XOR)
  • _ (wildcard character)
  • `
  • A

  • ABS()
  • ACOS()
  • ADDDATE()
  • addition (+)
  • AES_DECRYPT()
  • AES_ENCRYPT()
  • alias
  • ALTER COLUMN
  • ALTER TABLE, ALTER TABLE, ALTER TABLE
  • ANALYZE TABLE
  • AND, bitwise
  • AND, logical
  • arithmetic functions
  • AS, AS
  • ASCII()
  • ASIN()
  • ATAN()
  • ATAN2()
  • AUTO_INCREMENT, using with DBI
  • AVG()
  • B

  • backspace (\b)
  • BACKUP TABLE
  • BEGIN
  • BENCHMARK()
  • BETWEEN ... AND
  • BIGINT
  • BIN()
  • BINARY
  • BIT
  • bit functions
  • BIT_AND()
  • BIT_COUNT
  • BIT_COUNT()
  • BIT_LENGTH()
  • BIT_OR
  • BIT_OR()
  • BLOB, BLOB
  • BOOL
  • C

  • carriage return (\r)
  • CASE
  • CAST
  • casts
  • CC environment variable, CC environment variable
  • CC environment variable
  • CCX environment variable
  • CEILING()
  • CFLAGS environment variable, CFLAGS environment variable
  • CHAR, CHAR
  • CHAR VARYING
  • CHAR()
  • CHAR_LENGTH()
  • CHARACTER
  • CHARACTER VARYING
  • CHARACTER_LENGTH()
  • CHECK TABLE
  • ChopBlanks DBI method
  • COALESCE()
  • command-line options
  • Comment syntax
  • COMMIT, COMMIT
  • comparison operators
  • CONCAT()
  • CONCAT_WS()
  • configure option, --with-charset
  • configure option, --with-extra-charsets
  • connect() DBI method
  • CONNECTION_ID()
  • control flow functions
  • CONV()
  • CONVERT
  • COS()
  • COT()
  • COUNT()
  • COUNT(DISTINCT)
  • CREATE DATABASE
  • CREATE FUNCTION
  • CREATE INDEX
  • CREATE TABLE
  • CROSS JOIN
  • CURDATE()
  • CURRENT_DATE
  • CURRENT_TIME
  • CURRENT_TIMESTAMP
  • CURRENT_USER()
  • CURTIME()
  • CXX environment variable
  • CXX environment variable, CXX environment variable, CXX environment variable
  • CXXFLAGS environment variable, CXXFLAGS environment variable, CXXFLAGS environment variable, CXXFLAGS environment variable
  • D

  • data_sources() DBI method
  • DATABASE()
  • DATE, DATE, DATE
  • date and time functions
  • DATE_ADD()
  • DATE_FORMAT()
  • DATE_SUB()
  • DATETIME, DATETIME
  • DAYNAME()
  • DAYOFMONTH()
  • DAYOFWEEK()
  • DAYOFYEAR()
  • DBI->connect()
  • DBI->data_sources()
  • DBI->disconnect
  • DBI->do()
  • DBI->execute
  • DBI->fetchall_arrayref
  • DBI->fetchrow_array
  • DBI->fetchrow_arrayref
  • DBI->fetchrow_hashref
  • DBI->finish
  • DBI->prepare()
  • DBI->quote
  • DBI->quote()
  • DBI->rows
  • DBI->trace, DBI->trace
  • DBI->{ChopBlanks}
  • DBI->{insertid}
  • DBI->{is_blob}
  • DBI->{is_key}
  • DBI->{is_not_null}
  • DBI->{is_num}
  • DBI->{is_pri_key}
  • DBI->{length}
  • DBI->{max_length}
  • DBI->{NAME}
  • DBI->{NULLABLE}
  • DBI->{NUM_OF_FIELDS}
  • DBI->{table}
  • DBI->{type}
  • DBI_TRACE environment variable, DBI_TRACE environment variable
  • DBI_TRACE environment variable
  • DBI_USER environment variable
  • DEC
  • DECIMAL
  • DECODE()
  • DEGREES()
  • DELAYED
  • DELETE
  • DES_DECRYPT()
  • DES_ENCRYPT()
  • DESC
  • DESCRIBE, DESCRIBE
  • disconnect DBI method
  • DISTINCT, DISTINCT, DISTINCT
  • DIV
  • division (/)
  • DO
  • do() DBI method
  • DOUBLE
  • DOUBLE PRECISION
  • double quote (\")
  • DROP DATABASE
  • DROP FUNCTION
  • DROP INDEX, DROP INDEX
  • DROP PRIMARY KEY
  • DROP TABLE
  • DUMPFILE
  • E

  • ELT()
  • ENCODE()
  • ENCRYPT()
  • ENUM, ENUM
  • Environment variable, CC
  • environment variable, CC
  • environment variable, CC
  • Environment variable, CCX
  • Environment variable, CFLAGS
  • environment variable, CFLAGS
  • environment variable, CXX
  • environment variable, CXX
  • Environment variable, CXX
  • Environment variable, CXXFLAGS
  • environment variable, CXXFLAGS, environment variable, CXXFLAGS, environment variable, CXXFLAGS
  • environment variable, DBI_TRACE
  • Environment variable, DBI_TRACE, Environment variable, DBI_TRACE
  • Environment variable, DBI_USER
  • environment variable, HOME
  • Environment variable, HOME
  • environment variable, LD_RUN_PATH
  • Environment variable, LD_RUN_PATH, Environment variable, LD_RUN_PATH, Environment variable, LD_RUN_PATH
  • environment variable, MYSQL_DEBUG
  • Environment variable, MYSQL_DEBUG, Environment variable, MYSQL_DEBUG
  • environment variable, MYSQL_HISTFILE
  • Environment variable, MYSQL_HISTFILE
  • environment variable, MYSQL_HOST
  • Environment variable, MYSQL_HOST
  • Environment variable, MYSQL_PS1
  • environment variable, MYSQL_PWD, environment variable, MYSQL_PWD
  • Environment variable, MYSQL_PWD
  • environment variable, MYSQL_TCP_PORT
  • environment variable, MYSQL_TCP_PORT, environment variable, MYSQL_TCP_PORT
  • Environment variable, MYSQL_TCP_PORT
  • Environment variable, MYSQL_UNIX_PORT, Environment variable, MYSQL_UNIX_PORT
  • environment variable, MYSQL_UNIX_PORT, environment variable, MYSQL_UNIX_PORT
  • environment variable, MYSQL_UNIX_PORT
  • Environment variable, PATH
  • environment variable, PATH
  • Environment variable, TMPDIR, Environment variable, TMPDIR
  • Environment variable, TZ, Environment variable, TZ
  • Environment variable, UMASK, Environment variable, UMASK
  • Environment variable, UMASK_DIR, Environment variable, UMASK_DIR
  • Environment variable, USER
  • environment variable, USER
  • Environment variables, CXX
  • equal (=)
  • escape (\\)
  • execute DBI method
  • EXP()
  • EXPLAIN
  • EXPORT_SET()
  • EXTRACT()
  • F

  • fetchall_arrayref DBI method
  • fetchrow_array DBI method
  • fetchrow_arrayref DBI method
  • fetchrow_hashref DBI method
  • FIELD()
  • FILE
  • FIND_IN_SET()
  • finish DBI method
  • FLOAT, FLOAT
  • FLOAT(M,D)
  • FLOAT(precision), FLOAT(precision)
  • FLOOR()
  • FLUSH
  • FORCE INDEX, FORCE INDEX
  • FORMAT()
  • FOUND_ROWS()
  • FROM_DAYS()
  • FROM_UNIXTIME()
  • functions, arithmetic
  • functions, bit
  • functions, control flow
  • functions, date and time
  • functions, GROUP BY
  • functions, mathematical
  • functions, miscellaneous
  • functions, string
  • functions, string comparison
  • Functions, user-defined
  • G

  • GET_LOCK()
  • GRANT
  • GRANT statement, GRANT statement
  • GRANTS
  • greater than (>)
  • greater than or equal (>=)
  • GREATEST()
  • GROUP BY functions
  • H

  • HANDLER
  • HEX()
  • hexadecimal values
  • HOME environment variable
  • HOME environment variable
  • host.frm, problems finding
  • HOUR()
  • I

  • identifiers, quoting
  • IF()
  • IFNULL()
  • IGNORE INDEX, IGNORE INDEX
  • IGNORE KEY, IGNORE KEY
  • IN
  • INET_ATON()
  • INET_NTOA()
  • INNER JOIN
  • INSERT, INSERT
  • INSERT ... SELECT
  • INSERT DELAYED
  • INSERT statement, grant privileges
  • INSERT()
  • insertid DBI method
  • INSTR()
  • INT
  • INTEGER
  • INTERVAL()
  • IS NOT NULL
  • IS NULL
  • IS NULL, and indexes
  • is_blob DBI method
  • IS_FREE_LOCK()
  • is_key DBI method
  • is_not_null DBI method
  • is_num DBI method
  • is_pri_key DBI method
  • ISNULL()
  • ISOLATION LEVEL
  • J

  • JOIN
  • K

  • KILL
  • L

  • LAST_INSERT_ID()
  • LAST_INSERT_ID([expr])
  • LCASE()
  • LD_RUN_PATH environment variable, LD_RUN_PATH environment variable, LD_RUN_PATH environment variable, LD_RUN_PATH environment variable
  • LEAST()
  • LEFT JOIN, LEFT JOIN
  • LEFT OUTER JOIN
  • LEFT()
  • length DBI method
  • LENGTH()
  • less than (<)
  • less than or equal (<=)
  • LIKE
  • LIKE, and indexes
  • LIKE, and wildcards
  • LIMIT, LIMIT
  • LN()
  • LOAD DATA INFILE, LOAD DATA INFILE
  • LOAD_FILE()
  • LOCATE(), LOCATE()
  • LOCK TABLES
  • LOG()
  • LOG10()
  • LOG2()
  • Logical operators
  • LONGBLOB
  • LONGTEXT
  • LOWER()
  • LPAD()
  • LTRIM()
  • M

  • MAKE_SET()
  • MASTER_POS_WAIT()
  • MATCH ... AGAINST()
  • mathematical functions
  • MAX()
  • max_length DBI method
  • MD5()
  • MEDIUMBLOB
  • MEDIUMINT
  • MEDIUMTEXT
  • MID()
  • MIN()
  • minus, unary (-)
  • MINUTE()
  • miscellaneous functions
  • MOD()
  • modulo (%)
  • MONTH()
  • MONTHNAME()
  • multiplication (*)
  • my_init()
  • my_ulonglong C type
  • my_ulonglong values, printing
  • MySQL C type
  • MYSQL C type
  • mysql_affected_rows()
  • mysql_autocommit().
  • MYSQL_BIND C type
  • mysql_bind_param()
  • mysql_bind_result()
  • mysql_change_user()
  • mysql_character_set_name()
  • mysql_close()
  • mysql_commit().
  • mysql_connect()
  • mysql_create_db()
  • mysql_data_seek()
  • MYSQL_DEBUG environment variable, MYSQL_DEBUG environment variable
  • MYSQL_DEBUG environment variable
  • mysql_debug()
  • mysql_drop_db()
  • mysql_dump_debug_info()
  • mysql_eof()
  • mysql_errno()
  • mysql_error()
  • mysql_escape_string()
  • mysql_execute()
  • mysql_fetch()
  • mysql_fetch_field()
  • mysql_fetch_field_direct()
  • mysql_fetch_fields()
  • mysql_fetch_lengths()
  • mysql_fetch_row()
  • MYSQL_FIELD C type
  • mysql_field_count(), mysql_field_count()
  • MYSQL_FIELD_OFFSET C type
  • mysql_field_seek()
  • mysql_field_tell()
  • mysql_free_result()
  • mysql_get_client_info()
  • mysql_get_host_info()
  • mysql_get_proto_info()
  • mysql_get_server_info()
  • mysql_get_server_version()
  • MYSQL_HISTFILE environment variable
  • MYSQL_HISTFILE environment variable
  • MYSQL_HOST environment variable
  • MYSQL_HOST environment variable
  • mysql_info()
  • mysql_info(), mysql_info(), mysql_info(), mysql_info()
  • mysql_init()
  • mysql_insert_id()
  • mysql_insert_id()
  • mysql_kill()
  • mysql_list_dbs()
  • mysql_list_fields()
  • mysql_list_processes()
  • mysql_list_tables()
  • mysql_more_results().
  • mysql_next_result().
  • mysql_num_fields()
  • mysql_num_rows()
  • mysql_options()
  • mysql_param_count()
  • mysql_ping()
  • mysql_prepare()
  • mysql_prepare_result.
  • MYSQL_PS1 environment variable
  • MYSQL_PWD environment variable
  • MYSQL_PWD environment variable, MYSQL_PWD environment variable
  • mysql_query(), mysql_query()
  • mysql_real_connect()
  • mysql_real_escape_string()
  • mysql_real_escape_string()
  • mysql_real_query()
  • mysql_reload()
  • MYSQL_RES C type
  • mysql_rollback().
  • MYSQL_ROW C type
  • mysql_row_seek()
  • mysql_row_tell()
  • mysql_select_db()
  • mysql_send_long_data().
  • mysql_server_end()
  • mysql_server_init()
  • mysql_shutdown()
  • mysql_stat()
  • MYSQL_STMT C type
  • mysql_stmt_affected_rows()
  • mysql_stmt_close()
  • mysql_stmt_errno()
  • mysql_stmt_error().
  • mysql_stmt_store_result()
  • mysql_store_result(), mysql_store_result()
  • MYSQL_TCP_PORT environment variable, MYSQL_TCP_PORT environment variable
  • MYSQL_TCP_PORT environment variable, MYSQL_TCP_PORT environment variable
  • mysql_thread_end()
  • mysql_thread_id()
  • mysql_thread_init()
  • mysql_thread_safe()
  • MYSQL_UNIX_PORT environment variable, MYSQL_UNIX_PORT environment variable, MYSQL_UNIX_PORT environment variable
  • MYSQL_UNIX_PORT environment variable, MYSQL_UNIX_PORT environment variable
  • mysql_use_result()
  • N

  • NAME DBI method
  • NATIONAL CHAR
  • NATURAL LEFT JOIN
  • NATURAL LEFT OUTER JOIN
  • NATURAL RIGHT JOIN
  • NATURAL RIGHT OUTER JOIN
  • NCHAR
  • newline (\n)
  • NOT BETWEEN
  • not equal (!=)
  • not equal (<>)
  • NOT IN
  • NOT LIKE
  • NOT REGEXP
  • NOT, logical
  • NOW()
  • NUL
  • NULL, NULL
  • NULL value
  • NULLABLE DBI method
  • NULLIF()
  • NUM_OF_FIELDS DBI method
  • NUMERIC
  • O

  • OCT()
  • OCTET_LENGTH()
  • OLD_PASSWORD()
  • Operators, logical
  • OPTIMIZE TABLE
  • OR, bitwise
  • OR, logical
  • ORD()
  • ORDER BY
  • P

  • parentheses ( and )
  • PASSWORD(), PASSWORD(), PASSWORD(), PASSWORD()
  • PATH environment variable, PATH environment variable
  • PERIOD_ADD()
  • PERIOD_DIFF()
  • PI()
  • POSITION()
  • POW()
  • POWER()
  • prepare() DBI method
  • PRIMARY KEY, PRIMARY KEY
  • PROCESSLIST
  • Q

  • QUARTER()
  • QUOTE()
  • quote() DBI method
  • quoting of identifiers
  • R

  • RADIANS()
  • RAND()
  • REAL
  • REGEXP
  • RELEASE_LOCK()
  • RENAME TABLE
  • REPAIR TABLE
  • REPEAT()
  • REPLACE
  • REPLACE ... SELECT
  • REPLACE()
  • REQUIRE GRANT option
  • RESTORE TABLE
  • return (\r)
  • REVERSE()
  • REVOKE
  • RIGHT JOIN
  • RIGHT OUTER JOIN
  • RIGHT()
  • RLIKE
  • ROLLBACK, ROLLBACK
  • ROUND()
  • rows DBI method
  • RPAD()
  • RTRIM()
  • S

  • SEC_TO_TIME()
  • SECOND()
  • SELECT
  • SELECT INTO TABLE
  • SELECT speed
  • SELECT, optimising
  • SESSION_USER()
  • SET, SET
  • SET OPTION
  • SET PASSWORD statement
  • SET TRANSACTION
  • SHA()
  • SHA1()
  • SHOW COLUMNS
  • SHOW CREATE TABLE, SHOW CREATE TABLE
  • SHOW DATABASE INFO
  • SHOW DATABASES
  • SHOW FIELDS
  • SHOW GRANTS, SHOW GRANTS
  • SHOW INDEX
  • SHOW KEYS
  • SHOW MASTER LOGS
  • SHOW MASTER STATUS
  • SHOW PRIVILEGES
  • SHOW PROCESSLIST, SHOW PROCESSLIST
  • SHOW SLAVE STATUS
  • SHOW STATUS
  • SHOW TABLE STATUS
  • SHOW TABLE TYPES, SHOW TABLE TYPES
  • SHOW TABLES
  • SHOW VARIABLES
  • SHOW WARNINGS, SHOW WARNINGS
  • SIGN()
  • SIN()
  • single quote (\')
  • SMALLINT
  • SOUNDEX()
  • SOUNDS LIKE
  • SPACE()
  • SQL_CACHE
  • SQL_NO_CACHE
  • SQRT()
  • START TRANSACTION
  • statements, GRANT
  • statements, INSERT
  • STD()
  • STDDEV()
  • STRAIGHT_JOIN
  • STRCMP()
  • string comparison functions
  • string functions
  • SUBDATE()
  • SUBSTRING(), SUBSTRING()
  • SUBSTRING_INDEX()
  • subtraction (-)
  • SUM()
  • SYSDATE()
  • SYSTEM_USER()
  • T

  • tab (\t)
  • table DBI method
  • table_cache
  • TAN()
  • TEXT, TEXT
  • threads
  • TIME, TIME
  • TIME_FORMAT()
  • TIME_TO_SEC()
  • TIMESTAMP, TIMESTAMP
  • TINYBLOB
  • TINYINT
  • TINYTEXT
  • TMPDIR environment variable, TMPDIR environment variable
  • TO_DAYS()
  • trace DBI method, trace DBI method
  • TRIM()
  • TRUNCATE
  • TRUNCATE()
  • type DBI method
  • Types
  • TZ environment variable, TZ environment variable
  • U

  • UCASE()
  • UDF functions
  • ulimit
  • UMASK environment variable, UMASK environment variable
  • UMASK_DIR environment variable, UMASK_DIR environment variable
  • unary minus (-)
  • UNION, UNION
  • UNIQUE
  • UNIX_TIMESTAMP()
  • UNLOCK TABLES
  • UPDATE
  • UPPER()
  • USE
  • USE INDEX, USE INDEX
  • USE KEY, USE KEY
  • USER environment variable
  • USER environment variable
  • USER()
  • User-defined functions
  • V

  • VARCHAR, VARCHAR
  • VARIANCE()
  • VERSION()
  • W

  • WEEK()
  • WEEKDAY()
  • WHERE
  • Wildcard character (%)
  • Wildcard character (_)
  • without-server option
  • X

  • XOR, bitwise
  • XOR, logical
  • Y

  • YEAR, YEAR
  • YEAR()
  • | (bitwise OR)
  • || (logical OR)
  • ~
  • Concept Index

    A

  • aborted clients
  • aborted connection
  • access control
  • access denied errors
  • access privileges
  • Access program
  • ACID
  • ACID
  • ACLs
  • ActiveState Perl
  • adding, character sets
  • adding, native functions
  • adding, new functions
  • adding, new user privileges
  • adding, new users
  • adding, procedures
  • adding, user-definable functions
  • administration, server
  • ADO program
  • age, calculating
  • alias names, case-sensitivity
  • aliases, for expressions
  • aliases, for tables
  • aliases, in GROUP BY clauses
  • aliases, in ORDER BY clauses
  • aliases, names
  • aliases, on expressions
  • anonymous user, anonymous user, anonymous user, anonymous user
  • ANSI mode, running
  • ANSI SQL, differences from
  • ANSI SQL92, extensions to
  • answering questions, etiquette
  • Apache
  • APIs
  • APIs, Perl
  • applying, patches
  • argument processing
  • arithmetic expressions
  • AUTO-INCREMENT, ODBC
  • AUTO_INCREMENT
  • AUTO_INCREMENT, and NULL values
  • B

  • backing up, databases, backing up, databases
  • backslash, escape character
  • backups
  • backups, database
  • batch mode
  • batch, mysql option
  • BDB table type
  • BDB tables
  • benchmark suite
  • benchmarks
  • BerkeleyDB table type
  • Big5 Chinese character encoding
  • binary distributions
  • binary distributions, installing
  • binary distributions, on HP-UX
  • binary distributions, on Linux
  • binary log
  • Binlog_Dump
  • bit_functions, example
  • BitKeeper tree
  • BLOB columns, default values
  • BLOB columns, indexing
  • BLOB, inserting binary data
  • BLOB, size
  • Borland Builder 4 program
  • Borland C++ compiler
  • brackets, square
  • buffer sizes, client
  • buffer sizes, mysqld server
  • bug reports, criteria for
  • bugs database
  • bugs, known
  • bugs, reporting
  • bugs.mysql.com
  • building, client programs
  • C

  • C API, datatypes
  • C API, functions
  • C API, linking problems
  • C Prepared statements API, functions
  • C++
  • C++ APIs
  • C++ Builder
  • C++ compiler cannot create executables
  • C++ compiler, gcc
  • caches, clearing
  • calculating, dates
  • calling sequences for aggregate functions, UDF
  • calling sequences for simple functions, UDF
  • can't create/write to file
  • case-sensitivity, in access checking
  • case-sensitivity, in names
  • case-sensitivity, in searches
  • case-sensitivity, in string comparisons
  • case-sensitivity, of database names
  • case-sensitivity, of table names
  • cast operators
  • casts
  • cc1plus problems
  • certification
  • ChangeLog
  • changes to privileges
  • changes, log
  • changes, version 3.19
  • changes, version 3.20
  • changes, version 3.21
  • changes, version 3.22
  • changes, version 3.23
  • changes, version 4.0
  • changes, version 4.1
  • changes, version 5.0
  • changing socket location, changing socket location, changing socket location
  • changing, column
  • changing, column order
  • changing, field
  • changing, table, changing, table, changing, table
  • character sets, character sets
  • character sets, adding
  • character-sets-dir, mysql option
  • characters, multi-byte
  • check options, myisamchk
  • checking, tables for errors
  • checksum errors
  • Chinese
  • choosing types
  • choosing, a MySQL version
  • clearing, caches
  • client programs, building
  • client tools
  • clients, debugging
  • clients, threaded
  • closing, tables
  • ColdFusion program
  • collating, strings
  • column names, case-sensitivity
  • column, changing
  • columns, changing
  • columns, displaying
  • columns, indexes
  • columns, names
  • columns, other types
  • columns, selecting
  • columns, storage requirements
  • columns, types
  • command syntax
  • command-line history
  • command-line options, mysql
  • command-line tool
  • commands out of sync
  • commands, for binary distribution
  • commands, list of
  • commands, replication
  • comments, adding
  • comments, starting
  • commercial support, types
  • communications protocols
  • comparisons, MySQL vs. others
  • compatibility, between MySQL versions, compatibility, between MySQL versions, compatibility, between MySQL versions, compatibility, between MySQL versions
  • compatibility, with ANSI SQL
  • compatibility, with mSQL
  • compatibility, with ODBC, compatibility, with ODBC, compatibility, with ODBC, compatibility, with ODBC, compatibility, with ODBC, compatibility, with ODBC, compatibility, with ODBC
  • compatibility, with Oracle, compatibility, with Oracle, compatibility, with Oracle
  • compatibility, with PostgreSQL
  • compatibility, with Sybase
  • compiler, C++ gcc
  • compiling, on Windows
  • compiling, optimising
  • compiling, problems
  • compiling, speed
  • compiling, statically
  • compiling, user-defined functions
  • compliance, Y2K
  • compress, mysql option
  • compressed tables, compressed tables
  • config-file option
  • config.cache
  • config.cache file
  • configuration files
  • configuration options
  • configure option, --with-low-memory
  • configure script
  • configure, running after prior invocation
  • connect_timeout variable
  • connecting, remotely with SSH
  • connecting, to the server, connecting, to the server
  • connecting, verification
  • connection, aborted
  • Connector/J
  • Connector/ODBC
  • constant table, constant table
  • consulting
  • contact information
  • contributed programs
  • contributing companies, list of
  • contributors, list of
  • control access
  • conventions, typographical
  • converters
  • converting, tools
  • copyrights
  • costs, support
  • counting, table rows
  • crackers, security against
  • crash
  • crash, recovery
  • crash, repeated
  • crash-me
  • crash-me program, crash-me program
  • creating, bug reports
  • creating, databases
  • creating, default startup options
  • creating, tables
  • customer support, mailing address
  • customers, of MySQL
  • CVS tree
  • D

  • data, character sets
  • data, importing
  • data, loading into tables
  • data, retrieving
  • data, size
  • database design
  • database names, case-sensitivity, database names, case-sensitivity
  • database, deleting
  • database, mysql option
  • databases, backups
  • databases, creating
  • databases, defined
  • databases, displaying
  • databases, dumping, databases, dumping
  • databases, information about
  • databases, MySQL vs. others
  • databases, names
  • databases, replicating
  • databases, selecting
  • databases, symbolic links
  • databases, using
  • DataJunction
  • datatypes, C API
  • Date and Time types
  • date calculations
  • DATE columns, problems
  • date functions, Y2K compliance
  • date types
  • date types, Y2K issues
  • date values, problems
  • db table, sorting
  • DBI interface
  • DBI Perl module
  • DBI/DBD
  • DBUG package
  • debug-info, mysql option
  • debug, mysql option
  • debugging, client
  • debugging, server
  • decimal point
  • default hostname
  • default installation location
  • default options
  • default values, default values, default values, default values
  • default values, BLOB and TEXT columns
  • default values, suppression
  • default, privileges
  • default-character-set, mysql option
  • defaults, embedded
  • delayed_insert_limit
  • deleting, database
  • deleting, function
  • deleting, index, deleting, index
  • deleting, primary key
  • deleting, rows
  • deleting, table
  • deletion, mysql.sock
  • Delphi
  • Delphi program
  • design, choices
  • design, issues
  • design, limitations
  • developers, list of
  • development source tree
  • digits
  • directory structure, default
  • disconnecting, from the server
  • disk full
  • disk issues
  • disks, splitting data across
  • display size
  • displaying, database information
  • displaying, information, SHOW
  • displaying, table status
  • DNS
  • downgrading
  • downloading
  • dumping, databases, dumping, databases
  • dynamic table characteristics
  • E

  • e-mail lists
  • Eiffel Wrapper
  • embedded MySQL server library
  • employment with MySQL
  • employment, contact information
  • enable-named-commands, mysql option
  • entering, queries
  • ENUM, size
  • environment variables, environment variables, environment variables, environment variables
  • environment variables, list of
  • Errcode
  • errno
  • error mesaages, can't find file
  • error messages, displaying
  • error messages, languages
  • errors, access denied
  • errors, checking tables for
  • errors, common
  • errors, directory checksum
  • errors, handling for UDFs
  • errors, known
  • errors, linking
  • errors, list of
  • errors, reporting, errors, reporting, errors, reporting
  • escape characters
  • estimating, query performance
  • example option
  • examples, compressed tables
  • examples, myisamchk output
  • examples, queries
  • Excel
  • execute, mysql option
  • expression aliases, expression aliases
  • expressions, extended
  • extensions, to ANSI SQL
  • extracting, dates
  • F

  • fatal signal 11
  • features of MySQL
  • field, changing
  • files, binary log
  • files, config.cache
  • files, error messages
  • files, log, files, log
  • files, not found message
  • files, permissions
  • files, query log
  • files, repairing
  • files, script
  • files, size limits
  • files, slow query log
  • files, text
  • files, tmp
  • files, update log
  • files,`my.cnf'
  • floating-point number
  • floats
  • flush tables
  • force, mysql option
  • foreign keys, foreign keys, foreign keys
  • free licensing
  • FreeBSD troubleshooting
  • full disk
  • full-text search
  • FULLTEXT
  • function, deleting
  • functions for SELECT and WHERE clauses
  • functions, C API
  • functions, C Prepared statements API
  • functions, grouping
  • functions, native, adding
  • functions, new
  • functions, user-definable, adding
  • functions, user-defined
  • G

  • gcc
  • gdb, using
  • general information
  • General Public License
  • General Public License, MySQL
  • getting MySQL
  • global privileges
  • goals of MySQL
  • GPL, General Public License
  • GPL, GNU General Public License
  • GPL, MySQL
  • grant tables
  • grant tables, re-creating
  • grant tables, sorting, grant tables, sorting
  • granting, privleges
  • GROUP BY, aliases in
  • GROUP BY, extensions to ANSI SQL, GROUP BY, extensions to ANSI SQL
  • grouping, expressions
  • H

  • handling, errors
  • HEAP table type
  • help option
  • help, mysql option
  • hints, hints, hints, hints, hints
  • history file
  • history of MySQL
  • host table
  • host table, sorting
  • host, mysql option
  • hostname caching
  • hostname, default
  • HP-UX, binary distribution
  • html, mysql option
  • I

  • ID, unique
  • ignore-space, mysql option
  • importing, data
  • increasing, performance
  • increasing, speed
  • index, deleting, index, deleting
  • indexes
  • indexes, and BLOB columns
  • indexes, and IS NULL
  • indexes, and LIKE
  • indexes, and NULL values
  • indexes, and TEXT columns
  • indexes, block size
  • indexes, columns
  • indexes, leftmost prefix of
  • indexes, multi-column
  • indexes, multi-part
  • indexes, names
  • indexes, use of
  • InnoDB table type
  • InnoDB tables
  • INSERT DELAYED
  • inserting, speed of
  • installation layouts
  • installation overview
  • Installing many servers
  • installing, binary distribution
  • installing, Linux RPM packages
  • installing, Mac OS X PKG packages
  • installing, overview
  • installing, Perl
  • installing, Perl on Windows
  • installing, source distribution
  • installing, user-defined functions
  • integers
  • internal compiler errors
  • internal locking
  • internals
  • Internet Relay Chat
  • Internet Service Providers
  • IRC
  • ISAM table type
  • ISP services
  • J

  • Java connectivity
  • JDBC
  • jobs at MySQL
  • K

  • key space, MyISAM
  • keys
  • keys, foreign, keys, foreign
  • keys, multi-column
  • keys, searching on two
  • keywords
  • known errors
  • L

  • language support
  • last row, unique ID
  • layout of installation
  • leftmost prefix of indexes
  • legal names
  • LGPL, GNU Lesser General Public License
  • LGPL, GNU Library General Public License
  • LGPL, Lesser General Public License
  • LGPL, Library General Public License
  • libmysqld
  • library, mysqlclient
  • licenses
  • licensing costs
  • licensing policy
  • licensing terms
  • licensing, contact information
  • licensing, examples
  • licensing, free
  • limitations, design
  • limits, file-size
  • linking
  • linking, errors
  • linking, problems
  • linking, speed
  • links, symbolic
  • Linux, binary distribution
  • literals
  • loading, tables
  • locking
  • locking methods
  • locking, row-level
  • locking, tables
  • log files
  • Log files
  • log files, maintaining
  • log files, names
  • log option
  • log, changes
  • logos
  • M

  • Mac OS X, installation
  • mailing address, for customer support
  • mailing list address
  • mailing lists
  • mailing lists, archive location
  • mailing lists, guidelines
  • main features of MySQL
  • maintaining, log files
  • maintaining, tables
  • make_binary_distribution
  • manual, available formats
  • manual, online location
  • manual, typographical conventions
  • master-slave setup
  • matching, patterns
  • max memory used
  • max_allowed_packet
  • max_join_size
  • memory usage, myisamchk
  • memory use, memory use
  • MERGE table type
  • MERGE tables, defined
  • messages, languages
  • methods, locking
  • mirror sites
  • MIT-pthreads
  • modes, batch
  • modules, list of
  • monitor, terminal
  • mSQL compatibility
  • mSQL vs. MySQL, protocol
  • mSQL, MySQL vs mSQL, overview
  • msql2mysql
  • multi mysqld
  • multi-byte character sets
  • multi-byte characters
  • multi-column indexes
  • multi-part index
  • multiple servers
  • My, derivation
  • `my.cnf' file
  • MyISAM table type
  • MyISAM, compressed tables, MyISAM, compressed tables
  • MyISAM, size
  • myisamchk, myisamchk
  • myisamchk, example output
  • myisamchk, options
  • myisampack, myisampack, myisampack
  • MyODBC
  • MyODBC, reporting problems
  • mysql
  • MySQL AB, defined
  • MySQL binary distribution
  • MySQL certification
  • mysql command-line options
  • MySQL consulting
  • MySQL Dolphin name
  • MySQL history
  • MySQL mailing lists
  • MySQL name
  • MySQL source distribution
  • MySQL table types
  • MySQL tools, conversion
  • MySQL training
  • MySQL version
  • MySQL, defined
  • MySQL, introduction
  • MySQL, pronunciation
  • mysql.sock, changing location of
  • mysql.sock, protection
  • mysql_fix_privilege_tables
  • mysql_install_db
  • mysql_install_db script
  • mysqlaccess
  • mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin
  • mysqladmin option
  • mysqlbinlog, mysqlbinlog
  • mysqlbug
  • mysqlbug script
  • mysqlbug script, location
  • mysqlclient library
  • mysqld
  • mysqld option
  • mysqld options
  • mysqld options
  • mysqld server, buffer sizes
  • mysqld, starting
  • mysqld-max
  • mysqld_multi
  • mysqld_safe
  • mysqldump, mysqldump, mysqldump
  • mysqlimport, mysqlimport, mysqlimport, mysqlimport
  • mysqlshow
  • mysqltest, MySQL Test Suite
  • N

  • named pipes
  • names
  • names, case-sensitivity
  • names, variables
  • naming, releases of MySQL
  • native functions, adding
  • native thread support
  • negative values
  • net etiquette, net etiquette
  • net_buffer_length
  • netmask notation, in mysql.user table
  • new procedures, adding
  • new users, adding
  • no matching rows
  • no-auto-rehash, mysql option
  • no-beep, mysql option
  • no-log option
  • no-named-commands, mysql option
  • no-pager, mysql option
  • no-tee, mysql option
  • non-delimited strings
  • Non-transactional tables
  • NULL value
  • NULL values, and indexes
  • NULL values, vs. empty values
  • NULL, testing for null, NULL, testing for null, NULL, testing for null, NULL, testing for null
  • NULL values, and AUTO_INCREMENT columns
  • NULL values, and TIMESTAMP columns
  • numbers
  • numeric types
  • O

  • ODBC
  • ODBC compatibility, ODBC compatibility, ODBC compatibility, ODBC compatibility, ODBC compatibility, ODBC compatibility, ODBC compatibility
  • ODBC, administrator
  • odbcadmin program
  • OLEDB
  • one-database, mysql option
  • online location of manual
  • Open Source, defined
  • open tables, open tables
  • opening, tables
  • opens
  • OpenSSL
  • operating systems, file-size limits
  • operating systems, supported
  • operating systems, Windows versus Unix
  • operations, arithmetic
  • operators, cast, operators, cast
  • optimisation, tips
  • optimisations
  • optimising, DISTINCT
  • optimising, LEFT JOIN
  • optimising, LIMIT
  • optimising, tables
  • option files
  • options, command-line
  • options, command-line, mysql
  • options, configure
  • options, myisamchk
  • options, provided by MySQL
  • options, replication
  • Oracle compatibility, Oracle compatibility, Oracle compatibility
  • ORDER BY, aliases in
  • overview
  • P

  • pack_isam
  • pager, mysql option
  • parameters, server
  • partnering with MySQL AB
  • password encryption, reversibility of
  • password option
  • password, root user
  • password, mysql option
  • passwords, for users
  • passwords, forgotten
  • passwords, resetting
  • passwords, security
  • passwords, setting, passwords, setting, passwords, setting
  • patches, applying
  • pattern matching
  • performance, benchmarks
  • performance, disk issues
  • performance, estimating
  • performance, improving, performance, improving
  • Perl API
  • Perl DBI/DBD, installation problems
  • Perl, installing
  • Perl, installing on Windows
  • Perl, modules
  • permission checks, effect on speed
  • perror
  • PHP API
  • port, mysql option
  • portability
  • portability, types
  • porting, to other systems
  • post-install, many servers
  • post-installation, setup and testing
  • PostgreSQL compatibility
  • PostgreSQL vs. MySQL, benchmarks
  • PostgreSQL vs. MySQL, features
  • PostgreSQL vs. MySQL, overview
  • PostgreSQL vs. MySQL, strategies
  • prices, support
  • primary key, deleting
  • privilege information, location
  • privilege system
  • privilege system, described
  • privilege, changes
  • privileges, access
  • privileges, adding
  • privileges, default
  • privileges, display
  • privileges, granting
  • privileges, revoking
  • problems, access denied errors
  • problems, common errors
  • problems, compiling
  • problems, DATE columns
  • problems, date values
  • problems, installing on IBM-AIX
  • problems, installing on Solaris
  • problems, installing Perl
  • problems, linking
  • problems, ODBC
  • problems, reporting
  • problems, starting the server
  • problems, table locking
  • problems, timezone
  • procedures, adding
  • procedures, stored
  • process support
  • processes, display
  • processing, arguments
  • products, selling
  • programs, client
  • programs, contributed
  • programs, crash-me
  • programs, list of, programs, list of
  • prompt command
  • prompt, mysql option
  • prompts, meanings
  • pronunciation, MySQL
  • Protocol mismatch
  • protocol, mysql option, protocol, mysql option
  • Python API
  • Q

  • queries, entering
  • queries, estimating performance
  • queries, examples
  • queries, speed of
  • queries, Twin Studeis project
  • Query Cache
  • query log
  • questions
  • questions, answering
  • quick, mysql option
  • quotes, in strings
  • quoting
  • quoting binary data
  • quoting strings
  • R

  • raw, mysql option
  • re-creating, grant tables
  • reconfiguring, reconfiguring
  • reconnect, mysql option
  • recovery, from crash
  • reducing, data size
  • references
  • regex
  • regular expression syntax, described
  • relational databases, defined
  • release numbers
  • releases, naming scheme
  • releases, testing
  • releases, updating
  • reordering, columns
  • repair options, myisamchk
  • repairing, tables
  • replace
  • replication
  • replication, commands
  • replication, two-way
  • reporting, bugs
  • reporting, errors, reporting, errors
  • reporting, MyODBC problems
  • reserved words, exceptions
  • restarting, the server
  • retrieving, data from tables
  • return values, UDFs
  • revoking, privleges
  • root password
  • root user, password resetting
  • rounding errors, rounding errors
  • rows, counting
  • rows, deleting
  • rows, locking
  • rows, matching problems
  • rows, selecting
  • rows, sorting
  • RPM file
  • RPM Package Manager, RPM Package Manager
  • RPM, defined
  • RTS-threads
  • running a web server
  • running configure after prior invocation
  • running, ANSI mode
  • running, batch mode
  • running, multiple servers
  • running, queries
  • S

  • safe-mode command
  • safe-updates, mysql option
  • safe_mysqld
  • Sakila
  • script files
  • scripts, scripts, scripts
  • scripts, mysql_install_db
  • scripts, mysqlbug
  • searching, and case-sensitivity
  • searching, full-text
  • searching, MySQL web pages
  • searching, two keys
  • security system
  • security, against crackers
  • SELECT, Query Cache
  • select_limit
  • selecting, databases
  • selling products
  • sequence emulation
  • server administration
  • server, connecting, server, connecting
  • server, debugging
  • server, disconnecting
  • server, restart
  • server, shutdown
  • server, starting
  • server, starting and stopping
  • server, starting problems
  • servers, multiple
  • services, ISP
  • services, web
  • SET, size
  • set-variable, mysql option
  • setting, passwords
  • setup, post-installation
  • shell syntax
  • showing, database information
  • shutting down, the server
  • silent column changes
  • silent, mysql option
  • size of tables
  • sizes, display
  • skip-column-names, mysql option
  • skip-line-numbers, mysql option
  • slow queries
  • slow query log
  • socket location, changing
  • socket, mysql option
  • Solaris installation problems
  • Solaris troubleshooting
  • sorting, character sets
  • sorting, data
  • sorting, grant tables, sorting, grant tables
  • sorting, table rows
  • source distribution, installing
  • speed, compiling
  • speed, increasing
  • speed, inserting
  • speed, linking
  • speed, of queries, speed, of queries
  • SQL commands, replication
  • SQL, defined
  • sql_yacc.cc problems
  • square brackets
  • SSH
  • SSL and X509 Basics
  • SSL related options
  • stability
  • standards compatibility
  • Starting many servers
  • starting, comments
  • starting, mysqld
  • starting, the server
  • starting, the server automatically
  • startup options, default
  • startup parameters
  • startup parameters, mysql
  • startup parameters, tuning
  • statically, compiling
  • status command
  • status command, results
  • status, tables
  • stopping, the server
  • storage of data
  • storage requirements, column type
  • storage space, minimising
  • stored procedures and triggers, defined
  • string collating
  • string comparisons, case-sensitivity
  • string types
  • strings, defined
  • strings, escaping characters
  • strings, non-delimited
  • strings, quoting
  • striping, defined
  • subSELECTs
  • superuser
  • support costs
  • support terms
  • support, for operating systems
  • support, licensing
  • support, mailing address
  • support, types
  • suppression, default values
  • Sybase compatibility
  • symbolic links, symbolic links
  • syntax, regular expression
  • system optimisation
  • system table
  • system variables
  • system, privilege
  • system, security
  • T

  • table aliases
  • table cache
  • table is full, table is full
  • table names, case-sensitivity, table names, case-sensitivity
  • table types, choosing
  • table, changing, table, changing, table, changing
  • table, deleting
  • table, mysql option
  • tables, BDB
  • tables, Berkeley DB
  • tables, changing column order
  • tables, checking
  • tables, closing
  • tables, compressed
  • tables, compressed format
  • tables, constant, tables, constant
  • tables, counting rows
  • tables, creating
  • tables, defragment, tables, defragment
  • tables, defragmenting
  • tables, deleting rows
  • tables, displaying
  • tables, displaying status
  • tables, dumping, tables, dumping
  • tables, dynamic
  • tables, error checking
  • tables, flush
  • tables, fragmentation
  • tables, grant
  • tables, HEAP
  • tables, host
  • tables, improving performance
  • tables, information
  • tables, information about
  • tables, ISAM
  • tables, loading data
  • tables, locking
  • tables, maintenance regimen
  • tables, maximum size
  • tables, merging
  • tables, multiple
  • tables, names
  • tables, open
  • tables, opening
  • tables, optimising
  • tables, repairing
  • tables, retrieving data
  • tables, selecting columns
  • tables, selecting rows
  • tables, sorting rows
  • tables, symbolic links
  • tables, system
  • tables, too many
  • tables, unique ID for last row
  • tables, updating
  • tar, problems on Solaris
  • Tcl API
  • tcp-ip option
  • TCP/IP
  • technical support, licensing
  • technical support, mailing address
  • tee, mysql option
  • temporary file, write access
  • temporary tables, problems
  • terminal monitor, defined
  • testing mysqld, mysqltest
  • testing, connection to the server
  • testing, installation
  • testing, of MySQL releases
  • testing, post-installation
  • testing, the server
  • Texinfo
  • TEXT columns, default values
  • TEXT columns, indexing
  • text files, importing
  • TEXT, size
  • thread packages, differences between
  • thread support
  • thread support, non-native
  • threaded clients
  • threads, threads
  • threads, display
  • threads, RTS
  • time types
  • timeout, timeout, timeout
  • timeout, connect_timeout variable
  • TIMESTAMP, and NULL values
  • timezone problems
  • tips, optimisation
  • ToDo list for MySQL
  • TODO, embedded server
  • TODO, symlinks
  • tools, command-line
  • tools, converting
  • tools, mysqld_multi
  • tools, safe_mysqld
  • trademarks
  • training
  • transaction-safe tables, transaction-safe tables
  • transactions, support, transactions, support
  • triggers, stored
  • troubleshooting, FreeBSD
  • troubleshooting, Solaris
  • tutorial
  • Twin Studies, queries
  • type conversions
  • types of support
  • types, columns, types, columns
  • types, date
  • types, Date and Time
  • types, numeric
  • types, of tables
  • types, portability
  • types, strings
  • types, time
  • typographical conventions
  • U

  • UDFs, compiling
  • UDFs, defined
  • UDFs, return values
  • unbuffered, mysql option
  • unique ID
  • unloading, tables
  • update log
  • updating, releases of MySQL
  • updating, tables
  • upgrading
  • upgrading, 3.20 to 3.21
  • upgrading, 3.21 to 3.22
  • upgrading, 3.22 to 3.23
  • upgrading, 3.23 to 4.0
  • upgrading, 4.0 to 4.1, upgrading, 4.0 to 4.1
  • upgrading, different architecture
  • uptime
  • URLS for downloading MySQL
  • user names, and passwords
  • user option
  • user privileges, adding
  • user table, sorting
  • user variables
  • user-defined functions, adding, user-defined functions, adding
  • user, mysql option
  • users, adding
  • users, root
  • uses, of MySQL
  • using multiple disks to start data
  • utilities
  • V

  • valid numbers, examples
  • VARCHAR, size
  • variables, mysqld
  • variables, status
  • variables, System
  • variables, user
  • variables, values
  • verbose, mysql option
  • version option
  • version, choosing
  • version, latest
  • version, mysql option
  • vertical, mysql option
  • views
  • virtual memory, problems while compiling
  • Visual Basic
  • W

  • wait, mysql option
  • web server, running
  • What is an X509/Certificate?
  • What is encryption
  • wildcards, and LIKE
  • wildcards, in mysql.columns_priv table
  • wildcards, in mysql.db table
  • wildcards, in mysql.host table
  • wildcards, in mysql.tables_priv table
  • wildcards, in mysql.user table
  • Windows
  • Windows, compiling on
  • Windows, open issues
  • Windows, versus Unix
  • Word program
  • wrappers, Eiffel
  • write access, tmp
  • X

  • xml, mysql option
  • Y

  • Year 2000 compliance
  • Year 2000 issues

  • This document was generated on 3 April 2003 using the texi2html translator version 1.52 (extended by davida@detron.se).