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):
COMMIT command.
ROLLBACK to ignore your changes (if you are not
running in auto-commit mode).
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.
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 file that indicates whether
the table was closed correctly. If mysqld is started with
--myisam-recover, MyISAM tables will automatically be
checked and/or repaired on open if the table wasn't closed properly.
INSERT new rows in a table that doesn't have free blocks
in the middle of the datafile, at the same time other threads are
reading from the table (concurrent insert). An free block can come from
an update of a dynamic length row with much data to a row with less data
or when deleting rows. When all free blocks are used up, all future
inserts will be concurrent again.
AUTO_INCREMENT column. MyISAM
will automatically update this on INSERT/UPDATE. The
AUTO_INCREMENT value can be reset with myisamchk. This
will make AUTO_INCREMENT columns faster (at least 10%) and old
numbers will not be reused as with the old ISAM. Note that when an
AUTO_INCREMENT is defined on the end of a multi-part-key the old
behaviour is still present.
AUTO_INCREMENT
column) the key tree will be split so that the high node only contains one
key. This will improve the space utilisation in the key tree.
BLOB and TEXT columns can be indexed.
NULL values are allowed in indexed columns. This takes 0-1
bytes/key.
myisamchk.
myisamchk will mark tables as checked if one runs it with
--update-state. myisamchk --fast will only check those
tables that don't have this mark.
myisamchk -a stores statistics for key parts (and not only for
whole keys as in ISAM).
myisampack can pack BLOB and VARCHAR columns.
DATA/INDEX DIRECTORY="path" option to
CREATE TABLE). See section 6.5.3 CREATE TABLE Syntax.
MyISAM also supports the following things, which MySQL
will be able to use in the near future:
VARCHAR type; a VARCHAR column starts
with a length stored in 2 bytes.
VARCHAR may have fixed or dynamic record length.
VARCHAR and CHAR may be up to 64K.
All key segments have their own language definition. This will enable
MySQL to have different language definitions per column.
UNIQUE. This will allow
you to have UNIQUE on any combination of columns in a table. (You
can't search on a UNIQUE computed index, however.)
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.
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.
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.
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:
CHAR, NUMERIC, and DECIMAL columns are space-padded
to the column width.
myisamchk) unless a huge number of
records are deleted and you want to return free disk space to the operating
system.
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:
'') for string columns, or zero for numeric columns. (This isn't
the same as columns containing NULL values.) If a string column
has a length of zero after removal of trailing spaces, or a numeric
column has a value of zero, it is marked in the bit map and not saved to
disk. Non-empty strings are saved as a length byte plus the string
contents.
myisamchk
-r from time to time to get better performance. Use myisamchk -ei
tbl_name for some statistics.
3 + (number of columns + 7) / 8 + (number of char columns) + packed size of numeric columns + length of strings + (number of NULL columns + 7) / 8There is a penalty of 6 bytes for each link. A dynamic record is linked whenever an update causes an enlargement of the record. Each new link will be at least 20 bytes, so the next enlargement will probably go in the same link. If not, there will be another link. You may check how many links there are with
myisamchk -ed. All links may be removed with myisamchk -r.
This is a read-only type that is generated with the optional
myisampack tool (pack_isam for ISAM tables):
myisampack.
0 are stored using 1 bit.
BIGINT column (8 bytes) may
be stored as a TINYINT column (1 byte) if all values are in the range
0 to 255.
ENUM.
myisamchk.
MyISAM Table ProblemsThe 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.
MyISAM TablesEven 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:
mysqld process being killed in the middle of a write.
Typial typical symptoms for a corrupt table is:
Incorrect key file for table: '...'. Try to repair it
while selecting data from the table.
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.
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:
FLUSH or
because there isn't room in the table cache) the counter is
decremented if the table has been updated at any point.
In other words, the only ways this can go out of sync are:
MyISAM tables are copied without a LOCK and
FLUSH TABLES.
myisamchk --recover or myisamchk
--update-stateon a table that was in use by mysqld.
mysqld servers are using the table and one has done a
REPAIR or CHECK of the table while it was in use by
another server. In this setup the CHECK is safe to do (even if
you will get the warning from other servers), but REPAIR should
be avoided as it currently replaces the datafile with a new one, which
is not signaled to the other servers.
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:
myisampack, and then create a MERGE to use these as one.
MERGE table on this could be much faster than using
the big table. (You can, of course, also use a RAID to get the same
kind of benefits.)
MERGE table for others. You can even have many
different MERGE tables active, with possible overlapping files.
MERGE file than trying to repair a really big file.
MERGE table uses the
index of the individual tables. It doesn't need to maintain an index of
its one. This makes MERGE table collections VERY fast to make or
remap. Note that you must specify the key definitions when you create
a MERGE table!.
MERGE table on them on demand.
This is much faster and will save a lot of disk space.
MERGE
over one table. There shouldn't be any really notable performance
impacts of doing this (only a couple of indirect calls and memcpy()
calls for each read).
The disadvantages with MERGE tables are:
MyISAM tables for a MERGE table.
REPLACE doesn't work.
MERGE tables uses more file descriptors. If you are using a
MERGE table that maps over 10 tables and 10 users are using this, you
are using 10*10 + 10 file descriptors. (10 datafiles for 10 users
and 10 shared index files.)
MERGE
storage engine will need to issue a read on all underlying tables to check
which one most closely matches the given key. If you then do a "read-next"
then the MERGE storage engine will need to search the read buffers
to find the next key. Only when one key buffer is used up, the storage engine
will need to read the next key block. This makes MERGE keys much slower
on eq_ref searches, but not much slower on ref searches.
See section 5.2.1 EXPLAIN Syntax (Get Information About a SELECT).
DROP TABLE,
ALTER TABLE,
DELETE FROM table_name without a WHERE clause,
REPAIR TABLE,
TRUNCATE TABLE,
OPTIMIZE TABLE, or
ANALYZE TABLE
on any of the table that is
mapped by a MERGE table that is "open". If you do this, the
MERGE table may still refer to the original table and you will
get unexpected results. The easiest way to get around this deficiency
is to issue the FLUSH TABLES command, ensuring no MERGE
tables remain "open".
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:
DROP the table and re-create it
ALTER TABLE table_name UNION(...)
FLUSH TABLE on the
MERGE table and all underlying tables to force the storage engine to
read the new definition file.
MERGE Table Problems
The following are the known problems with MERGE tables:
MERGE table cannot maintain UNIQUE constraints over the
whole table. When you do INSERT, the data goes into the first or
last table (according to INSERT_METHOD=xxx) and this MyISAM
table ensures that the data are unique, but it knows nothing about
others MyISAM tables.
DELETE FROM merge_table used without a WHERE
will only clear the mapping for the table, not delete everything in the
mapped tables.
RENAME TABLE on a table used in an active MERGE table may
corrupt the table. This will be fixed in MySQL 4.0.x.
MERGE doesn't check if the underlying
tables are of compatible types. If you use MERGE tables in this
fashion, you are very likely to run into strange problems.
ALTER TABLE to first add an UNIQUE index to a
table used in a MERGE table and then use ALTER TABLE to
add a normal index on the MERGE table, the key order will be
different for the tables if there was an old non-unique key in the
table. This is because ALTER TABLE puts UNIQUE keys before
normal keys to be able to detect duplicate keys as early as possible.
MERGE table efficiently and may
sometimes produce non-optimal joins. This will be fixed in MySQL 4.0.x.
DROP TABLE on a table that is in use by a MERGE table will
not work on Windows because the MERGE storage engine does the table mapping
hidden from the upper layer of MySQL. Because Windows doesn't allow you
to drop files that are open, you first must flush all MERGE
tables (with FLUSH TABLES) or drop the MERGE table before
dropping the table. We will fix this at the same time we introduce
VIEWs.
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:
ISAM tables are not binary portable across OS/Platforms.
pack_isam rather than with myisampack.
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.
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:
MAX_ROWS in the CREATE statement
to ensure that you accidentally do not use all memory.
= and <=> (but are VERY fast).
HEAP tables can only use whole keys to search for a row; compare this
to MyISAM tables where any prefix of the key can be used to find rows.
HEAP tables use a fixed record length format.
HEAP doesn't support BLOB/TEXT columns.
HEAP doesn't support AUTO_INCREMENT columns.
HEAP doesn't support an index on a NULL
column.
HEAP table (this isn't common for
hashed tables).
HEAP tables are shared between all clients (just like any other
table).
ORDER BY).
HEAP tables are allocated in small blocks. The tables
are 100% dynamic (on inserting). No overflow areas and no extra key
space are needed. Deleted rows are put in a linked list and are
reused when you insert new data into the table.
HEAP tables that you want to use at
the same time.
DELETE FROM heap_table,
TRUNCATE heap_table or DROP TABLE heap_table.
MyISAM
table to a HEAP table.
HEAP tables bigger than max_heap_table_size.
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.
InnoDB Tables
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.
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:
SET
command of MS-DOS to print the value of WINDIR.
Where to specify options in Unix? On Unix `mysqld' reads options from the following files, if they exist, in the following order:
--defaults-extra-file=....
`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.
|
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
If InnoDB prints an operating system error in a file operation, usually the problem is one of the following:
innodb_data_home_dir
or innodb_data_file_path.
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.
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.
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.
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.
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.
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.
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.
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.
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:
READ UNCOMMITTED This is also called
'dirty read': non-locking SELECTs are performed
so that we do not look at a possible earlier version of a record;
thus they are not 'consistent' reads under this isolation level;
otherwise this level works like READ COMMITTED.
READ COMMITTED
Somewhat Oracle-like isolation level.
All SELECT ... FOR UPDATE and
SELECT ... LOCK IN SHARE MODE
statements
only lock the index records, NOT the gaps before them, and
thus allow free inserting of new records next to locked
records.
UPDATE and DELETE which use
a unique index with a unique search condition,
only lock the index record found, not the gap before it.
But still in range type
UPDATE and DELETE InnoDB
must set next-key or gap locks and block insertions
by other users to the
gaps covered by the range. This is necessary
since 'phantom rows' have to be blocked for MySQL
replication and recovery to work.
Consistent reads behave like in
Oracle: each consistent read, even within the same
transaction, sets and reads its own fresh snapshot.
REPEATABLE READ This is the default isolation level of
InnoDB.
SELECT ... FOR UPDATE, SELECT ... LOCK IN SHARE MODE,
UPDATE, and DELETE
which use
a unique index with a unique search condition,
only lock the index record found, not the gap before it.
Otherwise these operations employ next-key locking, locking
the index range scanned with next-key or gap locks, and
block new insertions by other users.
In consistent reads there is an important difference
from the previous isolation level: in this level
all consistent reads within the same transaction read the
same snapshot established by the first read. This convention
means that if you issue several plain SELECTs
within the same transaction, these SELECTs are
consistent also with respect to each other.
SERIALIZABLE This level is like
the previous one, but
all plain SELECTs are implicitly converted to
SELECT ... LOCK IN SHARE MODE.
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.
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.
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.
SELECT ... FROM ... : this is a consistent read, reading a
snapshot of the database and setting no locks.
SELECT ... FROM ... LOCK IN SHARE MODE : sets shared next-key locks
on all index records the read encounters.
SELECT ... FROM ... FOR UPDATE : sets exclusive next-key locks
on all index records the read encounters.
INSERT INTO ... VALUES (...) : sets an exclusive lock
on the inserted row; note that this lock is not a next-key lock
and does not prevent other users from inserting to the gap before the
inserted row. If a duplicate key error occurs, sets a shared lock
on the duplicate index record.
INSERT INTO T SELECT ... FROM S WHERE ... sets an exclusive
(non-next-key) lock on each row inserted into T. Does
the search on S as a consistent read, but sets shared next-key
locks on S if the MySQL logging is on. InnoDB has to set
locks in the latter case because in roll-forward recovery from a
backup every SQL statement has to be executed in exactly the same
way as it was done originally.
CREATE TABLE ... SELECT ... performs the SELECT
as a consistent read or with shared locks, like in the previous
item.
REPLACE is done like an insert if there is no collision
on a unique key. Otherwise, an exclusive next-key lock is placed
on the row which has to be updated.
UPDATE ... SET ... WHERE ... : sets an exclusive next-key
lock on every record the search encounters.
DELETE FROM ... WHERE ... : sets an exclusive next-key
lock on every record the search encounters.
FOREIGN KEY constraint is defined on a table,
any insert, update, or delete which requires checking of the constraint
condition sets shared record level locks on the records it
looks at to check the constraint. Also in the case where the
constraint fails, InnoDB sets these locks.
LOCK TABLES ... : sets table locks. In the implementation
the MySQL layer of code sets these locks. The automatic deadlock detection
of InnoDB cannot detect deadlocks where such table locks are involved:
see the following section.
Also, since MySQL does know about row level locks,
it is possible that you
get a table lock on a table where another user currently has row level
locks. But that does not put transaction integerity into danger.
See section 7.5.13 Restrictions on InnoDB Tables.
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.
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;
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:
SHOW INNODB STATUS in MySQL versions >= 3.23.52 and >= 4.0.3
to determine the cause of the latest deadlock. That can help you to tune
your application to avoid deadlocks.
SELECT ... FOR UPDATE
or ... LOCK IN SHARE MODE, try using a lower isolation
level READ COMMITTED.
EXPLAIN SELECT to determine that MySQL picks
appropriate indexes for your queries.
SELECT to return data
from an old snapshot, do not add the clause FOR UPDATE
or LOCK IN SHARE MODE to it. Using READ COMMITTED
isolation level is good here, because each consistent read
within the same transaction reads from its own fresh snapshot.
LOCK TABLES t1 WRITE, t2 READ, ... ;
[do something with tables t1 and t2 here]; UNLOCK TABLES.
Table level locks make you transactions to queue nicely,
and deadlocks are avoided. Note that LOCK TABLES
implicitly starts a transaction, just like the command BEGIN,
and UNLOCK TABLES implicitly ends the transaction in a COMMIT.
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.
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:
UNIV_SYNC_DEBUG
defined in `univ.i'.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
'Table is full' error
and InnoDB rolls back the SQL statement.
INSERT INTO ... SELECT ....
This will probably change so that the SQL statement will be rolled
back if you have not specified the IGNORE option in your
statement.
mysql_install_db script.
SHOW TABLE STATUS does not give accurate statistics
on InnoDB tables, except for the physical size reserved by the table.
The row count is only a rough estimate used in SQL optimisation.
CREATE TABLE T (A CHAR(20), B INT, UNIQUE (A(5))) TYPE = InnoDB;If you create a non-unique index on a prefix of a column, InnoDB will create an index over the whole column.
INSERT DELAYED is not supported for InnoDB tables.
LOCK TABLES operation does not know of InnoDB
row level locks set in already completed SQL statements: this means that
you can get a table lock on a table even if there still exist transactions
of other users which have row level locks on the same table. Thus
your operations on the table may have to wait if they collide with
these locks of other users. Also a deadlock is possible. However,
this does not endanger transaction integrity, because the row level
locks set by InnoDB will always take care of the integrity.
Also, a table lock prevents other transactions from acquiring more
row level locks (in a conflicting lock mode) on the table.
BLOB or TEXT column.
DELETE FROM TABLE does not regenerate the table but instead
deletes all rows, one by one, which is not that fast. In future versions
of MySQL you can use TRUNCATE which is fast.
HANDLER SQL commands now work also for InnoDB
type tables. InnoDB does the HANDLER reads always as
consistent reads. HANDLER is a direct access path to read
individual indexes of tables. In some cases HANDLER can be
used as a substitute of server-side cursors.
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
BDB or BerkeleyDB TablesBDB 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.
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.
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.
BDB tables:BDB storage engine maintains
log files. For maximum performance you should place these on another disk
than your databases by using the --bdb-logdir option.
BDB log
file is started, and removes any log files that are not needed for
current transactions. One can also run FLUSH LOGS at any time
to checkpoint the Berkeley DB tables.
For disaster recovery, one should use table backups plus
MySQL's binary log. See section 4.4.1 Database Backups.
Warning: If you delete old log files that are in use, BDB will
not be able to do recovery at all and you may lose data if something
goes wrong.
PRIMARY KEY in each BDB table to be
able to refer to previously read rows. If you don't create one,
MySQL will create an maintain a hidden PRIMARY KEY for
you. The hidden key has a length of 5 bytes and is incremented for each
insert attempt.
BDB table are part of the same index or
part of the primary key, then MySQL can execute the query
without having to access the actual row. In a MyISAM table the
above holds only if the columns are part of the same index.
PRIMARY KEY will be faster than any other key, as the
PRIMARY KEY is stored together with the row data. As the other keys are
stored as the key data + the PRIMARY KEY, it's important to keep the
PRIMARY KEY as short as possible to save disk and get better speed.
LOCK TABLES works on BDB tables as with other tables. If
you don't use LOCK TABLE, MySQL will issue an internal
multiple-write lock on the table to ensure that the table will be
properly locked if another thread issues a table lock.
BDB tables is done on page level.
SELECT COUNT(*) FROM table_name is slow as BDB tables doesn't
maintain a count of the number of rows in the table.
MyISAM tables as the data in
BDB tables stored in B-trees and not in a separate datafile.
BDB table may make an automatic rollback and any
read may fail with a deadlock error.
MyISAM
tables. In other words, the key information will take a little more
space in BDB tables compared to MyISAM tables.
BDB table to allow you to insert new rows in
the middle of the key tree. This makes BDB tables somewhat larger than
MyISAM tables.
BDB table. If you don't
issue a lot of DELETE or ROLLBACK statements, this number
should be accurate enough for the MySQL optimiser, but as MySQL
only stores the number on close, it may be incorrect if MySQL dies
unexpectedly. It should not be fatal even if this number is not 100%
correct. One can update the number of rows by executing ANALYZE
TABLE or OPTIMIZE TABLE. See section 4.5.2 ANALYZE TABLE Syntax . See section 4.5.1 OPTIMIZE TABLE Syntax.
BDB table, you will get an error
(probably error 28) and the transaction should roll back. This is in
contrast with MyISAM and ISAM tables where mysqld will
wait for enough free disk before continuing.
BDB in the near future:BDB tables at the same time. If you are
going to use BDB tables, you should not have a very big table cache
(like >256) and you should use --no-auto-rehash with the mysql
client. We plan to partly fix this in 4.0.
SHOW TABLE STATUS doesn't yet provide that much information for
BDB
tables.
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.
BDB Tables
Here follows the restrictions you have when using BDB tables:
BDB tables store in the `.db' file the path to the file as it was
created.
(This was done to be able to detect locks in a multi-user environment that
supports symlinks).
The effect of this is that BDB tables are not movable between directories!
BDB tables, you have to either use
mysqldump or take a backup of all table_name.db files and
the BDB log files. The BDB log files are the files in the base
data directory named log.XXXXXXXXXX (ten digits);
The BDB storage engine stores unfinished transactions in the log files
and requires these logs to be present when mysqld starts.
BDB Tableshostname.err log when
starting mysqld:
bdb: Ignoring log file: .../log.XXXXXXXXXX: unsupported log version #it means that the new
BDB version doesn't support the old log
file format. In this case you have to delete all BDB logs
from your database directory (the files with names that have the format
log.XXXXXXXXXX) and restart mysqld. We would also
recommend you to do a mysqldump --opt of your old BDB
tables, delete the old tables, and restore the dump.
001119 23:43:56 bdb: Missing log fileid entry
001119 23:43:56 bdb: txn_abort: Log undo failed for LSN:
1 3644744: Invalid
This is not fatal but we don't recommend that you delete tables if you are
not in auto-commit mode, until this problem is fixed (the fix is
not trivial).
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.
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.
MYSQL
MYSQL_RES
SELECT, SHOW, DESCRIBE, EXPLAIN). The
information returned from a query is called the result set in the
remainder of this section.
MYSQL_ROW
mysql_fetch_row().
MYSQL_FIELD
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
mysql_field_seek().) Offsets are field numbers
within a row, beginning at zero.
my_ulonglong
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
char * table
table value is an empty string.
char * def
mysql_list_fields().
enum enum_field_types type
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
|
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
unsigned int max_length
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
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)
|
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 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.
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().
mysql_affected_rows()
my_ulonglong mysql_affected_rows(MYSQL *mysql)
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().
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().
None.
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.
mysql_change_user()
my_bool mysql_change_user(MYSQL *mysql, const char *user, const
char *password, const char *db)
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.
Zero for success. Non-zero if an error occurred.
The same that you can get from mysql_real_connect().
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
ER_UNKNOWN_COM_ERROR
ER_ACCESS_DENIED_ERROR
ER_BAD_DB_ERROR
ER_DBACCESS_DENIED_ERROR
ER_WRONG_DB_NAME
if (mysql_change_user(&mysql, "user", "password", "new_database"))
{
fprintf(stderr, "Failed to change user. Error: %s\n",
mysql_error(&mysql));
}
mysql_character_set_name()
const char *mysql_character_set_name(MYSQL *mysql)
Returns the default character set for the current connection.
The default character set
None.
mysql_close()
void mysql_close(MYSQL *mysql)
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().
None.
None.
mysql_connect()
MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)
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.)
Same as for mysql_real_connect().
Same as for mysql_real_connect().
mysql_create_db()
int mysql_create_db(MYSQL *mysql, const char *db)
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.
Zero if the database was created successfully. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
if(mysql_create_db(&mysql, "my_database"))
{
fprintf(stderr, "Failed to create new database. Error: %s\n",
mysql_error(&mysql));
}
mysql_data_seek()
void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset)
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.
None.
None.
mysql_debug()
void mysql_debug(const char *debug)
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.
None.
None.
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");
mysql_drop_db()
int mysql_drop_db(MYSQL *mysql, const char *db)
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.
Zero if the database was dropped successfully. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
if(mysql_drop_db(&mysql, "my_database"))
fprintf(stderr, "Failed to drop the database: Error: %s\n",
mysql_error(&mysql));
mysql_dump_debug_info()
int mysql_dump_debug_info(MYSQL *mysql)
Instructs the server to write some debug information to the log. For
this to work, the connected user must have the SUPER privilege.
Zero if the command was successful. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_eof()
my_bool mysql_eof(MYSQL_RES *result)
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.)
Zero if no error occurred. Non-zero if the end of the result set has been reached.
None.
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));
}
mysql_errno()
unsigned int mysql_errno(MYSQL *mysql)
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'.
An error code value. Zero if no error occurred.
None.
mysql_error()
char *mysql_error(MYSQL *mysql)
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.
A character string that describes the error. An empty string if no error occurred.
None.
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.
mysql_fetch_field()
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)
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.
The MYSQL_FIELD structure for the current column. NULL
if no columns are left.
None.
MYSQL_FIELD *field;
while((field = mysql_fetch_field(result)))
{
printf("field name %s\n", field->name);
}
mysql_fetch_fields()
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)
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.
An array of MYSQL_FIELD structures for all columns of a result set.
None.
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);
}
mysql_fetch_field_direct()
MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int fieldnr)
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.
The MYSQL_FIELD structure for the specified column.
None.
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);
}
mysql_fetch_lengths()
unsigned long *mysql_fetch_lengths(MYSQL_RES *result)
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().
An array of unsigned long integers representing the size of each column (not
including any terminating null characters).
NULL if an error occurred.
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.
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]);
}
}
mysql_fetch_row()
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
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.
A MYSQL_ROW structure for the next row. NULL if
there are no more rows to retrieve or if an error occurred.
CR_SERVER_LOST
CR_UNKNOWN_ERROR
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");
}
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.
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?.
An unsigned integer representing the number of fields in a result set.
None.
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.
mysql_field_seek()
MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset)
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.
The previous value of the field cursor.
None.
mysql_field_tell()
MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result)
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().
The current offset of the field cursor.
None.
mysql_free_result()
void mysql_free_result(MYSQL_RES *result)
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().
None.
None.
mysql_get_client_info()
char *mysql_get_client_info(void)
Returns a string that represents the client library version.
A character string that represents the MySQL client library version.
None.
mysql_get_server_version()
unsigned long mysql_get_server_version(MYSQL *mysql)
Returns version number of server as an integer (new in 4.1).
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.
None.
mysql_get_host_info()
char *mysql_get_host_info(MYSQL *mysql)
Returns a string describing the type of connection in use, including the server host name.
A character string representing the server host name and the connection type.
None.
mysql_get_proto_info()
unsigned int mysql_get_proto_info(MYSQL *mysql)
Returns the protocol version used by current connection.
An unsigned integer representing the protocol version used by the current connection.
None.
mysql_get_server_info()
char *mysql_get_server_info(MYSQL *mysql)
Returns a string that represents the server version number.
A character string that represents the server version number.
None.
mysql_info()
char *mysql_info(MYSQL *mysql)
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 ...
Records: 100 Duplicates: 0 Warnings: 0
INSERT INTO ... VALUES (...),(...),(...)...
Records: 3 Duplicates: 0 Warnings: 0
LOAD DATA INFILE ...
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
ALTER TABLE
Records: 3 Duplicates: 0 Warnings: 0
UPDATE
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.
A character string representing additional information about the most
recently executed query. NULL if no information is available for the
query.
None.
mysql_init()
MYSQL *mysql_init(MYSQL *mysql)
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.
An initialised MYSQL* handle. NULL if there was
insufficient memory to allocate a new object.
In case of insufficient memory, NULL is returned.
mysql_insert_id()
my_ulonglong mysql_insert_id(MYSQL *mysql)
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.
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.
None.
mysql_kill()
int mysql_kill(MYSQL *mysql, unsigned long pid)
Asks the server to kill the thread specified by pid.
Zero for success. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_list_dbs()
MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild)
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().
A MYSQL_RES result set for success. NULL if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_list_fields()
MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
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().
A MYSQL_RES result set for success. NULL if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_list_processes()
MYSQL_RES *mysql_list_processes(MYSQL *mysql)
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().
A MYSQL_RES result set for success. NULL if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_list_tables()
MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild)
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().
A MYSQL_RES result set for success. NULL if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
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.
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?.
An unsigned integer representing the number of fields in a result set.
None.
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.
mysql_num_rows()
my_ulonglong mysql_num_rows(MYSQL_RES *result)
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.
The number of rows in the result set.
None.
mysql_options()
int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)
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.
Zero for success. Non-zero if you used an unknown option.
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.
mysql_ping()
int mysql_ping(MYSQL *mysql)
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.
Zero if the server is alive. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_UNKNOWN_ERROR
mysql_query()
int mysql_query(MYSQL *mysql, const char *query)
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().
Zero if the query was successful. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
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)
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:
MYSQL
structure. Before calling mysql_real_connect() you must call
mysql_init() to initialise the MYSQL structure. You can
change a lot of connect options with the mysql_options()
call. See section 8.1.3.163 mysql_options().
host may be either a hostname or an IP address. If
host is NULL or the string "localhost", a connection to
the local host is assumed. If the OS supports sockets (Unix) or named pipes
(Windows), they are used instead of TCP/IP to connect to the server.
user parameter contains the user's MySQL login ID. If
user is NULL, the current user is assumed. Under Unix, this is
the current login name. Under Windows ODBC, the current user name must be
specified explicitly.
See section 8.2.2 How to Fill in the Various Fields in the ODBC Administrator Program.
passwd parameter contains the password for user. If
passwd is NULL, only entries in the user table for the
user that have a blank (empty) password field will be checked for a match. This
allows the database administrator to set up the MySQL privilege
system in such a way that users get different privileges depending on whether
or not they have specified a password.
Note: Do not attempt to encrypt the password before calling
mysql_real_connect(); password encryption is handled automatically by
the client API.
db is the database name.
If db is not NULL, the connection will set the default
database to this value.
port is not 0, the value will be used as the port number
for the TCP/IP connection. Note that the host parameter
determines the type of the connection.
unix_socket is not NULL, the string specifies the
socket or named pipe that should be used. Note that the host
parameter determines the type of the connection.
client_flag is usually 0, but can be set to a combination
of the following flags in very special circumstances:
| Flag name | Flag description |
CLIENT_COMPRESS | Use compression protocol. |
CLIENT_FOUND_ROWS | Return the number of found (matched) rows, not the number of affected rows. |
CLIENT_IGNORE_SPACE | Allow spaces after function names. Makes all functions names reserved words. |
CLIENT_INTERACTIVE | Allow interactive_timeout seconds (instead of wait_timeout seconds) of inactivity before closing the connection.
|
CLIENT_NO_SCHEMA | Don't allow the db_name.tbl_name.col_name syntax. This is for ODBC. It causes the parser to generate an error if you use that syntax, which is useful for trapping bugs in some ODBC programs.
|
CLIENT_ODBC | The client is an ODBC client. This changes mysqld to be more ODBC-friendly.
|
CLIENT_SSL | Use SSL (encrypted protocol). |
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.
CR_CONN_HOST_ERROR
CR_CONNECTION_ERROR
CR_IPSOCK_ERROR
CR_OUT_OF_MEMORY
CR_SOCKET_CREATE_ERROR
CR_UNKNOWN_HOST
CR_VERSION_ERROR
--old-protocol option.
CR_NAMEDPIPEOPEN_ERROR
CR_NAMEDPIPEWAIT_ERROR
CR_NAMEDPIPESETSTATE_ERROR
CR_SERVER_LOST
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.
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.
mysql_real_escape_string()
unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length)
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.
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.
The length of the value placed into to, not including the
terminating null character.
None.
mysql_real_query()
int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)
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().
Zero if the query was successful. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_reload()
int mysql_reload(MYSQL *mysql)
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.
Zero for success. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_row_seek()
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset)
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.
The previous value of the row cursor. This value may be passed to a
subsequent call to mysql_row_seek().
None.
mysql_row_tell()
MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result)
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().
The current offset of the row cursor.
None.
mysql_select_db()
int mysql_select_db(MYSQL *mysql, const char *db)
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.
Zero for success. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_shutdown()
int mysql_shutdown(MYSQL *mysql)
Asks the database server to shut down. The connected user must have
SHUTDOWN privileges.
Zero for success. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_stat()
char *mysql_stat(MYSQL *mysql)
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.
A character string describing the server status. NULL if an
error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_store_result()
MYSQL_RES *mysql_store_result(MYSQL *mysql)
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?.
A MYSQL_RES result structure with the results. NULL if
an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_thread_id()
unsigned long mysql_thread_id(MYSQL *mysql)
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.
The thread ID of the current connection.
None.
mysql_use_result()
MYSQL_RES *mysql_use_result(MYSQL *mysql)
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.
A MYSQL_RES result structure. NULL if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_commit()
my_bool mysql_commit(MYSQL *mysql)
Commits the current transaction. Available from MySQL 4.1
Zero if successful. Non-zero if an error occured.
None
mysql_rollback()
my_bool mysql_rollback(MYSQL *mysql)
Rollbacks the current transaction. Available from MySQL 4.1
Zero if successful. Non-zero if an error occured.
None.
mysql_autocommit()
my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)
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
Zero if successful. Non-zero if an error occured
None.
mysql_more_results()
my_bool mysql_more_results(MYSQL *mysql)
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
TRUE if more results exists. FALSE if no more results exists.
None.
mysql_next_result()
int mysql_next_result(MYSQL *mysql)
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
Zero if successful. Non-zero if an error occured
None.
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.
Prepared statements mainly uses the following two MYSQL_STMT and
MYSQL_BIND structures:
MYSQL_STMT
mysql_prepare().
One connection can have 'n' statement handles, and the limit depends up on
the system resources.
MYSQL_BIND
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]
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]
unsigned long buffer_length [input]
*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]
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]
MYSQL_TIME
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) |
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.
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.
You need to use the following functions when you want to prepare and execute the queries.
mysql_prepare()
MYSQL_STMT * mysql_prepare(MYSQL *mysql, const char *query, unsigned
long length)
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().
MYSQL_STMT if the prepare was successful. NULL if an error
occured.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
If the prepare is not successful, i.e. when mysql_prepare() returned a
NULL statement, errors can be obtained by calling mysql_error().
For the usage of mysql_prepare() refer to the Example from
section 8.1.7.21 mysql_execute().
mysql_param_count()
unsigned int mysql_param_count(MYSQL_STMT *stmt)
Returns the number of parameter markers present from the prepared query.
An unsigned integer representing the number of parameters in a statement.
None
For the usage of mysql_param_count() refer to the Example from
section 8.1.7.21 mysql_execute().
mysql_prepare_result()
MYSQL_RES *mysql_prepare_result(MYSQL_STMT *stmt)
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:
A MYSQL_RES result structure. NULL if no meta information exists from
the prepared query.
CR_OUT_OF_MEMORY
CR_UNKNOWN_ERROR
For the usage of mysql_prepare_result() refer to the Example from
section 8.1.7.40 mysql_fetch()
mysql_bind_param()
int mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
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:
Zero if the bind was successful. Non-zero if an error occured.
CR_NO_PREPARE_STMT
CR_NO_PARAMETERS_EXISTS
CR_INVALID_BUFFER_USE
CR_UNSUPPORTED_PARAM_TYPE
CR_OUT_OF_MEMOR
CR_UNKNOWN_ERROR
For the usage of mysql_bind_param() refer to the Example from
section 8.1.7.21 mysql_execute().
mysql_execute()
int mysql_execute(MYSQL_STMT *stmt.
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().
|
CR_NO_PREPARE_QUERY
CR_ALL_PARAMS_NOT_BOUND
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
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!!!");
mysql_stmt_affected_rows()
ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)
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().
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().
None.
For the usage of mysql_stmt_affected_rows() refer to the Example
from section 8.1.7.21 mysql_execute().
mysql_bind_result()
my_bool mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
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:
Zero if the bind was successful. Non-zero if an error occured.
CR_NO_PREPARE_STMT
CR_UNSUPPORTED_PARAM_TYPE
CR_OUT_OF_MEMOR
CR_UNKNOWN_ERROR
For the usage of mysql_bind_result() refer to the Example from
section 8.1.7.40 mysql_fetch()
mysql_stmt_store_result()
int mysql_stmt_store_result(MYSQL_STMT *stmt)
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().
Zero if the results are buffered successfully or Non Zero in case of an error.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_fetch()
int mysql_fetch(MYSQL_STMT *stmt)
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'.
| 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 |
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
CR_UNSUPPORTED_PARAM_TYPE
mysql_bind_result().
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);
}
mysql_send_long_data()
int mysql_send_long_data(MYSQL_STMT *stmt, unsigned int
parameter_number, const char *data, ulong length)
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.
Zero if the data is sent successfully to server. Non-zero if an error occured.
CR_INVALID_PARAMETER_NO
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_OUT_OF_MEMOR
CR_UNKNOWN_ERROR
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'.
mysql_stmt_close()
my_bool mysql_stmt_close(MYSQL_STMT *)
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.
Zero if the statement was freed successfully. Non-zero if an error occured.
CR_SERVER_GONE_ERROR
CR_UNKNOWN_ERROR
For the usage of mysql_stmt_close() refer to the Example from
section 8.1.7.21 mysql_execute().
mysql_stmt_errno()
unsigned int mysql_stmt_errno(MYSQL_STMT *stmt)
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
An error code value. Zero if no error occured.
None
mysql_stmt_error()
char *mysql_stmt_error(MYSQL_STMT *stmt)
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.
A character string that describes the error. An empry string if no error occured.
None
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 */
}
}
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);
..
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.
my_init()
void my_init(void)
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().
None.
mysql_thread_init()
my_bool mysql_thread_init(void)
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().
None.
mysql_thread_end()
void mysql_thread_end(void)
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.
None.
mysql_thread_safe()
unsigned int mysql_thread_safe(void)
This function indicates whether the client is compiled as thread-safe.
1 is the client is thread-safe, 0 otherwise.
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.
mysql_server_init()
int mysql_server_init(int argc, char **argv, char **groups)
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.
#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;
}
0 if okay, 1 if an error occurred.
mysql_server_end()
void mysql_server_end(void)
This function must be called once in the program after all other MySQL functions. It shuts down the embedded server.
None.
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:
malloc() failure (for example, if the result set was too
large).
INSERT,
UPDATE, or DELETE).
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().
In addition to the result set returned by a query, you can also get the following information:
mysql_affected_rows() returns the number of rows affected by the last
query when doing an INSERT, UPDATE, or DELETE. An
exception is that if DELETE is used without a WHERE clause, the
table is re-created empty, which is much faster! In this case,
mysql_affected_rows() returns zero for the number of records
affected.
mysql_num_rows() returns the number of rows in a result set. With
mysql_store_result(), mysql_num_rows() may be called as soon as
mysql_store_result() returns. With mysql_use_result(),
mysql_num_rows() may be called only after you have fetched all the
rows with mysql_fetch_row().
mysql_insert_id() returns the ID generated by the last
query that inserted a row into a table with an AUTO_INCREMENT index.
See section 8.1.3.130 mysql_insert_id().
LOAD DATA INFILE ..., INSERT INTO
... SELECT ..., UPDATE) return additional information. The result is
returned by mysql_info(). See the description for mysql_info()
for the format of the string that it returns. mysql_info() returns a
NULL pointer if there is no additional information.
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
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.
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.
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:
mysql_query() and mysql_store_result() no other thread is using
the same connection.
mysql_store_result().
mysql_use_result, you have to ensure that no other thread
is using the same connection until the result set is closed.
However, it really is best for threaded clients that share the same
connection to use mysql_store_result().
mysql_query() and
mysql_store_result() call combination. Once
mysql_store_result() is ready, the lock can be released and other
threads may query the same connection.
pthread_mutex_lock() and pthread_mutex_unlock() to
establish and release a mutex lock.
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:
my_init() at the start of your program if it calls
any other MySQL function before calling mysql_real_connect().
mysql_thread_init() in the thread handler before calling
any MySQL function.
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.
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().
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.
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.
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.
[server] section. These will be read by
both MySQL versions.
[mysqld] section.
[embedded] section.
[ApplicationName_SERVER]
section.
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
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.
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.
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.
MyODBC on the Windows machine.
GRANT command. See section 4.3.1 GRANT and REVOKE Syntax.
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.
There are three possibilities for specifying the server name on Windows95:
ip hostnameFor example:
194.216.84.21 my_hostname
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().
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.
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.
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:
Microsoft Data Access
Components) from http://www.microsoft.com/data/. This will fix
the following bug in Access: when you export data to MySQL, the
table and column names aren't specified. Another way to around this bug
is to upgrade to MyODBC Version 2.50.33 and MySQL Version
3.23.x, which together provide a workaround for this bug!
You should also get and apply the Microsoft Jet 4.0 Service Pack 5 (SP5)
which can be found here
http://support.microsoft.com/support/kb/articles/Q 239/1/14.ASP.
This will fix some cases where columns are marked as #deleted#
in Access.
Note that if you are using MySQL Version 3.22, you must to apply the
MDAC patch and use MyODBC 2.50.32 or 2.50.34 and above to go around
this problem.
Return matching rows. For Access 2.0, you should additionally enable
Simulate ODBC 1.0.
TIMESTAMP(14) or simple TIMESTAMP
is recommended instead of other TIMESTAMP(X) variations.
#DELETED#.
DOUBLE float fields. Access fails when comparing with
single floats. The symptom usually is that new or updated rows may show
up as #DELETED# or that you can't find or update rows.
BIGINT as
one of the column, then the results will be displayed as #DELETED. The
work around solution is:
TIMESTAMP as the data type, preferably
TIMESTAMP(14).
'Change BIGINT columns to INT' in connection options dialog in
ODBC DSN Administrator
#DELETED#, but newly
added/updated records will be displayed properly.
Another user has changed your data after
adding a TIMESTAMP column, the following trick may help you:
Don't use table data sheet view. Create instead a form with the
fields you want, and use that form data sheet view. You should
set the DefaultValue property for the TIMESTAMP column to
NOW(). It may be a good idea to hide the TIMESTAMP column
from view so your users are not confused.
"Query|SQLSpecific|Pass-Through" from the Access menu.
BLOB columns as OLE OBJECTS. If
you want to have MEMO columns instead, you should change the
column to TEXT with ALTER TABLE.
DATE columns properly. If you have a problem
with these, change the columns to DATETIME.
BYTE, Access will try
to export this as TINYINT instead of TINYINT UNSIGNED.
This will give you problems if you have values > 127 in the column!
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.CloseAnother workaround is to use a
SELECT COUNT(*) statement
for a similar query to get the correct row count.
Return matching rows.
Don't optimize column widths and Return matching rows.
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!
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.
VARCHAR rather than ENUM, as
it exports the latter in a manner that causes MySQL grief.
CONCAT() function. For example:
select CONCAT(rise_time), CONCAT(set_time)
from sunrise_sunset;
Values retrieved as strings this way should be correctly recognised
as time values by Excel97.
The purpose of CONCAT() in this example is to fool ODBC into thinking
the column is of ``string type''. Without the CONCAT(), ODBC knows the
column is of time type, and Excel does not understand that.
Note that this is a bug in Excel, because it automatically converts a
string to a time. This would be great if the source was a text file, but
is plain stupid when the source is an ODBC connection that reports
exact types for each column.
MyODBC driver and the Add-in Microsoft Query help.
For example, create a db with a table containing 2 columns of text:
mysql client command-line tool.
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);
Return matching rows.
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.
[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.
Don't optimize column widths.
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;
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:
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).
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!
There are 2 supported JDBC drivers for MySQL:
MySQL Connector/J from MySQL AB, implemented in 100% native Java.
This product was formerly known as the mm.mysql driver.
You can download MySQL Connector/J from
http://www.mysql.com/products/connector-j/.
For documentation, consult any JDBC documentation, plus each driver's own documentation for MySQL-specific features.
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/).
-lz last when linking
with -lmysqlclient.
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.
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/mysqlshell>perldoc mysql
DBI InterfacePortable 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
$sth
$rc
$rv
Portable DBI Methods
connect($data_source, $username, $password)
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
mysql_read_default_group=group_name
[client] group. By specifying the mysql_read_default_group
option, the default group becomes the [group_name] group.
mysql_compression=1
mysql_socket=/path/to/socket
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
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)
($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
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)
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)
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
while(@row = $sth->fetchrow_array) {
print qw($row[0]\t$row[1]\t$row[2]\n);
}
fetchrow_arrayref
while($row_ref = $sth->fetchrow_arrayref) {
print qw($row_ref->[0]\t$row_ref->[1]\t$row_ref->[2]\n);
}
fetchrow_hashref
while($hash_ref = $sth->fetchrow_hashref) {
print qw($hash_ref->{firstname}\t$hash_ref->{lastname}\t\
$hash_ref->{title}\n);
}
fetchall_arrayref
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
$rc = $sth->finish;
rows
SELECT execute
statement. Example:
$rv = $sth->rows;
NULLABLE
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
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)
'localhost'.
Example:
@dbs = DBI->data_sources("mysql");
ChopBlanks
fetchrow_* methods will chop
leading and trailing blanks from the returned values.
Example:
$sth->{'ChopBlanks'} =1;
trace($trace_level)
trace($trace_level, $trace_filename)
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
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
BLOB.
Example:
$keys = $sth->{is_blob};
is_key
$keys = $sth->{is_key};
is_num
$nums = $sth->{is_num};
is_pri_key
$pri_keys = $sth->{is_pri_key};
is_not_null
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
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
$names = $sth->{NAME};
table
$tables = $sth->{table};
type
$types = $sth->{type};
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/.
MySQL Connector/C++ (or MySQL++) is the official MySQL API for C++. More
information can be found at http://www.mysql.com/products/mysql++/.
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.
mysql_init() with NULL as an argument, not a
pre-allocated MYSQL struct.
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/.
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/.
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.
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!
The MySQL server creates the following threads:
process_alarm() to force timeouts on connections
that have been idle too long.
mysqld is compiled with -DUSE_ALARM_THREAD, a dedicated
thread that handles alarms is created. This is only used on some systems where
there are problems with sigwait() or if one wants to use the
thr_alarm() code in ones application without a dedicated signal
handling thread.
--flush_time=# option, a dedicated thread is created
to flush all tables at the given interval.
INSERT DELAYED gets its
own thread.
--master-host, a slave replication thread will be
started to read and apply updates from the master.
mysqladmin processlist only shows the connection, INSERT DELAYED,
and replication threads.
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.
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.
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:
mysql-test/t/*.test
; terminated statements and is similar to the
input of mysql command-line client. A statement by default is a query
to be sent to MySQL server, unless it is recognised as internal
command (eg. sleep).
SELECT, SHOW,
EXPLAIN, etc., must be preceded with @/path/to/result/file. The
file must contain the expected results. An easy way to generate the result
file is to run mysqltest -r < t/test-case-name.test from
mysql-test directory, and then edit the generated result files, if
needed, to adjust them to the expected output. In that case, be very careful
about not adding or deleting any invisible characters - make sure to only
change the text and/or delete lines. If you have to insert a line, make sure
the fields are separated with a hard tab, and there is a hard tab at the end.
You may want to use od -c to make sure your text editor has not messed
anything up during edit. We, of course, hope that you will never have to edit
the output of mysqltest -r as you only have to do it when you find a
bug.
mysql-test/r directory and name them test_name.result. If the
test produces more than one result, you should use test_name.a.result,
test_name.b.result, etc.
--error error-number. The error number can be
a list of possible error numbers separated with ','.
source include/master-slave.inc;. To switch between
master and slave, use connection master; and connection slave;.
If you need to do something on an alternate connection, you can do
connection master1; for the master, and connection slave1; for
the slave.
let $1=1000;
while ($1)
{
# do your queries here
dec $1;
}
sleep command. It supports fractions
of a second, so you can do sleep 1.3;, for example, to sleep 1.3
seconds.
mysql-test/t/test_name-slave.opt. For
the master, put them in mysql-test/t/test_name-master.opt.
If your MySQL version doesn't pass the test suite you should do the following:
mysqlbug script
so that we can get information about your system and MySQL
version. See section 1.7.1.3 How to Report Bugs or Problems.
mysql-test-run, as well as
contents of all .reject files in mysql-test/r directory.
cd mysql-test mysql-test-run --local test-nameIf this fails, then you should configure MySQL with
--with-debug and run mysql-test-run with the
--debug option. If this also fails send the trace file
`var/tmp/master.trace' to ftp://support.mysql.com/pub/mysql/secret
so that we can examine it. Please remember to also include a full
description of your system, the version of the mysqld binary and how you
compiled it.
mysql-test-run with the --force option to
see if there is any other test that fails.
Result length mismatch or Result
content mismatch it means that the output of the test didn't match
exactly the expected output. This could be a bug in MySQL or
that your mysqld version produces slight different results under some
circumstances.
Failed test results are put in a file with the same base name as the
result file with the .reject extension. If your test case is
failing, you should do a diff on the two files. If you cannot see how
they are different, examine both with od -c and also check their
lengths.
mysql-test/var/log directory for hints of what went wrong.
mysql-test-run with the --gdb and/or --debug
options.
See section E.1.2 Creating Trace Files.
If you have not compiled MySQL for debugging you should probably
do that. Just specify the --with-debug options to configure!
See section 2.3 Installing a MySQL Source Distribution.
There are two ways to add new functions to MySQL:
CREATE FUNCTION and DROP FUNCTION statements.
See section 9.2.1 CREATE FUNCTION/DROP FUNCTION Syntax.
mysqld server and become
available on a permanent basis.
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().
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.
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)
| SQL type | C/C++ type |
STRING | char *
|
INTEGER | long long
|
REAL | double
|
xxx_init() (optional)
xxx(). It can be used to:
XXX().
REAL functions) the maximum number of decimals.
NULL.
xxx_deinit() (optional)
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)
xxx_add() (required)
When using aggregate UDF functions MySQL works the following way:
xxx_init() to let the aggregate function allocate the memory it
will need to store results.
GROUP BY expression.
xxx_reset() function.
xxx_add() function.
xxx() to get the result for the aggregate.
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().
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
1.34, 1.345, and 1.3, the default would be 3,
because 1.345 has 3 decimals.
unsigned int max_length
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
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.
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.
The args parameter points to a UDF_ARGS structure that has the
members listed here:
unsigned int arg_count
if (args->arg_count != 2)
{
strcpy(message,"XXX() requires two arguments");
return 1;
}
enum Item_result *arg_type
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:
STRING_RESULT is given as a string pointer plus a
length, to allow handling of binary data or data of arbitrary length. The
string contents are available as args->args[i] and the string length
is args->lengths[i]. You should not assume that strings are
null-terminated.
INT_RESULT, you must cast
args->args[i] to a long long value:
long long int_val; int_val = *((long long*) args->args[i]);
REAL_RESULT, you must cast
args->args[i] to a double value:
double real_val; real_val = *((double*) args->args[i]);
unsigned long *lengths
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).
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;
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:
metaphon() returns a metaphon string of the string argument.
This is something like a soundex string, but it's more tuned for English.
myfunc_double() returns the sum of the ASCII values of the
characters in its arguments, divided by the sum of the length of its arguments.
myfunc_int() returns the sum of the length of its arguments.
sequence([const int]) returns an sequence starting from the given
number or 1 if no number has been given.
lookup() returns the IP number for a hostname.
reverse_lookup() returns the hostname for an IP number.
The function may be called with a string "xxx.xxx.xxx.xxx" or
four numbers.
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.)
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:
sql_functions[] array.
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.
Item_num_func or
Item_str_func, depending on whether your function returns a number or a
string.
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().
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:
String *str argument provides a string buffer that may be
used to hold the result. (For more information about the String type,
take a look at the `sql_string.h' file.)
::str() function should return the string that holds the result or
(char*) 0 if the result is NULL.
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.
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:
max elements (default 256) is the maximum number of distinct values
analyse will notice per column. This is used by analyse to check if
the optimal column type should be of type ENUM.
max memory (default 8192) is the maximum memory analyse should
allocate per column while trying to find all distinct values.
SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])
For the moment, the only documentation for this is the source.
You can find all information about procedures by examining the following files:
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.
When you run into problems, the first thing you should do is to find out which program / piece of equipment is causing problems:
kbd_mode -a on it.
top, ps, taskmanager, or some similar program,
to check which program is taking all CPU or is locking the machine.
top, df, or a similar program if you are out of
memory, disk space, open files, or some other critical resource.
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:
top. Let the
program run for a while, it may be evaluating something heavy.
mysqld server that is causing problems, can you
do mysqladmin -u root ping or mysqladmin -u root processlist?
mysql, for example)
when you try to connect to the MySQL server?
Does the client jam? Do you get any output from the program?
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.
This section lists some errors that users frequently get. You will find descriptions of the errors, and how to solve the problem here.
Access denied Error
See section 4.2.11 Causes of Access denied Errors.
See section 4.2.6 How the Privilege System Works.
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:
hostname.err file. See section A.4.1 What To Do If MySQL Keeps Crashing.
mysqld and the involved tables where
checked with CHECK TABLE before you did the query, can you do
a test case for this? See section E.1.6 Making a Test Case If You Experience Table Corruption.
wait_timeout variable in the MySQL server ?
mysqladmin variables gives you the value of this
mysqld with --log and check if the
issued query appears in the log ?
See section 1.7.1.2 Asking Questions or Reporting Bugs.
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:
mysqld is not running.
mysqld uses the MIT-pthreads package. See section 2.2.5 Operating Systems Supported by MySQL. However,
not all MIT-pthreads versions support Unix sockets. On a system
without sockets support you must always specify the hostname explicitly
when connecting to the server. Try using this command to check the
connection to the server:
shell> mysqladmin -h `hostname` version
mysqld uses (default
`/tmp/mysqld.sock'). You might have a cron job that removes
the MySQL socket (for example, a job that removes old files
from the `/tmp' directory). You can always run mysqladmin
version and check that the socket mysqladmin is trying to use
really exists. The fix in this case is to change the cron job to
not remove `mysqld.sock' or to place the socket somewhere else.
See section A.4.5 How to Protect or Change the MySQL Socket File `/tmp/mysql.sock'.
mysqld server with
the --socket=/path/to/socket option. If you change the socket
pathname for the server, you must also notify the MySQL clients
about the new path. You can do this by providing the socket path
as an argument to the client. See section A.4.5 How to Protect or Change the MySQL Socket File `/tmp/mysql.sock'.
mysqld threads (for example, with the
mysql_zap script before you can start a new MySQL
server. See section A.4.1 What To Do If MySQL Keeps Crashing.
mysqld so that it uses a directory that you can access.
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 :
telnet your-host-name
tcp-ip-port-number and press Enter a couple of times. If there
is a MySQL server running on this port you should get a
responses that includes the version number of the running MySQL
server. If you get an error like telnet: Unable to connect to
remote host: Connection refused, then there is no server running on the
given port.
mysqld daemon on the local machine and check
the TCP/IP port that mysqld it's configured to use (variable port) with
mysqladmin variables.
mysqld server is not started with the
--skip-networking option.
Host '...' is blocked ErrorIf 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!
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.
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.
Out of memory ErrorIf 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).
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.
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:
mysql_close() before exit.
wait_timeout or
interactive_timeout without doing any requests.
See section 4.5.6.4 SHOW VARIABLES.
See section 4.5.6.4 SHOW VARIABLES.
When the above happens, the server variable Aborted_clients is
incremented.
The server variable Aborted_connects is incremented when:
connect_timeout seconds to get
a connect package.
See section 4.5.6.4 SHOW VARIABLES.
Note that the above could indicate that someone is trying to break into your database!
Other reasons for problems with Aborted clients / Aborted connections.
max_allowed_packet is too small or queries require more memory
than you have alloacated for mysqld. See section A.2.8 Packet too large Error.
The table is full ErrorThere is a couple of different cases when you can get this error:
tmp_table_size bytes.
To avoid this problem, you can use the -O tmp_table_size=# option
to make mysqld increase the temporary table size or use the SQL
option BIG_TABLES before you issue the problematic query.
See section 5.5.6 SET Syntax.
You can also start mysqld with the --big-tables option.
This is exactly the same as using BIG_TABLES for all queries.
In MySQL Version 3.23, in-memory temporary tables will automatically be
converted to a disk-based MyISAM table after the table size gets
bigger than tmp_table_size.
InnoDB tables and run out of room in the
InnoDB tablespace. In this case the solution is to extend the
InnoDB tablespace.
ISAM or MyISAM tables on an OS that only
supports files of 2G in size and you have hit this limit for the data
or index file.
MyISAM tables and the needed data or index size is
bigger than what MySQL has allocated pointers for. (If you don't specify
MAX_ROWS to CREATE TABLE MySQL will only allocate pointers
to hold 4G of data).
You can check the maximum data/index sizes by doing
SHOW TABLE STATUS FROM database LIKE 'table_name';or using
myisamchk -dv database/table_name.
If this is the problem, you can fix it by doing something like:
ALTER TABLE table_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;You only have to specify
AVG_ROW_LENGTH for tables with BLOB/TEXT
fields as in this case MySQL can't optimise the space required based
only on the number of rows.
Can't create/write to file ErrorIf 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
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.
Ignoring user ErrorIf 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:
mysqld with an old
user table.
You can check this by executing mysqlshow mysql user to see if
the password field is shorter than 16 characters. If so, you can correct this
condition by running the scripts/add_long_password script.
mysqld with the --old-protocol option.
Update the user in the user table with a new password or
restart mysqld with --old-protocol.
user table without using the
PASSWORD() function. Use mysql to update the user in the
user table with a new password. Make sure to use the PASSWORD()
function:
mysql> UPDATE user SET password=PASSWORD('your password')
-> WHERE user='XXX';
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.
Can't initialize character set xxx errorIf you get an error like:
MySQL Connection Failed: Can't initialize character set xxx
This means one of the following things:
--with-charset=xxx or with --with-extra-charsets=xxx.
See section 2.3.3 Typical configure Options.
All standard MySQL binaries are compiled with
--with-extra-character-sets=complex which will enable support for
all multi-byte character sets. See section 4.6.1 The Character Set Used for Data and Sorting.
mysqld and the character set definition files are not in the place
where the client expects to find them.
In this case you need to:
configure Options.
--character-sets-dir=path-to-charset-dir option.
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!
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:
LD_LIBRARY_PATH environment variable.
LD_LIBRARY environment variable.
ldconfig.
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!
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:
mysqladmin shutdown).
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/datadirIf 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.
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.
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.
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.
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:
mysqld or the machine in the middle
of an update.
mysqld that caused it to die in the
middle of an update.
mysqld servers on the same data on a
system that doesn't support good filesystem locks (normally handled by
the lockd daemon ) or if you are running
multiple servers with --skip-external-locking
mysqld confused.
ALTER TABLE on a
repaired copy of the table!
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:
mysqld daemon with mysqladmin shutdown, run
myisamchk --silent --force */*.MYI on all tables, and restart the
mysqld daemon. This will ensure that you are running from a clean
state. See section 4 Database Administration.
mysqld --log and try to determine from the information in the log
whether some specific query kills the server. About 95% of all bugs are
related to a particular query! Normally this is one of the last queries in
the log file just before MySQL restarted. See section 4.9.2 The General Query Log.
If you can repeatadly kill MySQL with one of the queries, even
when you have checked all tables just before doing the query, then you
have been able to locate the bug and should do a bug report for this!
See section 1.7.1.3 How to Report Bugs or Problems.
fork_test.pl and fork2_test.pl.
--with-debug option or
--with-debug=full to configure and then recompile.
See section E.1 Debugging a MySQL server.
--skip-external-locking option to mysqld. On some
systems, the lockd lock manager does not work properly; the
--skip-external-locking option tells mysqld not to use external
locking. (This means that you cannot run 2 mysqld servers on the same
data and that you must be careful if you use myisamchk, but it may be
instructive to try the option as a test.)
mysqladmin -u root processlist when mysqld
appears to be running but not responding? Sometimes mysqld is not
comatose even though you might think so. The problem may be that all
connections are in use, or there may be some internal lock problem.
mysqladmin processlist will usually be able to make a connection even
in these cases, and can provide useful information about the current number
of connections and their status.
mysqladmin -i 5 status or mysqladmin -i 5
-r status or in a separate window to produce statistics while you run
your other queries.
mysqld from gdb (or in another debugger).
See section E.1.3 Debugging mysqld under gdb.
mysqld has crashed inside
gdb:
backtrace info local up info local up info localWith gdb you can also examine which threads exist with
info
threads and switch to a specific thread with thread #, where
# is the thread id.
BLOB/TEXT columns (but only VARCHAR columns), you
can try to change all VARCHAR to CHAR with ALTER
TABLE. This will force MySQL to use fixed-size rows.
Fixed-size rows take a little extra space, but are much more tolerant to
corruption!
The current dynamic row code has been in use at MySQL AB for at
least 3 years without any problems, but by nature dynamic-length rows are
more prone to errors, so it may be a good idea to try the above to see if
it helps!
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:
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.
mysqld with the --skip-grant-tables option.
mysqladmin password command:
shell> mysqladmin -u root password 'mynewpassword'
mysqld and restart it normally,
or just load the privilege tables with:
shell> mysqladmin -h hostname flush-privileges
Alternatively, you can set the new password using the mysql client:
mysqld with the --skip-grant-tables
option as described above.
mysqld server with:
shell> mysql -u root mysql
mysql client:
mysql> UPDATE user SET Password=PASSWORD('mynewpassword')
-> WHERE User='root';
mysql> FLUSH PRIVILEGES;
mysqld and restart it normally.
When a disk-full condition occurs, MySQL does the following:
To alleviate the problem, you can take the following actions:
mysqladmin kill to the thread.
The thread will be aborted the next time it checks the disk (in 1 minute).
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).
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.
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:
/etc/my.cnf:
[client] socket=path-for-socket-file [mysqld] socket=path-for-socket-fileSee section 4.1.2 `my.cnf' Option Files.
safe_mysqld and most
clients with the --socket=path-for-socket-file option.
MYSQL_UNIX_PORT environment
variable.
configure option
--with-unix-socket-path=path-for-socket-file. See section 2.3.3 Typical configure Options.
You can test that the socket works with this command:
shell> mysqladmin --socket=/path/to/socket version
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.
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.
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:
DATE and DATETIME columns.
DATE column and you only know part
of the date.
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.
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.
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.
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:
SELECT the rows based on some WHERE condition in the main table.
DELETE the rows in the main table based on the same condition.
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.
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:
EXPLAIN and check if you can find something that is
obviously wrong. See section 5.2.1 EXPLAIN Syntax (Get Information About a SELECT).
WHERE clause.
LIMIT 10 with the query.
SELECT for the column that should have matched a row against
the table that was last removed from the query.
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.
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.sqlPost the test file using
mysqlbug to mysql@lists.mysql.com.
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 |
+------+-------+-------+
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.
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:
INSERT INTO new_table SELECT fields-in-new_table-order FROM old_table.
old_table.
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.
The following are a list of the limitations with TEMPORARY TABLES.
HEAP, ISAM,
MyISAM, MERGE, or InnoDB.
mysql> SELECT * FROM temporary_table, temporary_table AS t2;
RENAME on a TEMPORARY table.
Note that ALTER TABLE org_name RENAME new_name works!
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.
libmysql.dll, by bsilva@umesd.k12.or.us.
TmySQL, a library to use MySQL with Delphi.
guile that allows guile to interact with SQL
databases. By Hal Roberts.
mydsn.dll. mydsn should be used to build
and remove the DSN registry file for the MyODBC driver in Coldfusion
applications. By Miguel Angel Solórzano.
PROCEDURE that can be loaded runtime.
mysqldump output to a C header file. By Harry Brueckner,
brueckner@mail.respublica.de.
access_to_mysql.txt, except that this
one is fully configurable, has better type conversion (including
detection of TIMESTAMP fields), provides warnings and suggestions
while converting, quotes all special characters in text and
binary data, and so on. It will also convert to mSQL v1 and v2,
and is free of charge for anyone. See
http://www.cynergi.net/exportsql/ for the latest version. By
Pedro Freire, support@cynergi.net. Note: Doesn't work with
Access2!
exportsql. By Brian Andrews.
Note: Doesn't work with Access2!
exportsql.txt. That is,
it imports data from MySQL into an Access database via
ODBC. This is very handy when combined with exportsql, because it lets you
use Access for all DB design and administration, and synchronise with
your actual MySQL server either way. Free of charge. See
http://www.netdive.com/freebies/importsql/ for any updates.
Created by Laurent Bossavit of NetDIVE.
Note: doesn't work with Access2!
mSQL to MySQL. By alfred@sb.net
mysqldump and pipe it to
the sqlconv.pl script. The script will parse through the
mysqldump output and will rearrange the fields so they can be
inserted into a new table. An example is when you want to create a new
table for a different site you are working on, but the table is just a
bit different (that is - fields in different order, etc.).
By Steve Shreeve.
This appendix lists the developers, contributors, and supporters that have helped to make MySQL what it is today.
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.
mysqld).
mysys library.
ISAM and MyISAM libraries (B-tree index file
handlers with index compression and different record formats).
HEAP library. A memory table system with our superior full dynamic
hashing. In use since 1981 and published around 1984.
replace program (take a look at it, it's COOL!).
MyODBC, the ODBC driver for Windows95.
mSQL tools like msqlperl, DBD/DBI, and
DB2mysql.
crash-me and the foundation for the MySQL benchmarks.
texi2html.
mysys are left.
mysqlimport
PROCEDURE ANALYSE()
zlib) in the client/server protocol.
INSERT
mysqldump -e option
LOAD DATA LOCAL INFILE
SQL_CALC_FOUND_ROWS SELECT option
--max-user-connections=... option
net_read and net_write_timeout
GRANT/REVOKE and SHOW GRANTS FOR
UNION in 4.0
DELETE/UPDATE
MySQL++ C++ API and the MySQLGUI client.
CASE expression.
MD5() and COALESCE() functions.
RAID support for MyISAM tables.
SHOW CREATE TABLE.
mysql-bench
libmysqld, the embedded server.
MERGE library.
ALTER TABLE ... ORDER BY ....
UPDATE ... ORDER BY ....
DELETE ... ORDER BY ....
MySQLCC (MySQL Control Center)
SHA1(), AES_ENCRYPT() and AES_DECRYPT() functions.
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:
mysqlshutdown.exe and
mysqlwatch.exe
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.)
WHERE column REGEXP regexp.
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).
mysqldump (previously msqldump, but ported and enhanced by
Monty).
DBD (Perl) interface.
mysqlhotcopy.
_MB character set macros and the ujis and sjis character sets.
mysqlaccess, a program to show the access rights for a user.
xmysql, a graphical X client for MySQL Server.
DBD::mysql module.
FROM_UNIXTIME() time formatting, ENCRYPT() functions, and
bison advisor.
Active mailing list member.
DBI/DBD. Have
been of great help with crash-me and running benchmarks. Some new
date functions. The mysql_setpermissions script.
DBI/DBD section in the manual.
CREATE FUNCTION and
DROP FUNCTION.
AGGREGATE extension to UDF functions.
mysqlaccess more secure.
pthread_mutex() for OS/2.
MERGE tables to handle INSERTS. Active member
on the MySQL mailing lists.
DECIMAL.
Author of mysql_tableinfo.
mysqli extension (API) for use with MySQL 4.1 and up.
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:
DBD-mysql questions.
xmysql-related questions and basic installation questions.
mysqlbug.
DBD, Linux, some SQL syntax questions.
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.
mysqld version.
--skip-show-database
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!
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:
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.
SELECT * FROM t1 WHERE t1.a=(SELECT t2.b FROM t2); SELECT * FROM t1 WHERE (1,2,3) IN (SELECT a,b,c FROM t2);
SELECT t1.a FROM t1, (SELECT * FROM t2) t3 WHERE t1.a=t3.a;
INSERT ... ON DUPLICATE KEY UPDATE ... syntax. This allows you to
UPDATE an existing row if the insert would cause a duplicate value
in a PRIMARY or UNIQUE key. (REPLACE allows you to
overwrite an existing row, which is something entirely different.)
See section 6.4.3 INSERT Syntax.
BTREE index on HEAP tables.
SHOW WARNINGS shows warnings for the last command.
See section 4.5.6.9 SHOW WARNINGS | ERRORS.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table LIKE table.
HELP command that can be used in the mysql
command line client (and other clients) to get help for SQL commands.
For a full list of changes, please refer to the changelog sections for each individual 4.1.x release.
localhost.
REPAIR of MyISAM tables now uses less temporary disk space when
sorting char columns.
DATE/DATETIME checking is now a bit stricter then before
to be able to automatically distinguish between date, datetime, and time
with microseconds. For example, dates of type YYYYMMDD HHMMDD are not
supported anymore; One must either have separators between each
DATE/TIME part or not at all.
help
week in the mysql client and get help for the week()
function.
mysql_get_server_version().
record_in_range() method to MERGE tables to be
able to choose the right index when there are many to choose from.
RAND() and user variables @var.
ANSI_QUOTES on the fly.
EXPLAIN SELECT now can be killed. See section 4.5.5 KILL Syntax.
REPAIR TABLE now can be killed. See section 4.5.5 KILL Syntax.
USE|IGNORE|FORCE INDEX.
DROP TEMPORARY TABLE now only drops temporary tables and doesn't
end transactions.
UNION in derived tables
TIMESTAMP is now returned as string of type 'YYYY-MM-DD HH:MM:DD'.
CREATE TABLE foo (a int not null primary key) the
PRIMARY word is now optional.
CREATE TABLE the attribute SERIAL is now an alias for
BIGINT NOT NULL AUTO_INCREMENT UNIQUE.
SELECT ... FROM DUAL is an alias for SELECT ....
(To be compatible with some other databases).
CHAR/VARCHAR it's now
automatically changed to TEXT or BLOB; One will get a
warning in this case.
BLOB/TEXT types with the
syntax BLOB(length) and TEXT(length). MySQL will
automatically change it to one of the internal BLOB/TEXT
types.
CHAR BYTE is an alias for CHAR BINARY.
VARCHARACTER is an alias for VARCHAR.
integer MOD integer and integer DIV integer.
SERIAL DEFAULT VALUE added as an alias for AUTO_INCREMENT.
TRUE and FALSE added as alias for 1 and 0, respectively.
SELECT .. LIMIT 0 to return proper row count for
SQL_CALC_FOUND_ROWS.
--tmpdir=dirname1:dirname2:dirname3.
SELECT * from t1 where t1.a=(SELECT t2.b FROM t2).
SELECT a.col1, b.col2
FROM (SELECT MAX(col1) AS col1 FROM root_table) a,
other_table b
WHERE a.col1=b.col1;
BTREE index on HEAP tables.
CREATE TABLE.
SHOW FULL COLUMNS FROM table_name shows column comments.
ALTER DATABASE.
SHOW [COUNT(*)] WARNINGS shows warnings from the last command.
CREATE TABLE
... SELECT by defining the column in the CREATE part.
CREATE TABLE foo (a tinyint not null) SELECT b+1 AS 'a' FROM bar;
expr SOUNDS LIKE expr same as SOUNDEX(expr)=SOUNDEX(expr).
VARIANCE(expr) returns the variance of expr
CREATE
[TEMPORARY] TABLE [IF NOT EXISTS] table (LIKE table). The table can
be either normal or temporary.
--reconnect and disable-reconnect for the
mysql client, to reconnect automatically or not if the
connection is lost.
START SLAVE (STOP SLAVE) does not return an error
anymore if the slave is already started (stopped); it returns a
warning instead.
SLAVE START and SLAVE STOP are not accepted by the query
parser anymore, use START SLAVE and STOP SLAVE instead.
Version 4.0 of the MySQL server includes many enhancements and new features:
InnoDB table type is now included in the standard binaries,
adding transactions, row-level locking, and foreign keys.
See section 7.5 InnoDB Tables.
MERGE tables, now supporting INSERTs and
AUTO_INCREMENT.
See section 7.2 MERGE Tables.
UNION syntax in SELECT.
See section 6.4.1.2 UNION Syntax.
DELETE statements.
See section 6.4.6 DELETE Syntax.
libmysqld, the embedded server library.
See section 8.1.15 libmysqld, the Embedded MySQL Server Library.
GRANT privilege options for even tighter control and
security.
See section 4.3.1 GRANT and REVOKE Syntax.
GRANT system, particularly
useful for ISPs and other hosting providers.
See section 4.3.6 Limiting user resources.
SET Syntax.
For a full list of changes, please refer to the changelog sections for each individual 4.0.x release.
Functionality added or changed:
CREATE TABLE, first
try if the default table type exists before falling back to MyISAM.
SHOW PROCESSLIST.
MEMORY as an alias for HEAP.
rnd to my_rnd as the name was too generic
and is an exported symbol in libmysqlclient (thanks to Dennis Haney
for the initial patch).
mysqldump does not silently delete the binlogs when called with
--master-data or --first-slave anymore;
while this behaviour was convenient for some
users, others may suffer from it. Now one has to explicitely ask for
this deletion with the new --delete-master-logs option.
replicate-wild-ignore-table=mysql.%)
to exclude mysql.user, mysql.host, mysql.db,
mysql.tables_priv and mysql.columns_priv from
replication, then GRANT and REVOKE will not be replicated.
Bugs fixed:
multi-table updates which occured whenever a
temporary table, containing update data, had to be converted from
HEAP to MyISAM.
LOAD DATA INFILE IGNORE : when reading
the binary log, mysqlbinlog and the replication code read REPLACE
instead of IGNORE. This could make the slave's table
become different from the master's table. Bug #218.
relay_log_space_limit was set to a too
small value. Bug #79.
MyISAM when a row is inserted into a table with a
large number of NULL columns. Bug was caused by wrong calculation
of the record length, as the space required for storage of NULL
bits was not added to the total record length.
SELECT @nonexistent_variable caused the
error in client - server protocl due to net_printf() being sent to
the client twice.
SQL_BIG_SELECTS option.
SHOW PROCESSLIST which only displayed a localhost
in the "Host" column. This was caused by a glitch that only used
current thread info instead info from the linked list of threads.
multi-table-update for InnoDB tables as well.
multi-table-updates that caused some rows to be
updated several times.
mysqldump when it was called with
--master-data: the CHANGE MASTER TO commands appended to
the SQL dump had wrong coordinates (bug #159).
USER() was replicated
on the slave ; this caused segfault on the slave (bug
#178). USER() is still badly replicated on the slave (it is
replicated to "").
Functionality added or changed:
SHOW PROCESSLIST will now include the client TCP port after the
hostname to make it easier to know from which client the request
originated.
Bugs fixed:
sort_buffer variable.
INSERT INTO u SELECT ... FROM t was written too late to the
binary log if t was very frequently updated during the execution of
this query. This could cause a problem with mysqlbinlog or
replication. The master must be upgraded, not the slave. (bug #136).
WHERE clause (bug #142).
multi-table updates with InnoDB
tables. This bug occured as, in many cases, InnoDB tables can not
be updated "on the fly", but offsets to the records have to be stored in
a temporary table.
server
RPM subpackage (bug #141).
.MYI files.
BACKUP TABLE to overwrite existing files.
UPDATEs when user had all privileges
on the database where tables are located and there were any entries in
tables_priv table, i.e. grant_option was true.
TRUNCATE any table in the same database.
LOCK TABLE followed by DROP
TABLE in the same thread. In this case one could still kill the thread
with KILL.
LOAD DATA LOCAL INFILE was not properly written to the binary
log (hence not properly replicated). (bug #82).
RAND() entries were not read correctly by mysqlbinlog from
the binary log which caused problems when restoring a table that was
inserted with RAND(). INSERT INTO t1 VALUES(RAND()). In
replication this worked ok.
SET SQL_LOG_BIN=0 was ignored for INSERT DELAYED
queries. (bug #104).
SHOW SLAVE STATUS reported too old positions
(columns Relay_Master_Log_File and Exec_master_log_pos)
for the last executed statement from the master, if this statement
was the COMMIT of a transaction. The master must be upgraded for that,
not the slave. (bug #52).
LOAD DATA INFILE was not replicated by the slave if
replicate_*_table was set on the slave. (bug #86).
RESET SLAVE, the coordinates displayed by SHOW
SLAVE STATUS looked un-reset (though they were, but only
internally). (bug #70).
LOAD DATA.
ANALYZE procedure with error.
CHAR(0) columns that could cause wrong
results from the query.
AUTO_INCREMENT column,
as a secondary column in a multi-column key (see section 3.5.9 Using AUTO_INCREMENT), when
data was inserted with INSERT ... SELECT or LOAD DATA into
an empty table.
STOP SLAVE didn't stop the slave until the slave
got one new command from the master (this bug has been fixed for MySQL 4.0.11
by releasing updated 4.0.11a windows packages, which include this individual
fix on top of the 4.0.11 sources). (bug #69).
LOAD DATA command
was issued with full table name specified, including database prefix.
pthread_attr_getstacksize on
HP-UX 10.20 (Patch was also included in 4.0.11a sources).
bigint test to not fail on some platforms (e.g. HP-UX and
Tru64) due to different return values of the atof() function.
rpl_rotate_logs test to not fail on certain platforms (e.g.
Mac OS X) due to a too long file name (changed slave-master-info.opt
to .slave-mi).
Functionality added or changed:
NULL is now sorted LAST if you use ORDER BY ... DESC
(as it was before before MySQL 4.0.2). This is change was required to
follow ANSI SQL 99. (The original change was because we thought that
ANSI SQL 99 required NULL to be always sorted at the same position, but
this was wrong).
START TRANSACTION (ANSI SQL-99 syntax) as alias for BEGIN.
This is recommended to use instead of BEGIN to start a transaction.
OLD_PASSWORD() as a synonym for PASSWORD().
ALL in group functions.
INNER JOIN and JOIN syntaxes.
For example, SELECT * FROM t1 INNER JOIN t2 didn't work before.
Bugs fixed:
multi-table-delete and InnoDB tables.
BLOB NOT NULL columns used with IS NULL.
CREATE TABLE (...)
AUTO_INCREMENT=#.
MIN(key_column) could in some cases return NULL on a column
with NULL and other values.
MIN(key_column) and MAX(key_column) could in some cases
return wrong values when used in OUTER JOIN.
MIN(key_column) and MAX(key_column) could return wrong
values if one of the tables was empty.
INTERVAL,
CASE, FIELD, CONCAT_WS, ELT and
MAKE_SET functions.
--lower-case-table-names (default on windows)
and you had tables or databases with mixed case on disk, then
executing SHOW TABLE STATUS followed with DROP DATABASE
or DROP TABLE could fail with Errcode 13.
Functionality added or changed:
--log-error[=file_name] to mysqld_safe and
mysqld. This option will force all error messages to be put in a
log file if the option --console is not given. On Windows
--log-error is enabled as default, with a default name of
host_name.err if the name is not specified.
Warning: to Note: in the log files.
GROUP BY ... ORDER BY NULL
then result is not sorted.
SHOW VARIABLES.
gethostbyaddr() to resolve a hostname. You can fix
this for earlier MySQL versions by starting mysqld with
--thread-stack=192K.
mysql_waitpid to the binary distribution and the
MySQL-client RPM subpackage (required for mysql-test-run).
MySQL RPM package to MySQL-server. When
updating from an older version, MySQL-server.rpm will simply replace
MySQL.rpm.
replicate_wild_do_table=db.% or
replicate_wild_ignore_table=db.%, these rules will be applied to
CREATE/DROP DATABASE too.
MASTER_POS_WAIT().
Bugs fixed:
rand() distribution from the first call.
mysqld to hang when a
table was opened with the HANDLER command and then
dropped without being closed.
NULL in an auto_increment field and also
uses LAST_INSERT_ID().
ORDER BY constant_expression.
mysqladmin --relative.
show status reported a strange number for
Open_files and Open_streams.
EXPLAIN on empty table.
LEFT JOIN that caused zero rows to be returned in
the case the WHERE condition was evaluated as FALSE after
reading const tables. (Unlikely condition).
FLUSH PRIVILEGES didn't correctly flush table/column privileges
when mysql.tables_priv is empty.
LOAD DATA INFILE one a file
that updated and auto_increment field with NULL or 0. This
bug only affected MySQL 4.0 masters (not slaves or MySQL 3.23 masters).
NOTE: If you have a slave that has replicated a file with
generated auto_increment fields then the slave data is corrupted and you
should reinitialise the affected tables from the master.
NOT NULL field to an
expression that returned NULL.
str LIKE "%other_str%" where str or
other_str contained characters >= 128.
LOAD DATA and InnoDB failed
with table full error the binary log was corrupted.
Functionality added or changed:
OPTIMIZE TABLE will for MyISAM tables treat all NULL
values as different when calculating cardinality. This helps in
optimising joins between tables where one of the tables has a lot of
NULL values in a indexed column:
SELECT * from t1,t2 where t1.a=t2.key_with_a_lot_of_null;
FORCE INDEX (key_list). This acts likes
USE INDEX (key_list) but with the addition that a table scan is
assumed to be VERY expensive. One bad thing with this is that it makes
FORCE a reserved word.
Bugs fixed:
LOAD DATA INFILE statement that
caused log rotation.
Functionality added or changed:
max_packet_length for libmysqld.c is now 1024*1024*1024.
max_allowed_packet in a file ready by
mysql_options(MYSQL_READ_DEFAULT_FILE).
for clients.
ON UPDATE CASCADE in
FOREIGN KEY constraints. See the InnoDB section in the manual
for the InnoDB changelog.
Bugs fixed:
ALTER TABLE with BDB tables.
QUOTE() function.
GROUP BY when used on BLOB column with NULL values.
NULLs in CASE ... WHEN ...
Functionality added or changed:
mysqlbug now also reports the compiler version used for building
the binaries (if the compiler supports the option --version).
Bugs fixed:
-DBIG_TABLES
on a 32 bit system.
mysql_drop_db() didn't check permissions properly so anyone could
drop another users database. DROP DATABASE is checked properly.
Functionality added or changed:
CHARACTER SET xxx and CHARSET=xxx
table options (to be able to read table dumps from 4.1).
IFNULL(A,B) is now set to be the
more 'general' of the types of A and B. (The order is
STRING, REAL or INTEGER).
Qcache_lowmem_prunes status variable (number of queries that were
deleted from cache because of low memory).
mysqlcheck so it can deal with table names containing dashes.
SHOW VARIABLES)
is no longer used when inserting small (less than 100) number of rows.
SELECT ... FROM merge_table WHERE indexed_column=constant_expr.
LOCALTIME and LOCALTIMESTAMP as synonyms for
NOW().
CEIL is now an alias for CEILING.
CURRENT_USER() function can be used to get a user@host
value as it was matched in the GRANT system.
See section 6.3.6.2 Miscellaneous Functions.
CHECK constraints to be compatible with ANSI SQL. This made
CHECK a reserved word. (Checking of CHECK constraints is
still not implemented).
CAST(... as CHAR).
LIMIT syntax:
SELECT ... LIMIT # OFFSET #
mysql_change_user() will now reset the connection to the state
of a fresh connect (Ie, ROLLBACK any active transaction, close
all temporary tables, reset all user variables etc..)
Bugs fixed:
multi table updates
--lower-case-table-names default on Mac OS X as the file system
is case sensitive.
AUTOCOMMIT=0 mode didn't rotate binary log.
SELECT with joined tables with
ORDER BY and LIMIT clause when filesort had to be used.
In that case LIMIT was applied to filesort of one of the tables,
although it could not be.
This fix solved problems with LEFT JOIN too.
mysql_server_init() now makes a copy of all arguments. This fixes
a problem when using the embedded server in C# program.
libmysqlclient library
that allowed a malicious MySQL server to crash the client
application.
mysql_change_user() handling.
All users are strongly recommended to upgrade to version 4.0.6.
--chroot command-line option of
mysqld from working.
"..." in boolean full-text search.
OPTIMIZE TABLE to corrupt the table
under some rare circumstances.
LOCK TABLES now works together with multi-table-update and
multi-table-delete.
--replicate-do=xxx didn't work for UPDATE commands.
(Bug introduced in 4.0.0)
REPLACE, AUTO_INCREMENT,
INSERT INTO ... SELECT ... were fixed. See the InnoDB changelog
in the InnoDB section of the manual.
Functionality added or changed:
SHOW PROCESSLIST
command
WEEK() so that one can get
week number according to the ISO 8601 specification.
(Old code should still work).
INSERT DELAYED threads doesn't hang on Waiting for
INSERT when one sends a SIGHUP to mysqld.
AND works according to SQL ANSI99 when it comes to
NULL handling. In practice, this only affects queries where you
do something like WHERE ... NOT (NULL AND 0).
mysqld will now resolve basedir to its full path (with
realpath()). This enables one to use relative symlinks to the
MySQL installation directory. This will however cause show
variables to report different directories on systems where there is
a symbolic link in the path.
IGNORE INDEX or USE INDEX.
to be ignored.
--use-frm option to mysqlcheck. When used with
REPAIR, it gets the table structure from the .frm file, so the
table can be repaired even if the .MYI header is corrupted.
MAX() optimisation when used with JOIN and
ON expressions.
BETWEEN behaviour changed (see section 6.3.1.2 Comparison Operators).
Now datetime_col BETWEEN timestamp AND timestamp should work
as expected.
TEMPORARY MERGE tables now.
DELETE FROM myisam_table now shrinks not only the `.MYD' file but
also the `.MYI' file.
--open-files-limit=# option to mysqld_safe
it's now passed on to mysqld.
EXPLAIN from 'where used' to
'Using where' to make it more in line with other output.
safe_show_database as it was not used anymore.
automake 1.5 and
libtool 1.4.
--ignore-space) back to the
original --ignore-spaces in mysqlclient. (Both syntaxes will
work).
UPDATE privilege when using REPLACE.
DROP TEMPORARY TABLE ..., to be used to make
replication safer.
BEGIN/COMMIT are now stored in the binary log on
COMMIT and not stored if one does ROLLBACK. This fixes
some problems with non-transactional temporary tables used inside
transactions.
SELECT * FROM (t2 LEFT JOIN t3 USING (a)), t1 worked, but
not SELECT * FROM t1, (t2 LEFT JOIN t3 USING (a)). Note that
braces are simply removed, they do not change the way the join is
executed.
READ UNCOMMITTED and READ COMMITTED.
For a detailed InnoDB changelog, see section 7.5.14 InnoDB Change History
in this manual.
Bugs fixed:
MAX() optimisation when used with JOIN and
ON expressions.
INSERT DELAY threads don't hang on Waiting for
INSERT when one sends a SIGHUP to mysqld.
IGNORE INDEX or USE INDEX.
root user in mysqld_safe.
CHECK
or REPAIR.
GROUP BY queries that
didn't return any result.
mysqlshow to work properly with wildcarded database names and
with database names that contain underscores.
MyISAM crash when using dynamic-row tables with huge numbers of
packed fields.
BDB transactions.
MATCH
relevance calculations.
IN BOOLEAN MODE that made MATCH
to return incorrect relevance value in some complex joins.
MyISAM key length to a value
slightly less that 500. It is exactly 500 now.
GROUP BY on columns that may have a NULL value
doesn't always use disk based temporary tables.
--des-key-file argument to mysqld
is interpreted relative to the data directory if given as a relative pathname.
NULL has to be MyISAM. This was okay for 3.23, but not
needed in 4.*. This resulted in slowdown in many queries since 4.0.2.
ORDER BY ... LIMIT #
to not return all rows.
REPAIR TABLE and myisamchk
to corrupt FULLTEXT indexes.
mysql grant table database. Now queries
in this database are not cached in the query cache.
mysqld_safe for some shells.
MyISAM MERGE table has more than 2 ^ 32 rows and
MySQL was not compiled with -DBIG_TABLES.
ORDER BY ... DESC problems with InnoDB tables.
GRANT/REVOKE failed if hostname was given in
non-matching case.
LOAD DATA INFILE when setting a
timestamp to a string value of '0'.
myisamchk -R mode.
mysqld to crash on REVOKE.
ORDER BY when there is a constant in the SELECT
statement.
mysqld couldn't open the
privilege tables.
SET PASSWORD FOR ... closed the connection in case of errors (bug
from 4.0.3).
max_allowed_packet in mysqld to 1GB.
INSERT on a table with an
AUTO_INCREMENT key which was not in the first part of the key.
LOAD DATA INFILE to not recreate index if the table had
rows from before.
AES_DECRYPT() with incorrect arguments.
--skip-ssl can now be used to disable SSL in the MySQL clients,
even if one is using other SSL options in an option file or previously
on the command line.
MATCH ... AGAINST( ... IN BOOLEAN MODE)
used with ORDER BY.
LOCK TABLES and CREATE TEMPORARY TABLES privilege on
the database level. One must run the mysql_fix_privilege_tables
script on old installations to activate these.
SHOW TABLE ... STATUS, compressed tables sometimes showed up as
dynamic.
SELECT @@[global|session].var_name didn't report
global | session in the result column name.
FLUSH LOGS in a circular
replication setup created an infinite number of binary log files.
Now a rotate-binary-log command in the binary log will not cause slaves
to rotate logs.
STOP EVENT from binary log when doing FLUSH LOGS.
SHOW NEW MASTER FOR SLAVE as this needs to be
completely changed in 4.1.
UNIQUE key) appeared in ORDER BY
part of SELECT DISTINCT.
--log-binary=a.b.c now properly strips off .b.c.
FLUSH LOGS removed numerical extension for all future update logs.
GRANT ... REQUIRE didn't store the SSL information in the
mysql.user table if SSL was not enabled in the server.
GRANT ... REQUIRE NONE can now be used to remove SSL information.
AND is now optional between REQUIRE options.
REQUIRE option was not properly saved, which could cause strange
output in SHOW GRANTS.
mysqld --help reports correct values for --datadir
and --bind-address.
mysqld was started.
SHOW VARIABLES on some 64 bit systems
(like Solaris sparc).
--set-variable syntax didn't work for
those options that didn't have a valid variable in my_option struct.
This affected at least default-table-type option.
REPAIR TABLE and
myisamchk --recover to fail on tables with duplicates in a unique
key.
CREATE TABLE table_name
SELECT expression(),...
SELECT * FROM table-list GROUP BY ... and
SELECT DISTINCT * FROM ....
--slow-log when logging an administrator command
(like FLUSH TABLES).
OPTIMIZE of locked and modified table,
reported table corruption.
--skip-,
--enable-). --skip-external-locking didn't work and the bug
may have affected other similar options.
tee option.
SELECT ... FROM many_tables .. ORDER BY key limit #
SHOW OPEN TABLES when a user didn't have access
permissions to one of the opened tables.
configure ... --localstatedir=....
mysql.server script.
mysqladmin shutdown when pid file was modified
while mysqladmin was still waiting for the previous one to
disappear. This could happen during a very quick restart and caused
mysqladmin to hang until shutdown_timeout seconds had
passed.
AUTO_INCREMENT columns to
NULL in LOAD DATA INFILE.
SHOW MASTER STATUS now returns an empty set if binary log is not
enabled.
SHOW SLAVE STATUS now returns an empty set if slave is not initialised.
SELECT DISTINCT ... FROM many_tables ORDER BY
not-used-column.
BIGINTs and quoted strings.
QUOTE() function that performs SQL quoting to produce values
that can be used as data values in queries.
DELAY_KEY_WRITE to an enum to allow one set
DELAY_KEY_WRITE for all tables without taking down the server.
IF(condition,column,NULL) so that it returns
the value of the column type.
safe_mysqld a symlink to mysqld_safe in binary distribution.
user.db
table.
CREATE TABLE ... SELECT function().
mysqld now has the option --temp-pool enabled by default as this
gives better performance with some operating systems.
CHANGE MASTER TO if the slave thread died very quickly.
--code-file option is specified, the server calls
setrlimit() to set the maximum allowed core file size to unlimited,
so core files can be generated.
--count=N (-c) option to mysqladmin, to make the
program do only N iterations. To be used with --sleep (-i).
Useful in scripts.
UPDATE: when updating a table,
do_select() became confused about reading records from a cache.
UPDATE when several fields were referenced
from a single table
REVOKE that caused user resources to be randomly set.
GRANT for the new CREATE TEMPORARY TABLE privilege.
DELETE when tables are re-ordered in the
table initialisation method and ref_lengths are of different sizes.
SELECT DISTINCT with large tables.
DEFAULT with INSERT statement.
myisam_max_sort_file_size and
myisam_max_extra_sort_file_size are now given in bytes, not megabytes.
MyISAM/ISAM files is now turned
off by default. One can turn this on with --external-locking.
(For most users this is never needed).
INSERT ... SET db_name.table_name.colname=''.
DROP DATABASE
SET [GLOBAL | SESSION] syntax to change thread-specific and global
server variables at runtime.
slave_compressed_protocol.
query_cache_startup_type to query_cache_type,
myisam_bulk_insert_tree_size to bulk_insert_buffer_size,
record_buffer to read_buffer_size and
record_rnd_buffer to record_rnd_buffer_size.
--skip-locking to --skip-external-locking.
query_buffer_size.
mysql client
non-functional.
AUTO_INCREMENT support to MERGE tables.
LOG() function to accept an optional arbitrary base
parameter.
See section 6.3.3.2 Mathematical Functions.
LOG2() function (useful for finding out how many bits
a number would require for storage).
LN() natural logarithm function for compatibility with
other databases. It is synonymous with LOG(X).
NULL handling for default values in DESCRIBE
table_name.
truncate() to round up negative values to the nearest integer.
--chroot=path option to execute chroot() immediately
after all options have been parsed.
lower_case_table_names now also affects database names.
XOR operator (logical and bitwise XOR) with ^
as a synonym for bitwise XOR.
IS_FREE_LOCK("lock_name").
Based on code contributed by Hartmut Holzgraefe hartmut@six.de.
mysql_ssl_clear() from C API, as it was not needed.
DECIMAL and NUMERIC types can now read exponential numbers.
SHA1() function to calculate 160 bit hash value as described
in RFC 3174 (Secure Hash Algorithm). This function can be considered a
cryptographically more secure equivalent of MD5().
See section 6.3.6.2 Miscellaneous Functions.
AES_ENCRYPT() and AES_DECRYPT() functions to perform
encryption according to AES standard (Rijndael).
See section 6.3.6.2 Miscellaneous Functions.
--single-transaction option to mysqldump, allowing a
consistent dump of InnoDB tables.
See section 4.8.5 mysqldump, Dumping Table Structure and Data.
innodb_log_group_home_dir in SHOW VARIABLES.
FULLTEXT index is present and no tables are used.
CREATE TEMPORARY TABLES, EXECUTE,
LOCK TABLES, REPLICATION CLIENT, REPLICATION SLAVE,
SHOW DATABASES and SUPER. To use these, you must have
run the mysql_fix_privilege_tables script after upgrading.
TRUNCATE TABLE; This fixes some core
dump/hangup problems when using TRUNCATE TABLE.
DELETE when optimiser uses only indices.
ALTER TABLE table_name RENAME new_table_name is as fast
as RENAME TABLE.
GROUP BY with two or more fields, where at least one
field can contain NULL values.
Turbo Boyer-Moore algorithm to speed up LIKE "%keyword%"
searches.
DROP DATABASE with symlink.
REPAIR ... USE_FRM.
EXPLAIN with LIMIT offset != 0.
"..." in boolean full-text search.
* in boolean full-text search.
+word*s in the query).
MATCH expression that did not use an index appeared twice.
mysqldump.
ft_min_word_len characters.
--without-query-cache.
INET_NTOA() now returns NULL if you give it an argument that
is too large (greater than the value corresponding to 255.255.255.255).
SQL_CALC_FOUND_ROWS to work with UNIONs. It will work only
if the first SELECT has this option and if there is global LIMIT
for the entire statement. For the moment, this requires using parentheses for
individual SELECT queries within the statement.
SQL_CALC_FOUND_ROWS and LIMIT.
CREATE TABLE ...(... VARCHAR(0)).
SIGINT and SIGQUIT problems in `mysql.cc' on Linux
with some glibc versions.
net_store_length() linked in the CONVERT::store() method.
DOUBLE and FLOAT columns now honor the UNSIGNED flag
on storage.
InnoDB now retains foreign key constraints through ALTER TABLE
and CREATE/DROP INDEX.
InnoDB now allows foreign key constraints to be added through the
ALTER TABLE syntax.
InnoDB tables can now be set to automatically grow in size (autoextend).
--ignore-lines=n option to mysqlimport. This has the
same effect as the IGNORE n LINES clause for LOAD DATA.
UNION with last offset being transposed to total result
set.
REPAIR ... USE_FRM added.
DEFAULT_SELECT_LIMIT is always imposed on UNION
result set.
SELECT options can appear only in the first
SELECT.
LIMIT with UNION, where last select is in
the braces.
UNION operations.
SELECT with an empty
HEAP table.
ORDER BY column DESC now sorts NULL values first.
(In other words, NULL values sort first in all cases, whether or
not DESC is specified.). This is changed back in 4.0.10.
WHERE key_name='constant' ORDER BY key_name DESC.
SELECT DISTINCT ... ORDER BY DESC optimisation.
... HAVING 'GROUP_FUNCTION'(xxx) IS [NOT] NULL.
--user=# option for mysqld to be specified
as a numeric user ID.
SQL_CALC_ROWS returned an incorrect value when used
with one table and ORDER BY and with InnoDB tables.
SELECT 0 LIMIT 0 doesn't hang thread.
USE/IGNORE INDEX when using
many keys with the same start column.
BerkeleyDB and InnoDB tables when
we can use an index that covers the whole row.
InnoDB sort-buffer handling to take less memory.
DELETE and InnoDB tables.
TRUNCATE and InnoDB tables that produced the
error Can't execute the given command because you have active locked
tables or an active transaction.
NO_UNSIGNED_SUBTRACTION to the set of flags that may be
specified with the --sql-mode option for mysqld. It disables
unsigned arithmetic rules when it comes to subtraction. (This will make
MySQL 4.0 behave more closely to 3.23 with UNSIGNED columns).
|, <<, ...) is now of
type unsigned integer.
nan values in MyISAM to make it possible to
repair tables with nan in float or double columns.
myisamchk where it didn't correctly update number of
``parts'' in the MyISAM index file.
autoconf 2.52 (from autoconf 2.13).
const tables. This fix also
improves performance a bit when referring to another table from a
const table.
UPDATE statement.
DELETE.
SELECT CONCAT(argument_list) ... GROUP BY 1.
INSERT ... SELECT did a full rollback in case of an error. Fixed
so that we only roll back the last statement in the current transaction.
NULL.
BIT_LENGTH() function.
GROUP BY BINARY column.
NULL keys in HEAP tables.
ORDER BY in queries of type:
SELECT * FROM t WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC
FLUSH QUERY CACHE.
CAST() and CONVERT() functions. The CAST and
CONVERT functions are nearly identical and mainly useful when you
want to create a column with a specific type in a CREATE ... SELECT
statement. For more information, read section 6.3.5 Cast Functions.
CREATE ... SELECT on DATE and TIME functions now
create columns of the expected type.
Null and Index_type to SHOW INDEX
output.
--no-beep and --prompt options to mysql command-line client.
GRANT ... WITH MAX_QUERIES_PER_HOUR N1
MAX_UPDATES_PER_HOUR N2
MAX_CONNECTIONS_PER_HOUR N3;
See section 4.3.6 Limiting user resources.
mysql_secure_installation to the `scripts/' directory.
HANDLER was used with some unsupported table type.
mysqldump now puts ALTER TABLE tbl_name DISABLE KEYS and
ALTER TABLE tbl_name ENABLE KEYS in the sql dump.
mysql_fix_extensions script.
LOAD DATA FROM MASTER on OSF/1.
DES_ENCRYPT() and DES_DECRYPT() functions.
FLUSH DES_KEY_FILE statement.
--des-key-file option to mysqld.
HEX(string) now returns the characters in string converted to
hexadecimal.
GRANT when using lower_case_table_names=1.
SELECT ... IN SHARE MODE to
SELECT ... LOCK IN SHARE MODE (as in MySQL 3.23).
SELECT queries.
MATCH ... AGAINST(... IN BOOLEAN MODE) can now work
without FULLTEXT index.
FULLTEXT indexes.
DELETE ... WHERE ... MATCH ....
MATCH ... AGAINST(... IN BOOLEAN MODE).
Note: you must rebuild your tables with
ALTER TABLE tablename TYPE=MyISAM to be
able to use boolean full-text search.
LOCATE() and INSTR() are now case-sensitive if either
argument is a binary string.
RAND() initialisation so that RAND(N) and
RAND(N+1) are more distinct.
UPDATE ... ORDER BY.
INSERT INTO ... SELECT to stop on errors by default.
DATA DIRECTORY and INDEX DIRECTORY directives on Windows.
MODIFY and CHANGE in ALTER TABLE to accept
the FIRST and AFTER keywords.
ORDER BY on a whole InnoDB table.
--xml option to mysql for producing XML output.
ft_min_word_len, ft_max_word_len, and
ft_max_word_len_for_sort.
libmysqld, the embedded MySQL server
library. Also added example programs (a mysql client and
mysqltest test program) which use libmysqld.
my_thread_init() and my_thread_end()
from `mysql_com.h', and added mysql_thread_init() and
mysql_thread_end() to `mysql.h'.
MyISAM to be able to handle these.
BIGINT constants now work. MIN() and MAX()
now handle signed and unsigned BIGINT numbers correctly.
latin1_de which provides correct German sorting.
STRCMP() now uses the current character set when doing comparisons,
which means that the default comparison behaviour now is case-insensitive.
TRUNCATE TABLE and DELETE FROM tbl_name are now separate
functions. One bonus is that DELETE FROM tbl_name now returns
the number of deleted rows, rather than zero.
DROP DATABASE now executes a DROP TABLE on all tables in
the database, which fixes a problem with InnoDB tables.
UNION.
DELETE operations.
HANDLER interface to MyISAM tables.
INSERT on MERGE tables. Patch from
Benjamin Pflugmann.
WEEK(#,0) to match the calendar in the USA.
COUNT(DISTINCT) is about 30% faster.
IS NULL, ISNULL() and some other internal primitives.
myisam_bulk_insert_tree_size variable.
CHAR/VARCHAR) keys is now much faster.
SELECT DISTINCT * from tbl_name ORDER by key_part1 LIMIT #.
SHOW CREATE TABLE now shows all table attributes.
ORDER BY ... DESC can now use keys.
LOAD DATA FROM MASTER ``automatically'' sets up a slave.
safe_mysqld to mysqld_safe to make this name more
in line with other MySQL scripts/commands.
MyISAM tables. Symlink handling is
now enabled by default for Windows.
SQL_CALC_FOUND_ROWS and FOUND_ROWS(). This makes it
possible to know how many rows a query would have returned
without a LIMIT clause.
SHOW OPEN TABLES.
SELECT expression LIMIT ....
IDENTITY as a synonym for AUTO_INCREMENT (like Sybase).
ORDER BY syntax to UPDATE and DELETE.
SHOW INDEXES is now a synonym for SHOW INDEX.
ALTER TABLE tbl_name DISABLE KEYS and
ALTER TABLE tbl_name ENABLE KEYS commands.
IN as a synonym for FROM in SHOW commands.
FULLTEXT indexes.
REPAIR TABLE, ALTER TABLE, and OPTIMIZE TABLE
for tables with FULLTEXT indexes are now up to 100 times faster.
X'hexadecimal-number'.
FLUSH TABLES WITH READ LOCK.
DATETIME = constant in WHERE optimisation.
--master-data and --no-autocommit options to
mysqldump. (Thanks to Brian Aker for this.)
mysql_explain_log.sh to distribution.
(Thanks to mobile.de).
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
InnoDB
BerkeleyDB or BDB
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.
LOAD DATA INFILE IGNORE : when reading
the binary log, mysqlbinlog and the replication code read REPLACE
instead of IGNORE. This could make the slave's table
become different from the master's table. Bug #218.
MyISAM when a row is inserted into a table with a
large number of NULL columns. Bug was caused by wrong calculation
of the record length, as the space required for storage of NULL
bits was not added to the total record length.
TRUNCATE table_name or
DELETE FROM table_name which could cause an INSERT to
table_name to be written to the binary log before the
TRUNCATE/ DELETE command.
UPDATE of InnoDB tables where one row could be
updated multiple times.
PROCEDURE ANALYSE() to report DATE instead of
NEWDATE.
PROCEDURE ANALYSE(#) to restrict number of values in
enum to # also for string values.
mysqldump does not silently delete the binlogs when called with
--master-data or --first-slave anymore;
while this behaviour was convenient for some
users, others may suffer from it. Now one has to explicitely ask for
this deletion with the new --delete-master-logs option.
mysqldump when it was called with
--master-data: the CHANGE MASTER TO commands appended to
the SQL dump had wrong coordinates (bug #159).
sort_buffer variable.
GRANT UPDATE on column level.
HAVING with GROUP BY.
WHERE clause (Bug #142).
.MYI files.
--user
option specified on the command line. (Normally this comes from
`/etc/my.cnf')
BACKUP TABLE to overwrite existing files.
LOCK TABLE and
another thread did a DROP TABLE. In this case one could do
a KILL on one of the threads to resolve the deadlock.
LOAD DATA INFILE was not replicated by slave if
replicate_*_table was set on the slave.
CHAR(0) columns that could cause wrong
results from the query.
SHOW VARIABLES on 64-bit platforms. The bug was
caused by wrong declaration of variable server_id.
SHOW TABLE STATUS now reports that it can
contain NULL values (which is the case for a crashed `.frm' file).
rpl_rotate_logs test to not fail on certain platforms (e.g.
Mac OS X) due to a too long file name (changed slave-master-info.opt
to .slave-mi).
BLOB NOT NULL columns used with IS NULL.
MAX() optimization in MERGE tables.
RAND() initialization for new connections.
poll() system call, which resulted in timeout the value specified as
it was executed in both select() and poll().
SELECT * FROM table WHERE datetime1 IS NULL OR datetime2 IS NULL.
INTERVAL,
CASE, FIELD, CONCAT_WS, ELT and
MAKE_SET functions.
--lower-case-table-names (default on windows)
and you had tables or databases with mixed case on disk, then
executing SHOW TABLE STATUS followed with DROP DATABASE
or DROP TABLE could fail with Errcode 13.
NULL in an auto_increment field and also
uses LAST_INSERT_ID().
mysqladmin --relative.
show status reported a strange number for
Open_files and Open_streams.
free'd pointer bug in mysql_change_user()
handling, that enabled a specially hacked version of MySQL client
to crash mysqld. Note, that one needs to login to the server
by using a valid user account to be able to exploit this bug.
--slow-log when logging an administrator command
(like FLUSH TABLES).
GROUP BY when used on BLOB column with NULL values.
NULLs in CASE ... WHEN ....
--chroot (see section D.4.4 Changes in release 3.23.54 (05 Dec 2002))
is reverted. Unfortunately, there is no way to make it to work, without
introducing backward-incompatible changes in `my.cnf'.
Those who need --chroot functionality, should upgrade to MySQL 4.0.
(The fix in the 4.0 branch did not break backward-compatibility).
--lower-case-table-names default on Mac OS X as the file system
is case insensitive.
NOHUP_NICENESS
testing.
AUTOCOMMIT=0 mode didn't rotate binary log.
scripts/make_binary_distribution that resulted in
a remaining @HOSTNAME@ variable instead of replacing it with the
correct path to the hostname binary.
SHOW PROCESSLIST to core
dump in pthread_mutex_unlock() if a new thread was connecting.
SLAVE STOP if the thread executing the query has locked
tables. This removes a possible deadlock situation.
mysqld
with a specially crafted packet.
free'd pointer) when altering a
temporary table.
libmysqlclient library
that allowed malicious MySQL server to crash the client
application.
mysql_change_user() handling.
All users are strongly recommended to upgrade to the version 3.23.54.
--chroot command-line option of mysqld
from working.
OPTIMIZE TABLE to corrupt the table
under some rare circumstances.
mysqlcheck so it can deal with table names containing dashes.
NULL field with <=> NULL.
IGNORE INDEX and USE INDEX sometimes
to be ignored.
GROUP BY queries that
didn't return any result.
MATCH ... AGAINST () >=0 was treated as if it was
>.
SHOW PROCESSLIST when running with an
active slave (unlikely timing bug).
TEMPORARY MERGE tables now.
--core-file works on Linux (at least on kernel 2.4.18).
BDB and ALTER TABLE.
GROUP BY
... ORDER BY queries. Symptom was that mysqld died in function
send_fields.
BLOB values in internal
temporary tables used for some (unlikely) GROUP BY queries.
WHERE column_name = key_column_name was calculated as true
for NULL values.
LEFT JOIN ... WHERE key_column=NULL.
MyISAM crash when using dynamic-row tables with huge numbers of
packed fields.
automake 1.5 and
libtool 1.4.
SHOW INNODB STATUS was used and skip-innodb
was defined.
LOCK TABLES on windows when one connects to a
database that contains upper case letters.
--skip-show-databases doesn't reset the --port option.
safe_mysqld for some shells.
FLUSH STATUS doesn't reset Delayed_insert_threads.
BINARY cast on a NULL value.
GRANT at the same time a new
user logged in or did a USE DATABASE.
ALTER TABLE and RENAME TABLE when running with
-O lower_case_table_names=1 (typically on windows) when giving the
table name in uppercase.
-O lower_case_table_names=1 also converts database
names to lower case.
SELECT ... ORDER BY ... LIMIT.
AND/OR to report that they can return NULL. This fixes a
bug in GROUP BY on AND/OR expressions that return
NULL.
OPTIMIZE of locked and modified MyISAM table,
reported table corruption.
BDB-related ALTER TABLE bug with dropping a column
and shutting down immediately thereafter.
configure ... --localstatedir=....
UNSIGNED BIGINT on AIX (again).
BEGIN/COMMIT around transaction in the binary log.
This makes replication honour transactions.
user.db
table.
RND() to make it less predicatable.
GROUP BY on result with expression that created a
BLOB field.
GROUP BY on columns that have NULL values.
To solve this we now create an MyISAM temporary table when doing a
GROUP BY on a possible NULL item.
From MySQL 4.0.5 we can use in memory HEAP tables for this case.
SLAVE START, SLAVE STOP and automatic repair
of MyISAM tables that could cause table cache to be corrupted.
OPTIMIZE TABLE and REPAIR TABLE.
UNIQUE() key where first part could contain NULL values.
MERGE tables and MAX() function.
ALTER TABLE with BDB tables.
LOAD DATA INFILE to binary log with no
active database.
DROP DATABASE on a
database with InnoDB tables.
mysql_info() returns 0 for 'Duplicates' when using
INSERT DELAYED IGNORE.
-DHAVE_BROKEN_REALPATH to the Mac OS X (darwin) compile
options in `configure.in' to fix a failure under high load.
mysqldump XML output.
ENUM values. (This fixed a problem with
SHOW CREATE TABLE.)
CONCAT_WS() that cut the result.
Com_show_master_stat to
Com_show_master_status and Com_show_slave_stat to
Com_show_slave_status.
gethostbyname() to make the client library
thread-safe even if gethostbyname_r doesn't exist.
GRANT.
DROP DATABASE with symlinked directory.
DATETIME and value outside
DATETIME range.
BDB doc files from the source tree, as they're not
needed (MySQL covers BDB in its own documentation).
glibc 2.2 (needed for
make dist).
FLOAT(X+1,X) is not converted to FLOAT(X+2,X).
(This also affected DECIMAL, DOUBLE and REAL types)
IF() is case in-sensitive if the second and
third arguments are case sensitive.
gethostbyname_r.
'+11111' for
DECIMAL(5,0) UNSIGNED columns, we will just drop the sign.
ISNULL(expression_which_cannot_be_null) and
ISNULL(constant_expression).
glibc library that we used with the 3.23.50
Linux-x86 binaries.
<row> tags for mysqldump XML output.
crash-me and gcc 3.0.4.
@@unknown_variable doesn't hang server.
@@VERSION as a synonym for VERSION().
SHOW VARIABLES LIKE 'xxx' is now case-insensitive.
GET_LOCK() on HP-UX with DCE threads.
SIGINT and SIGQUIT problems in mysql.
InnoDB now retains foreign key constraints through ALTER TABLE
and CREATE/DROP INDEX.
InnoDB now allows foreign key constraints to be added through the
ALTER TABLE syntax.
InnoDB tables can now be set to automatically grow in size (autoextend).
gcc 3.0.4, which
should make them a bit faster.
--enable-named-pipe.
WHERE key_column = 'J' or key_column='j'.
--log-bin with LOAD DATA
INFILE without an active database.
RENAME TABLE when used with
lower_case_table_names=1 (default on Windows).
DROP TABLE on a table
that was in use by a thread that also used queries on only temporary tables.
SHOW CREATE TABLE and PRIMARY KEY when using
32 indexes.
SET PASSWORD for the anonymous user.
mysql_options().
--enable-local-infile.
bison.
DATE_FORMAT() returned empty string when used
with GROUP BY.
mysqldump --disable-keys to work.
NULL.
LOAD DATA LOCAL INFILE more secure.
glibc library,
which has serious problems under high load and RedHat 7.2. The 3.23.49 binary
release doesn't have this problem.
--xml option to mysqldump for producing XML output.
autoconf 2.52 (from autoconf 2.13)
const tables.
InnoDB.
InnoDB variables were always shown in SHOW VARIABLES as
OFF on high-byte-first systems (like SPARC).
InnoDB table and another
thread doing an ALTER TABLE on the same table. Before that,
mysqld could crash with an assertion failure in `row0row.c',
line 474.
InnoDB SQL optimiser to favor index searches more often
over table scans.
InnoDB tables when several large
SELECT queries are run concurrently on a multiprocessor Linux
computer. Large CPU-bound SELECT queries will now also generally
run faster on all platforms.
InnoDB now prints after crash recovery the
latest MySQL binlog name and the offset InnoDB was able to recover
to. This is useful, for example, when resynchronising a master and a
slave database in replication.
InnoDB
tables.
InnoDB tablespace.
InnoDB now prevents a FOREIGN KEY declaration where the
signedness is not the same in the referencing and referenced integer columns.
SHOW CREATE TABLE or SHOW TABLE STATUS could cause
memory corruption and make mysqld crash. Especially at risk was
mysqldump, because it frequently calls SHOW CREATE TABLE.
AUTO_INCREMENT column were
wrapped inside one LOCK TABLES, InnoDB asserted in
`lock0lock.c'.
NULL values in a UNIQUE secondary
index for an InnoDB table. But CHECK TABLE was not relaxed: it
reports the table as corrupt. CHECK TABLE no longer complains in
this situation.
SHOW GRANTS now shows REFERENCES instead of REFERENCE.
SELECT ... WHERE key=@var_name OR key=@var_name2
InnoDB keys to 500 bytes.
InnoDB now supports NULL in keys.
SELECT RELEASE_LOCK().
DO expression,[expression]
slave-skip-errors option.
SHOW STATUS is
now much longer.)
InnoDB tables.
GROUP BY expr DESC works.
t1 LEFT JOIN t2 ON t2.key=constant.
mysql_config now also works with binary (relocated) distributions.
InnoDB and BDB tables will now use index when doing an
ORDER BY on the whole table.
BDB tables.
ANALYZE, REPAIR, and OPTIMIZE TABLE when
the thread is waiting to get a lock on the table.
ANALYZE TABLE.
INSERT DELAYED
which could cause the binary log to have rows that were not yet written
to MyISAM tables.
(UPDATE|DELETE) ...WHERE MATCH bugfix.
MyISAM files.
--core-file now works on Solaris.
InnoDB to complain if it cannot find
free blocks from the buffer cache during recovery.
InnoDB insert buffer B-tree handling that could cause
crashes.
InnoDB lock timeout handling.
ALTER TABLE on a TEMPORARY InnoDB
table.
OPTIMIZE TABLE that reset index cardinality if it
was up to date.
t1 LEFT_JOIN t2 ... WHERE t2.date_column IS NULL when
date_column was declared as NOT NULL.
BDB tables and keys on BLOB columns.
MERGE tables on OS with 32-bit file pointers.
TIME_TO_SEC() when using negative values.
Rows_examined count in slow query log.
AVG() column in HAVING.
DAYOFYEAR(column), will return NULL for 0000-00-00 dates.
SELECT * FROM date_col="2001-01-01" and date_col=time_col)
Can't write, because of unique
constraint with some GROUP BY queries.
sjis character strings used within quoted table
names.
CREATE ... FULLTEXT keys with other
storage engines than MyISAM.
signal() on Windows because this appears to not be
100% reliable.
WHERE col_name=NULL on an indexed column
that had NULL values.
LEFT JOIN ... ON (col_name = constant) WHERE col_name = constant.
% could cause
a core dump.
TCP_NODELAY was not used on some systems. (Speed problem.)
The following changes are for InnoDB tables:
InnoDB variables to SHOW VARIABLES.
InnoDB tables.
DROP DATABASE now works also for InnoDB tables.
InnoDB now supports datafiles and raw disk partitions bigger
than 4 GB on those operating systems that have big files.
InnoDB calculates better table cardinality estimates for the
MySQL optimiser.
latin1 are ordered
according to the MySQL ordering.
Note: if you are using latin1 and have inserted characters whose
code is greater than 127 into an indexed CHAR column, you should
run CHECK TABLE on your table when you upgrade to 3.23.44, and
drop and reimport the table if CHECK TABLE reports an error!
innodb_thread_concurrency, helps in
performance tuning in heavily concurrent environments.
innodb_fast_shutdown, speeds up
server shutdown.
innodb_force_recovery, helps to save
your data in case the disk image of the database becomes corrupt.
innodb_monitor has been improved and a new
innodb_table_monitor added.
AUTO_INCREMENT columns with
multiple-line inserts.
MAX(col) is selected from an empty table, and
col is not the first column in a multi-column index.
INSERT DELAYED and FLUSH TABLES introduced
in 3.23.42.
SELECT with
many tables and multi-column indexes and 'range' type.
EXPLAIN SELECT when using
many tables and ORDER BY.
LOAD DATA FROM MASTER when using table with
CHECKSUM=1.
BDB tables.
BDB tables and UNIQUE columns defined
as NULL.
myisampack when using pre-space filled CHAR
columns.
--safe-user-create.
LOCK TABLES and BDB tables.
REPAIR TABLE on MyISAM tables with row
lengths in the range from 65517 to 65520 bytes.
mysqladmin shutdown when there was
a lot of activity in other threads.
INSERT DELAYED where delay thread could be
hanging on upgrading locks with no apparent reason.
myisampack and BLOB.
MERGE table come from the same
database.
LOAD DATA INFILE and transactional tables.
INSERT DELAYED with wrong column definition.
REPAIR of some particularly broken tables.
InnoDB and AUTO_INCREMENT columns.
InnoDB and RENAME TABLE columns.
InnoDB and BLOB columns. If you have
used BLOB columns larger than 8000 bytes in an InnoDB
table, it is necessary to dump the table with mysqldump, drop it and
restore it from the dump.
InnoDB when one could get the error Can't
execute the given command... even when no transaction was active.
ALTER TABLE). Now --lower_case_names
also works on Unix.
--sql-mode=option[,option[,option]] option to mysqld.
See section 4.1.1 mysqld Command-line Options.
shutdown on Solaris where the
`.pid' file wasn't deleted.
InnoDB now supports < 4 GB rows. The former limit was 8000 bytes.
doublewrite file flush method is used in InnoDB.
It reduces the need for Unix fsync() calls to a fraction and
improves performance on most Unix flavors.
InnoDB Monitor to print a lot of InnoDB state
information, including locks, to the standard output. This is useful in
performance tuning.
InnoDB have been fixed.
record_buffer to record_buffer and
record_rnd_buffer. To make things compatible to previous MySQL
versions, if record_rnd_buffer is not set, then it takes the
value of record_buffer.
ORDER BY where some ORDER BY parts
where wrongly removed.
ALTER TABLE and MERGE tables.
my_thread_init() and my_thread_end() to
`mysql_com.h'
--safe-user-create option to mysqld.
SELECT DISTINCT ... HAVING that caused error message
Can't find record in #...
--low-priority-updates and INSERT statements.
slave_net_timeout for replication.
UPDATE and BDB tables.
BDB tables when using key parts.
GRANT FILE ON database.* ...; previously
we added the DROP privilege for the database.
DELETE FROM tbl_name ... LIMIT 0 and
UPDATE FROM tbl_name ... LIMIT 0, which acted as though the
LIMIT clause was not present (they deleted or updated all selected
rows).
CHECK TABLE now checks if an AUTO_INCREMENT column contains
the value 0.
SIGHUP to mysqld will now only flush the logs,
not reset the replication.
1.0e1 (no sign after e).
--force to myisamchk now also updates states.
--warnings to mysqld. Now mysqld
prints the error Aborted connection only if this option is used.
SHOW CREATE TABLE when you didn't have a
PRIMARY KEY.
innodb_unix_file_flush_method variable to
innodb_flush_method.
BIGINT UNSIGNED to DOUBLE. This caused
a problem when doing comparisons with BIGINT values outside of the
signed range.
BDB tables when querying empty tables.
COUNT(DISTINCT) with LEFT JOIN and
there weren't any matching rows.
GEMINI table
type. GEMINI is not released under an Open Source license.
AUTO_INCREMENT sequence wasn't reset when dropping
and adding an AUTO_INCREMENT column.
CREATE ... SELECT now creates non-unique indexes delayed.
LOCK TABLES tbl_name READ followed by
FLUSH TABLES put an exclusive lock on the table.
REAL @variable values were represented with only 2 digits when
converted to strings.
LOAD TABLE FROM MASTER failed.
myisamchk --fast --force will no longer repair tables
that only had the open count wrong.
-lcma thread library on HP-UX 10.20 so
that MySQL will be more stable on HP-UX.
IF() and number of decimals in the result.
INSERT DELAYED was waiting for
a LOCK TABLE.
InnoDB when tablespace was full.
MERGE tables and big tables (> 4G) when using
ORDER BY.
SELECT from MERGE table
sometimes results in incorrectly ordered rows.
REPLACE() when using the ujis character set.
BDB patches 3.2.9.1 and 3.2.9.2.
--skip-stack-trace option to mysqld.
CREATE TEMPORARY now works with InnoDB tables.
InnoDB now promotes sub keys to whole keys.
CONCURRENT to LOAD DATA.
max_allowed_packet is too low to
read a very long log event from the master.
SELECT DISTINCT ... HAVING.
SHOW CREATE TABLE now returns TEMPORARY for temporary tables.
Rows_examined to slow query log.
WHERE that didn't match any rows.
mysqlcheck.
CHECK,
REPAIR, OPTIMIZE.
InnoDB.
SELECT * FROM tbl_name,tbl_name2 ... ORDER BY key_part1 LIMIT #
will use index on key_part1 instead of filesort.
LOCK TABLE to_table WRITE,...; INSERT INTO to_table... SELECT ...
when to_table was empty.
LOCK TABLE and BDB tables.
MATCH() in HAVING clause.
HEAP tables with LIKE.
--mysql-version option to safe_mysqld
INNOBASE to InnoDB (because the INNOBASE
name was already used). All configure options and mysqld
start options now use innodb instead of innobase. This
means that before upgrading to this version, you have to change any
configuration files where you have used innobase options!
CHAR(255) NULL columns.
master-host is not set, as
long as server-id is set and valid `master.info' is present.
SET SQL_SLAVE_SKIP_COUNTER=1; SLAVE START after a manual sanity
check/correction of data integrity.
REGEXP on 64-bit machines.
UPDATE and DELETE with WHERE unique_key_part IS NULL
didn't update/delete all rows.
INSERT DELAYED for tables that support transactions.
TEXT/BLOB column
with wrong date format.
ALTER TABLE and LOAD DATA INFILE that disabled
key-sorting. These commands should now be faster in most cases.
FLUSH or REPAIR) would not use indexes for the
next query.
ALTER TABLE to InnoDB tables on FreeBSD.
mysqld variables myisam_max_sort_file_size and
myisam_max_extra_sort_file_size.
InnoDB.
tis620 character set to make comparisons
case-independent and to fix a bug in LIKE for this character set.
Note: All tables that uses the tis620 character set must be
fixed with myisamchk -r or REPAIR TABLE !
--skip-safemalloc option to mysqld.
mysqld is run
as root.
FLUSH TABLES and TEMPORARY tables.
(Problem with freeing the key cache and error Can't reopen table....)
InnoDB with other character sets than latin1
and another problem when using many columns.
DISTINCT and summary functions.
SET TRANSACTION ISOLATION LEVEL ...
SELECT ... FOR UPDATE.
UPDATE where keys weren't always used to find the
rows to be updated.
CONCAT_WS() where it returned incorrect results.
CREATE ... SELECT and INSERT ... SELECT to not
allow concurrent inserts as this could make the binary log hard to repeat.
(Concurrent inserts are enabled if you are not using the binary or update log.)
glibc 2.2.
ORDER BY.
CLIENT_TRANSACTIONS.
SHOW VARIABLES when using INNOBASE tables.
SELECT DISTINCT didn't work.
SHOW ANALYZE for small tables.
run-all-tests.
INNOBASE support
to be compiled.
INNOBASE storage engine and the BDB storage engine
to the MySQL source distribution.
GEMINI tables.
INSERT DELAYED that caused threads to hang when
inserting NULL into an AUTO_INCREMENT column.
CHECK TABLE / REPAIR TABLE that could cause
a thread to hang.
REPLACE will not replace a row that conflicts with an
AUTO_INCREMENT generated key.
mysqld now only sets CLIENT_TRANSACTIONS in
mysql->server_capabilities if the server supports a
transaction-safe storage engine.
LOAD DATA INFILE to allow numeric values to be read into
ENUM and SET columns.
ALTER TABLE ... ORDER BY.
max_user_connections variable to mysqld.
max_allowed_packet, not the
arbitrary limit of 4 MB.
= in argument to --set-variable.
Waiting for table.
SHOW CREATE TABLE now displays the UNION() for MERGE
tables.
ALTER TABLE now remembers the old UNION() definition.
BDB storage engine that occurred when using an index
on multi-part key where a key part may be NULL.
MAX() optimisation on sub-key for BDB tables.
BDB
tables and BLOB or TEXT fields when joining many tables.
BDB tables and TEXT columns.
BLOB key where a const row wasn't found.
mysqlbinlog writes the timestamp value for each query.
This ensures that one gets same values for date functions like NOW()
when using mysqlbinlog to pipe the queries to another server.
--skip-gemini, --skip-bdb, and --skip-innodb
options to be specified when invoking mysqld, even if these storage
engines are not compiled in to mysqld.
GROUP BY ... DESC.
SET code, when one ran SET @foo=bar,
where bar is a column reference, an error was not properly generated.
--character-sets-dir option to myisampack.
REPAIR TABLE ... EXTENDED.
GROUP BY on an alias,
where the alias was the same as an existing column name.
SEQUENCE() as an example UDF function.
mysql_install_db to use BINARY for CHAR
columns in the privilege tables.
TRUNCATE tbl_name to TRUNCATE TABLE tbl_name
to use the same syntax as Oracle. Until 4.0 we will also allow
TRUNCATE tbl_name to not crash old code.
MyISAM tables when a BLOB was
first part of a multi-part key.
CASE didn't work with GROUP BY.
--sort-recover option to myisamchk.
myisamchk -S and OPTIMIZE TABLE now work on Windows.
DISTINCT on results from functions that referred
to a group function, like:
SELECT a, DISTINCT SEC_TO_TIME(SUM(a)) FROM tbl_name GROUP BY a, b;
libmysqlclient library.
Fixed bug in handling STOP event after ROTATE event in
replication.
DROP DATABASE.
Table_locks_immediate and Table_locks_waited status
variables.
SET SQL_SLAVE_SKIP_COUNTER=n command to recover from
replication glitches without a full database copy.
max_binlog_size variable; the binary log will be rotated
automatically when the size crosses the limit.
Last_error, Last_errno, and Slave_skip_counter
variables to SHOW SLAVE STATUS.
MASTER_POS_WAIT() function.
SIGILL, and SIGBUS in addition to
SIGSEGV.
mysqltest to take care of the timing issues in the test
suite.
ALTER TABLE can now be used to change the definition for a
MERGE table.
MERGE tables on Windows.
--temp-pool option to mysqld. Using this option
will cause most temporary files created to use a small set of names,
rather than a unique name for each new file. This is to work around a
problem in the Linux kernel dealing with creating a bunch of new files
with different names. With the old behaviour, Linux seems to "leak"
memory, as it's being allocated to the directory entry cache instead of
the disk cache.
BACKUP, RESTORE, CHECK, REPAIR, and
ANALYZE TABLE.
FULL to SHOW COLUMNS. Now we show the
privilege list for the columns only if this option is given.
SHOW LOGS when there weren't any BDB logs.
mysql_list_fields(). This is
to keep this code compatible with SHOW FIELDS.
MERGE tables didn't work on Windows.
SET PASSWORD=... on Windows.
TRIM("foo" from "foo") didn't return an empty string.
--with-version-suffix option to configure.
mysql_close().
RESTORE TABLE when trying to restore from a non-existent
directory.
SET PASSWORD.
MASTER_POS_WAIT().
BDB interface code. During
testing we found and fixed many errors in the interface code.
HAVING on an empty table could produce one result row when
it shouldn't.
HEAP tables on Windows.
SHOW TABLE STATUS didn't show correct average row length for tables
larger than 4G.
CHECK TABLE ... EXTENDED didn't check row links for fixed size tables.
MEDIUM to CHECK TABLE.
DECIMAL() keys on negative numbers.
HOUR() (and some other TIME functions) on a CHAR column
always returned NULL.
setrlimit() on Linux to get
-O --open-files-limit=# to work on Linux.
bdb_version variable to mysqld.
SELECT ... FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=t2.aIn this case the test in the
WHERE clause was wrongly optimised away.
MyISAM when deleting keys with possible NULL
values, but the first key-column was not a prefix-compressed text column.
mysql.server to read the [mysql.server] option file group
rather than the [mysql_server] group.
safe_mysqld and mysql.server to also read the
server option section.
Threads_created status variable to mysqld.
SHOW OPEN TABLES command.
myisamdump works against old mysqld servers.
myisamchk -k# so that it works again.
LOCK TABLES will now automatically start a new transaction.
BDB tables to not use internal subtransactions and reuse
open files to get more speed.
--mysqld=# option to safe_mysqld.
--fields-*-by and
--lines-terminated-by options to mysqldump and
mysqlimport. By Paul DuBois.
--safe-show-database option to mysqld.
have_bdb, have_gemini, have_innobase,
have_raid and have_openssl to SHOW VARIABLES to make it
easy to test for supported extensions.
--open-files-limit option to mysqld.
--open-files option to --open-files-limit in
safe_mysqld.
HEAP tables
that had many keys.
--bdb-no-sync works.
--bdb-recover to --bdb-no-recover as recover should
be on by default.
BDB locks to 10000.
BDB tables.
mysqld_multi.sh to use configure variables. Patch by
Christopher McCrory.
--skip-networking on Debian Linux.
UNOPENED in error messages.
SHOW LOGS queries.
<=> operator.
REPLACE with BDB tables.
LPAD() and RPAD() will shorten the result string if it's longer
than the length argument.
SHOW LOGS command.
BDB logs on shutdown.
PRIMARY keys first, followed by
UNIQUE keys.
UPDATE involving multi-part keys where one
specified all key parts both in the update and the WHERE part. In
this case MySQL could try to update a record that didn't match
the whole WHERE part.
mysqld to report the
hostname as '' in some error messages.
HEAP type tables; the variable
max_heap_table_size wasn't used. Now either MAX_ROWS or
max_heap_table_size can be used to limit the size of a HEAP
type table.
bdb_lock_max variable to bdb_max_lock.
AUTO_INCREMENT on sub-fields for BDB tables.
ANALYZE of BDB tables.
BDB tables, we now store the number of rows; this helps to optimise
queries when we need an approximation of the number of rows.
ROLLBACK when you have updated a non-transactional table
you will get an error as a warning.
--bdb-shared-data option to mysqld.
Slave_open_temp_tables status variable to mysqld
binlog_cache_size and max_binlog_cache_size variables to
mysqld.
DROP TABLE, RENAME TABLE, CREATE INDEX and
DROP INDEX are now transaction endpoints.
DROP DATABASE on a symbolically linked database, both
the link and the original database is deleted.
DROP DATABASE to work on OS/2.
SELECT DISTINCT ... table1 LEFT JOIN
table2 ... when table2 was empty.
--abort-slave-event-count and
--disconnect-slave-event-count options to mysqld for
debugging and testing of replication.
SHOW KEYS now shows whether key is FULLTEXT.
mysqld_multi. See section 4.7.3 mysqld_multi, A Program for Managing Multiple MySQL Servers.
mysql-multi.server.sh. Thanks to
Tim Bunce Tim.Bunce@ig.co.uk for modifying mysql.server to
easily handle hosts running many mysqld processes.
safe_mysqld, mysql.server, and mysql_install_db have
been modified to use mysql_print_defaults instead of various hacks
to read the `my.cnf' files. In addition, the handling of various
paths has been made more consistent with how mysqld handles them
by default.
FULLTEXT indexes in one table.
REPAIR/OPTIMIZE.
Yuri Dario.
FLUSH TABLES tbl_name didn't always flush the index tree
to disk properly.
--bootstrap is now run in a separate thread. This fixes a problem
that caused mysql_install_db to core dump on some Linux machines.
mi_create() to use less stack space.
MATCH() when used
with UNIQUE key.
crash-me and the MySQL benchmarks to also work
with FrontBase.
RESTRICT and CASCADE after DROP TABLE to make
porting easier.
--slow-log.
connect_timeout variable to mysql and mysqladmin.
connect-timeout as an alias for timeout for option files
read by mysql_options().
--pager[=...], --no-pager,
--tee=... and --no-tee to the mysql client. The
new corresponding interactive commands are pager, nopager,
tee and notee. See section 4.8.2 mysql, The Command-line Tool, mysql --help
and the interactive help for more information.
MyISAM table failed.
SELECT, UPDATE and INSERT
statements running. The symptom was that the UPDATE and
INSERT queries were locked for a long time while new SELECT
statements were executed before the updates.
options_files with mysql_options() the
return-found-rows option was ignored.
interactive-timeout in the option file that
is read by mysql_options(). This makes it possible to force
programs that run for a long time (like mysqlhotcopy) to use the
interactive_timeout time instead of the wait_timeout time.
--log-long-format then also queries that
do not use an index are logged, even if the query takes less than
long_query_time seconds.
LEFT JOIN which caused all columns in a reference
table to be NULL.
NATURAL JOIN without keys.
TEXT or BLOB.
DROP of temporary tables wasn't stored in the update/binary log.
SELECT DISTINCT * ... LIMIT # only returned one row.
strstr() for SPARC and cleaned up
the `global.h' header file to avoid a problem with bad aliasing with
the compiler submitted with RedHat 7.0. (Reported by Trond Eivind Glomsrød)
--skip-networking option now works properly on NT.
ISAM tables when a row with a length
of more than 65K was shortened by a single byte.
MyISAM when running multiple updating processes on
the same table.
FLUSH TABLE tbl_name.
--replicate-ignore-table, --replicate-do-table,
--replicate-wild-ignore-table, and --replicate-wild-do-table
options to mysqld.
IO_CACHE mechanism instead of
FILE to avoid OS problems when there are many files open.
--open-files and --timezone options to safe_mysqld.
CREATE TEMPORARY TABLE ... SELECT ....
CREATE TABLE ... SELECT NULL.
large_file_support,net_read_timeout,
net_write_timeout and query_buffer_size to SHOW VARIABLES.
created_tmp_files and sort_merge_passes
to SHOW STATUS.
FOREIGN KEY definition.
TRUNCATE table_name as a synonym for
DELETE FROM table_name.
BDB key compare function when comparing part keys.
bdb_lock_max variable to mysqld.
mysql_connect() now aborts on Linux if the server doesn't answer in
timeout seconds.
SLAVE START did not work if you started with
--skip-slave-start and had not explicitly run CHANGE MASTER TO.
SHOW MASTER STATUS to be consistent with
SHOW SLAVE STATUS. (It now has no directory in the log name.)
PURGE MASTER LOGS TO.
SHOW MASTER LOGS.
--safemalloc-mem-limit option to mysqld to simulate memory
shortage when compiled with the --with-debug=full option.
SHOW SLAVE STATUS was using an uninitialised mutex if the slave had
not been started yet.
ELT() and MAKE_SET() when the query used
a temporary table.
CHANGE MASTER TO without specifying MASTER_LOG_POS would
set it to 0 instead of 4 and hit the magic number in the master binlog.
ALTER TABLE ... ORDER BY ... syntax added. This will create the
new table with the rows in a specific order.
MyISAM tables sometimes failed
when the datafile was corrupt.
SHOW CREATE when using AUTO_INCREMENT columns.
BDB tables to use new compare function in Berkeley DB 3.2.3.
latin5 (turkish) character set.
FLUSH MASTER and FLUSH SLAVE to RESET MASTER
and RESET SLAVE.
<> to work properly with NULL.
SUBSTRING_INDEX() and REPLACE().
(Patch by Alexander Igonitchev)
CREATE TEMPORARY TABLE IF NOT EXISTS not to produce an error
if the table exists.
PRIMARY KEY in a BDB table, a hidden
PRIMARY KEY will be created.
BDB tables.
LEFT JOIN in some cases preferred a full table scan when there was
no WHERE clause.
--log-slow-queries, don't count the time waiting for a lock.
MyISAM tables if you start mysqld with
--myisam-recover.
TYPE= keyword from CHECK and
REPAIR. Allow CHECK options to be combined. (You can still
use TYPE=, but this usage is deprecated.)
--replicate-rewrite-db option to mysqld.
--skip-slave-start option to mysqld.
INSERT INTO foo(some_key)
values (1),(1)) erroneously terminated the slave thread.
DISTINCT is only used on columns
from some of the tables.
1e1).
SHOW GRANTS didn't always show all column grants.
--default-extra-file=# option to all MySQL clients.
INSERT statements now are initialised properly.
UPDATE didn't always work when used with a range on a timestamp that
was part of the key that was used to find rows.
FULLTEXT index when inserting a NULL column.
mkstemp() instead of tempnam(). Based
on a patch from John Jones.
databasename works as second argument to mysqlhotcopy.
UMASK and UMASK_DIR environment variables
now can be specified in octal by beginning the value with a zero.
RIGHT JOIN. This makes RIGHT a reserved word.
@@IDENTITY as a synonym for LAST_INSERT_ID().
(This is for MSSQL compatibility.)
myisamchk and REPAIR when using FULLTEXT
index.
LOAD DATA INFILE now works with FIFOs.
(Patch by Toni L. Harbaugh-Blackford.)
FLUSH LOGS broke replication if you specified a log name with an
explicit extension as the value of the log-bin option.
MyISAM with packed multi-part keys.
CHECK TABLE on Windows.
FULLTEXT index always used the koi8_ukr
character set.
CHECK TABLE.
MyISAM repair/reindex code didn't use the --tmpdir
option for its temporary files.
BACKUP TABLE and RESTORE TABLE.
CHANGE MASTER TO when the slave did not have
the master to start with.
Time in the processlist for Connect of
the slave thread.
FLUSH MASTER if you didn't specify
a filename argument to --log-bin.
--memlock option to mysqld to lock mysqld
in memory on systems with the mlockall() call (like in Solaris).
HEAP tables didn't use keys properly. (Bug from 3.23.23.)
MERGE tables (keys, mapping, creation,
documentation...). See section 7.2 MERGE Tables.
mysqldump from 3.23 which caused some CHAR columns
not to be quoted.
analyze, check, optimize and repair code.
OPTIMIZE TABLE is now mapped to REPAIR with statistics and
sorting of the index tree. This means that for the moment it only
works on MyISAM tables.
ORDER BY bug with BDB tables.
mysqld couldn't remove the `.pid' file
under Windows.
--log-isam to log MyISAM tables instead of isam
tables.
CHECK TABLE to work on Windows.
pwrite() safe on Windows.
created_tmp_disk_tables variable to mysqld.
TIMESTAMP(X) columns, MySQL now reports columns with X
other than 14 or 8 to be strings.
latin1 as it was before MySQL Version 3.23.23.
Any table that was created or modified with 3.23.22 must be repaired if it has
CHAR columns that may contain characters with ASCII values greater than
128!
BDB tables and reading on a unique (not primary) key.
win1251 character set (it's now only marked deprecated).
REPAIR TABLE or myisamchk before use!
--core-file option to mysqld to get a core file on
Linux if mysqld dies on the SIGSEGV signal.
mysql now starts with option
--no-named-commands (-g) by default. This option can be
disabled with --enable-named-commands (-G). This may cause
incompatibility problems in some cases, for example, in SQL scripts that
use named commands without a semicolon, etc. ! Long format commands
still work from the first line.
DROP TABLE statements at
the same time.
LEFT JOIN on an
empty table.
mysqld with incorrect options.
free() bug in mysqlimport.
MyISAM index handling of
DECIMAL/NUMERIC keys.
MyISAM tables. In some contexts,
usage of MIN(key_part) or MAX(key_part) returned an empty set.
mysqlhotcopy to use the new FLUSH TABLES table_list
syntax. Only tables which are being backed up are flushed now.
--enable-thread-safe-client so
that both non-threaded (-lmysqlclient) and threaded
(-lmysqlclient_r) libraries are built. Users who linked
against a threaded -lmysqlclient will need to link against
-lmysqlclient_r now.
RENAME TABLE command.
NULL values in COUNT(DISTINCT ...).
ALTER TABLE, LOAD DATA INFILE on empty tables and
INSERT ... SELECT ... on empty tables to create non-unique indexes
in a separate batch with sorting. This will make the above calls much
faster when you have many indexes.
ALTER TABLE now logs the first used insert_id correctly.
BLOB column.
DATE_ADD/DATE_SUB where it returned a datetime instead
of a date.
***DEAD*** in SHOW PROCESSLIST.
pthread_rwlock_rdlock code.
HEAP table, all rows
weren't always deleted.
HEAP tables for searches on a part
index.
SELECT on part keys to work with BDB tables.
INSERT INTO bdb_table ... SELECT to work with BDB tables.
CHECK TABLE now updates key statistics for the table.
ANALYZE TABLE will now only update tables that have been changed
since the last ANALYZE. Note that this is a new feature and tables
will not be marked to be analysed until they are updated in any way with
3.23.23 or newer. For older tables, you have to do CHECK TABLE
to update the key distribution.
CHECK, ANALYZE,
REPAIR and SHOW CREATE commands.
CHANGE MASTER TO statement.
FAST, QUICK EXTENDED check types to
CHECK TABLES.
myisamchk so that --fast and
--check-only-changed are also honored with --sort-index and
--analyze.
LOAD TABLE FROM MASTER that did not lock the
table during index re-build.
LOAD DATA INFILE broke replication if the database was excluded
from replication.
SHOW SLAVE STATUS and SHOW MASTER STATUS.
SLAVE STOP now will not return until the slave thread actually exits.
MATCH() function and FULLTEXT index type
(for MyISAM files). This makes FULLTEXT a reserved word.
lex_hash.h is created properly for each MySQL
distribution.
MASTER and COLLECTION are not reserved words.
--slow-query-log didn't contain the whole queries.
BDB tables are rolled back if the
connection is closed unexpectedly.
gcc 2.96 (intel) and gcc 2.9
(IA64) in gen_lex_hash.c.
host= in the
`my.cnf' file.
DATE_ADD()/DATE_SUB()
against a number.
-F, --fast for myisamchk. Added
-C, --check-only-changed option to myisamchk.
ANALYZE tbl_name to update key statistics for tables.
0x... to be regarded as integers by default.
SHOW PROCESSLIST.
auto-rehash on reconnect for the mysql client.
MyISAM, where the index file couldn't
get bigger than 64M.
SHOW MASTER STATUS and SHOW SLAVE STATUS.
mysql_character_set_name() function to the
MySQL C API.
mysql_config script.
< or > with a char column that was only
partly indexed.
mysqladmin to use CREATE DATABASE and DROP
DATABASE statements instead of the old deprecated API calls.
chown warning in safe_mysqld.
ORDER BY that was introduced in 3.23.19.
DELETE FROM tbl_name to do a drop+create of
the table if we are in AUTOCOMMIT mode (needed for BDB tables).
ISAM/MyISAM
index files get full during an INSERT/UPDATE.
myisamchk didn't correctly update row checksum when used with
-ro (this only gave a warning in subsequent runs).
REPAIR TABLE so that it works with tables without indexes.
DROP DATABASE.
LOAD TABLE FROM MASTER is sufficiently bug-free to announce it as
a feature.
MATCH and AGAINST are now reserved words.
DELETE FROM tbl_name removed the `.frm' file.
SHOW CREATE TABLE.
MyISAM table
when doing update based on key on a table with many keys and some key changed
values.
ORDER BY can now use REF keys to find subsets of the rows
that need to be sorted.
print_defaults program to my_print_defaults
to avoid name confusion.
NULLIF() to work according to ANSI SQL99.
net_read_timeout and net_write_timeout as startup
parameters to mysqld.
myisamchk --sort-records
on a table with prefix compressed index.
pack_isam and myisampack to the standard MySQL
distribution.
BEGIN WORK (the same as BEGIN).
ORDER BY on a CONV() expression.
LOAD TABLE FROM MASTER.
FLUSH MASTER and FLUSH SLAVE.
FLUSH TABLES WITH READ LOCK to make a global lock suitable for
making a copy of MySQL datafiles.
CREATE TABLE ... SELECT ... PROCEDURE now works.
GROUP BY on VARCHAR/CHAR columns.
READ and a
WRITE lock.
myisamchk and RAID tables.
FIND_IN_SET() when the first argument was NULL.
LEFT JOIN and ORDER BY where the first
table had only one matching row.
duplicated key problem when doing big GROUP BY operations.
(This bug was probably introduced in 3.23.15.)
INNER JOIN to match ANSI SQL.
NATURAL JOIN syntax.
BDB interface.
--no-defaults and --defaults-file to
safe_mysqld.sh and mysql_install_db.sh.
USE INDEX works with PRIMARY keys.
BEGIN statement to start a transaction in AUTOCOMMIT mode.
AUTOCOMMIT mode
and if there is a pending transaction. If there is a pending transaction,
the client library will give an error before reconnecting to the server to
let the client know that the server did a rollback.
The protocol is still backward-compatible with old clients.
KILL now works on a thread that is locked on a 'write' to a dead client.
log-slave-updates option to mysqld, to allow
daisy-chaining the slaves.
pthread_t
is not the same as int.
INSERT DELAYED code when doing
ALTER TABLE.
INSERT DELAYED.
SLAVE START and SLAVE STOP statements.
TYPE=QUICK option to CHECK and to REPAIR.
REPAIR TABLE when the table was in use by other threads.
gdb when one does a lot of reconnects. This will also improve
systems where you can't use persistent connections.
UPDATE IGNORE will not abort if an update results in a
DUPLICATE_KEY error.
CREATE TEMPORARY TABLE commands in the update log.
delay_key_write tables and CHECK TABLE.
replicate-do-db and replicate-ignore-db options to
mysqld, to restrict which databases get replicated.
SQL_LOG_BIN option.
mysqld as root, you must now use the --user=root option.
FLUSH TABLES command.
slow_launch_time variable and the Slow_launch_threads
status variable to mysqld. These can be examined with
mysqladmin variables and mysqladmin extended-status.
INET_NTOA() and INET_ATON().
IF() now depends on the second and
third arguments and not only on the second argument.
myisamchk could go into a loop when trying to
repair a crashed table.
INSERT DELAYED to update log if SQL_LOG_UPDATE=0.
REPLACE on HEAP tables.
SHOW VARIABLES output.
DELETE of many rows on a table with
compressed keys where MySQL scanned the index to find the rows.
CHECK on table with deleted keyblocks.
LAST_INSERT_ID() to update
a table with an AUTO_INCREMENT key.
NULLIF() function.
LOAD DATA INFILE on a table with
BLOB/TEXT columns.
MyISAM to be faster when inserting keys in sorted order.
EXPLAIN SELECT ... now also prints out whether MySQL needs to
create a temporary table or use file sorting when resolving the SELECT.
ORDER BY parts where the part is a
constant expression in the WHERE part. Indexes can now be used
even if the ORDER BY doesn't match the index exactly, as long as
all the unused index parts and all the extra ORDER BY
columns are constants in the WHERE clause. See section 5.4.3 How MySQL Uses Indexes.
UPDATE and DELETE on a whole unique key in the WHERE part
are now faster than before.
RAID_CHUNKSIZE to be in 1024-byte increments.
LOAD_FILE(NULL).
mysql_real_escape_string() function to the MySQL C API.
CONCAT() where one of the arguments was a function
that returned a modified argument.
myisamchk, where it updated the header in
the index file when one only checked the table. This confused the
mysqld daemon if it updated the same table at the same time. Now
the status in the index file is only updated if one uses
--update-state. With older myisamchk versions you should
use --read-only when only checking tables, if there is the
slightest chance that the mysqld server is working on the table at the
same time!
DROP TABLE is logged in the update log.
DECIMAL() key field
where the column data contained leading zeros.
myisamchk when the AUTO_INCREMENT column isn't
the first key.
DATETIME in ISO8601 format: 2000-03-12T12:00:00
mysqld binary can now handle many different
character sets (you can choose which when starting mysqld).
REPAIR TABLE.
mysql_thread_safe() function to the MySQL C API.
UMASK_DIR environment variable.
CONNECTION_ID() function to return the client connection thread
ID.
= on BLOB or VARCHAR BINARY keys, where
only a part of the column was indexed, the whole column of the result
row wasn't compared.
sjis character set and ORDER BY.
GROUP BY part.
LOCK TABLE command; this fixed the problem one got when running
the test-ATIS test with --fast or --check-only-changed.
SQL_BUFFER_RESULT option to SELECT.
CHECK TABLE command.
MyISAM in 3.23.12 that didn't get into the source
distribution because of CVS problems.
mysqladmin shutdown will wait for the local server
to close down.
print_defaults program to the `.rpm' files. Removed
mysqlbug from the client `.rpm' file.
MyISAM involving REPLACE ... SELECT ... which could
give a corrupted table.
myisamchk where it incorrectly reset the
AUTO_INCREMENT value.
DISTINCT on HEAP temporary tables to use hashed
keys to quickly find duplicated rows. This mostly concerns queries of
type SELECT DISTINCT ... GROUP BY .... This fixes a problem where
not all duplicates were removed in queries of the above type. In
addition, the new code is MUCH faster.
IF NOT EXISTS clause to CREATE DATABASE.
--all-databases and --databases options to mysqldump
to allow dumping of many databases at the same time.
DECIMAL() index in MyISAM tables.
mysqladmin shutdown on a local connection, mysqladmin
now waits until the PID file is gone before terminating.
COUNT(DISTINCT ...) queries.
myisamchk works properly with RAID tables.
LEFT JOIN and key_field IS NULL.
net_clear() which could give the error Aborted
connection in the MySQL clients.
USE INDEX (key_list) and IGNORE INDEX (key_list) as
parameters in SELECT.
DELETE and RENAME should now work on RAID tables.
ALTER TABLE tbl_name ADD (field_list) syntax.
GRANT/REVOKE ALL PRIVILEGES doesn't affect
GRANT OPTION.
SHOW GRANTS.
UNIQUE INDEX in CREATE statements.
mysqlhotcopy - fast online hot-backup utility for local
MySQL databases. By Tim Bunce.
mysqlaccess. Thanks to Steve Harvey for this.
--i-am-a-dummy and --safe-updates options to mysql.
select_limit and max_join_size variables to mysql.
SQL_MAX_JOIN_SIZE and SQL_SAFE_UPDATES options.
READ LOCAL lock that doesn't lock the table for concurrent
inserts. (This is used by mysqldump.)
LOCK TABLES ... READ doesn't anymore allow concurrent
inserts.
--skip-delay-key-write option to mysqld.
_rowid can now be used as an alias for an integer type unique indexed
column.
SIGPIPE when compiling with --thread-safe-clients
to make things safe for old clients.
LOCK TABLES.
INSERT DELAYED.
date_col BETWEEN const_date AND const_date works.
NULL in a table with
BLOB/TEXT columns.
WHERE K1=1 and K3=2 and (K2=2 and K4=4 or K2=3 and K4=5)
source command to mysql to allow reading of batch files
inside the mysql client. Original patch by Matthew Vanecek.
WITH GRANT OPTION option.
GRANT error when using tables from many
databases in the same query.
SELECT when using many overlapping indexes.
MySQL should now be able to choose keys even better when there
are many keys to choose from.
=). For example, the following type of queries should now
be faster: SELECT * from key_part_1=const and key_part_2 > const2
VARCHAR columns to CHAR columns
didn't change row type from dynamic to fixed.
SELECT FLOOR(POW(2,63)).
mysqld startup option from --delay-key-write to
--delay-key-write-for-all-tables.
read-next-on-key to HEAP tables. This should fix all
problems with HEAP tables when using non-UNIQUE keys.
--log-slow-queries option to mysqld to log all queries
that take a long time to a separate log file with a time indicating how
long the query took.
WHERE key_col=RAND(...).
SELECT ... LEFT JOIN ... key_col IS NULL,
when key_col could contain NULL values.
LOAD DATA INFILE.
NISAM.
ISAM when doing some ORDER BY ... DESC queries.
--delay-key-write didn't enable delayed key writing.
TEXT column which involved only case changes.
INSERT DELAYED doesn't update timestamps that are given.
YEARWEEK() and options x, X, v and
V to DATE_FORMAT().
MAX(indexed_column) and HEAP tables.
BLOB NULL keys and LIKE "prefix%".
MyISAM and fixed-length rows < 5 bytes.
GROUP BY queries.
ENUM field value
was too big.
pthread_mutex_timedwait,
which is used with INSERT DELAYED. See section 2.6.1 Linux Notes (All Linux Versions).
MyISAM with keys > 250 characters.
MyISAM one can now do an INSERT at the same time as other
threads are reading from the table.
max_write_lock_count variable to mysqld to force a
READ lock after a certain number of WRITE locks.
delay_key_write on show variables.
concurrency variable to thread_concurrency.
LOCATE(substr,str), POSITION(substr IN str),
LOCATE(substr,str,pos), INSTR(str,substr),
LEFT(str,len), RIGHT(str,len),
SUBSTRING(str,pos,len), SUBSTRING(str FROM pos FOR len),
MID(str,pos,len), SUBSTRING(str,pos), SUBSTRING(str
FROM pos), SUBSTRING_INDEX(str,delim,count), RTRIM(str),
TRIM([[BOTH | TRAILING] [remstr] FROM] str),
REPLACE(str,from_str,to_str), REVERSE(str),
INSERT(str,pos,len,newstr), LCASE(str), LOWER(str),
UCASE(str) and UPPER(str); patch by Wei He.
FULL to SHOW PROCESSLIST.
--verbose to mysqladmin.
HEAP to MyISAM.
HEAP tables when doing insert + delete + insert + scan the
table.
REPLACE() and LOAD DATA INFILE.
interactive_timeout variable to mysqld.
mysql_data_seek() from ulong to
ulonglong.
-O lower_case_table_names={0|1} option to mysqld to allow
users to force table names to lowercase.
SELECT ... INTO DUMPFILE.
--ansi option to mysqld to make some functions
ANSI SQL compatible.
#sql.
` (" in --ansi mode).
snprintf() when printing floats to avoid some buffer
overflows on FreeBSD.
FLOOR() overflow safe on FreeBSD.
--quote-names option to mysqldump.
PRIMARY KEY NOT NULL.
encrypt() to be thread-safe and not reuse buffer.
mysql_odbc_escape_string() function to support big5 characters in
MyODBC.
FLOAT and DOUBLE (without any length modifiers)
no longer are fixed decimal point numbers.
FLOAT(X): Now this is the same as FLOAT if
X <= 24 and a DOUBLE if 24 < X <= 53.
DECIMAL(X) is now an alias for DECIMAL(X,0) and DECIMAL
is now an alias for DECIMAL(10,0). The same goes for NUMERIC.
ROW_FORMAT={default | dynamic | fixed | compressed} to
CREATE_TABLE.
DELETE FROM table_name didn't work on temporary tables.
CHAR_LENGTH() to be multi-byte character safe.
ORD(string).
SELECT DISTINCT ... ORDER BY RAND().
MyISAM
level.
ALTER TABLE didn't work.
AUTO_INCREMENT column in two keys
MyISAM, you now can have an AUTO_INCREMENT column as a key
sub part:
CREATE TABLE foo (a INT NOT NULL AUTO_INCREMENT, b CHAR(5), PRIMARY KEY (b,a))
MyISAM with packed char keys that could be NULL.
AS on field name with CREATE TABLE table_name SELECT ... didn't
work.
NATIONAL and NCHAR when defining character columns.
This is the same as not using BINARY.
NULL columns in a PRIMARY KEY (only in UNIQUE
keys).
LAST_INSERT_ID() if one uses this in ODBC:
WHERE auto_increment_column IS NULL. This seems to fix some problems
with Access.
SET SQL_AUTO_IS_NULL=0|1 now turns on/off the handling of
searching after the last inserted row with WHERE
auto_increment_column IS NULL.
concurrency to mysqld for Solaris.
--relative option to mysqladmin to make
extended-status more useful to monitor changes.
COUNT(DISTINCT ...) on an empty table.
LOAD DATA INFILE and BLOB columns.
~ (negation).
UDF functions.
DATETIME into a TIME column no longer will
try to store 'days' in it.
SUM().)
LIKE "%" on an index that may have NULL values.
REVOKE ALL PRIVILEGES didn't revoke all privileges.
GRANT option for a database, he couldn't grant
privileges to other users.
SHOW GRANTS FOR user (by Sinisa).
date_add syntax: date/datetime + INTERVAL # interval_type.
By Joshua Chamas.
LOAD DATA REPLACE.
REGEXP is now case-insensitive if you use non-binary strings.
MyISAM.
ASC is now the default again for ORDER BY.
LIMIT to UPDATE.
mysql_change_user() function to the MySQL C API.
SHOW VARIABLES.
--[whitespace] comments.
INSERT into tbl_name VALUES (), that is, you may now specify
an empty value list to insert a row in which each column is set to its
default value.
SUBSTRING(text FROM pos) to conform to ANSI SQL. (Before this
construct returned the rightmost pos characters.)
SUM() with GROUP BY returned 0 on some systems.
SHOW TABLE STATUS.
DELAY_KEY_WRITE option to CREATE TABLE.
AUTO_INCREMENT on any key part.
YEAR(NOW()) and YEAR(CURDATE()).
CASE construct.
COALESCE().
SELECT * FROM table_name WHERE
key_part1 >= const AND (key_part2 = const OR key_part2 = const). The
bug was that some rows could be duplicated in the result.
myisamchk without -a updated the index
distribution incorrectly.
SET SQL_LOW_PRIORITY_UPDATES=1 was causing a parse error.
WHERE clause.
UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100
'1999-01-00'.
SELECT ... WHERE key_part1=const1 AND
key_part_2=const2 AND key_part1=const4 AND key_part2=const4; indextype
should be range instead of ref.
egcs 1.1.2 optimiser bug (when using BLOBs) on Linux Alpha.
LOCK TABLES combined with DELETE FROM table.
MyISAM tables now allow keys on NULL and BLOB/TEXT columns.
SELECT ... FROM t1 LEFT JOIN t2 ON ... WHERE t2.not_null_column IS NULL.
ORDER BY and GROUP BY can be done on functions.
ORDER BY RAND().
WHERE key_column = function.
WHERE key_column = col_name even if
the columns are not identically packed.
WHERE col_name IS NULL.
MyISAM tables)
HEAP temporary tables to MyISAM tables
in case of 'table is full' errors.
--init-file=file_name option to mysqld.
COUNT(DISTINCT value, [value, ...]).
CREATE TEMPORARY TABLE now creates a temporary table, in its own
namespace, that is automatically deleted if connection is dropped.
CASE): CASE, THEN, WHEN, ELSE and END.
EXPORT_SET() and MD5().
MyISAM) with a lot of new features.
See section 7.1 MyISAM Tables.
HEAP tables which are extremely fast for
lookups.
LOAD_FILE(filename) to get the contents of a file as a
string value.
<=> which will act as = but will return TRUE
if both arguments are NULL. This is useful for comparing changes
between tables.
EXTRACT(interval FROM datetime) function.
FLOAT(X) are not rounded on storage and may be
in scientific notation (1.0 E+10) when retrieved.
REPLACE is now faster than before.
LIKE character comparison to behave as =;
This means that 'e' LIKE ''e' is now true. (If the line doesn't
display correctly, the latter 'e' is a French 'e' with a dot above.)
SHOW TABLE STATUS returns a lot of information about the tables.
LIKE to the SHOW STATUS command.
Privileges column to SHOW COLUMNS.
Packed and Comment columns to SHOW INDEX.
CREATE TABLE ... COMMENT "xxx").
UNIQUE, as in
CREATE TABLE table_name (col int not null UNIQUE)
CREATE TABLE table_name SELECT ...
CREATE TABLE IF NOT EXISTS ...
CHAR(0) columns.
DATE_FORMAT() now requires `%' before any format character.
DELAYED is now a reserved word (sorry about that :( ).
analyse, file: `sql_analyse.c'.
This will describe the data in your query. Try the following:
SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])This procedure is extremely useful when you want to check the data in your table!
BINARY cast to force a string to be compared in case-sensitive fashion.
--skip-show-database option to mysqld.
UPDATE now also works
with BLOB/TEXT columns.
INNER join syntax. NOTE: This made INNER
a reserved word!
IP/NETMASK syntax.
NOT NULL DATE/DATETIME column with IS
NULL, this is changed to a compare against 0 to satisfy some ODBC
applications. (By shreeve@uci.edu.)
NULL IN (...) now returns NULL instead of 0. This will
ensure that null_column NOT IN (...) doesn't match
NULL values.
TIME columns.
TIME strings to be more strict. Now the
fractional second part is detected (and currently skipped). The
following formats are supported:
DATETIME.
LOW_PRIORITY attribute to LOAD DATA INFILE.
LOAD DATA INFILE.
DECIMAL(x,y) now works according to ANSI SQL.
LAST_INSERT_ID() is now updated for INSERT INTO ... SELECT.
SELECT DISTINCT is much faster; it uses the new UNIQUE
functionality in MyISAM. One difference compared to MySQL Version 3.22
is that the output of DISTINCT is not sorted anymore.
mysql_num_fields() on
a MYSQL object, you must use mysql_field_count() instead.
LIBWRAP; patch by Henning P. Schmiedehausen.
AUTO_INCREMENT for other than numerical columns.
AUTO_INCREMENT will now automatically make the column
NOT NULL.
NULL as the default value for AUTO_INCREMENT columns.
SQL_BIG_RESULT; SQL_SMALL_RESULT is now default.
--enable-large-files and --disable-large-files switches
to configure. See `configure.in' for some systems where this is
automatically turned off because of broken implementations.
readline to 4.0.
CREATE TABLE options: PACK_KEYS and CHECKSUM.
--default-table-type option to mysqld.
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.
STD().
ISAM library from 3.23.
INSERT DELAYED.
LEFT JOIN/STRAIGHT_JOIN
on a table with only one row.
GROUP BY on TINYBLOB columns; this
caused bugzilla to not show rows in some queries.
LOCK TABLE.
SELECT DISTINCT queries.
mysqlhotcopy, a fast online hot-backup utility for local MySQL
databases. By Tim Bunce.
mysqlaccess. Thanks to Steve Harvey for this.
GROUP functions.
ISAM code when deleting rows on tables with
packed indexes.
SELECT when using many overlapping indexes.
SELECT FLOOR(POW(2,63)).
WITH GRANT OPTION option.
GROUP BY queries.
ENUM field value
was too big.
mysqlshutdown.exe and mysqlwatch.exe to the Windows
distribution.
ORDER BY on a reference key.
INSERT DELAYED doesn't update timestamps that are given.
LEFT JOIN and COUNT() on a column which
was declared NULL + and it had a DEFAULT value.
CONCAT() in a WHERE clause.
AVG() and STD() with NULL values.
BLOB columns.
ROUND() will now work on Windows.
BLOB/TEXT column argument to
REVERSE().
/*! */ with version numbers.
SUBSTRING(text FROM pos) to conform to ANSI SQL. (Before this
construct returned the rightmost 'pos' characters.)
LOCK TABLES combined with DELETE FROM table
INSERT ... SELECT didn't use BIG_TABLES.
SET SQL_LOW_PRIORITY_UPDATES=# didn't work.
GRANT ... IDENTIFIED BY
SELECT * FROM table_name WHERE key_part1 >= const AND (key_part2 = const
OR key_part2 = const).
ISAM.
DATA is not a reserved word anymore.
LOCK TABLES table_name READ; FLUSH TABLES;
isamchk should now work on Windows.
libtool 1.3.2.
configure.
--defaults-file=### to option file handling to force use
of only one specific option file.
CREATE syntax to ignore MySQL Version 3.23 keywords.
INSERT DELAYED on a table locked with
LOCK TABLES.
DROP TABLE on a table that was
locked by another thread.
GRANT/REVOKE commands in the update log.
isamchk to detect a new error condition.
NATURAL LEFT JOIN.
mysql_close() directly after
mysql_init().
delayed_insert_thread counting when you couldn't create a new
delayed_insert thread.
CONCAT() with many arguments.
DELETE FROM TABLE when table was locked by
another thread.
LEFT JOIN involving empty tables.
mysql.db column from CHAR(32) to CHAR(60).
MODIFY and DELAYED are not reserved words anymore.
TIME column.
Host '...' is not allowed to connect to this MySQL
server after one had inserted a new MySQL user with a GRANT
command.
TCP_NODELAY also on Linux (should give faster TCP/IP
connections).
STD() for big tables when result should be 0.
INSERT DELAYED had some garbage at end in the update log.
mysql_install_db (from 3.22.17).
BLOB
columns.
shutdown
not all threads died properly.
-O flush_time=# to mysqld. This is mostly
useful on Windows and tells how often MySQL should close all
unused tables and flush all updated tables to disk.
VARCHAR column compared with CHAR column
didn't use keys efficiently.
--log-update and connecting
without a default database.
configure and portability problems.
LEFT JOIN on tables that had circular dependencies caused
mysqld to hang forever.
mysqladmin processlist could kill the server if a new user logged in.
DELETE FROM tbl_name WHERE key_column=col_name didn't find any matching
rows. Fixed.
DATE_ADD(column, ...) didn't work.
INSERT DELAYED could deadlock with status 'upgrading lock'
ENCRYPT() to take longer salt strings than 2 characters.
longlong2str is now much faster than before. For Intel x86
platforms, this function is written in optimised assembler.
MODIFY keyword to ALTER TABLE.
GRANT used with IDENTIFIED BY didn't take effect until privileges
were flushed.
SHOW STATUS.
ORDER BY with 'only index' optimisation when there
were multiple key definitions for a used column.
DATE and DATETIME columns are now up to 5 times faster than
before.
INSERT DELAYED can be used to let the client do other things while the
server inserts rows into a table.
LEFT JOIN USING (col1,col2) didn't work if one used it with tables
from 2 different databases.
LOAD DATA LOCAL INFILE didn't work in the Unix version because of
a missing file.
VARCHAR/BLOB on very short rows (< 4 bytes);
error 127 could occur when deleting rows.
BLOB/TEXT through formulas didn't work for short (< 256 char)
strings.
GRANT on a new host, mysqld could die on the first
connect from this host.
ORDER BY on column name that was the same
name as an alias.
BENCHMARK(loop_count,expression) function to time expressions.
mysqld to make it easier to start from shell
scripts.
TIMESTAMP column to NULL didn't record the timestamp
value in the update log.
INSERT INTO TABLE ... SELECT ... GROUP BY.
localtime_r() on Windows so that it will not crash
anymore if your date is > 2039, but instead will return a time of all zero.
^Z (ASCII 26) to \Z as ^Z doesn't
work with pipes on Windows.
mysql_fix_privileges adds a new column to the mysql.func to
support aggregate UDF functions in future MySQL releases.
NOW(), CURDATE() or CURTIME() directly in a
column didn't work.
SELECT COUNT(*) ... LEFT JOIN ... didn't work with no WHERE part.
pthread_cond() on the Windows version.
get_lock() now correctly times out on Windows!
DATE_ADD() and DATE_SUB() in a
WHERE clause.
GRANT ... TO user
IDENTIFIED BY 'password' syntax.
GRANT checking with SELECT on many tables.
mysql_fix_privilege_tables to the RPM
distribution. This is not run by default because it relies on the client
package.
SQL_SMALL_RESULT to SELECT to force use of
fast temporary tables when you know that the result set will be small.
DATE_ADD/DATE_SUB() doesn't have enough days.
GRANT compares columns in case-insensitive fashion.
ALTER TABLE dump core in
some contexts.
user@hostname can now include `.' and `-'
without quotes in the context of the GRANT, REVOKE and
SET PASSWORD FOR ... statements.
isamchk for tables which need big temporary files.
mysql_fix_privilege_tables script
when you upgrade to this version! This is needed because of the new
GRANT system. If you don't do this, you will get Access
denied when you try to use ALTER TABLE, CREATE INDEX, or
DROP INDEX.
GRANT to allow/deny users table and column access.
USER() to return a value in user@host format.
Formerly it returned only user.
PASSWORD for another user.
FLUSH STATUS that resets most status variables to zero.
aborted_threads, aborted_connects.
connection_timeout.
SET SQL_WARNINGS=1 to get a warning count also for simple
inserts.
SIGTERM instead of SIGQUIT with
shutdown to work better on FreeBSD.
\G (print vertically) to mysql.
SELECT HIGH_PRIORITY ... killed mysqld.
IS NULL on a AUTO_INCREMENT column in a LEFT JOIN didn't
work as expected.
MAKE_SET().
mysql_install_db no longer starts the MySQL server! You
should start mysqld with safe_mysqld after installing it! The
MySQL RPM will, however, start the server as before.
--bootstrap option to mysqld and recoded
mysql_install_db to use it. This will make it easier to install
MySQL with RPMs.
+, - (sign and minus), *, /, %,
ABS() and MOD() to be BIGINT aware (64-bit safe).
ALTER TABLE that caused mysqld to crash.
INSERT.)
INSERT INTO tbl_name SET col_name=value, col_name=value, ...
MYSQL_INIT_COMMAND to mysql_options() to make
a query on connect or reconnect.
MYSQL_READ_DEFAULT_FILE and
MYSQL_READ_DEFAULT_GROUP to mysql_options() to read the
following parameters from the MySQL option files: port,
socket, compress, password, pipe, timeout,
user, init-command, host and database.
maybe_null to the UDF structure.
IGNORE to INSERT statements with many rows.
koi8 character sets; users of
koi8 must run isamchk -rq on each table that has an
index on a CHAR or VARCHAR column.
mysql_setpermission, by Luuk de Boer. It allows easy
creation of new users with permissions for specific databases.
LOAD DATA INFILE).
SHOW STATUS and changed format of output to
be like SHOW VARIABLES.
extended-status command to mysqladmin which will show the
new status variables.
SET SQL_LOG_UPDATE=0 caused a lockup of the server.
FLUSH [ TABLES | HOSTS | LOGS | PRIVILEGES ] [, ...]
KILL thread_id.
ALTER TABLE from a INT
to a short CHAR() column.
SELECT HIGH_PRIORITY; this will get a lock for the
SELECT even if there is a thread waiting for another
SELECT to get a WRITE LOCK.
wild_compare() to string class to be able to use LIKE on
BLOB/TEXT columns with \0.
ESCAPE option to LIKE.
mysqladmin debug.
mysqld on Windows with the --flush option.
This will flush all tables to disk after each update. This makes things
much safer on the Windows platforms but also much slower.
my_strcoll()! The patch should always be safe to install (for any
system), but as this patch changes ISAM internals it's not yet in the
default distribution.
DATE_ADD() and DATE_SUB() didn't work with group functions.
mysql will now also try to reconnect on USE DATABASE commands.
ORDER BY and LEFT JOIN and const tables.
ORDER BY if the first ORDER BY column
was a key and the rest of the ORDER BY columns wasn't part of the key.
OPTIMIZE TABLE.
DROP TABLE and mysqladmin shutdown on Windows
(a fatal bug from 3.22.6).
TIME columns and negative strings.
LIMIT clause for the DELETE statement.
/*! ... */ syntax to hide MySQL-specific
keywords when you write portable code. MySQL will parse the code
inside the comments as if the surrounding /*! and */ comment
characters didn't exist.
OPTIMIZE TABLE tbl_name can now be used to reclaim disk space
after many deletes. Currently, this uses ALTER TABLE to
regenerate the table, but in the future it will use an integrated
isamchk for more speed.
libtool to get the configure more portable.
UPDATE and DELETE operations when using
DATETIME or DATE keys.
mysqladmin proc to display information about your own
threads. Only users with the PROCESS privilege can get
information about all threads.
(In 4.0.2 one needs the SUPER privilege for this.)
YYMMDD, YYYYMMDD,
YYMMDDHHMMSS for numbers when using DATETIME and
TIMESTAMP types. (Formerly these formats only worked with strings.)
CLIENT_IGNORE_SPACE to allow use of spaces
after function names and before `(' (Powerbuilder requires this).
This will make all function names reserved words.
--log-long-format option to mysqld to enable timestamps
and INSERT_ID's in the update log.
--where option to mysqldump (patch by Jim Faucette).
mysqldump.
LOAD DATA INFILE statement, you can now use the new LOCAL
keyword to read the file from the client. mysqlimport will
automatically use LOCAL when importing with the TCP/IP protocol.
DROP TABLE, ALTER TABLE, DELETE FROM
TABLE and mysqladmin flush-tables under heavy usage.
Changed locking code to get better handling of locks of different types.
DBI to 1.00 and DBD to 1.2.0.
mysqld. (To avoid errors if you accidentally
try to use an old error message file.)
affected_rows(),
insert_id(), ...) are now of type BIGINT to allow 64-bit values
to be used.
This required a minor change in the MySQL protocol which should affect
only old clients when using tables with AUTO_INCREMENT values > 16M.
mysql_fetch_lengths() has changed from uint *
to ulong *. This may give a warning for old clients but should work
on most machines.
mysys and dbug libraries to allocate all thread variables
in one struct. This makes it easier to make a threaded `libmysql.dll'
library.
gethostname() (instead of uname()) when
constructing `.pid' file names.
COUNT(), STD() and AVG() are extended to handle more than
4G rows.
-838:59:59 <= x <=
838:59:59 in a TIME column.
TIME column to too short a value, MySQL now
assumes the value is given as: [[[D ]HH:]MM:]SS instead of
HH[:MM[:SS]].
TIME_TO_SEC() and SEC_TO_TIME() can now handle negative times
and hours up to 32767.
SET SQL_LOG_UPDATE={0|1} to allow users with
the PROCESS privilege to bypass the update log.
(Modified patch from Sergey A Mukhin violet@rosnet.net.)
LPAD().
BLOB reading from
pipes safer.
-O max_connect_errors=# option to mysqld.
Connect errors are now reset for each correct connection.
max_allowed_packet to 1M in
mysqld.
--low-priority-updates option to mysqld, to give
table-modifying operations (INSERT, REPLACE, UPDATE,
DELETE) lower priority than retrievals. You can now use
{INSERT | REPLACE | UPDATE | DELETE} LOW_PRIORITY ... You can
also use SET SQL_LOW_PRIORITY_UPDATES={0|1} to change
the priority for one thread. One side effect is that LOW_PRIORITY
is now a reserved word. :(
INSERT INTO table ... VALUES(...),(...),(...),
to allow inserting multiple rows with a single statement.
INSERT INTO tbl_name is now also cached when used with LOCK TABLES.
(Previously only INSERT ... SELECT and LOAD DATA INFILE were
cached.)
GROUP BY functions with HAVING:
mysql> SELECT col FROM table GROUP BY col HAVING COUNT(*)>0;
mysqld will now ignore trailing `;' characters in queries. This
is to make it easier to migrate from some other SQL servers that require the
trailing `;'.
SELECT INTO OUTFILE.
GREATEST() and LEAST() functions. You must now use
these instead of the MAX() and MIN() functions to get the
largest/smallest value from a list of values. These can now handle REAL,
BIGINT and string (CHAR or VARCHAR) values.
DAYOFWEEK() had offset 0 for Sunday. Changed the offset to 1.
GROUP BY columns and fields when
there is no GROUP BY specification.
--vertical option to mysql, for printing results in
vertical mode.
--tmpdir option to mysqld, for specifying the location
of the temporary file directory.
SELECT ... FROM table WHERE auto_increment_column IS NULLto:
SELECT ... FROM table WHERE auto_increment_column == LAST_INSERT_ID()This allows some ODBC programs (Delphi, Access) to retrieve the newly inserted row to fetch the
AUTO_INCREMENT id.
DROP TABLE now waits for all users to free a table before deleting it.
BIN(), OCT(), HEX() and CONV() for
converting between different number bases.
SUBSTRING() with 2 arguments.
ORDER BY and
GROUP BY.
mysqld now automatically disables system locking on Linux and Windows,
and for systems that use MIT-pthreads. You can force the use of locking
with the --enable-external-locking option.
--console option to mysqld, to force a console window
(for error messages) when using Windows.
DATE_ADD() and DATE_SUB() functions.
mysql_ping() to the client library.
--compress option to all MySQL clients.
byte to char in `mysql.h' and `mysql_com.h'.
<<, >>, RPAD() and LPAD().
ORDER BY to work when no records are found
when using fields that are not in GROUP BY (MySQL extension).
--chroot option to mysqld, to start mysqld in
a chroot environment (by Nikki Chumakov nikkic@cityline.ru).
--one-thread option to mysqld, for debugging with
LinuxThreads (or glibc). (This replaces the -T32 flag)
DROP TABLE IF EXISTS to prevent an error from occurring if the
table doesn't exist.
IF and EXISTS are now reserved words (they would have to
be sooner or later).
mysqldump.
mysql_ping().
mysql_init() and mysql_options().
You now MUST call mysql_init() before you call
mysql_real_connect().
You don't have to call mysql_init() if you only use
mysql_connect().
mysql_options(...,MYSQL_OPT_CONNECT_TIMEOUT,...) so you can set a
timeout for connecting to a server.
--timeout option to mysqladmin, as a test of
mysql_options().
AFTER column and FIRST options to
ALTER TABLE ... ADD columns.
This makes it possible to add a new column at some specific location
within a row in an existing table.
WEEK() now takes an optional argument to allow handling of weeks when
the week starts on Monday (some European countries). By default,
WEEK() assumes the week starts on Sunday.
TIME columns weren't stored properly (bug in MySQL Version 3.22.0).
UPDATE now returns information about how many rows were
matched and updated, and how many ``warnings'' occurred when doing the update.
FORMAT(-100,2).
ENUM and SET columns were compared in binary (case-sensitive)
fashion; changed to be case-insensitive.
mysql_real_connect() call is changed to:
mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
const char *passwd, const char *db, uint port,
const char *unix_socket, uint client_flag)
accept() thread. This fixes permanently the telnet bug
that was a topic on the mail list some time ago.
mysqld now has a local hostname
resolver cache so connections should actually be faster than before,
even with this feature.
tbl_name@db_name or db_name.tbl_name. This makes it possible to
give a user read access to some tables and write access to others simply by
keeping them in different databases!
--user option to mysqld, to allow it to run
as another Unix user (if it is started as the Unix root user).
mysqladmin password 'new_password'. This uses encrypted passwords
that are not logged in the normal MySQL log!
SELECT code to handle some very specific queries
involving group functions (like COUNT(*)) without a GROUP BY but
with HAVING. The following now works:
mysql> SELECT COUNT(*) as C FROM table HAVING C > 1;
malloc().
-T32 option to mysqld, for running all queries under the
main thread. This makes it possible to debug mysqld under Linux with
gdb!
not_null_column IS NULL (needed for some Access
queries).
STRAIGHT_JOIN to be used between two tables to force the optimiser
to join them in a specific order.
VARCHAR rather than CHAR and
the column type is now VARCHAR for fields saved as VARCHAR.
This should make the MyODBC driver better, but may break some old
MySQL clients that don't handle FIELD_TYPE_VARCHAR the same
way as FIELD_TYPE_CHAR.
CREATE INDEX and DROP INDEX are now implemented through
ALTER TABLE.
CREATE TABLE is still the recommended (fast) way to create indexes.
--set-variable option wait_timeout to mysqld.
mysqladmin processlist to show how long a query
has taken or how long a thread has slept.
show variables and some new to
show status.
YEAR. YEAR is stored in 1 byte with allowable
values of 0, and 1901 to 2155.
DATE type that is stored in 3 bytes rather than 4 bytes.
All new tables are created with the new date type if you don't use the
--old-protocol option to mysqld.
Error from table handler: # on some operating systems.
--enable-assembler option to configure, for x86 machines
(tested on Linux + gcc). This will enable assembler functions for the
most important string functions for more speed!
Version 3.21 is quite old now, and should be avoided if possible. This information is kept here for historical purposes only.
SIGHUP to mysqld;
mysqld core dumped when starting from boot on some systems.
DELETE FROM tbl_name without a WHERE condition is now done the
long way when you use LOCK TABLES or if the table is in use, to
avoid race conditions.
INSERT INTO TABLE (timestamp_column) VALUES (NULL); didn't set timestamp.
mysqladmin
refresh often. This could in some very rare cases corrupt the header of the
index file and cause error 126 or 138.
refresh() when running with the
--skip-external-locking option. There was a ``very small'' time gap after
a mysqladmin refresh when a table could be corrupted if one
thread updated a table while another thread did mysqladmin
refresh and another thread started a new update ont the same table
before the first thread had finished. A refresh (or
--flush-tables) will now not return until all used tables are
closed!
SELECT DISTINCT with a WHERE clause that didn't match any rows
returned a row in some contexts (bug only in 3.21.31).
GROUP BY + ORDER BY returned one empty row when no rows where
found.
Use_count: Wrong count for ... in the error log file.
TINYINT type on Irix.
LEFT("constant_string",function).
FIND_IN_SET().
LEFT JOIN core dumped if the second table is used with a constant
WHERE/ON expression that uniquely identifies one record.
DATE_FORMAT() and incorrect dates.
DATE_FORMAT() now ignores '%' to make it possible to extend
it more easily in the future.
mysql now returns an exit code > 0 if the query returned an error.
mysql client.
By Tommy Larsen tommy@mix.hive.no.
safe_mysqld to redirect startup messages to
'hostname'.err instead
of 'hostname'.log to reclaim file space on mysqladmin refresh.
ENUM always had the first entry as default value.
ALTER TABLE wrote two entries to the update log.
sql_acc() now closes the mysql grant tables after a reload to
save table space and memory.
LOAD DATA to use less memory with tables and BLOB
columns.
SELECT problem with LEFT() when using the czech
character set.
isamchk; it couldn't repair a packed table in a very
unusual case.
SELECT statements with & or | (bit functions) failed on
columns with NULL values.
LOCK TABLES + DELETE from tbl_name never removed locks properly.
OR function.
umask() and creating new databases.
SELECT ... INTO OUTFILE ...
MIN(integer) or MAX(integer) in
GROUP BY.
WEEK("XXXX-xx-01").
Error from table handler: # on some operating systems.
GET_LOCK(string,timeout),
RELEASE_LOCK(string).
Opened_tables to show status.
mysqld through telnet + TCP/IP.
WHERE key_part_1 >= something AND key_part_2 <= something_else.
configure for detection of FreeBSD 3.0 9803xx and above
WHERE with string_col_key = constant_string didn't always
find all rows if the column had many values differing only with
characters of the same sort value (like e and 'e).
umask() to make log files non-readable for normal users.
--old-protocol option to mysqld.
SELECT which matched all key fields returned the values in the
case of the matched values, not of the found values. (Minor problem.)
FROM_DAYS(0) now returns "0000-00-00".
DATE_FORMAT(), PM and AM were swapped for hours 00 and 12.
BLOB/TEXT in GROUP BY with many
tables.
ENUM field that is not declared NOT NULL has NULL as
the default value.
(Previously, the default value was the first enumeration value.)
INDEX (Organisation,Surname(35),Initials(35)).
SELECT ... FROM many_tables much faster.
accept() to possibly fix some problems on some
Linux machines.
typedef 'string' to typedef 'my_string' for better
portability.
isamchk. Try isamchk --help.
filesort() didn't work.
Affects DISTINCT, ORDER BY and GROUP BY on 64-bit
processors.
SELECT on the
table.
OR operators on key parts
inside each other.
MIN() and MAX() to work properly with strings and
HAVING.
0664 to 0660.
LEFT JOIN and constant expressions in the ON
part.
configure now works better on OSF/1 (tested on 4.0D).
LIKE optimisation with international character
support.
DBI to 0.93.
TIME, DATE, TIMESTAMP, TEXT, BIT,
ENUM, NO, ACTION, CHECK, YEAR,
MONTH, DAY, HOUR, MINUTE, SECOND,
STATUS, VARIABLES.
TIMESTAMP to NULL in LOAD DATA INFILE ... didn't
set the current time for the TIMESTAMP.
BETWEEN to recognise binary strings. Now BETWEEN is
case-sensitive.
--skip-thread-priority option to mysqld, for systems
where mysqld's thread scheduling doesn't work properly (BSDI 3.1).
DAYNAME() and MONTHNAME().
TIME_FORMAT(). This works like DATE_FORMAT(),
but takes a time string ('HH:MM:DD') as argument.
ORs of key parts
inside ANDs.
variables command to mysqladmin.
ALTER TABLE to work with Windows (Windows can't rename
open files). Also fixed a couple of small bugs in the Windows version.
crash-me and the benchmarks on
the following platforms: SunOS 5.6 sun4u, SunOS 5.5.1 sun4u, SunOS 4.14 sun4c,
SunOS 5.6 i86pc, Irix 6.3 mips5k, HP-UX 10.20 hppa, AIX 4.2.1 ppc,
OSF/1 V4.0 alpha, FreeBSD 2.2.2 i86pc and BSDI 3.1 i386.
COUNT(*) problems when the WHERE clause didn't match any
records. (Bug from 3.21.17.)
NULL = NULL is true. Now you must use IS NULL
or IS NOT NULL to test whether a value is NULL.
(This is according to ANSI SQL but may break
old applications that are ported from mSQL.)
You can get the old behaviour by compiling with -DmSQL_COMPLIANT.
LEFT OUTER JOIN clauses.
ORDER BY on string formula with possible NULL values.
<= on sub index.
DAYOFYEAR(), DAYOFMONTH(), MONTH(),
YEAR(), WEEK(), QUARTER(), HOUR(), MINUTE(),
SECOND() and FIND_IN_SET().
SHOW VARIABLES command.
mysql> SELECT 'first ' 'second'; -> 'first second'
mysqlaccess to 2.02.
LIKE.
WHERE data_field = date_field2 AND date_field2 = constant.
SHOW STATUS command.
mysqladmin stat to return the right number of queries.
AUTO_INCREMENT attribute or is a TIMESTAMP. This is needed for
the new Java driver.
configure bugs and increased maximum table size
from 2G to 4G.
DBD to 1.1823. This version implements mysql_use_result
in DBD-Mysql.
REVERSE() (by Zeev Suraski).
DBI to 0.91.
LEFT OUTER JOIN.
CROSS JOIN syntax. CROSS is now a reserved word.
yacc/bison stack allocation to be even safer and to allow
MySQL to handle even bigger expressions.
ORDER BY was slow when used with key ranges.
--with-unix-socket-path to avoid
confusion.
LEFT OUTER JOIN.
LEFT, NATURAL,
USING.
MYSQL_HOST as the default host if it's defined.
SELECT col_name, SUM(expr) now returns NULL for col_name
when there are matching rows.
BLOBs with ASCII
characters over 127.
mysqld
restart if one thread was reading data that another thread modified.
LIMIT offset,count didn't work in INSERT ... SELECT.
POWER(), SPACE(),
COT(), DEGREES(), RADIANS(), ROUND(2 arg)
and TRUNCATE().
LOCATE() parameters were
swapped according to ODBC standard. Fixed.
TIME_TO_SEC().
NOT NULL fields.
UPDATE SET ... statements.
BLOB and TEXT, to
be compatible with mysqldump.
mysqlperl is now from
Msql-Mysql-modules. This means that connect() now takes
host, database, user, password arguments! The old
version took host, database, password, user.
DATE '1997-01-01', TIME '12:10:10' and
TIMESTAMP '1997-01-01 12:10:10' formats required by ANSI SQL.
Warning: Incompatible change! This has the unfortunate
side-effect that you no longer can have columns named DATE, TIME
or TIMESTAMP. :( Old columns can still be accessed through
tablename.columnname!)
make programs trying to rebuild it.
readline library upgraded to version 2.1.
DBI/DBD is now included in the distribution. DBI
is now the recommended way to connect to MySQL from Perl.
DBD, with test results from
mSQL 2.0.3, MySQL, PostgreSQL 6.2.1 and Solid server 2.2.
crash-me is now included with the benchmarks; this is a Perl program
designed to find as many limits as possible in a SQL server. Tested with
mSQL, PostgreSQL, Solid and MySQL.
mysql command-line tool, by Zeev
Suraski and Andi Gutmans.
REPLACE that works like INSERT but
replaces conflicting records with the new record. REPLACE INTO
TABLE ... SELECT ... works also.
CREATE DATABASE db_name and DROP
DATABASE db_name.
RENAME option to ALTER TABLE: ALTER TABLE name
RENAME TO new_name.
make_binary_distribution now includes `libgcc.a' in
`libmysqlclient.a'. This should make linking work for people who don't
have gcc.
net_write() to my_net_write() because of a name
conflict with Sybase.
DAYOFWEEK() compatible with ODBC.
bison memory overrun checking to make MySQL
safer with weird queries.
configure problems on some platforms.
DATE_FORMAT().
NOT IN.
{fn now() }
DATE and TIME values with NULL.
FLOAT. Previously, the
values were converted to INTs before sorting.
key_column=constant.
DOUBLE values sorted on integer results instead.
mysql no longer requires a database argument.
HAVING should be. According to ANSI, it should
be after GROUP BY but before ORDER BY. MySQL Version 3.20
incorrectly had it last.
USE DATABASE to start using another database.
mysqld doesn't crash even if you haven't done a
ulimit -n 256 before starting mysqld.
errno.
This makes Linux systems much safer!
SELECT.
LIKE on number key.
--table option to mysql to print in table format.
Moved time and row information after query result.
Added automatic reconnect of lost connections.
!= as a synonym for <>.
VERSION() to make easier logs.
ftruncate() call in MIT-pthreads. This made isamchk
destroy the `.ISM' files on (Free)BSD 2.x systems.
__P_ patch in MIT-pthreads.
NULL
if the returned string should be longer than max_allowed_packet bytes.
INTERVAL type to ENUM, because
INTERVAL is used in ANSI SQL.
JOIN + GROUP + INTO OUTFILE,
the result wasn't grouped.
LIKE with '_' as last character didn't work. Fixed.
TRIM() function.
CURTIME().
ENCRYPT() function by Zeev Suraski.
FOREIGN KEY syntax skipping. New reserved words:
MATCH, FULL, PARTIAL.
mysqld now allows IP number and hostname for the --bind-address
option.
SET CHARACTER SET cp1251_koi8 to enable conversions of
data to and from the cp1251_koi8 character set.
CREATE COLUMN syntax of NOT NULL columns to be after
the DEFAULT value, as specified in the ANSI SQL standard. This will
make mysqldump with NOT NULL and default values incompatible with
MySQL Version 3.20.
ALTER TABLE tbl_name ALTER COLUMN col_name SET DEFAULT
NULL.
CHAR and BIT as synonyms for CHAR(1).
SELECT privilege.
INSERT ... SELECT ... GROUP BY didn't work in some cases. An
Invalid use of group function error occurred.
LIMIT, SELECT now always uses keys instead of record
scan. This will give better performance on SELECT and a WHERE
that matches many rows.
BIT_OR() and BIT_AND().
CHECK and REFERENCES.
CHECK is now a reserved word.
ALL option to GRANT for better compatibility. (GRANT
is still a dummy function.)
ORDER BY and GROUP BY with NULL columns.
LAST_INSERT_ID() SQL function to retrieve last
AUTO_INCREMENT
value. This is intended for clients to ODBC that can't use the
mysql_insert_id() API function, but can be used by any client.
--flush-logs option to mysqladmin.
STATUS to mysql.
ORDER BY/GROUP BY because of bug in gcc.
INSERT ... SELECT ... GROUP BY.
mysqlaccess.
CREATE now supports all ODBC types and the mSQL TEXT type.
All ODBC 2.5 functions are also supported (added REPEAT). This provides
better portability.
TINYTEXT, TEXT, MEDIUMTEXT and
LONGTEXT. These are actually BLOBtypes, but all searching is
done in case-insensitive fashion.
BLOB fields are now TEXT fields. This only
changes that all searching on strings is done in case-sensitive fashion.
You must do an ALTER TABLE and change the field type to BLOB
if you want to have tests done in case-sensitive fashion.
configure issues.
test-select works.
--enable-unix-socket=pathname option to configure.
SUM() functions.
For example, you can now use SUM(column)/COUNT(column).
PI(), ACOS(), ASIN(), ATAN(), COS(),
SIN() and TAN().
net_print() in `procedure.cc'.
SELECT ... INTO OUTFILE syntax.
GROUP BY and SELECT on key with many values.
mysql_fetch_lengths() sometimes returned incorrect lengths when you used
mysql_use_result(). This affected at least some cases of
mysqldump --quick.
WHERE const op field.
NULL fields.
--pid-file=# option to mysqld.
FROM_UNIXTIME(), originally by Zeev Suraski.
BETWEEN in range optimiser (did only test = of the first
argument).
mysql_errno(), to get the error number of
the error message. This makes error checking in the client much easier.
This makes the new server incompatible with the 3.20.x server when running
without --old-protocol. The client code is backward-compatible.
More information can be found in the `README' file!
sigwait and sigset
defines).
configure should now be able to detect the last argument to
accept().
-O tmp_table_size=# option to mysqld.
FROM_UNIXTIME(timestamp) which returns a date string in
'YYYY-MM-DD HH:MM:DD' format.
SEC_TO_TIME(seconds) which returns a string in
'HH:MM:SS' format.
SUBSTRING_INDEX(), originally by Zeev Suraski.
mysqld doesn't work on it yet.
pthread_create to work.
mysqld doesn't accept hostnames that start with digits followed by a
'.', because the hostname may look like an IP number.
--skip-networking option to mysqld, to allow only socket
connections. (This will not work with MIT-pthreads!)
free() that killed the server on
CREATE DATABASE or DROP DATABASE.
mysqld -O options to better names.
-O join_cache_size=# option to mysqld.
-O max_join_size=# option to mysqld, to be able to set a
limit how big queries (in this case big = slow) one should be able to handle
without specifying SET SQL_BIG_SELECTS=1. A # = is about 10
examined records. The default is ``unlimited''.
TIME, DATE, DATETIME or TIMESTAMP
column to a constant, the constant is converted to a time value before
performing the comparison.
This will make it easier to get ODBC (particularly Access97) to work with
the above types. It should also make dates easier to use and the comparisons
should be quicker than before.
query() in
mysqlperl to take a query with \0 in it.
YYMMDD) didn't work.
UPDATE
clause.
SELECT * INTO OUTFILE, which didn't correctly if the outfile already
existed.
mysql now shows the thread ID when starting or doing a reconnect.
--new, but it crashes core a lot yet...
isam library should be relatively 64-bit clean.
isamchk which can detect and fix more problems.
isamlog.
mysqladmin: you can now do mysqladmin kill 5,6,7,8 to kill
multiple threads.
-O backlog=# option to mysqld.
ALTER TABLE now returns warnings from field conversions.
ASCII().
BETWEEN(a,b,c). Use the standard ANSI
syntax instead: expr BETWEEN expr AND expr.
SUM() functions.
tbl_name.field_name in UPDATE.
SELECT DISTINCT when using 'hidden group'. For example:
mysql> SELECT DISTINCT MOD(some_field,10) FROM test
-> GROUP BY some_field;
Note: some_field is normally in the SELECT part. ANSI SQL should
require it.
INTERVAL, EXPLAIN, READ,
WRITE, BINARY.
CHAR(num,...).
IN. This uses a binary search to find a match.
LOCK TABLES tbl_name [AS alias] {READ|WRITE} ...
--log-update option to mysqld, to get a log suitable for
incremental updates.
EXPLAIN SELECT ... to get information about how the
optimiser will do the join.
FIELD_TYPE_TINY_BLOB, FIELD_TYPE_MEDIUM_BLOB,
FIELD_TYPE_LONG_BLOB or FIELD_TYPE_VAR_STRING (as
previously returned by mysql_list_fields). You should instead only use
FIELD_TYPE_BLOB or FIELD_TYPE_STRING. If you want exact
types, you should use the command SHOW FIELDS.
0x###### which can be used as a string
(default) or a number.
FIELD_TYPE_CHAR is renamed to FIELD_TYPE_TINY.
DEFAULT values no longer need to be NOT NULL.
ENUM
SET
double or long long.
This will provide the full 64-bit range with bit functions and fix some
conversions that previously could result in precision losses. One should
avoid using unsigned long long columns with full 64-bit range
(numbers bigger than 9223372036854775807) because calculations are done
with signed long long.
ORDER BY will now put NULL field values first. GROUP BY
will also work with NULL values.
WHERE with expressions.
mysql> SELECT * FROM tbl_name
-> WHERE key_part_1="customer"
-> AND key_part_2>=10 AND key_part_2<=10;
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.
-p# (remove # directories from path) to isamlog.
All files are written with a relative path from the database directory
Now mysqld shouldn't crash on shutdown when using the
--log-isam option.
mysqlperl version. It is now compatible with msqlperl-0.63.
DBD module available.
STD() (standard deviation).
mysqld server is now compiled by default without debugging
information. This will make the daemon smaller and faster.
--basedir option to
mysqld. All other paths are relative in a normal installation.
BLOB columns sometimes contained garbage when used with a SELECT
on more than one table and ORDER BY.
GROUP BY work as expected
(ANSI SQL extension).
Example:
mysql> SELECT id,id+1 FROM table GROUP BY id;
MYSQL_PWD was reversed. Now MYSQL_PWD is
enabled as default in the default release.
mysqld to core dump with
Arithmetic error on SPARC-386.
--unbuffered option to mysql, for new mysqlaccess.
BLOB columns and the functions IS NULL and
IS NOT NULL in the WHERE clause.
max_allowed_packet is now 64K for
the server and 512K for the client. This is mainly used to catch
incorrect packets that could trash all memory. The server limit may be
changed when it is started.
safe_mysqld to check for running daemon.
ELT() function is renamed to FIELD(). The new
ELT() function returns a value based on an index: FIELD()
is the inverse of ELT() Example: ELT(2,"A","B","C") returns
"B". FIELD("B","A","B","C") returns 2.
COUNT(field), where field could have a NULL value, now
works.
SELECT ... GROUP BY.
WHERE with many unoptimisable brace levels.
get_hostname, only the IP is checked.
Previously, you got Access denied.
INSERT INTO ... SELECT ... WHERE could give the error
Duplicated field.
safe_mysqld to make it ``safer''.
LIKE was case-sensitive in some places and case-insensitive in others.
Now LIKE is always case-insensitive.
'#' anywhere on the line.
SET SQL_SELECT_LIMIT=#. See the FAQ for more details.
mysqlaccess script.
FROM_DAYS() and WEEKDAY() to also take a full
TIMESTAMP or DATETIME as argument. Before they only took a
number of type YYYYMMDD or YYMMDD.
UNIX_TIMESTAMP(timestamp_column).
mysqld to work around a bug in MIT-pthreads. This makes multiple
small SELECT operations 20 times faster. Now lock_test.pl should
work.
mysql_FetchHash(handle) to mysqlperl.
mysqlbug script is now distributed built to allow for reporting
bugs that appear during the build with it.
getpwuid() instead of
cuserid().
SELECT optimiser when using many tables with the same
column used as key to different tables.
latin2 and Russian KOI8 character tables.
GRANT command to satisfy Powerbuilder.
packets out of order when using MIT-pthreads.
fcntl() fails. Thanks to Mike Bretz for finding this bug.
termbits from `mysql.cc'. This conflicted with
glibc 2.0.
SELECT as superuser without a database.
SELECT with group calculation to outfile.
-p or --password option to mysql without
an argument, the user is solicited for the password from the tty.
MYSQL_PWD (by Elmar Haneke).
kill to mysqladmin to kill a specific
MySQL thread.
AUTO_INCREMENT key with ALTER_TABLE.
AVG() gave too small value on some SELECTs with
GROUP BY and ORDER BY.
DATETIME type (by Giovanni Maruzzelli
maruzz@matrice.it).
DONT_USE_DEFAULT_FIELDS works.
CREATE INDEX.
DATE, TIME and
TIMESTAMP.
OR of multiple tables (gave empty set).
DATE and TIME types.
SELECT with AND-OR levels.
LIMIT and ORDER BY.
ORDER BY and GROUP BY on items that aren't in the
SELECT list.
(Thanks to Wim Bonis bonis@kiss.de, for pointing this out.)
INSERT.
SELECT ... WHERE ... = NULL.
glibc 2.0. To get glibc to work, you should
add the `gibc-2.0-sigwait-patch' before compiling glibc.
ALTER TABLE when changing a NOT NULL field to
allow NULL values.
CREATE TABLE.
CREATE TABLE now allows FLOAT(4) and FLOAT(8) to mean
FLOAT and DOUBLE.
mysqlaccess by Yves.Carlier@rug.ac.be.
This program shows the access rights for a specific user and the grant
rows that determine this grant.
WHERE const op field (by bonis@kiss.de).
SELECT ... INTO OUTFILE, all temporary tables are ISAM
instead of HEAP to allow big dumps.
ALTER TABLE according to SQL92.
--port and --socket options to all utility programs and
mysqld.
readdir_r(). Now mysqladmin create database
and mysqladmin drop database should work.
tempnam(). This should fix the ``sort
aborted'' bug.
sql_update. This fixed slow updates
on first connection. (Thanks to Vaclav Bittner for the test.)
INSERT INTO ... SELECT ...
MEDIUMBLOB fixed.
ALTER TABLE and BLOBs.
SELECT ... INTO OUTFILE now creates the file in the current
database directory.
DROP TABLE now can take a list of tables.
DESCRIBE (DESC).
make_binary_distribution.
configure's
C++ link test.
--without-perl option to configure.
ALTER TABLE didn't copy null bit. As a result, fields that were allowed
to have NULL values were always NULL.
CREATE didn't take numbers as DEFAULT.
ALTER TABLE and multi-part keys.
ALTER TABLE, SELECT ... INTO OUTFILE and
LOAD DATA INFILE.
NOW().
File_priv to mysql/user table.
add_file_priv which adds the new field File_priv
to the user table. This script must be executed if you want to
use the new SELECT ... INTO and LOAD DATA INFILE ... commands
with a version of MySQL earlier than 3.20.7.
lock_test.pl test fail.
status command to mysqladmin for short logging.
-k option to mysqlshow, to get key information for a table.
mysqldump.
configure cannot find a -lpthreads
library.
program --help.
RAND([init]).
sql_lex to handle \0 unquoted, but the client can't send
the query through the C API, because it takes a str pointer.
You must use mysql_real_query() to send the query.
mysql_get_client_info().
mysqld now uses the N_MAX_KEY_LENGTH from `nisam.h' as
the maximum allowable key length.
mysql> SELECT filter_nr,filter_nr FROM filter ORDER BY filter_nr;Previously, this resulted in the error:
Column: 'filter_nr' in order clause is ambiguous.
mysql now outputs '\0', '\t', '\n' and '\\'
when encountering ASCII 0, tab, newline or '\' while writing
tab-separated output.
This is to allow printing of binary data in a portable format.
To get the old behaviour, use -r (or --raw).
mysql_fetch_lengths(MYSQL_RES *), which
returns an array of column lengths (of type uint).
IS NULL in WHERE clause.
SELECT option STRAIGHT_JOIN to tell the optimiser that
it should join tables in the given order.
'--' in `mysql.cc'
(Postgres syntax).
SELECT expressions and table columns in a SELECT
which are not used in the group part. This makes it efficient to implement
lookups. The column that is used should be a constant for each group because
the value is calculated only once for the first row that is found for a group.
mysql> SELECT id,lookup.text,SUM(*) FROM test,lookup
-> WHERE test.id=lookup.id GROUP BY id;
SUM(function) (could cause a core dump).
AUTO_INCREMENT placement in the SQL query:
INSERT INTO table (auto_field) VALUES (0);inserted 0, but it should insert an
AUTO_INCREMENT value.
mysql now allows doubled '' or "" within strings for
embedded ' or ".
EXP(), LOG(), SQRT(), ROUND(), CEILING().
configure source now compiles a thread-free client library
-lmysqlclient. This is the only library that needs to be linked
with client applications. When using the binary releases, you must
link with -lmysql -lmysys -ldbug -lmystrings as before.
readline library from bash-2.0.
configure and makefiles (and related source).
VPATH. Tested with GNU Make 3.75.
safe_mysqld and mysql.server changed to be more compatible
between the source and the binary releases.
LIMIT now takes one or two numeric arguments.
If one argument is given, it indicates the maximum number of rows in
a result. If two arguments are given, the first argument indicates the offset
of the first row to return, the second is the maximum number of rows.
With this it's easy to do a poor man's next page/previous page WWW
application.
FIELDS() to ELT().
Changed SQL function INTERVALL() to INTERVAL().
SHOW COLUMNS a synonym for SHOW FIELDS.
Added compatibility syntax FRIEND KEY to CREATE TABLE. In
MySQL, this creates a non-unique key on the given columns.
CREATE INDEX and DROP INDEX as compatibility functions.
In MySQL, CREATE INDEX only checks if the index exists and
issues an error if it doesn't exist. DROP INDEX always succeeds.
sql_acl (core on new connection).
host, user and db tables from database test
in the distribution.
FIELD_TYPE_CHAR can now be signed (-128 to 127) or unsigned (0 to 255)
Previously, it was always unsigned.
CONCAT() and WEEKDAY().
mysqld to be compiled with SunPro
compiler.
'(' immediately after the function name
(no intervening space).
For example, 'USER(' is regarded as beginning a function call, and
'USER (' is regarded as an identifier USER followed by a
'(', not as a function call.
configure and Automake.
It will make porting much easier. The readline library is included
in the distribution.
DBD will follow when the new DBD code
is ported.
mysqld can now be started with Swedish
or English (default) error messages.
INSERT(), RTRIM(), LTRIM() and
FORMAT().
mysqldump now works correctly for all field types (even
AUTO_INCREMENT). The format for SHOW FIELDS FROM tbl_name
is changed so the Type column contains information suitable for
CREATE TABLE. In previous releases, some CREATE TABLE
information had to be patched when re-creating tables.
BLOB and TIMESTAMP) are corrected.
TIMESTAMP now returns different date information depending on its
create length.
'_'.
Version 3.19 is quite old now, and should be avoided if possible. This information is kept here for historical purposes only.
DATABASE(), USER(), POW(),
LOG10() (needed for ODBC).
WHERE with an ORDER BY on fields from only one table,
the table is now preferred as first table in a multi-join.
HAVING and IS NULL or IS NOT NULL now works.
SUM(),
AVG()...) didn't work together. Fixed.
mysqldump: Didn't send password to server.
'Locked' to process list as info if a query is
locked by another query.
IF(arg,syntax_error,syntax_error) crashed.
CEILING(), ROUND(), EXP(), LOG() and SQRT().
BETWEEN to handle strings.
SELECT with grouping on BLOB columns not to return
incorrect BLOB info. Grouping, sorting and distinct on BLOB
columns will not yet work as
expected (probably it will group/sort by the first 7 characters in the
BLOB). Grouping on formulas with a fixed string size (use MID()
on a BLOB) should work.
BLOB
fields, the BLOB was garbage on output.
DISTINCT with calculated columns.
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!
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.
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.
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.
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.
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:
mysqld server:
nm -n libexec/mysqld > /tmp/mysqld.symNote 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
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.
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.
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:
mysqladmin shutdown).
myisamchk -s database/*.MYI. Repair any
wrong tables with myisamchk -r database/table.MYI.
mysqld with --log-bin. See section 4.9.4 The Binary Log.
If you want to find a query that crashes mysqld, you should use
--log --log-bin.
mysqld server.
mysqld server without --log-bin
mysqlbinlog update-log-file | mysql.
The update log is saved in the MySQL database directory with
the name hostname-bin.#.
mysqld to die with the
above command, you have found reproducible bug that should be easy to
fix! FTP the tables and the binary log to
ftp://support.mysql.com/pub/mysql/secret/ and enter it into
our bugs system at http://bugs.mysql.com/.
If you are a support customer), you can also support@mysql.com to
alert the MySQL team about the problem and have it fixed as soon as possible.
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.
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.
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.
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:
GROUP
BY on a large part of the data or if one has to often scan the whole table.
Table locks are superior to page level / row level locks in the following cases:
UPDATE table_name SET column=value WHERE unique_key# DELETE FROM table_name WHERE unique_key=#
SELECT combined with INSERT (and very few UPDATEs
and DELETEs).
GROUP BY on the whole table without any writers.
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.
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:
-DHAVE_rts_threads.
thr_alarm.
thr_alarm. If it runs without any ``warning'', ``error'' or aborted
messages, you are on the right track. Here is a successful run on
Solaris:
Main thread: 1 Thread 0 (5) started Thread: 5 Waiting process_alarm Thread 1 (6) started Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 1 (1) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 2 (2) sec Thread: 6 Simulation of no alarm needed Thread: 6 Slept for 0 (3) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 4 (4) sec Thread: 6 Waiting process_alarm thread_alarm Thread: 5 Slept for 10 (10) sec Thread: 5 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 5 (5) sec Thread: 6 Waiting process_alarm process_alarm ... thread_alarm Thread: 5 Slept for 0 (1) sec end
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:
ps may show the different threads. If one thread aborts, the
whole process aborts. Most system calls are thread-safe and should
require very little overhead. Solaris, HP-UX, AIX and OSF/1 have kernel
threads.
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''.
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.
|
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:
^
mysql> SELECT "fo\nfo" REGEXP "^fo$"; -> 0 mysql> SELECT "fofo" REGEXP "^fo"; -> 1
$
mysql> SELECT "fo\no" REGEXP "^fo\no$"; -> 1 mysql> SELECT "fo\no" REGEXP "^fo$"; -> 0
.
mysql> SELECT "fofo" REGEXP "^f.*"; -> 1 mysql> SELECT "fo\nfo" REGEXP "^f.*"; -> 1
a*
a characters.
mysql> SELECT "Ban" REGEXP "^Ba*n"; -> 1 mysql> SELECT "Baaan" REGEXP "^Ba*n"; -> 1 mysql> SELECT "Bn" REGEXP "^Ba*n"; -> 1
a+
a characters.
mysql> SELECT "Ban" REGEXP "^Ba+n"; -> 1 mysql> SELECT "Bn" REGEXP "^Ba+n"; -> 0
a?
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
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)*
abc.
mysql> SELECT "pi" REGEXP "^(pi)*$"; -> 1 mysql> SELECT "pip" REGEXP "^(pi)*$"; -> 0 mysql> SELECT "pipi" REGEXP "^(pi)*$"; -> 1
{1}
{2,3}
a*
a{0,}.
a+
a{1,}.
a?
a{0,1}.
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]
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.]]
ch
collating element, then the regular expression [[.ch.]]*c matches the
first five characters of chchcc.
[=character_class=]
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:]
[: 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 | xdigit |
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
[[:<:]]
[[:>:]]
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
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.
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.
9.4 NO WARRANTY
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.
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.]
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.
9.6 NO WARRANTY
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!
CC environment variable
CXX environment variable
DBI_TRACE environment variable
CC
CXX
DBI_TRACE
HOME
MYSQL_DEBUG
MYSQL_HISTFILE
MYSQL_HOST
MYSQL_PWD, environment variable, MYSQL_PWD
MYSQL_TCP_PORT, environment variable, MYSQL_TCP_PORT
MYSQL_UNIX_PORT, environment variable, MYSQL_UNIX_PORT
USER
HOME environment variable
my_init()
mysql_affected_rows()
mysql_autocommit().
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()
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_count(), mysql_field_count()
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_HOST environment variable
mysql_info()
mysql_init()
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_PWD environment variable, MYSQL_PWD environment variable
mysql_query(), mysql_query()
mysql_real_connect()
mysql_real_escape_string()
mysql_real_query()
mysql_reload()
mysql_rollback().
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_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_thread_end()
mysql_thread_id()
mysql_thread_init()
mysql_thread_safe()
MYSQL_UNIX_PORT environment variable, MYSQL_UNIX_PORT environment variable
mysql_use_result()
USER environment variable
ACID
GROUP BY clauses
ORDER BY clauses
AUTO_INCREMENT, and NULL values
batch, mysql option
BDB table type
BDB tables
BerkeleyDB table type
Binlog_Dump
BLOB columns, default values
BLOB columns, indexing
BLOB, inserting binary data
BLOB, size
mysqld server
gcc
cc1plus problems
character-sets-dir, mysql option
mysql
gcc
compress, mysql option
config.cache file
configure script
configure, running after prior invocation
connect_timeout variable
database, mysql option
db table, sorting
DBI interface
DBI Perl module
DBI/DBD
debug-info, mysql option
debug, mysql option
BLOB and TEXT columns
default-character-set, mysql option
mysql.sock
SHOW
enable-named-commands, mysql option
myisamchk output
execute, mysql option
fatal signal 11
config.cache
tmp
force, mysql option
SELECT and WHERE clauses
gcc
GROUP BY, aliases in
GROUP BY, extensions to ANSI SQL, GROUP BY, extensions to ANSI SQL
HEAP table type
help, mysql option
host table
host table, sorting
host, mysql option
html, mysql option
ignore-space, mysql option
BLOB columns
IS NULL
LIKE
NULL values
TEXT columns
InnoDB table type
InnoDB tables
ISAM table type
mysqlclient
make_binary_distribution
max_allowed_packet
max_join_size
MERGE table type
msql2mysql
MyISAM table type
myisamchk, myisamchk
myisamchk, example output
myisamchk, options
myisampack, myisampack, myisampack
mysql
mysql command-line options
mysql.sock, protection
mysql_fix_privilege_tables
mysql_install_db
mysql_install_db script
mysqlaccess
mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin, mysqladmin
mysqlbinlog, mysqlbinlog
mysqlbug
mysqlbug script
mysqlbug script, location
mysqlclient library
mysqld
mysqld options
mysqld server, buffer sizes
mysqld, starting
mysqld-max
mysqld_multi
mysqld_safe
mysqldump, mysqldump, mysqldump
mysqlimport, mysqlimport, mysqlimport, mysqlimport
mysqlshow
net_buffer_length
mysql.user table
no-auto-rehash, mysql option
no-beep, mysql option
no-named-commands, mysql option
no-pager, mysql option
no-tee, mysql option
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
one-database, mysql option
Open Source, defined
mysql
myisamchk
ORDER BY, aliases in
pack_isam
pager, mysql option
password, mysql option
port, mysql option
DATE columns
prompt command
prompt, mysql option
protocol, mysql option, protocol, mysql option
quick, mysql option
raw, mysql option
reconnect, mysql option
replace
configure after prior invocation
safe-mode command
safe-updates, mysql option
safe_mysqld
mysql_install_db
mysqlbug
SELECT, Query Cache
select_limit
set-variable, mysql option
silent, mysql option
skip-column-names, mysql option
skip-line-numbers, mysql option
socket, mysql option
sql_yacc.cc problems
mysqld
mysql
status command
SELECTs
table, mysql option
BDB
Berkeley DB
HEAP
host
tee, mysql option
TEXT columns, default values
TEXT columns, indexing
TEXT, size
connect_timeout variable
TIMESTAMP, and NULL values
unbuffered, mysql option
user table, sorting
user, mysql option
VARCHAR, size
mysqld
verbose, mysql option
version, mysql option
vertical, mysql option
wait, mysql option
LIKE
mysql.columns_priv table
mysql.db table
mysql.host table
mysql.tables_priv table
mysql.user table
xml, mysql option
This document was generated on 3 April 2003 using the texi2html translator version 1.52 (extended by davida@detron.se).