|
|
The MySQL (R) software delivers a very fast, multi-threaded, multi-user, and robust SQL (Structured Query Language) database server. MySQL Server is intended for mission-critical, heavy-load production systems as well as for embedding into mass-deployed software. MySQL is a registered trademark of MySQL AB.
The MySQL software is Dual Licensed. Users can choose to use the MySQL software as an Open Source product under the terms of the GNU General Public License (http://www.fsf.org/licenses/) or can purchase a standard commercial license from MySQL AB. See http://www.mysql.com/company/legal/licensing/ for more information on our licensing policies.
The following list describes some sections of particular interest in this manual:
Important:
Reports of errors (often called ``bugs''), as well as questions and comments, should be sent to http://bugs.mysql.com. See section 1.4.1.3 How to Report Bugs or Problems.
If you have found a sensitive security bug in MySQL Server, please let us know immediately by sending an email message to security@mysql.com.
This is the Reference Manual for the MySQL Database System. It documents MySQL up to Version 4.1.10a, but is also applicable for older versions of the MySQL software (such as 3.23 or 4.0-production) because functional changes are indicated with reference to a version number.
Because this manual serves as a reference, it does not provide general instruction on SQL or relational database concepts. It also will not teach you how to use your operating system or command-line interpreter.
The MySQL Database Software is under constant development, and the Reference Manual is updated frequently as well. The most recent version of the manual is available online in searchable form at http://dev.mysql.com/doc/. Other formats also are available, including HTML, PDF, and Windows CHM versions.
The primary document is the Texinfo file.
The HTML version is produced automatically using a modified version of
texi2html
.
The plain text and Info versions are produced with makeinfo
.
The PostScript version is produced using texi2dvi
and dvips
.
The PDF version is produced with pdftex
.
If you have any suggestions concerning additions or corrections to this manual, please send them to the documentation team at docs@mysql.com.
This manual was initially written by David Axmark and Michael ``Monty'' Widenius. It is maintained by the MySQL Documentation Team, consisting of Paul DuBois, Stefan Hinz, Mike Hillyer, Jon Stephens, and Russell Dyer. For the many other contributors, see section B Credits.
The copyright (2004) to this manual is owned by the Swedish company MySQL AB. MySQL and the MySQL logo are (registered) trademarks of MySQL AB. Other trademarks and registered trademarks referred to in this manual are the property of their respective owners, and are used for identification purposes only.
This manual uses certain typographical conventions:
constant
mysqladmin
works, invoke it with the
--help
option.''
When commands are shown that are meant to be executed from within a particular
program, the program is indicated by a prompt shown before the command. For
example, shell>
indicates a command that you execute from your login
shell, and mysql>
indicates a statement that you execute from the
mysql
client program:
shell> type a shell command here mysql> type a mysql statement here
The ``shell'' is your command interpreter. On Unix, this is typically a
program such as sh
or csh
. On Windows, the equivalent program is
command.com
or cmd.exe
, typically run in a console window.
When you enter a command or statement shown in an example, do not type the prompt shown in the example.
Database, table, and column names must often be substituted into statements. To indicate that such substitution is necessary, this manual uses db_name, tbl_name, and col_name. For example, you might see a statement like this:
mysql> SELECT col_name FROM db_name.tbl_name;
This means that if you were to enter a similar statement, you would supply your own database, table, and column names, perhaps like this:
mysql> SELECT author_name FROM biblio_db.author_list;
SQL keywords are not case sensitive and may be written in uppercase or lowercase. This manual uses uppercase.
In syntax descriptions, square brackets (`[' and `]') are used
to indicate optional words or clauses. For example, in the following
statement, IF EXISTS
is optional:
DROP TABLE [IF EXISTS] tbl_name
When a syntax element consists of a number of alternatives, the alternatives are separated by vertical bars (`|'). When one member from a set of choices may be chosen, the alternatives are listed within square brackets (`[' and `]'):
TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
When one member from a set of choices must be chosen, the alternatives are listed within braces (`{' and `}'):
{DESCRIBE | DESC} tbl_name [col_name | wild]
An ellipsis (...
) indicates the omission of a section of a statement,
typically to provide a shorter version of more complex syntax. For example,
INSERT ... SELECT
is shorthand for the form of INSERT
statement
that is followed by a SELECT
statement.
An ellipsis can also indicate that the preceding syntax element of a statement may be repeated. In the following example, multiple reset_option values may be given, with each of those after the first preceded by commas:
RESET reset_option [,reset_option] ...
Commands for setting shell variables are shown using Bourne shell syntax. For example, the sequence to set an environment variable and run a command looks like this in Bourne shell syntax:
shell> VARNAME=value some_command
If you are using csh
or tcsh
, you must issue commands somewhat
differently. You would execute the sequence just shown like this:
shell> setenv VARNAME value shell> some_command
MySQL, the most popular Open Source SQL database management system, is developed, distributed, and supported by MySQL AB. MySQL AB is a commercial company, founded by the MySQL developers. It is a second generation Open Source company that unites Open Source values and methodology with a successful business model.
The MySQL Web site (http://www.mysql.com/) provides the latest information about MySQL software and MySQL AB.
The official way to pronounce ``MySQL'' is ``My Ess Que Ell'' (not ``my sequel''), but we don't mind if you pronounce it as ``my sequel'' or in some other localized way.
We started out with the intention of using mSQL
to connect to our
tables using our own fast low-level (ISAM) routines. However, after some
testing, we came to the conclusion that mSQL
was not fast enough or
flexible enough for our needs. This resulted in a new SQL interface to our
database but with almost the same API interface as mSQL
. This API was
designed to allow third-party code that was written for use with mSQL
to
be ported easily for use with MySQL.
The derivation of the name MySQL is not clear. Our base directory and a large number of our libraries and tools have had the prefix ``my'' for well over 10 years. However, co-founder Monty Widenius's daughter is also named My. Which of the two gave its name to MySQL is still a mystery, even for us.
The name of the MySQL Dolphin (our logo) is ``Sakila,'' which was chosen by the founders of MySQL AB from a huge list of names suggested by users in our ``Name the Dolphin'' contest. The winning name was submitted by Ambrose Twebaze, an Open Source software developer from Swaziland, Africa. According to Ambrose, the name Sakila has its roots in SiSwati, the local language of Swaziland. Sakila is also the name of a town in Arusha, Tanzania, near Ambrose's country of origin, Uganda.
The following list describes some of the important characteristics of the MySQL Database Software. See also section 1.3 MySQL Development Roadmap for more information about current and upcoming features.
MyISAM
) with index compression.
FLOAT
, DOUBLE
, CHAR
, VARCHAR
,
TEXT
, BLOB
, DATE
, TIME
, DATETIME
,
TIMESTAMP
, YEAR
, SET
, ENUM
, and OpenGIS spatial
types.
See section 11 Column Types.
SELECT
and WHERE
clauses of queries. For example:
mysql> SELECT CONCAT(first_name, ' ', last_name) -> FROM citizen -> WHERE income/dependents > 10000 AND age > 30;
GROUP BY
and
ORDER BY
clauses. Support
for group functions (COUNT()
,
COUNT(DISTINCT ...)
,
AVG()
, STD()
,
SUM()
, MAX()
, MIN()
, and GROUP_CONCAT()
).
LEFT OUTER JOIN
and RIGHT OUTER JOIN
with both standard
SQL and ODBC syntax.
DELETE
, INSERT
, REPLACE
, and UPDATE
return
the number of rows that were changed (affected). It is possible to return
the number of rows matched instead by setting a flag when connecting to the
server.
SHOW
command can be used to retrieve
information about databases, tables, and indexes. The EXPLAIN
command
can be used to determine how the optimizer resolves a query.
ABS
is a valid column name. The only restriction is that for a
function call, no spaces are allowed between the function name and the
`(' that follows it. See section 9.6 Treatment of Reserved Words in MySQL.
CHAR
, VARCHAR
,
BLOB
, or TEXT
column types.
--shared-memory
option. Clients can
connect through shared memory by using the --protocol=memory
option.
latin1
(ISO-8859-1), german
, big5
, ujis
,
and more. For example,
the Scandinavian characters `â', `ä' and `ö' are
allowed in table and column names.
Unicode support is available as of MySQL 4.1.
mysqlcheck
client. MySQL also includes
myisamchk
, a very fast command-line utility for performing these
operations on MyISAM
tables.
See section 5 Database Administration.
--help
or -?
options to obtain online assistance.
This section addresses the questions, ``How stable is MySQL Server?'' and, ``Can I depend on MySQL Server in this project?'' We will try to clarify these issues and answer some important questions that concern many potential users. The information in this section is based on data gathered from the mailing lists, which are very active in identifying problems as well as reporting types of use.
The original code stems back to the early 1980s. It provides a stable code
base, and the ISAM
table format used by the original storage engine
remains backward-compatible.
At TcX, the predecessor of MySQL AB, MySQL code has worked
in projects since mid-1996, without any problems.
When the MySQL Database Software initially was released to a wider public,
our new users quickly found some pieces of untested code. Each new release
since then has had fewer portability problems, even though each new release
has also had many new features.
Each release of the MySQL Server has been usable. Problems have occurred only when users try code from the ``gray zones.'' Naturally, new users don't know what the gray zones are; this section therefore attempts to document those areas that are currently known. The descriptions mostly deal with Version 3.23, 4.0 and 4.1 of MySQL Server. All known and reported bugs are fixed in the latest version, with the exception of those listed in the bugs section, which are design-related. See section 1.5.7 Known Errors and Design Deficiencies in MySQL.
The MySQL Server design is multi-layered with independent modules. Some of the newer modules are listed here with an indication of how well-tested each of them is:
InnoDB
tables (Stable)
InnoDB
transactional storage engine has been declared
stable in the MySQL 3.23 tree, starting from version 3.23.49.
InnoDB
is being used in large, heavy-load production systems.
BDB
tables (Stable)
Berkeley DB
code is very stable, but we are still improving
the BDB
transactional storage engine interface in MySQL Server.
MyODBC
3.51 (Stable)
MyODBC
3.51 uses ODBC SDK 3.51 and is in wide production use.
Some issues brought up appear to be application-related and independent of
the ODBC driver or underlying database server.
MySQL 3.22 had a 4GB (4 gigabyte) limit on table size. With the
MyISAM
storage engine in MySQL 3.23, the maximum table
size was increased to 8 million terabytes (2 ^ 63 bytes). With this larger
allowed table size, the maximum effective table size for MySQL
databases is usually determined by operating system constraints
on file sizes, not by MySQL internal limits.
The InnoDB
storage engine maintains InnoDB
tables within a
tablespace that can be created from several files. This allows a
table to exceed the maximum individual file size. The tablespace can include
raw disk partitions, which allows extremely large tables. The maximum
tablespace size is 64TB.
The following table lists some examples of operating system file-size limits. This is only a rough guide and is not intended to be definitive. For the most up-to-date information, be sure to check the documentation specific to your operating system.
Operating System | File-size Limit |
Linux 2.2-Intel 32-bit | 2GB (LFS: 4GB) |
Linux 2.4 | (using ext3 filesystem) 4TB |
Solaris 9/10 | 16TB |
NetWare w/NSS filesystem | 8TB |
win32 w/ FAT/FAT32 | 2GB/4GB |
win32 w/ NTFS | 2TB (possibly larger) |
MacOS X w/ HFS+ | 2TB |
On Linux 2.2, you can get MyISAM
tables larger than 2GB in size by
using the Large File Support (LFS) patch for the ext2 filesystem. On Linux
2.4, patches also exist for ReiserFS to get support for big files (up to 2TB). Most
current Linux distributions are based on kernel 2.4 and include all
the required LFS patches. With JFS and XFS, petabyte and larger files
are possible on Linux. However, the maximum available file size still depends
on several factors, one of them being the filesystem used to store MySQL tables.
For a detailed overview about LFS in Linux, have a look at Andreas Jaeger's Large File Support in Linux page at http://www.suse.de/~aj/linux_lfs.html.
Windows users please note: FAT and VFAT (FAT32) are not considered suitable for production use with MySQL. Use NTFS instead.
By default, MySQL creates MyISAM
tables with an internal
structure that allows a maximum size of about 4GB. You can
check the maximum table size for a table with the SHOW TABLE STATUS
statement or with myisamchk -dv tbl_name
.
See section 13.5.4 SHOW
Syntax.
If you need a MyISAM
table that will be larger than 4GB in size (and your
operating system supports large files), the CREATE TABLE
statement
allows AVG_ROW_LENGTH
and MAX_ROWS
options.
See section 13.2.6 CREATE TABLE
Syntax.
You can also change these options with ALTER TABLE
after the table has
been created, to increase the table's maximum allowable size.
See section 13.2.2 ALTER TABLE
Syntax.
Other ways to work around file-size limits for MyISAM
tables are as
follows:
myisampack
to
compress it. myisampack
usually compresses a table by at
least 50%, so you can have, in effect, much bigger tables.
myisampack
also can merge multiple tables into a single table.
See section 8.2 myisampack
, the MySQL Compressed Read-only Table Generator.
MyISAM
data files is by using the RAID
options.
See section 13.2.6 CREATE TABLE
Syntax.
MERGE
library that allows
you to handle a collection of MyISAM
tables that have identical
structure as a single MERGE
table.
See section 14.2 The MERGE
Storage Engine.
The MySQL Server itself has no problems with Year 2000 (Y2K) compliance:
2037
for TIMESTAMP
values. For DATE
and DATETIME
values, dates through the year 9999
are accepted.
YEAR
column type
can store years 0
and 1901
to 2155
in one byte and
display them using two or four digits.
All two-digit years are considered to be in the range
1970
to 2069
, which means that if you store 01
in a
YEAR
column, MySQL Server treats it as 2001
.
The following simple demonstration illustrates that MySQL Server
has no problems with DATE
or DATETIME
values through the year
9999, and no problems with TIMESTAMP
values until after the year 2030:
mysql> DROP TABLE IF EXISTS y2k; Query OK, 0 rows affected (0.01 sec) mysql> CREATE TABLE y2k (date DATE, -> date_time DATETIME, -> time_stamp TIMESTAMP); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO y2k VALUES -> ('1998-12-31','1998-12-31 23:59:59',19981231235959), -> ('1999-01-01','1999-01-01 00:00:00',19990101000000), -> ('1999-09-09','1999-09-09 23:59:59',19990909235959), -> ('2000-01-01','2000-01-01 00:00:00',20000101000000), -> ('2000-02-28','2000-02-28 00:00:00',20000228000000), -> ('2000-02-29','2000-02-29 00:00:00',20000229000000), -> ('2000-03-01','2000-03-01 00:00:00',20000301000000), -> ('2000-12-31','2000-12-31 23:59:59',20001231235959), -> ('2001-01-01','2001-01-01 00:00:00',20010101000000), -> ('2004-12-31','2004-12-31 23:59:59',20041231235959), -> ('2005-01-01','2005-01-01 00:00:00',20050101000000), -> ('2030-01-01','2030-01-01 00:00:00',20300101000000), -> ('2040-01-01','2040-01-01 00:00:00',20400101000000), -> ('9999-12-31','9999-12-31 23:59:59',99991231235959); Query OK, 14 rows affected (0.01 sec) Records: 14 Duplicates: 0 Warnings: 2 mysql> SELECT * FROM y2k; +------------+---------------------+----------------+ | date | date_time | time_stamp | +------------+---------------------+----------------+ | 1998-12-31 | 1998-12-31 23:59:59 | 19981231235959 | | 1999-01-01 | 1999-01-01 00:00:00 | 19990101000000 | | 1999-09-09 | 1999-09-09 23:59:59 | 19990909235959 | | 2000-01-01 | 2000-01-01 00:00:00 | 20000101000000 | | 2000-02-28 | 2000-02-28 00:00:00 | 20000228000000 | | 2000-02-29 | 2000-02-29 00:00:00 | 20000229000000 | | 2000-03-01 | 2000-03-01 00:00:00 | 20000301000000 | | 2000-12-31 | 2000-12-31 23:59:59 | 20001231235959 | | 2001-01-01 | 2001-01-01 00:00:00 | 20010101000000 | | 2004-12-31 | 2004-12-31 23:59:59 | 20041231235959 | | 2005-01-01 | 2005-01-01 00:00:00 | 20050101000000 | | 2030-01-01 | 2030-01-01 00:00:00 | 20300101000000 | | 2040-01-01 | 2040-01-01 00:00:00 | 00000000000000 | | 9999-12-31 | 9999-12-31 23:59:59 | 00000000000000 | +------------+---------------------+----------------+ 14 rows in set (0.00 sec)
The final two TIMESTAMP
column values are zero because the
year values (2040
, 9999
) exceed the TIMESTAMP
maximum. The
TIMESTAMP
data type, which is used to store the current time,
supports values that range from 19700101000000
to
20300101000000
on 32-bit machines (signed value). On 64-bit
machines, TIMESTAMP
handles values up to 2106
(unsigned
value).
Although MySQL Server itself is Y2K-safe, you may run into
problems if you use it with applications that are not Y2K-safe.
For example, many old applications store or manipulate years using
two-digit values (which are ambiguous) rather than four-digit values.
This problem may be compounded by applications that use
values such as 00
or 99
as ``missing'' value indicators.
Unfortunately, these problems may be difficult to fix because different
applications may be written by different programmers, each of whom may
use a different set of conventions and date-handling functions.
Thus, even though MySQL Server has no Y2K problems, it is the application's responsibility to provide unambiguous input. See section 11.3.4 Y2K Issues and Date Types for MySQL Server's rules for dealing with ambiguous date input data that contains two-digit year values.
This section provides a snapshot of the MySQL development roadmap, including major features implemented or planned for MySQL 4.0, 4.1, 5.0, and 5.1. The following sections provide information for each release series.
The current production release series is MySQL 4.1, which was declared stable for production use as of Version 4.1.7, released in October 2004. The previous production release series is MySQL 4.0, which was declared stable for production use as of Version 4.0.12, released in March 2003. Production status means that future 4.1 and 4.0 development is limited only to bugfixes. For the older MySQL 3.23 series, only critical bugfixes are made.
Active MySQL development currently is taking place in the MySQL 5.0 release series, this means that new features are being added there. MySQL 5.0 is available in alpha status.
Before upgrading from one release series to the next, please see the notes at section 2.10 Upgrading MySQL.
Plans for some of the most requested features are summarized in the following table.
Feature | MySQL Series |
Unions | 4.0 |
Subqueries | 4.1 |
R-trees | 4.1 (for MyISAM tables)
|
Stored procedures | 5.0 |
Views | 5.0 |
Cursors | 5.0 |
Foreign keys | 5.1 (implemented in 3.23 for InnoDB )
|
Triggers | 5.0 and 5.1 |
Full outer join | 5.1 |
Constraints | 5.1 |
MySQL Server 4.0 is available in production status.
MySQL 4.0 is available for download at http://dev.mysql.com/ and from our mirrors. MySQL 4.0 has been tested by a large number of users and is in production use at many large sites.
The major new features of MySQL Server 4.0 are geared toward our existing business and community users, enhancing the MySQL database software as the solution for mission-critical, heavy-load database systems. Other new features target the users of embedded databases.
INSERT
statements, searching on
packed indexes, full-text searching (using FULLTEXT
indexes), and
COUNT(DISTINCT)
.
InnoDB
storage engine as standard
InnoDB
storage engine is offered as a standard feature of the
MySQL server. This means full support for ACID transactions, foreign
keys with cascading UPDATE
and DELETE
, and row-level locking
are standard features.
See section 15 The InnoDB
Storage Engine.
FULLTEXT
search properties of MySQL Server 4.0 enables
FULLTEXT
indexing of large text masses with both binary
and natural-language searching logic. You can customize minimal word
length and define your own stop word lists in any human language,
enabling a new set of applications to be built with MySQL Server.
See section 12.6 Full-Text Search Functions.
UNION
statement, a standard SQL feature.
TRUNCATE TABLE
(as in Oracle).
latin1_de
, which ensures that the
German sorting order sorts words with umlauts in the same order
as do German telephone books.
mysqld
parameters (startup options) can be set without taking
down the server. This is a convenient feature for database administrators
(DBAs).
See section 13.5.3 SET
Syntax.
DELETE
and UPDATE
statements have been added.
MyISAM
storage engine supports symbolic
linking at the table level (and not just the database level as before).
SQL_CALC_FOUND_ROWS
and FOUND_ROWS()
are new functions that make it
possible to find out the number of rows a SELECT
query that includes a
LIMIT
clause would have returned without that clause.
The news section of this manual includes a more in-depth list of features. See section D.3 Changes in release 4.0.x (Production).
The libmysqld
embedded server library makes MySQL Server suitable for
a vastly expanded realm of applications. By using this library, developers can
embed MySQL Server into various applications and electronics devices, where
the end user has no knowledge of there actually being an underlying
database. Embedded MySQL Server is ideal for use behind
the scenes in Internet appliances, public kiosks, turnkey
hardware/software combination units, high performance Internet
servers, self-contained databases distributed on CD-ROM, and so on.
Many users of libmysqld
will benefit from the MySQL
Dual Licensing. For those not wishing to be bound by the GPL,
the software is also made available under a commercial license.
See http://www.mysql.com/company/legal/licensing/ for more information
on the licensing policy of MySQL AB.
The embedded MySQL library uses the same interface as the normal
client library, so it is convenient and easy to use.
See section 22.2.16 libmysqld, the Embedded MySQL Server Library.
On Windows there are two different libraries:
libmysqld.lib | Dynamic library for threaded applications. |
mysqldemb.lib | Static library for not threaded applications. |
MySQL Server 4.0 laid the foundation for new features implemented in MySQL 4.1, such as subqueries and Unicode support, and for the work on stored procedures being done in version 5.0. These features come at the top of the wish list of many of our customers. Well-known for its stability, speed, and ease of use, MySQL Server is able to fulfill the requirement checklists of very demanding buyers.
MySQL Server 4.1 is currently in production status, and binaries are available for download at http://dev.mysql.com/downloads/mysql/4.1.html. All binary releases pass our extensive test suite without any errors on the platforms on which we test. See section D.2 Changes in release 4.1.x (Production).
For those wishing to use the most recent development source for MySQL 4.1, we also make our BitKeeper repositories publicly available. See section 2.8.3 Installing from the Development Source Tree.
This section lists features implemented in MySQL 4.1. New features that will be available in MySQL 5.0 are described in section C.1 New Features Planned for 5.0.
SELECT
statement nested within another statement.
A ``derived table'' (an unnamed view) is a subquery in the FROM
clause
of another statement.
See section 13.1.8 Subquery Syntax.
BTREE
indexing is supported for HEAP
tables,
significantly improving response time for non-exact searches.
CREATE TABLE tbl_name2 LIKE tbl_name1
allows you to create, with
a single statement, a new table with a structure exactly like that of an
existing table.
MyISAM
storage engine supports
OpenGIS spatial types for storing geographical data.
See section 18 Spatial Extensions in MySQL.
SHOW WARNINGS
shows warnings for the last command.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
utf8
and ucs2
character sets.
HELP
command that can be used
to get help information for SQL statements.
The advantage of having this information on the server side is that the
information is always applicable to the particular server version that you
actually are using.
Because this information is available by issuing an SQL statement, any client
can be written to access it.
For example, the help
command of the mysql
command-line client
has been modified to have this capability.
INSERT ... ON DUPLICATE KEY UPDATE ...
syntax has been
implemented. This allows you to UPDATE
an existing row if the
INSERT
would have caused a duplicate in a PRIMARY
or
UNIQUE
index.
See section 13.1.4 INSERT
Syntax.
GROUP_CONCAT()
adds the extremely useful capability of concatenating column values from
grouped rows into a single result string.
See section 12.9 Functions and Modifiers for Use with GROUP BY
Clauses.
The news section of this manual includes a more in-depth list of features. See section D.2 Changes in release 4.1.x (Production).
New development for MySQL is focused on the 5.0 release, featuring stored procedures, views (including updatable views), rudimentary triggers, and other new features. See section C.1 New Features Planned for 5.0.
For those wishing to take a look at the bleeding edge of MySQL development, we make our BitKeeper repository for MySQL version 5.0 publicly available. See section 2.8.3 Installing from the Development Source Tree. As of December 2003, binary builds of version 5.0 have also been available.
This section introduces the MySQL mailing lists and provides guidelines as to how the lists should be used. When you subscribe to a mailing list, you will receive all postings to the list as email messages. You can also send your own questions and answers to the list.
To subscribe to or unsubscribe from any of the mailing lists described in this section, visit http://lists.mysql.com/. For most of them, you can select the regular version of the list where you get individual messages, or a digest version where you get one large message per day.
Please do not send messages about subscribing or unsubscribing to any of the mailing lists, because such messages are distributed automatically to thousands of other users.
Your local site may have many subscribers to a MySQL mailing list.
If so, the site may have a local mailing list, so that messages sent from
lists.mysql.com
to your site are propagated to the local list. In such
cases, please contact your system administrator to be added to or dropped
from the local MySQL list.
If you wish to have traffic for a mailing list go to a separate mailbox in
your mail program, set up a filter based on the message headers. You can
use either the List-ID:
or Delivered-To:
headers to identify
list messages.
The MySQL mailing lists are as follows:
announce
mysql
bugs
internals
mysqldoc
benchmarks
packagers
java
win32
myodbc
gui-tools
MySQL
Administrator
and the MySQL Control Center
graphical client.
cluster
dotnet
plusplus
perl
DBD::mysql
.
If you're unable to get an answer to your questions from a MySQL mailing list, one option is to purchase support from MySQL AB. This will put you in direct contact with MySQL developers.
The following table shows some MySQL mailing lists in languages other than English. These lists are not operated by MySQL AB.
mysql-france-subscribe@yahoogroups.com
list@tinc.net
subscribe mysql your@email.address
to this list.
mysql-de-request@lists.4t2.com
subscribe mysql-de your@email.address
to this list.
You can find information about this mailing list at
http://www.4t2.com/mysql/.
mysql-br-request@listas.linkway.com.br
subscribe mysql-br your@email.address
to this list.
mysql-alta@elistas.net
subscribe mysql your@email.address
to this list.
Before posting a bug report or question, please do the following:
If you can't find an answer in the manual or the archives, check with your local MySQL expert. If you still can't find an answer to your question, please follow the guidelines on sending mail to a MySQL mailing list, outlined in the next section, before contacting us.
The normal place to report bugs is http://bugs.mysql.com/, which is the address for our bugs database. This database is public, and can be browsed and searched by anyone. If you log in to the system, you will also be able to enter new reports.
Writing a good bug report takes patience, but doing it right the first time saves time both for us and for yourself. A good bug report, containing a full test case for the bug, makes it very likely that we will fix the bug in the next release. This section will help you write your report correctly so that you don't waste your time doing things that may not help us much or at all.
We encourage everyone to use the mysqlbug
script to generate a bug
report (or a report about any problem). mysqlbug
can be
found in the `scripts' directory (source distribution) and in the
`bin' directory under your MySQL installation directory (binary distribution).
If you are unable to use mysqlbug
(for example, if you are running
on Windows), it is still vital that you include all the necessary information
noted in this section (most importantly, a description of the operating system
and the MySQL version).
The mysqlbug
script helps you generate a report by determining much
of the following information automatically, but if something important is
missing, please include it with your message. Please read this section
carefully and make sure that all the information described here is included
in your report.
Preferably, you should test the problem using the latest production or
development version of MySQL Server before posting. Anyone should be
able to repeat the bug by just using mysql test < script_file
on the
included test case or by running the shell or Perl script that is included in the
bug report.
All bugs posted in the bugs database at http://bugs.mysql.com/ will be corrected or documented in the next MySQL release. If only minor code changes are needed to correct a problem, we may also post a patch that fixes the problem.
If you have found a sensitive security bug in MySQL, you can send email to security@mysql.com.
If you have a repeatable bug report, please report it to the bugs
database at http://bugs.mysql.com/. Note that even in this case
it's good to run the mysqlbug
script first to find information
about your system. Any bug that we are able to repeat has a high chance
of being fixed in the next MySQL release.
To report other problems, you can use one of the MySQL mailing lists.
Remember that it is possible for us to respond to a message containing too much information, but not to one containing too little. People often omit facts because they think they know the cause of a problem and assume that some details don't matter. A good principle is this: If you are in doubt about stating something, state it. It is faster and less troublesome to write a couple more lines in your report than to wait longer for the answer if we must ask you to provide information that was missing from the initial report.
The most common errors made in bug reports are (a) not including the version number of the MySQL distribution used, and (b) not fully describing the platform on which the MySQL server is installed (including the platform type and version number). This is highly relevant information, and in 99 cases out of 100, the bug report is useless without it. Very often we get questions like, ``Why doesn't this work for me?'' Then we find that the feature requested wasn't implemented in that MySQL version, or that a bug described in a report has been fixed in newer MySQL versions. Sometimes the error is platform-dependent; in such cases, it is next to impossible for us to fix anything without knowing the operating system and the version number of the platform.
If you compiled MySQL from source, remember also to provide information about your compiler, if it is related to the problem. Often people find bugs in compilers and think the problem is MySQL-related. Most compilers are under development all the time and become better version by version. To determine whether your problem depends on your compiler, we need to know what compiler you use. Note that every compiling problem should be regarded as a bug and reported accordingly.
It is most helpful when a good description of the problem is included in the bug report. That is, give a good example of everything you did that led to the problem and describe, in exact detail, the problem itself. The best reports are those that include a full example showing how to reproduce the bug or problem. See section E.1.6 Making a Test Case If You Experience Table Corruption.
If a program produces an error message, it is very important to include the message in your report. If we try to search for something from the archives using programs, it is better that the error message reported exactly matches the one that the program produces. (Even the lettercase should be observed.) You should never try to reproduce from memory what the error message was; instead, copy and paste the entire message into your report.
If you have a problem with Connector/ODBC (MyODBC), please try to generate a trace file and send it with your report. See section 23.1.1.9 How to Report MyODBC Problems or Bugs.
Please remember that many of the people who will read your report will
do so using an 80-column display. When generating reports or examples
using the mysql
command-line tool, you should therefore use
the --vertical
option (or the \G
statement terminator)
for output that would exceed the available width for such a display
(for example, with the EXPLAIN SELECT
statement; see the
example later in this section).
Please include the following information in your report:
mysqladmin version
. The mysqladmin
program can be found in the `bin' directory under your MySQL
installation directory.
uname -a
.
mysqld
died, you should also report the query that crashed
mysqld
. You can usually find this out by running mysqld
with
query logging enabled, and then looking in the log after mysqld
crashes
See section E.1.5 Using Log Files to Find Cause of Errors in mysqld
.
mysqldump --no-data db_name tbl_name
. This is very easy
to do and is a powerful way to get information about any table in a database.
The information will help us create a situation matching the one you have.
SELECT
statements, you
should always include the output of EXPLAIN SELECT ...
, and at
least the number of rows that the SELECT
statement produces. You
should also include the output from SHOW CREATE TABLE tbl_name
for each involved table. The more information you give about your
situation, the more likely it is that someone can help you.
The following is an example of a very good bug report. It should be posted
with the mysqlbug
script. The example uses the mysql
command-line tool. Note the use of the \G
statement terminator for
statements whose output width would otherwise exceed that of an 80-column
display device.
mysql> SHOW VARIABLES; mysql> SHOW COLUMNS FROM ...\G <output from SHOW COLUMNS> mysql> EXPLAIN SELECT ...\G <output from EXPLAIN> mysql> FLUSH STATUS; mysql> SELECT ...; <A short version of the output from SELECT, including the time taken to run the query> mysql> SHOW STATUS; <output from SHOW STATUS>
mysqld
, try to provide an
input script that will reproduce the anomaly. This script should include any
necessary source files. The more closely the script can reproduce your
situation, the better. If you can make a reproducible test case, you should
post it on http://bugs.mysql.com/ for high-priority treatment.
If you can't provide a script, you should at least include the output
from mysqladmin variables extended-status processlist
in your mail to
provide some information on how your system is performing.
mysqldump
and create a `README' file
that describes your problem.
Create a compressed archive of your files using
tar
and gzip
or zip
, and use FTP to transfer the
archive to ftp://ftp.mysql.com/pub/mysql/upload/. Then enter
the problem into our bugs database at http://bugs.mysql.com/.
mysqld
server as well as the options that you use to run any MySQL client programs.
The options to programs such as mysqld
and mysql
, and to the
configure
script, are often keys to answers and are very relevant.
It is never a bad idea to include them. If you use any modules, such
as Perl or PHP, please include the version numbers of those as well.
mysqlaccess
, the output of mysqladmin reload
, and all
the error messages you get when trying to connect. When you test your
privileges, you should first run mysqlaccess
. After this, execute
mysqladmin reload version
and try to connect with the program that
gives you trouble. mysqlaccess
can be found in the `bin'
directory under your MySQL installation directory.
parse error
, please check your syntax closely. If
you can't find something wrong with it, it's extremely likely that your
current version of MySQL Server doesn't support the syntax you are
using. If you are using the current version and the manual at
http://dev.mysql.com/doc/ doesn't cover the
syntax you are using, MySQL Server doesn't support your query. In this
case, your only options are to implement the syntax yourself or email
licensing@mysql.com and ask for an offer to implement it.
If the manual covers the syntax you are using, but you have an older version
of MySQL Server, you should check the MySQL change history to see
when the syntax was implemented. In this case, you have the option of
upgrading to a newer version of MySQL Server. See section D MySQL Change History.
CHECK TABLE
and REPAIR TABLE
or with myisamchk
.
See section 5 Database Administration.
If you are running Windows, please verify that lower_case_table_names
is 1 or 2 with SHOW VARIABLES LIKE 'lower_case_table_names'
.
mysqld
should never crash a table if nothing killed it in the
middle of an update. If you can find the cause of mysqld
dying,
it's much easier for us to provide you with a fix for the problem.
See section A.1 How to Determine What Is Causing a Problem.
If you are a support customer, please cross-post the bug report to mysql-support@mysql.com for higher-priority treatment, as well as to the appropriate mailing list to see whether someone else has experienced (and perhaps solved) the problem.
For information on reporting bugs in MyODBC, see section 23.1.1.9 How to Report MyODBC Problems or Bugs.
For solutions to some common problems, see section A Problems and Common Errors.
When answers are sent to you individually and not to the mailing list, it is considered good etiquette to summarize the answers and send the summary to the mailing list so that others may have the benefit of responses you received that helped you solve your problem.
If you consider your answer to have broad interest, you may want to post it to the mailing list instead of replying directly to the individual who asked. Try to make your answer general enough that people other than the original poster may benefit from it. When you post to the list, please make sure that your answer is not a duplication of a previous answer.
Try to summarize the essential part of the question in your reply; don't feel obliged to quote the entire original message.
Please don't post mail messages from your browser with HTML mode turned on. Many users don't read mail with a browser.
In addition to the various MySQL mailing lists, you can find experienced
community people on IRC
(Internet Relay Chat
).
These are the best networks/channels currently known to us:
#mysql
Primarily MySQL questions, but other database and general SQL questions are welcome.
Questions about PHP, Perl or C in combination with MySQL are also common.
#mysql
MySQL questions.
If you are looking for IRC client software to connect to an IRC network,
take a look at X-Chat
(http://www.xchat.org/).
X-Chat (GPL licensed) is available for Unix as well as for Windows platforms.
The latest community support resource are the forums at http://forums.mysql.com.
There are a variety of forums available, grouped in the following general categories:
This section describes how MySQL relates to the ANSI/ISO SQL standards. MySQL Server has many extensions to the SQL standard, and here you will find out what they are and how to use them. You will also find information about functionality missing from MySQL Server, and how to work around some differences.
The SQL standard has been evolving since 1986 and several versions exist. In this manual, ``SQL-92'' refers to the standard released in 1992, ``SQL:1999'' refers to the standard released in 1999, and ``SQL:2003'' refers to the current version of the standard. We use the phrase ``the SQL standard'' to mean the current version of the SQL Standard at any time.
Our goal is to not restrict MySQL Server usability for any usage without a very good reason for doing so. Even if we don't have the resources to perform development for every possible use, we are always willing to help and offer suggestions to people who are trying to use MySQL Server in new territories.
One of our main goals with the product is to continue to work toward
compliance with the SQL standard, but without sacrificing speed or reliability.
We are not afraid to add extensions to SQL or support for non-SQL
features if this greatly increases the usability of MySQL Server for a large
segment of our user base.
The HANDLER
interface in MySQL Server 4.0 is an example of this
strategy. See section 13.1.3 HANDLER
Syntax.
We will continue to support transactional and non-transactional databases to satisfy both mission-critical 24/7 usage and heavy Web or logging usage.
MySQL Server was originally designed to work with medium size databases (10-100 million rows, or about 100MB per table) on small computer systems. Today MySQL Server handles terabyte-size databases, but the code can also be compiled in a reduced version suitable for hand-held and embedded devices. The compact design of the MySQL server makes development in both directions possible without any conflicts in the source tree.
Currently, we are not targeting realtime support, although MySQL replication capabilities offer significant functionality.
Database cluster support exists through third-party clustering solutions as well as the integration of our acquired NDB Cluster technology, available from version 4.1.2. See section 16 MySQL Cluster.
We are also looking at providing XML support in the database server.
We are aiming toward supporting the full ANSI/ISO SQL standard, but without making concessions to speed and quality of the code.
ODBC levels 0-3.51.
The MySQL server can operate in different SQL modes, and can apply these modes differentially for different clients. This allows an application to tailor server operation to its own requirements.
Modes define what SQL syntax MySQL should support and what kind of validation checks it should perform on the data. This makes it easier to use MySQL in a lot of different environments and to use MySQL together with other database servers.
You can set the default SQL mode by starting mysqld
with the
--sql-mode="modes"
option. Beginning with MySQL 4.1, you can also
change the mode after startup time by setting the sql_mode
variable
with a SET [SESSION|GLOBAL] sql_mode='modes'
statement.
For more information on setting the server mode, see section 5.2.2 The Server SQL Mode.
You can tell mysqld
to use the ANSI mode with the --ansi
startup option. See section 5.2.1 mysqld
Command-Line Options.
Running the server in ANSI mode is the same as starting it with these options
(specify the --sql_mode
value on a single line):
--transaction-isolation=SERIALIZABLE --sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,ONLY_FULL_GROUP_BY
In MySQL 4.1, you can achieve the same effect with these two statements
(specify the sql_mode
value on a single line):
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET GLOBAL sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,ONLY_FULL_GROUP_BY';
See section 1.5.2 Selecting SQL Modes.
In MySQL 4.1.1, the sql_mode
options shown can be also be set with
this statement:
SET GLOBAL sql_mode='ansi';
In this case, the value of the sql_mode
variable will be set to all
options that are relevant for ANSI mode. You can check the result like this:
mysql> SET GLOBAL sql_mode='ansi'; mysql> SELECT @@global.sql_mode; -> 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI';
MySQL Server includes some extensions that you probably will not find in
other SQL databases. Be warned that if you use them, your code will not be
portable to other SQL servers. In some cases, you can write code that
includes MySQL extensions, but is still portable, by using comments
of the form /*! ... */
. In this case, MySQL Server will parse and
execute the code within the comment as it would any other MySQL
statement, but other SQL servers will ignore the extensions. For example:
SELECT /*! STRAIGHT_JOIN */ col_name FROM table1,table2 WHERE ...
If you add a version number after the `!' character, the syntax within the comment will be executed only if the MySQL version is equal to or newer than the specified version number:
CREATE /*!32302 TEMPORARY */ TABLE t (a INT);
This means that if you have Version 3.23.02 or newer, MySQL
Server will use the TEMPORARY
keyword.
The following descriptions list MySQL extensions, organized by category.
MyISAM
or ISAM
storage engines.
For example, to rename a MyISAM
table, rename the `.MYD',
`.MYI', and `.frm' files to which the table corresponds.
User space
.
MySQL Server doesn't support tablespaces such as used in statements like this:
CREATE TABLE ralph.my_table...IN my_tablespace
.
ANALYZE TABLE
, CHECK TABLE
, OPTIMIZE TABLE
, and
REPAIR TABLE
statements.
CREATE DATABASE
and DROP DATABASE
statements.
See section 13.2.4 CREATE DATABASE
Syntax.
DO
statement.
EXPLAIN SELECT
to get a description of how tables are joined.
FLUSH
and RESET
statements.
SET
statement. See section 13.5.3 SET
Syntax.
SHOW
statement.
See section 13.5.4 SHOW
Syntax.
LOAD DATA INFILE
. In many cases, this syntax is compatible with
Oracle's LOAD DATA INFILE
. See section 13.1.5 LOAD DATA INFILE
Syntax.
RENAME TABLE
. See section 13.2.12 RENAME TABLE
Syntax.
REPLACE
instead of DELETE
+ INSERT
.
See section 13.1.6 REPLACE
Syntax.
CHANGE col_name
, DROP col_name
, or DROP
INDEX
, IGNORE
or RENAME
in an ALTER TABLE
statement.
Use of multiple ADD
, ALTER
, DROP
, or CHANGE
clauses in an ALTER TABLE
statement.
See section 13.2.2 ALTER TABLE
Syntax.
INDEX
or KEY
in a CREATE TABLE
statement. See section 13.2.6 CREATE TABLE
Syntax.
TEMPORARY
or IF NOT EXISTS
with CREATE TABLE
.
IF EXISTS
with DROP TABLE
.
DROP TABLE
statement.
ORDER BY
and LIMIT
clauses of the UPDATE
and
DELETE
statements.
INSERT INTO ... SET col_name = ...
syntax.
DELAYED
clause of the INSERT
and REPLACE
statements.
LOW_PRIORITY
clause of the INSERT
, REPLACE
,
DELETE
, and UPDATE
statements.
INTO OUTFILE
and STRAIGHT_JOIN
in a SELECT
statement. See section 13.1.7 SELECT
Syntax.
SQL_SMALL_RESULT
option in a SELECT
statement.
GROUP BY
part.
This gives better performance for some very specific, but quite normal
queries.
See section 12.9 Functions and Modifiers for Use with GROUP BY
Clauses.
ASC
and DESC
with GROUP BY
.
:=
assignment
operator:
mysql> SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg -> FROM test_table; mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
MEDIUMINT
, SET
, ENUM
, and the
different BLOB
and TEXT
types.
AUTO_INCREMENT
, BINARY
, NULL
,
UNSIGNED
, and ZEROFILL
.
||
and &&
operators to mean
logical OR and AND, as in the C programming language. In MySQL Server,
||
and OR
are synonyms, as are &&
and AND
.
Because of this nice syntax, MySQL Server doesn't support
the standard SQL ||
operator for string concatenation; use
CONCAT()
instead. Because CONCAT()
takes any number
of arguments, it's easy to convert use of the ||
operator to
MySQL Server.
COUNT(DISTINCT list)
where list
has more than one element.
BINARY
attribute or use the BINARY
cast, which causes
comparisons to be done using the underlying character code values rather
then a lexical ordering.
%
operator is a synonym for MOD()
. That is,
N % M
is equivalent to MOD(N,M)
. %
is supported
for C programmers and for compatibility with PostgreSQL.
=
, <>
, <=
,<
, >=
,>
,
<<
, >>
, <=>
, AND
, OR
, or LIKE
operators may be used in column comparisons to the left of the
FROM
in SELECT
statements. For example:
mysql> SELECT col1=1 AND col2=2 FROM tbl_name;
LAST_INSERT_ID()
function that returns the most recent
AUTO_INCREMENT
value.
See section 12.8.3 Information Functions.
LIKE
is allowed on numeric columns.
REGEXP
and NOT REGEXP
extended regular expression
operators.
CONCAT()
or CHAR()
with one argument or more than two
arguments. (In MySQL Server, these functions can take any number of
arguments.)
BIT_COUNT()
, CASE
, ELT()
,
FROM_DAYS()
, FORMAT()
, IF()
, PASSWORD()
,
ENCRYPT()
, MD5()
, ENCODE()
, DECODE()
,
PERIOD_ADD()
, PERIOD_DIFF()
, TO_DAYS()
, and
WEEKDAY()
functions.
TRIM()
to trim substrings. Standard SQL supports removal
of single characters only.
GROUP BY
functions STD()
, BIT_OR()
,
BIT_AND()
, BIT_XOR()
, and GROUP_CONCAT()
.
See section 12.9 Functions and Modifiers for Use with GROUP BY
Clauses.
For a prioritized list indicating when new extensions will be added to MySQL Server, you should consult the online MySQL TODO list at http://dev.mysql.com/doc/mysql/en/TODO.html. That is the latest version of the TODO list in this manual. See section C MySQL and the Future (the TODO).
We try to make MySQL Server follow the ANSI SQL standard and the ODBC SQL standard, but MySQL Server performs operations differently in some cases:
VARCHAR
columns, trailing spaces are removed when the value is
stored. (Fixed in MySQL 5.0.3). See section 1.5.7 Known Errors and Design Deficiencies in MySQL.
CHAR
columns are silently converted to VARCHAR
columns when you define a table or alter its structure. (Fixed in MySQL 5.0.3).
See section 13.2.6.1 Silent Column Specification Changes.
REVOKE
statement to revoke
privileges for a table. See section 13.5.1.3 GRANT
and REVOKE
Syntax.
CAST()
function does not support cast to REAL
or
BIGINT
. See section 12.7 Cast Functions and Operators.
HAVING
clause in a SELECT
statement be able to refer to columns in the GROUP BY
clause. This
cannot be done before MySQL 5.0.2.
MySQL 4.1 supports subqueries and derived tables.
A ``subquery'' is a SELECT
statement nested within another statement.
A ``derived table'' (an unnamed view) is a subquery in the FROM
clause
of another statement.
See section 13.1.8 Subquery Syntax.
For MySQL versions older than 4.1, most subqueries can be rewritten using joins or other methods. See section 13.1.8.11 Rewriting Subqueries as Joins for Earlier MySQL Versions for examples that show how to do this.
SELECT INTO TABLE
MySQL Server doesn't support the Sybase SQL extension:
SELECT ... INTO TABLE ...
. Instead, MySQL Server supports the
standard SQL syntax INSERT INTO ... SELECT ...
, which is basically
the same thing. See section 13.1.4.1 INSERT ... SELECT
Syntax.
INSERT INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
Alternatively, you can use SELECT INTO OUTFILE ...
or
CREATE TABLE ... SELECT
.
From version 5.0, MySQL supports SELECT ... INTO
with user
variables. The same syntax may also be used inside stored procedures using
cursors and local variables.
See section 19.1.6.3 SELECT ... INTO
Statement.
MySQL Server (version 3.23-max and all versions 4.0 and above) supports
transactions with the InnoDB
and BDB
transactional storage engines.
InnoDB
provides full ACID
compliance.
See section 14 MySQL Storage Engines and Table Types.
The other non-transactional storage engines in MySQL Server (such as
MyISAM
) follow a different paradigm for data integrity called
``atomic operations.'' In transactional terms, MyISAM
tables effectively always operate in AUTOCOMMIT=1
mode.
Atomic operations often offer comparable integrity with higher performance.
With MySQL Server supporting both paradigms, you can decide whether your applications are best served by the speed of atomic operations or the use of transactional features. This choice can be made on a per-table basis.
As noted, the trade-off for transactional versus non-transactional table
types lies mostly in performance. Transactional tables have significantly
higher memory and diskspace requirements, and more CPU overhead.
On the other hand, transactional table types such as InnoDB
also
offer many significant features. MySQL Server's modular design allows the
concurrent use of different storage engines to suit different
requirements and deliver optimum performance in all situations.
But how do you use the features of MySQL Server to maintain rigorous
integrity even with the non-transactional MyISAM
tables, and how
do these features compare with the transactional table types?
ROLLBACK
rather than
COMMIT
in critical situations, transactions are more
convenient. Transactions also ensure that unfinished updates or
corrupting activities are not committed to the database; the server is
given the opportunity to do an automatic rollback and your database is
saved.
If you use non-transactional tables,
MySQL Server in almost all cases allows you to resolve potential problems
by including simple checks before updates and by running simple scripts
that check the databases for inconsistencies and automatically repair
or warn if such an inconsistency occurs. Note that just by using the
MySQL log or even adding one extra log, you can normally fix tables
perfectly with no data integrity loss.
LOCK TABLES
or atomic updates, ensuring
that you never will get an automatic abort from the server, which is
a common problem with transactional database systems.
The transactional paradigm has its benefits and its drawbacks. Many users and application developers depend on the ease with which they can code around problems where an abort appears to be, or is necessary. However, even if you are new to the atomic operations paradigm, or more familiar with transactions, do consider the speed benefit that non-transactional tables can offer on the order of three to five times the speed of the fastest and most optimally tuned transactional tables.
In situations where integrity is of highest importance, MySQL Server offers
transaction-level reliability and integrity even for non-transactional tables.
If you lock tables with LOCK TABLES
, all updates will stall
until any integrity checks are made. If you obtain a READ LOCAL
lock
(as opposed to a write lock) for a table that allows concurrent inserts at the
end of the table, reads are allowed, as are inserts by other clients.
The new inserted records will not be seen by the
client that has the read lock until it releases the lock.
With INSERT DELAYED
, you can queue inserts into a local
queue, until the locks are released, without having the client wait
for the insert to complete. See section 13.1.4.2 INSERT DELAYED
Syntax.
``Atomic,'' in the sense that we mean it, is nothing magical. It only means that you can be sure that while each specific update is running, no other user can interfere with it, and there will never be an automatic rollback (which can happen with transactional tables if you are not very careful). MySQL Server also guarantees that there will not be any dirty reads.
Following are some techniques for working with non-transactional tables:
LOCK TABLES
, and you don't need cursors to update
records on the fly.
ROLLBACK
, you can use the following strategy:
LOCK TABLES
to lock all the tables you want to access.
UNLOCK TABLES
to release your locks.
WHERE
clause in the UPDATE
statement. If the record wasn't
updated, we give the client a message: ``Some of the data you have changed
has been changed by another user.'' Then we show the old row versus the new
row in a window so that the user can decide which version of the customer
record to use.
This gives us something that is similar to column locking but is actually
even better because we only update some of the columns, using values that
are relative to their current values. This means that typical UPDATE
statements look something like these:
UPDATE tablename SET pay_back=pay_back+125; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_owed_to_us=money_owed_to_us-125 WHERE customer_id=id AND address='old address' AND phone='old phone';This is very efficient and works even if another client has changed the values in the
pay_back
or money_owed_to_us
columns.
LOCK TABLES
and/or ROLLBACK
for the purpose of managing unique identifiers. This can be handled much
more efficiently without locking or rolling back by using an
AUTO_INCREMENT
column and either the
LAST_INSERT_ID()
SQL function or the mysql_insert_id()
C API function.
See section 12.8.3 Information Functions.
See section 22.2.3.33 mysql_insert_id()
.
You can generally code around the need for row-level locking. Some situations
really do need it, and InnoDB
tables support row-level locking. With
MyISAM
tables, you can use a flag column in the table and do something
like the following:
UPDATE tbl_name SET row_flag=1 WHERE id=ID;MySQL returns
1
for the number of affected rows if the row was
found and row_flag
wasn't 1
in the original row.
You can think of it as though MySQL Server changed the preceding query to:
UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;
Stored procedures are implemented in MySQL version 5.0. See section 19 Stored Procedures and Functions.
Triggers are currently being implemented, with basic functionality in MySQL 5.0, with further development planned for MySQL 5.1.
In MySQL Server 3.23.44 and up, the InnoDB
storage engine supports
checking of foreign key constraints, including CASCADE
, ON
DELETE
, and ON UPDATE
. See section 15.7.4 FOREIGN KEY
Constraints.
For storage engines other than InnoDB
, MySQL Server parses the
FOREIGN KEY
syntax in CREATE TABLE
statements, but does not
use or store it. In the future, the implementation will be
extended to store this information in the table specification file so that it
may be retrieved by mysqldump
and ODBC. At a later stage,
foreign key constraints will be implemented for MyISAM
tables as well.
Foreign key enforcement offers several benefits to database developers:
Do keep in mind that these benefits come at the cost of additional overhead for the database server to perform the necessary checks. Additional checking by the server affects performance, which for some applications may be sufficiently undesirable as to be avoided if possible. (Some major commercial applications have coded the foreign-key logic at the application level for this reason.)
MySQL gives database developers the choice of which approach to use. If you
don't need foreign keys and want to avoid the overhead associated with
enforcing referential integrity, you can choose another table type instead,
such as MyISAM
. (For example, the MyISAM
storage engine offers
very fast performance for applications that perform only INSERT
and
SELECT
operations, because the inserts can be performed concurrently
with retrievals. See section 7.3.2 Table Locking Issues.)
If you choose not to take advantage of referential integrity checks, keep the following considerations in mind:
ON DELETE
is the only referential integrity capability an
application needs, note that as of MySQL Server 4.0, you can use
multiple-table DELETE
statements to delete rows from many
tables with a single statement. See section 13.1.1 DELETE
Syntax.
ON DELETE
is to add
the appropriate DELETE
statement to your application when you
delete records from a table that has a foreign key. In practice, this is often
as quick as using foreign keys, and is more portable.
Be aware that the use of foreign keys can in some instances lead to problems:
FOREIGN KEY
Constraints.
As of MySQL 4.1.1,
mysqldump
generates dump files that take advantage of this
capability automatically when reloaded.)
Note that foreign keys in SQL are used to check and enforce referential
integrity, not to join tables. If you want to get results from multiple
tables from a SELECT
statement, you do this by performing a join
between them:
SELECT * FROM t1, t2 WHERE t1.id = t2.id;
See section 13.1.7.1 JOIN
Syntax. See section 3.6.6 Using Foreign Keys.
The FOREIGN KEY
syntax without ON DELETE ...
is often used
by ODBC applications to produce automatic WHERE
clauses.
Views (including updatable views) are implemented in the 5.0 version
of MySQL Server. Views are available in binary releases from 5.0.1
and up.
See section 13.2.7 CREATE VIEW
Syntax.
Views are useful for allowing users to access a set of relations (tables) as if it were a single table, and limiting their access to just that. Views can also be used to restrict access to rows (a subset of a particular table). For access control to columns, you can also use the sophisticated privilege system in MySQL Server. See section 5.5 The MySQL Access Privilege System.
In designing an implementation of views, our ambitious goal, as much as is possible within the confines of SQL, has been full compliance with ``Codd's Rule #6'' for relational database systems: ``All views that are theoretically updatable, should in practice also be updatable.''
Some other SQL databases use `--' to start comments.
MySQL Server uses `#' as the start comment character. You can also use
the C comment style /* this is a comment */
with MySQL Server.
See section 9.5 Comment Syntax.
MySQL Server 3.23.3 and above support the `--' comment style,
provided the comment is followed by a space (or by a control character such
as a newline). The requirement for a space is to prevent problems with
automatically generated SQL queries that have used something like the following code, where we automatically insert the value of the payment for
!payment!
:
UPDATE account SET credit=credit-!payment!
Think about what happens if the value of payment
is a negative value
such as -1
:
UPDATE account SET credit=credit--1
credit--1
is a legal expression in SQL, but if --
is interpreted
as the start of a comment, part of the expression is discarded. The result is a
statement that has a completely different meaning than intended:
UPDATE account SET credit=credit
The statement produces no change in value at all! This illustrates that allowing comments to start with `--' can have serious consequences.
Using our implementation of this method of commenting in MySQL Server
3.23.3 and up, credit--1
is actually safe.
Another safe feature is that the mysql
command-line client
removes all lines that start with `--'.
The following information is relevant only if you are running a MySQL version earlier than 3.23.3:
If you have an SQL program in a text file that contains `--'
comments, you should use the replace
utility as follows to convert the
comments to use `#' characters:
shell> replace " --" " #" < text-file-with-funny-comments.sql \ | mysql db_name
instead of the usual:
shell> mysql db_name < text-file-with-funny-comments.sql
You can also edit the command file ``in place'' to change the `--' comments to `#' comments:
shell> replace " --" " #" -- text-file-with-funny-comments.sql
Change them back with this command:
shell> replace " #" " --" -- text-file-with-funny-comments.sql
MySQL allows you to work both with transactional tables that allow rollback and with non-transactional tables that do not. Because of this, constraint handling is a bit different in MySQL than in other databases. We must handle the case when you have inserted or updated a lot of rows in a non-transactional table for which changes cannot be rolled back when an error occurs.
The basic philosophy is that MySQL Server tries to produce an error for anything that it can detect while parsing a statement to be executed, and tries to recover from any errors that occur while executing the statement. We do this in most cases, but not yet for all. See section C.3 New Features Planned for the Near Future.
The options MySQL has when an error occurs are to stop the statement in the middle or to recover as well as possible from the problem and continue. By default, the server follows the latter course. This means, for example, that the server may coerce illegal values to the closest legal values.
Beginning with MySQL 5.0.2, several SQL mode options are available to provide greater control over how accepting to be of bad data values and whether to continue executing a statement or abort it when errors occur. Using these options, you can configure MySQL Server to act in a more traditional fashion that is like other DBMSs that reject improper input. The SQL mode can be set at runtime, which enables individual clients to select the behavior most appropriate for their requirements. See section 5.2.2 The Server SQL Mode.
The following sections describe what happens for the different types of constraints.
PRIMARY KEY
and UNIQUE
Index Constraints
Normally, an error occurs when you try to INSERT
or UPDATE
a row that causes a primary key, unique key, or foreign key violation.
If you are using a transactional storage engine such as InnoDB
, MySQL
automatically rolls back the statement. If you are using a non-transactional
storage engine, MySQL stops processing the statement at the row for which
the error occurred and leaves any remaining rows unprocessed.
If you wish to ignore such key violations, MySQL supports an IGNORE
keyword for INSERT
and UPDATE
. In this case, MySQL ignores
any key violations and continues processing with the next row.
See section 13.1.4 INSERT
Syntax.
See section 13.1.10 UPDATE
Syntax.
You can get information about the number of rows actually inserted or
updated with the mysql_info()
C API function.
See section 22.2.3.31 mysql_info()
.
In MySQL 4.1 and up, you also can use the SHOW WARNINGS
statement.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
For the moment, only InnoDB
tables support foreign keys.
See section 15.7.4 FOREIGN KEY
Constraints.
Foreign key support in MyISAM
tables is scheduled for implementation
in MySQL 5.1.
Before MySQL 5.0.2, MySQL is forgiving of illegal or improper data values and coerces them to legal values for data entry. In MySQL 5.0.2 and up, that remains the default behavior, but you can select more traditional treatment of bad values such that the server rejects them and aborts the statement in which they occur. This section describes the default (forgiving) behavior of MySQL, as well as the newer strict SQL mode and how it differs.
The following holds true when you are not using strict mode.
If you insert an ``incorrect'' value into a column, such as a NULL
into a NOT NULL
column or a too-large numeric value into a
numeric column, MySQL sets the column to the ``best possible value''
instead of producing an error:
NULL
into a column that doesn't take NULL
values, MySQL Server stores 0 or ''
(the empty string) instead.
DATE
and
DATETIME
columns (such as '2000-02-31'
or '2000-02-00'
).
The idea is that it's not the job of the SQL server to validate dates. If
MySQL can store a date value and retrieve exactly the same value, MySQL
stores it as given. If the date is totally wrong (outside the server's
ability to store it), the special date value '0000-00-00'
is stored
in the column instead.
INSERT
statement specifies no value for a column, MySQL inserts
its default value if the column definition includes an explicit DEFAULT
clause. If the definition has no such DEFAULT
clause, MySQL inserts
the implicit default value for the column data type. In general,
this is the empty string for string columns, 0 for numeric columns,
and '0000-00-00'
for date columns. Implicit default values are
discussed in section 13.2.6 CREATE TABLE
Syntax.
The reason for the preceding rules is that we can't check these conditions until the statement has begun executing. We can't just roll back if we encounter a problem after updating a few rows, because the storage engine may not support rollback. The option of terminating the statement is not that good; in this case, the update would be ``half done,'' which is probably the worst possible scenario. In this case, it's better to ``do the best you can'' and then continue as if nothing happened.
In MySQL 5.0.2 and up, you can select stricter treatment of input values by
using the STRICT_TRANS_TABLES
or STRICT_ALL_TABLES
SQL modes.
See section 5.2.2 The Server SQL Mode.
STRICT_TRANS_TABLES
works like this: For transactional storage
engines, bad data values occurring anywhere in the statement causes
the to abort and roll back. For non-transactional storage engines,
the statement aborts if the error occurs in the first row to be inserted
or updated. (In this case, the statement can be regarded to leave the
table unchanged, just as for a transactional table.) Errors in rows
after the first do not abort the statement. Instead, bad data values
are adjusted and result in warnings rather than errors. In other words,
with STRICT_TRANS_TABLES
, a wrong value causes MySQL to roll back,
if it can, all updates done so far.
For stricter checking, enable STRICT_ALL_TABLES
. This is the same as
STRICT_TRANS_TABLES
except that for non-transactional storage engines,
errors abort the statement even for bad data in rows following the first row.
This means that if an error occurs partway through a multiple-row insert or
update for a non-transactional table, a partial update results. Earlier rows
are inserted or updated, but those from the point of the error on are not.
To avoid this for non-transactional tables, either use single-row statements
or else use STRICT_TRANS_TABLES
if conversion warnings rather than
errors are acceptable. To avoid problems in the first place, do not use
MySQL to check column content. It is safest (and often faster) to let the
application ensure that it passes only legal values to the database.
With either of the strict mode options, you can cause errors to be treated
as warnings by using INSERT IGNORE
or UPDATE IGNORE
.
ENUM
and SET
Constraints
ENUM
and SET
columns provide an efficient way to define columns
that can contain only a given set of values. However, before MySQL 5.0.2,
ENUM
and SET
are not real constraints. This is for the same
reasons that NOT NULL
is not honored.
See section 1.5.6.2 Constraints on Invalid Data.
ENUM
columns always have a default value. If you don't specify
a default value, then it will be NULL
for columns that can have
NULL
, otherwise the first enumeration value is used as the default
value.
If you insert an incorrect value into an ENUM
column or if you
force a value into an ENUM
column with IGNORE
, it is set
to the reserved enumeration value of 0
, which is displayed as an
empty string in string context. See section 11.4.4 The ENUM
Type.
If you insert an incorrect value into a SET
column, the incorrect value
is ignored. For example, if the column can contain the values
'a'
, 'b'
, and 'c'
, an attempt to assign 'a,x,b,y'
results in a value of 'a,b'
.
See section 11.4.5 The SET
Type.
As of MySQL 5.0.2, you can configure the server to use strict SQL mode.
See section 5.2.2 The Server SQL Mode.
When strict mode is not enabled, values entered into ENUM
and SET
columns are handled as just described for MySQL 4.x. However, if strict
mode is enabled, the definition of a ENUM
or SET
column does
act as a constraint on values entered into the column. An error occurs
for values that do not satisfy these conditions:
ENUM
value must be one of those listed in the column definition, or
the internal numeric equivalent thereof. The value cannot be the error value
(that is, 0 or the empty string).
For a column defined as ENUM('a','b','c')
, values such as ''
,
'd'
, and 'ax'
are illegal and are rejected.
SET
value must be the empty string or a value consisting of one or
more of the values listed in the column definition separated by commas.
For a column defined as SET('a','b','c')
, values such as
'd'
, and 'a,b,c,d'
are illegal and are rejected.
Errors for invalid values can be suppressed in strict mode if you use
INSERT IGNORE
or UPDATE IGNORE
. In this case, a warning is
generated rather than an error. For ENUM
, the value is inserted as the
error member (0
). For SET
, the value is inserted as given except
that any invalid substrings are deleted. For example, 'a,x,b,y'
results in a value of 'a,b'
, as described earlier.
The following known errors or bugs are not fixed in MySQL 3.23 because fixing them would involve changing a lot of code that could introduce other even worse bugs. The bugs are also classified as ``not fatal'' or ``bearable.''
LOCK TABLE
to lock
multiple tables and then in the same connection use DROP TABLE
to
drop one of them while another thread is trying to lock it. (To break the
deadlock, you can use KILL
to terminate any of the threads involved.)
This issue is resolved as of MySQL 4.0.12.
SELECT MAX(key_column) FROM t1,t2,t3...
where one of the tables are
empty doesn't return NULL
but instead returns the maximum value for the
column. This issue is resolved as of MySQL 4.0.11.
DELETE FROM heap_table
without a WHERE
clause doesn't work on
a locked HEAP
table.
The following known errors or bugs are not fixed in MySQL 4.0 because fixing them would involve changing a lot of code that could introduce other even worse bugs. The bugs are also classified as ``not fatal'' or ``bearable.''
HAVING
you can get a crash or wrong result if you use an alias to
a RAND()
function. This is fixed in 4.1.10 but will not be fixed
in 4.0 because the fix 'may' cause side effects for some applications.
UNION
, the first SELECT
determines the type,
max_length
, and NULL
properties for the resulting
columns. This issue is resolved as of MySQL 4.1.1; the property values are
based on the rows from all UNION
parts.
DELETE
with many tables, you can't refer to tables to be
deleted through an alias. This is fixed as of MySQL 4.1.
UNION ALL
and UNION DISTINCT
in the same query.
If you use ALL
for one UNION
, it is used for all
of them. This is fixed as of MySQL 4.1.2. The rules for mixed UNION
types are given in section 13.1.7.2 UNION
Syntax.
FLUSH TABLES WITH READ LOCK
does not block CREATE TABLE
, which
may cause a problem with the binary log position when
doing a full backup of tables and the binary log.
mysqldump --single-transaction --master-data
behaved like
mysqldump --master-data
, so the dump was a blocking one. This is fixed
starting from MySQL 4.1.8.
RPAD()
function (or any function adding spaces to the
right) in a query that had to be resolved by using a temporary table, all
resulting strings had rightmost spaces removed (i.e. RPAD()
did not
work).
The following problems are known and fixing them is a high priority:
NULL
value to a subquery using ALL/ANY/SOME
and the subquery returns an empty result, the comparison might evaluate
to the non-standard result of NULL
rather than to TRUE
or
FALSE
. This will be fixed in MySQL 5.0.
lower_case_table_names=2
(which enables
MySQL to remember the used case for databases and table names) MySQL
will not on case insensitive systems remember the used case for database
names for the function DATABASE()
or in various logs.
FOREIGN KEY
constraint doesn't work in replication because
the constraint may have another name on the slave.
REPLACE
(and LOAD DATA
with the REPLACE
option) does not
trigger ON DELETE CASCADE
.
DISTINCT
with ORDER BY
doesn't work inside GROUP_CONCAT()
if you don't use all and only those columns that are in the
DISTINCT
list.
DROP TABLE
command before the table is
used in the transaction itself. We plan to fix this in 5.0 by
having the DROP TABLE
wait until the table is not used in any
transaction.
FLUSH TABLES WITH READ LOCK
does not block COMMIT
if the server
is running without binary logging, which may cause a problem (of consistency
between tables) when doing a full backup.
ANALYZE TABLE
on a BDB
table may in some cases make the table
unusable until you restart mysqld
. If this happens, you will
see errors of the following form in the MySQL error file:
001207 22:07:56 bdb: log_flush: LSN past current end-of-log
FROM
clause of a SELECT
statement, but silently
ignores them. The reason for not giving an error is that many clients
that automatically generate queries add parentheses in the FROM
clause even where they are not needed.
RIGHT JOINS
or combining LEFT
and
RIGHT
join in the same query may not give a correct answer because
MySQL only generates NULL
rows for the table preceding a LEFT
or
before a RIGHT
join. This will be fixed in 5.0 at the same time
we add support for parentheses in the FROM
clause.
ALTER TABLE
on a BDB
table on which you are
running multiple-statement transactions until all those transactions complete.
(The transaction will probably be ignored.)
ANALYZE TABLE
, OPTIMIZE TABLE
, and REPAIR TABLE
may
cause problems on tables for which you are using INSERT DELAYED
.
LOCK TABLE ...
and FLUSH TABLES ...
doesn't
guarantee that there isn't a half-finished transaction in progress on the
table.
BDB
tables are a bit slow to open. If you have many BDB
tables
in a database, it will take a long time to use the mysql
client on
the database if you are not using the -A
option or if you are using
rehash
. This is especially notable when you have a large table cache.
CREATE ... SELECT
or
INSERT ... SELECT
statements that
insert zero or NULL
values into an AUTO_INCREMENT
column.
DELETE
if you are
deleting rows from a table that has foreign keys with ON DELETE
CASCADE
properties.
REPLACE ... SELECT
,
INSERT IGNORE ... SELECT
if you have
duplicate key values in the inserted data.
ORDER BY
clause guaranteeing a deterministic order.
For example, for INSERT ... SELECT
with no ORDER
BY
, the SELECT
may return rows in a different order
(which will result in a row having different ranks, hence getting a
different number in the AUTO_INCREMENT
column),
depending on the choices made by the optimizers on the master and
slave. A query will be optimized differently on the master and slave only if:
OPTIMIZE TABLE
was run on the master tables and not on
the slave tables. (To fix this, OPTIMIZE TABLE
, ANALYZE TABLE
,
and REPAIR TABLE
are written to the binary log as of MySQL 4.1.1).
InnoDB
on the master,
but MyISAM
on the slave if the slave has less available disk
space.)
key_buffer_size
, and so on) are different on
the master and slave.
mysqlbinlog|mysql
.
The easiest way to avoid this problem in all cases is to add an
ORDER BY
clause to
such non-deterministic queries to ensure that the rows are always
stored or modified in the same order.
In future MySQL versions, we will automatically add an ORDER BY
clause when needed.
The following problems are known and will be fixed in due time:
--log-bin=old_host_name-bin
if you change your hostname to something
else. Another option is to just rename the old files to reflect your
hostname change (and if these are binary logs, you will also need to edit the
binary log index file and fix the binlog names there). See section 5.2.1 mysqld
Command-Line Options.
mysqlbinlog
will not delete temporary files left after a
LOAD DATA INFILE
command. See section 8.5 The mysqlbinlog
Binary Log Utility.
RENAME
doesn't work with TEMPORARY
tables or tables used in a
MERGE
table.
CHAR(255)
) in table names, column names, or enumerations.
This is scheduled to be fixed in version 5.1 when we have new table
definition format files.
SET CHARACTER SET
, you can't use translated
characters in database, table, and column names.
ESCAPE
in LIKE
... ESCAPE
.
DECIMAL
column in which the same number is stored in
different formats (for example, +01.00
, 1.00
, 01.00
),
GROUP BY
may regard each value as a different value.
BLOB
and TEXT
values can't ``reliably'' be used in GROUP
BY
or ORDER BY
or DISTINCT
. Only the first
max_sort_length
bytes are used when comparing BLOB
values in
these cases. The default value of max_sort_length
value is 1024. It
can be changed at server startup time. As of MySQL 4.0.3, it can also be
changed at runtime. For older versions, a workaround for most cases is to
use a substring. For example:
SELECT DISTINCT LEFT(blob_col,2048) FROM tbl_name;
BIGINT
or DOUBLE
(both are
normally 64 bits long). Which precision you get depends on the function.
The general rule is that bit functions are done with BIGINT
precision, IF
and ELT()
with BIGINT
or DOUBLE
precision, and the rest with DOUBLE
precision. You should try to
avoid using unsigned long long values if they resolve to be bigger than
63 bits (9223372036854775807) for anything other than bit fields.
MySQL Server 4.0 has better BIGINT
handling than 3.23.
BLOB
and TEXT
columns, automatically
have all trailing spaces removed when retrieved. For CHAR
types, this
is okay. The bug is
that in MySQL Server, VARCHAR
columns are treated the same way.
ENUM
and SET
columns in one table.
MIN()
, MAX()
, and other aggregate functions, MySQL
currently compares ENUM
and SET
columns by their string
value rather than by the string's relative position in the set.
mysqld_safe
redirects all messages from mysqld
to the
mysqld
log. One problem with this is that if you execute
mysqladmin refresh
to close and reopen the log,
stdout
and stderr
are still redirected to the old log.
If you use --log
extensively, you should edit mysqld_safe
to
log to `host_name.err' instead of `host_name.log' so that you can
easily reclaim the space for the old log by deleting the old one and
executing mysqladmin refresh
.
UPDATE
statement, columns are updated from left to right. If
you refer to an updated column, you get the updated value instead of the
original value. For example, the following statement increments KEY
by 2
, not 1
:
mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;
mysql> SELECT * FROM temp_table, temp_table AS t2; ERROR 1137: Can't reopen table: 'temp_table'
DISTINCT
differently when you are using
``hidden'' columns in a join than when you are not. In a join, hidden
columns are counted as part of the result (even if they are not shown),
whereas in normal queries, hidden columns don't participate in the
DISTINCT
comparison. We will probably change this in the future to
never compare the hidden columns when executing DISTINCT
.
An example of this is:
SELECT DISTINCT mp3id FROM band_downloads WHERE userid = 9 ORDER BY id DESC;and
SELECT DISTINCT band_downloads.mp3id FROM band_downloads,band_mp3 WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id ORDER BY band_downloads.id DESC;In the second case, you might in MySQL Server 3.23.x get two identical rows in the result set (because the values in the hidden
id
column may differ).
Note that this happens only for queries where you don't have the
ORDER BY
columns in the result.
PROCEDURE
on a query that returns an empty set,
in some cases the PROCEDURE
will not transform the columns.
MERGE
doesn't check whether the underlying
tables are of compatible types.
ALTER TABLE
first to add a UNIQUE
index to a
table used in a MERGE
table and then to
add a normal index on the MERGE
table, the key order will be
different for the tables if there was an old key that was not unique in the
table. This is because ALTER TABLE
puts UNIQUE
indexes before
normal indexes to be able to detect duplicate keys as early as possible.
The following are known bugs in earlier versions of MySQL:
LOCK TABLE
with WRITE
.
FLUSH TABLES
.
UPDATE
that updated a key with
a WHERE
on the same key may have failed because the key was used to
search for records and the same row may have been found multiple times:
UPDATE tbl_name SET KEY=KEY+1 WHERE KEY > 100;A workaround is to use:
UPDATE tbl_name SET KEY=KEY+1 WHERE KEY+0 > 100;This will work because MySQL Server will not use an index on expressions in the
WHERE
clause.
For information about platform-specific bugs, see the installation and porting instructions in section 2.12 Operating System-Specific Notes and section E Porting to Other Systems.
This chapter describes how to obtain and install MySQL:
GnuPG
.
Before installing MySQL, you should do the following:
This section contains the information necessary to carry out these steps. After doing so, you can use the instructions in later sections of the chapter to install the distribution that you choose.
This section lists the operating systems on which you can expect to be able to run MySQL.
We use GNU Autoconf, so it is possible to port MySQL to all modern systems that have a C++ compiler and a working implementation of POSIX threads. (Thread support is needed for the server. To compile only the client code, the only requirement is a C++ compiler.) We use and develop the software ourselves primarily on Linux (SuSE and Red Hat), FreeBSD, and Sun Solaris (Versions 8 and 9).
MySQL has been reported to compile successfully on the following combinations of operating system and thread package. Note that for many operating systems, native thread support works only in the latest versions.
glibc
2.0.7+ for various
CPU architectures. See section 2.12.1 Linux Notes.
Not all platforms are equally well-suited for running MySQL. How well a certain platform is suited for a high-load mission-critical MySQL server is determined by the following factors:
pthread_mutex_lock()
is too anxious to yield CPU time, this will hurt
MySQL tremendously. If this issue is not taken care of, adding extra CPUs
will actually make MySQL slower.
Based on the preceding criteria, the best platforms for running
MySQL at this point are x86 with SuSE Linux using a 2.4 kernel, and
ReiserFS (or any similar Linux distribution) and SPARC with Solaris
(2.7-9). FreeBSD comes third, but we really hope it will join the top
club once the thread library is improved. We also hope that at some
point we will be able to include into the top category all other platforms
on which MySQL currently compiles and runs okay, but not quite with the
same level of stability and performance. This will require some
effort on our part in cooperation with the developers of the operating system
and library components that MySQL depends on. If you are interested in
improving one of those components, are in a position to influence its
development, and need more detailed instructions on what MySQL
needs to run better, send an email message to the MySQL internals
mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
Please note that the purpose of the preceding comparison is not to say that one operating system is better or worse than another in general. We are talking only about choosing an OS for the specific purpose of running MySQL. With this in mind, the result of this comparison would be different if we considered more factors. In some cases, the reason one OS is better than the other could simply be that we have been able to put more effort into testing and optimizing for a particular platform. We are just stating our observations to help you decide which platform to use for running MySQL.
When preparing to install MySQL, you should decide which version to use. MySQL development occurs in several release series, and you can pick the one that best fits your needs. After deciding which version to install, you can choose a distribution format. Releases are available in binary or source format.
The first decision to make is whether you want to use a production (stable) release or a development release. In the MySQL development process, multiple release series co-exist, each at a different stage of maturity:
We don't believe in a complete freeze, as this also leaves out bugfixes and things that ``must be done.'' ``Somewhat frozen'' means that we may add small things that ``almost surely will not affect anything that's currently working.'' Naturally, relevant bugfixes from an earlier series propagate to later series.
Normally, if you are beginning to use MySQL for the first time or trying to port it to some system for which there is no binary distribution, we recommend going with the production release series. Currently this is MySQL 4.1. All MySQL releases, even those from development series, are checked with the MySQL benchmarks and an extensive test suite before being issued.
If you are running an old system and want to upgrade, but don't want to take the chance of having a non-seamless upgrade, you should upgrade to the latest version in the same release series you are using (where only the last part of the version number is newer than yours). We have tried to fix only fatal bugs and make small, relatively safe changes to that version.
If you want to use new features not present in the production release series, you can use a version from a development series. Note that development releases are not as stable as production releases.
If you want to use the very latest sources containing all current patches and bugfixes, you can use one of our BitKeeper repositories. These are not ``releases'' as such, but are available as previews of the code on which future releases will be based.
The MySQL naming scheme uses release names that consist of three
numbers and a suffix; for example, mysql-4.1.2-alpha
.
The numbers within the release name are interpreted like this:
4
) is the major version and also describes the
file format. All Version 4 releases have the same file format.
1
) is the release level.
Taken together, the major version and release level constitute the release
series number.
2
) is the version number within the
release series. This is incremented for each new release. Usually you
want the latest version for the series you have chosen.
For each minor update, the last number in the version string is incremented. When there are major new features or minor incompatibilities with previous versions, the second number in the version string is incremented. When the file format changes, the first number is increased.
Release names also include a suffix to indicates the stability level of the release. Releases within a series progress through a set of suffixes to indicate how the stability level improves. The possible suffixes are:
alpha
indicates that the release contains some large section of
new code that hasn't been 100% tested. Known bugs (usually there are none)
should be documented in the News section. See section D MySQL Change History. There are also new
commands and extensions in most alpha releases. Active development that
may involve major code changes can occur in an alpha release, but everything
will be tested before issuing a release. For this reason, there should be
no known bugs in any MySQL release.
beta
means that all new code has been tested. No major new
features that could cause corruption in old code are added. There should
be no known bugs. A version changes from alpha to beta when there
haven't been any reported fatal bugs within an alpha version for at least
a month and we have no plans to add any features that could make any old
command unreliable.
gamma
is a beta that has been around a while and seems to work fine.
Only minor fixes are added. This is what many other companies call a release.
MySQL uses a naming scheme that is slightly different from most other products. In general, it's relatively safe to use any version that has been out for a couple of weeks without being replaced with a new version within the release series.
All releases of MySQL are run through our standard tests and benchmarks to ensure that they are relatively safe to use. Because the standard tests are extended over time to check for all previously found bugs, the test suite keeps getting better.
All releases have been tested at least with:
crash-me
test
Another test is that we use the newest MySQL version in our internal production environment, on at least one machine. We have more than 100GB of data to work with.
After choosing which version of MySQL to install, you should decide
whether to use a binary distribution or a source distribution. In
most cases, you should probably use a binary distribution, if one
exists for your platform. Binary distributions are available in native format
for many platforms, such as RPM files for Linux or DMG package installers for
Mac OS X. Distributions also are available as Zip archives or compressed
tar
files.
Reasons to choose a binary distribution include the following:
-max
suffix and is configured with the same options as
mysqld-max
. See section 5.1.2 The mysqld-max
Extended MySQL Server.
If you want to use the MySQL-Max
RPM, you must first
install the standard MySQL-server
RPM.
Under some circumstances, you probably will be better off installing MySQL from a source distribution:
mysqld
with some extra features that are not
included in the standard binary distributions. Here is a list of the most
common extra options that you may want to use:
--with-innodb
(default for MySQL 4.0 and up)
--with-berkeley-db
(not available on all platforms)
--with-raid
--with-libwrap
--with-named-z-libs
(this is done for some of the binaries)
--with-debug[=full]
mysqld
without some features that are
included in the standard binary distributions. For example,
distributions normally are compiled with support for all character
sets. If you want a smaller MySQL server, you can recompile it with support
for only the character sets you need.
pgcc
) or want to use compiler
options that are better optimized for your processor. Binary distributions
are compiled with options that should work on a variety of processors from
the same processor family.
MySQL is evolving quite rapidly here at MySQL AB and we want to share new developments with other MySQL users. We try to make a release when we have very useful features that others seem to have a need for.
We also try to help out users who request features that are easy to implement. We take note of what our licensed users want to have, and we especially take note of what our support customers want and try to help them out.
No one has to download a new release. The News section will tell you if the new release has something you really want. See section D MySQL Change History.
We use the following policy when updating MySQL:
We put a lot of time and effort into making our releases bug-free. To our knowledge, we have not released a single MySQL version with any known ``fatal'' repeatable bugs. (A ``fatal'' bug is something that crashes MySQL under normal usage, produces incorrect answers for normal queries, or has a security problem.)
We have documented all open problems, bugs, and issues that are dependent on design decisions. See section 1.5.7 Known Errors and Design Deficiencies in MySQL.
Our aim is to fix everything that is fixable without risk of making a stable MySQL version less stable. In certain cases, this means we can fix an issue in the development versions, but not in the stable (production) version. Naturally, we document such issues so that users are aware of them.
Here is a description of how our build process works:
mysql
and announce
mailing
lists.
See section 1.4.1.1 The MySQL Mailing Lists.
The announcement message contains a list
of all changes to the release and any known problems with the release.
The Known Problems section in the release notes has been needed
for only a handful of releases.
'a'
release for that
platform. Thanks to our large user base, problems are found quickly.
glibc
library on one of our build
machines that took us a long time to track down.
As a service of MySQL AB, we provide a set of binary distributions of MySQL that are compiled on systems at our site or on systems where supporters of MySQL kindly have given us access to their machines.
In addition to the binaries provided in platform-specific package formats,
we offer binary distributions for a number of platforms in the form of
compressed tar
files (.tar.gz
files).
See section 2.2 Standard MySQL Installation Using a Binary Distribution.
For Windows distributions, see section 2.3 Installing MySQL on Windows.
These distributions are generated using the script
Build-tools/Do-compile
, which compiles the source code and creates
the binary tar.gz
archive using
scripts/make_binary_distribution
.
These binaries are configured and built with the following compilers and
options. This information can also be obtained by looking at the variables
COMP_ENV_INFO
and CONFIGURE_LINE
inside the script
bin/mysqlbug
of every binary tar
file distribution.
The following binaries are built on MySQL AB development systems:
gcc
2.95.3:
CFLAGS="-O2 -mcpu=pentiumpro" CXX=gcc CXXFLAGS="-O2 -mcpu=pentiumpro -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static
icc
(Intel C++ Compiler 8.0):
CC=icc CXX=icc CFLAGS="-O3 -unroll2 -ip -mp -no-gcc -restrict" CXXFLAGS="-O3 -unroll2 -ip -mp -no-gcc -restrict" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static --with-embedded-server --with-innodb
ecc
(Intel C++ Itanium Compiler 7.0):
CC=ecc CFLAGS="-O2 -tpp2 -ip -nolib_inline" CXX=ecc CXXFLAGS="-O2 -tpp2 -ip -nolib_inline" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile
ecc
(Intel C++ Itanium Compiler 7.0):
CC=ecc CFLAGS=-tpp1 CXX=ecc CXXFLAGS=-tpp1 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile
ccc
(Compaq C V6.2-505 / Compaq C++ V6.3-006):
CC=ccc CFLAGS="-fast -arch generic" CXX=cxx CXXFLAGS="-fast -arch generic -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared --disable-shared
gcc
2.95.4:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb
gcc
2.95.3:
CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static
gcc
3.2.1:
CXX=gcc ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
gcc
3.2.3:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb
gcc
3.2:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --with-named-curses-libs=-lcurses --disable-shared
gcc
3.2:
CC=gcc CFLAGS="-O3 -m64 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -m64 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --with-named-curses-libs=-lcurses --disable-shared
gcc
2.95.3:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-curses-libs=-lcurses --disable-shared
cc-5.0
(Sun Forte 5.0):
CC=cc-5.0 CXX=CC ASFLAGS="-xarch=v9" CFLAGS="-Xa -xstrconst -mt -D_FORTEC_ -xarch=v9" CXXFLAGS="-noex -mt -D_FORTEC_ -xarch=v9" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=no --enable-thread-safe-client --disable-shared
gcc
3.2.3:
CFLAGS="-O2 -mcpu=powerpc -Wa,-many " CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared
xlC_r
(IBM Visual Age C/C++ 6.0):
CC=xlc_r CFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS ="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared --with-innodb
gcc
3.3:
CFLAGS="-O2 -mcpu=powerpc -Wa,-many" CXX=gcc CXXFLAGS="-O2 -mcpu=powerpc -Wa,-many -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared
xlC_r
(IBM Visual Age C/C++ 6.0):
CC=xlc_r CFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" CXX=xlC_r CXXFLAGS="-ma -O2 -qstrict -qoptimize=2 -qmaxmem=8192" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --disable-shared --with-embedded-server --with-innodb
gcc
3.1:
CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc CXXFLAGS="-DHPUX -I/opt/dce /include -felide-constructors -fno-exceptions -fno-rtti -O3 -fPIC" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-pthread --with-named-thread-libs=-ldce --with-lib-ccflags=-fPIC --disable-shared
aCC
(HP ANSI C++ B3910B A.03.50):
CC=cc CXX=aCC CFLAGS=+DAportable CXXFLAGS=+DAportable ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb
aCC
(HP ANSI C++ B3910B A.03.33):
CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
aCC
(HP ANSI C++ B3910B A.03.33):
CC=cc CXX=aCC CFLAGS="+DAportable" CXXFLAGS="+DAportable" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb
aCC
(HP aC++/ANSI C B3910B A.05.50):
CC=cc CXX=aCC CFLAGS="+DD64 +DSitanium2" CXXFLAGS="+DD64 +DSitanium2" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-embedded-server --with-innodb
gcc
3.1:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
gcc
2.95.4:
CFLAGS=-DHAVE_BROKEN_REALPATH ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-z-libs=not-used --disable-shared
gcc
2.95.4:
CFLAGS="-DHAVE_BROKEN_REALPATH -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads" CXXFLAGS="-DHAVE_BROKEN_REALPATH -D__USE_UNIX98 -D_REENTRANT -D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads" ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --enable-thread-safe-client --enable-local-infile --enable-assembler --with-named-thread-libs="-DHAVE_GLIBC2_STYLE_GETHOSTBYNAME_R -D_THREAD_SAFE -I /usr/local/include/pthread/linuxthreads -L/usr/local/lib -llthread -llgcc_r" --disable-shared --with-embedded-server --with-innodb
gcc
2.95.3qnx-nto 20010315:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
The following binaries are built on third-party systems kindly provided to MySQL AB by other users. These are provided only as a courtesy; MySQL AB does not have full control over these systems, so we can provide only limited support for the binaries built on them.
gcc
2.95.3:
CFLAGS="-O3 -mpentium" LDFLAGS=-static CXX=gcc CXXFLAGS="-O3 -mpentium -felide-constructors" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --enable-thread-safe-client --disable-shared
CC
3.2:
CC=cc CFLAGS="-O" CXX=CC ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-z-libs=no --enable-thread-safe-client --disable-shared
cc/cxx
(Compaq C V6.3-029i / DIGITAL C++ V6.1-027):
CC="cc -pthread" CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all" CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -fast -inline speed -speculate all -noexceptions -nortti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --with-named-thread-libs="-lpthread -lmach -lexc -lc" --disable-shared --with-mysqld-ldflags=-all-static
gcc
3.0.1:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared
gcc
3.2.1:
CFLAGS=-DHAVE_BROKEN_REALPATH ./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --libexecdir=/usr/local/mysql/bin --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --disable-shared --with-innodb
The following compile options have been used for binary packages that MySQL AB provided in the past. These binaries no longer are being updated, but the compile options are listed here for reference purposes.
egcs
1.1.2:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex --enable-thread-safe-client --enable-local-infile --enable-assembler --disable-shared
gcc
2.95.2:
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --enable-assembler --with-mysqld-ldflags=-all-static --disable-shared --with-extra-charsets=complex
gcc
2.7.2.1:
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors" ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-assembler
egcs
1.0.3a or 2.90.27 or
gcc
2.95.2 and newer:
CC=gcc CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex --enable-assembler
gcc
2.8.1:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-low-memory --with-extra-charsets=complex
gcc
2.7.2.1:
CC=gcc CXX=gcc CXXFLAGS=-O ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
gcc
2.7.2:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
gcc
2.7.2.2:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql --with-extra-charsets=complex
Anyone who has more optimal options for any of the preceding configurations
listed can always mail them to the MySQL internals
mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
RPM distributions prior to MySQL 3.22 are user-contributed. Beginning with MySQL 3.22, RPM distributions are generated by MySQL AB.
If you want to compile a debug version of MySQL, you should add
--with-debug
or --with-debug=full
to the preceding
configure
commands and remove any -fomit-frame-pointer
options.
Check the MySQL downloads page (http://dev.mysql.com/downloads/) for information about the current version and for downloading instructions. For a complete up-to-date list of MySQL download mirror sites, see http://dev.mysql.com/downloads/mirrors.html. There you will also find information about becoming a MySQL mirror site and how to report a bad or out-of-date mirror.
Our main mirror is located at http://mirrors.sunsite.dk/mysql/.
GnuPG
After you have downloaded the MySQL package that suits your needs and before you attempt to install it, you should make sure that it is intact and has not been tampered with. MySQL AB offers three means of integrity checking:
GnuPG
, the GNU Privacy Guard
The following sections describe how to use these methods.
If you notice that the MD5 checksum or GPG signatures do not match, first try to download the respective package one more time, perhaps from another mirror site. If you repeatedly cannot successfully verify the integrity of the package, please notify us about such incidents, including the full package name and the download site you have been using, at webmaster@mysql.com or build@mysql.com. Do not report downloading problems using the bug-reporting system.
After you have downloaded a MySQL package, you should make sure that its MD5
checksum matches the one provided on the MySQL download pages. Each package
has an individual checksum that you can verify with the following command,
where package_name
is the name of the package you downloaded:
shell> md5sum package_name
Example:
shell> md5sum mysql-standard-4.0.17-pc-linux-i686.tar.gz 60f5fe969d61c8f82e4f7f62657e1f06 mysql-standard-4.0.17-pc-linux-i686.tar.gz
You should verify that the resulting checksum (the string of hexadecimal digits) matches the one displayed on the download page immediately below the respective package.
Note: Make sure to verify the checksum of the archive file
(e.g. the .zip
or .tar.gz
file) and not of the files that are
contained inside of the archive!
Note that not all operating systems support the md5sum
command. On
some, it is simply called md5
and others do not ship it at all. On
Linux, it is part of the GNU Text Utilities
package, which is
available for a wide range of platforms. You can download the source code
from http://www.gnu.org/software/textutils/ as well. If you have
OpenSSL
installed, you can also use the command openssl md5
package_name
instead. A DOS/Windows implementation of the md5
command line utility is available from http://www.fourmilab.ch/md5/.
A graphical MD5 checking tool is winMd5Sum
, which can be obtained
from http://winmd5sum.solidblue.biz/.
GnuPG
Another method of verifying the integrity and authenticity of a package is to use cryptographic signatures. This is more reliable than using MD5 checksums, but requires more work.
Beginning with MySQL 4.0.10 (February 2003), MySQL AB started signing
downloadable packages with GnuPG
(GNU Privacy Guard
).
GnuPG
is an Open Source alternative to the very well-known
Pretty Good Privacy
(PGP
) by Phil Zimmermann.
See http://www.gnupg.org/ for more information about GnuPG
and how to obtain and install it on your system. Most Linux distributions
ship with GnuPG
installed by default. For more information
about OpenPGP
, see http://www.openpgp.org/.
To verify the signature for a specific package, you first need to obtain a
copy of MySQL AB's public GPG build key. You can download the key from
http://www.keyserver.net/. The key that you want to obtain is named
build@mysql.com
. Alternatively, you can cut and paste the key
directly from the following text:
Key ID: pub 1024D/5072E1F5 2003-02-03 MySQL Package signing key (www.mysql.com) <build@mysql.com> Fingerprint: A4A9 4068 76FC BD3C 4567 70C8 8C71 8D3B 5072 E1F5 Public Key (ASCII-armored): -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3 RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ fw2vOUgCmYv2hW0hyDHuvYlQA/BThQoADgj8AW6/0Lo7V1W9/8VuHP0gQwCgvzV3 BqOxRznNCRCRxAuAuVztHRcEAJooQK1+iSiunZMYD1WufeXfshc57S/+yeJkegNW hxwR9pRWVArNYJdDRT+rf2RUe3vpquKNQU/hnEIUHJRQqYHo8gTxvxXNQc7fJYLV K2HtkrPbP72vwsEKMYhhr0eKCbtLGfls9krjJ6sBgACyP/Vb7hiPwxh6rDZ7ITnE kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q7TXlTUUwgUGFj a2FnZSBzaWduaW5nIGtleSAod3d3Lm15c3FsLmNvbSkgPGJ1aWxkQG15c3FsLmNv bT6IXQQTEQIAHQUCPj6jDAUJCWYBgAULBwoDBAMVAwIDFgIBAheAAAoJEIxxjTtQ cuH1cY4AnilUwTXn8MatQOiG0a/bPxrvK/gCAJ4oinSNZRYTnblChwFaazt7PF3q zIhMBBMRAgAMBQI+PqPRBYMJZgC7AAoJEElQ4SqycpHyJOEAn1mxHijft00bKXvu cSo/pECUmppiAJ41M9MRVj5VcdH/KN/KjRtW6tHFPYhMBBMRAgAMBQI+QoIDBYMJ YiKJAAoJELb1zU3GuiQ/lpEAoIhpp6BozKI8p6eaabzF5MlJH58pAKCu/ROofK8J Eg2aLos+5zEYrB/LsrkCDQQ+PqMdEAgA7+GJfxbMdY4wslPnjH9rF4N2qfWsEN/l xaZoJYc3a6M02WCnHl6ahT2/tBK2w1QI4YFteR47gCvtgb6O1JHffOo2HfLmRDRi Rjd1DTCHqeyX7CHhcghj/dNRlW2Z0l5QFEcmV9U0Vhp3aFfWC4Ujfs3LU+hkAWzE 7zaD5cH9J7yv/6xuZVw411x0h4UqsTcWMu0iM1BzELqX1DY7LwoPEb/O9Rkbf4fm Le11EzIaCa4PqARXQZc4dhSinMt6K3X4BrRsKTfozBu74F47D8Ilbf5vSYHbuE5p /1oIDznkg/p8kW+3FxuWrycciqFTcNz215yyX39LXFnlLzKUb/F5GwADBQf+Lwqq a8CGrRfsOAJxim63CHfty5mUc5rUSnTslGYEIOCR1BeQauyPZbPDsDD9MZ1ZaSaf anFvwFG6Llx9xkU7tzq+vKLoWkm4u5xf3vn55VjnSd1aQ9eQnUcXiL4cnBGoTbOW I39EcyzgslzBdC++MPjcQTcA7p6JUVsP6oAB3FQWg54tuUo0Ec8bsM8b3Ev42Lmu QT5NdKHGwHsXTPtl0klk4bQk4OajHsiy1BMahpT27jWjJlMiJc+IWJ0mghkKHt92 6s/ymfdf5HkdQ1cyvsz5tryVI3Fx78XeSYfQvuuwqp2H139pXGEkg0n6KdUOetdZ Whe70YGNPw1yjWJT1IhMBBgRAgAMBQI+PqMdBQkJZgGAAAoJEIxxjTtQcuH17p4A n3r1QpVC9yhnW2cSAjq+kr72GX0eAJ4295kl6NxYEuFApmr1+0uUq/SlsQ== =YJkx -----END PGP PUBLIC KEY BLOCK-----
You can import the build key into your personal public GPG keyring by using
gpg --import
. For example, if you save the key in a file named
`mysql_pubkey.asc', the import command looks like this:
shell> gpg --import mysql_pubkey.asc
See the GPG documentation for more information on how to work with public keys.
After you have downloaded and imported the public build key, download your desired MySQL package and the corresponding signature, which also is available from the download page. The signature file has the same name as the distribution file with an `.asc' extension. For example:
Distribution file | mysql-standard-4.0.17-pc-linux-i686.tar.gz
|
Signature file | mysql-standard-4.0.17-pc-linux-i686.tar.gz.asc
|
Make sure that both files are stored in the same directory and then run the following command to verify the signature for the distribution file:
shell> gpg --verify package_name.asc
Example:
shell> gpg --verify mysql-standard-4.0.17-pc-linux-i686.tar.gz.asc gpg: Warning: using insecure memory! gpg: Signature made Mon 03 Feb 2003 08:50:39 PM MET using DSA key ID 5072E1F5 gpg: Good signature from "MySQL Package signing key (www.mysql.com) <build@mysql.com>"
The Good signature
message indicates that everything is all right.
You can ignore the insecure memory
warning.
RPM
For RPM packages, there is no separate signature. RPM packages have a built-in GPG signature and MD5 checksum. You can verify a package by running the following command:
shell> rpm --checksig package_name.rpm
Example:
shell> rpm --checksig MySQL-server-4.0.10-0.i386.rpm MySQL-server-4.0.10-0.i386.rpm: md5 gpg OK
Note: If you are using RPM 4.1 and it complains about (GPG)
NOT OK (MISSING KEYS: GPG#5072e1f5)
, even though you have imported the
MySQL public build key into your own GPG keyring, you need to import the
key into the RPM keyring first. RPM 4.1 no longer uses your personal GPG
keyring (or GPG itself). Rather, it maintains its own keyring because it is
a system-wide application and a user's GPG public keyring is a user-specific
file. To import the MySQL public key into the RPM keyring, first obtain the
key as described in the previous section. Then use rpm --import
to import the key. For example, if you have the public key stored in a file
named `mysql_pubkey.asc', import it using this command:
shell> rpm --import mysql_pubkey.asc
If you need to obtain the MySQL public key, see section 2.1.4.2 Signature Checking Using GnuPG
.
This section describes the default layout of the directories created by installing binary or source distributions provided by MySQL AB. If you install a distribution provided by another vendor, some other layout might be used.
On Windows, the default installation directory is `C:\mysql'. With MySQL version 4.1.5 and higher, this has changed to `C:\Program Files\MySQL\MySQL Server 4.1', where 4.1 will be the major version of the installation. The folder has the following subdirectories:
Directory | Contents of Directory |
`bin' | Client programs and the mysqld server
|
`data' | Log files, databases |
`Docs' | Documentation |
`examples' | Example programs and scripts |
`include' | Include (header) files |
`lib' | Libraries |
`scripts' | Utility scripts |
`share' | Error message files |
Installations created from Linux RPM distributions result in files under the following system directories:
Directory | Contents of Directory |
`/usr/bin' | Client programs and scripts |
`/usr/sbin' | The mysqld server
|
`/var/lib/mysql' | Log files, databases |
`/usr/share/doc/packages' | Documentation |
`/usr/include/mysql' | Include (header) files |
`/usr/lib/mysql' | Libraries |
`/usr/share/mysql' | Error message and character set files |
`/usr/share/sql-bench' | Benchmarks |
On Unix, a tar
file
binary distribution is installed by unpacking it at the installation
location you choose (typically `/usr/local/mysql') and creates the
following directories in that location:
Directory | Contents of Directory |
`bin' | Client programs and the mysqld server
|
`data' | Log files, databases |
`docs' | Documentation, ChangeLog |
`include' | Include (header) files |
`lib' | Libraries |
`scripts' | mysql_install_db
|
`share/mysql' | Error message files |
`sql-bench' | Benchmarks |
A source distribution is installed after you configure and compile it. By default, the installation step installs files under `/usr/local', in the following subdirectories:
Directory | Contents of Directory |
`bin' | Client programs and scripts |
`include/mysql' | Include (header) files |
`info' | Documentation in Info format |
`lib/mysql' | Libraries |
`libexec' | The mysqld server
|
`share/mysql' | Error message files |
`sql-bench' | Benchmarks and crash-me test
|
`var' | Databases and log files |
Within an installation directory, the layout of a source installation differs from that of a binary installation in the following ways:
mysqld
server is installed in the `libexec'
directory rather than in the `bin' directory.
mysql_install_db
is installed in the `bin' directory
rather than in the `scripts' directory.
You can create your own binary installation from a compiled source distribution by executing the `scripts/make_binary_distribution' script from the top directory of the source distribution.
The next several sections cover the installation of MySQL on platforms where we offer packages using the native packaging format of the respective platform. (This is also known as performing a ``binary install.'') However, binary distributions of MySQL are available for many other platforms as well. See section 2.7 Installing MySQL on Other Unix-Like Systems for generic installation instructions for these packages that apply to all platforms.
See section 2.1 General Installation Issues for more information on what other binary distributions are available and how to obtain them.
A native Windows version of MySQL has been available from MySQL AB since version 3.21 and represents a sizable percentage of the daily downloads of MySQL. This section describes the process for installing MySQL on Windows.
With the release of MySQL 4.1.5, MySQL AB has introduced a new installer for the Windows version of MySQL, combined with a new GUI Configuration Wizard. This combination automatically installs MySQL, creates an option file, starts the server, and secures the default user accounts.
If you have installed a version of MySQL prior to version 4.1.5, you must perform the following steps:
This process also must be followed with newer MySQL installations where the installation package does not include an installer.
MySQL for Windows is available in two distribution formats:
Generally speaking, you should use the binary distribution. It's simpler, and you need no additional tools to get MySQL up and running.
This section describes how to install MySQL on Windows using a binary distribution. To install using a source distribution, see section 2.8.6 Installing MySQL from Source on Windows.
To run MySQL on Windows, you need the following:
You may also have the following optional requirements:
MAX_ROWS
and
AVG_ROW_LENGTH
when you create tables.
See section 13.2.6 CREATE TABLE
Syntax.
Starting with MySQL version 4.1.5, there are three install packages to choose from when installing MySQL on Windows. The Packages are as follows:
The Essentials package is recommended for most users.
Your choice of install package affects the installation process you must follow. If you choose to install either the Essentials or Complete install packages, see section 2.3.3 Installing MySQL with the Automated Installer. If you choose to install MySQL from the Noinstall archive, see section 2.3.6 Installing MySQL from a noinstall Zip Archive.
Starting with MySQL 4.1.5, users can use the new MySQL Installation Wizard and MySQL Configuration Wizard to install MySQL on Windows. The MySQL Installation Wizard and MySQL Configuration Wizard are designed to install and configure MySQL in such a way that new users can immediately get started using MySQL.
The MySQL Installation Wizard and MySQL Configuration Wizard are available in the Essentials and Complete install packages, and are recommended for most standard MySQL installations. Exceptions include users who need to install multiple instances of MySQL on a single server and advanced users who want complete control of server configuration.
If you are installing a version of MySQL prior to MySQL 4.1.5, please follow the instructions for installing MySQL from the Noinstall installation package. See section 2.3.6 Installing MySQL from a noinstall Zip Archive.
MySQL Installation Wizard is a new installer for the MySQL server that uses the latest installer technologies for Microsoft Windows. The MySQL Installation Wizard, in combination with the MySQL Configuration Wizard, allows a user to install and configure a MySQL server that is ready for use immediately after installation.
The MySQL Installation Wizard is the standard installer for all MySQL server distributions, version 4.1.5 and higher. Users of previous versions of MySQL need to manually shut down and remove their existing MySQL installations before installing MySQL with the MySQL Installation Wizard. See section 2.3.4.7 Upgrading MySQL for more information on upgrading from a previous version.
Microsoft has included an improved version of their Microsoft Windows Installer (MSI) in the recent versions of Windows. Using the MSI has become the de-facto standard for application installations on Windows 2000, Windows XP, and Windows Server 2003. The MySQL Installation Wizard makes use of this technology to provide a smoother and more flexible installation progress.
The Microsoft Windows Installer Engine was updated with the release of Windows XP; those using a previous version of Windows can reference this Microsoft Knowledge Base article for information on upgrading to the latest version of the Windows Installer Engine.
Further, Microsoft has introduced the WiX (Windows Installer XML) tool set recently. It is the first highly acknowledged Open Source project from Microsoft. We switched to WiX because it is an Open Source project and it allows us to handle the complete Windows installation process in a flexible way with scripts.
Improving the MySQL Installation Wizard depends on the support and feedback of users like you. If you find that the MySQL Installation Wizard is lacking some feature important to you, or if you discover a bug, please use our MySQL Bug System to request features or report problems.
The MySQL server install packages can be downloaded from http://dev.mysql.com/downloads/. If the package you download is contained within a Zip archive, you need to extract the archive first.
The process for starting the wizard depends on the contents of the
install package you download. If there is a
setup.exe
file present, double-click it to start
the install process. If there is a .msi
file
present, double-click it to start the install process.
There are up three installation types available:
Typical
, Complete
, and
Custom
.
The Typical
installation type installs the MySQL
server, the mysql
command-line client, and the
command-line utilities. The command-line clients and utilities
include mysqldump
, myisamchk
,
and several other tools to help you manage the MySQL server.
The Complete
installation type installs all
components included in the installation package. The full
installation package includes components such as the embedded server
library, the benchmark suite, support scripts, and documentation.
The Custom
installation type gives you complete
control over which packages you wish to install and the installation
path that will be used. See
section 2.3.4.4 The Custom Install Dialog
for more information on performing a custom install.
If you choose the Typical
or
Complete
installation types and click the
Next button, you advance to the confirmation
screen to confirm your choices and begin the installation. If you
choose the Custom
installation type and click the
Next button, you advance to the custom install
dialog, described in
section 2.3.4.4 The Custom Install Dialog
If you wish to change the installation path or the specific
components that are installed by the MySQL Installation Wizard, you should
choose the Custom
installation type.
All available components are listed in a tree view on the left side
of the custom install dialog. Components that will not be installed
have a red X
icon, components that will be
installed have a gray icon. To change whether a component is
installed, click on the component's icon and choose an new option
from the drop-down list that appears.
You can change the default installation path by clicking the Change... button to the right of the displayed installation path.
After choosing your install components and installation path, click the Next button to advance to the confirmation dialog.
Once you choose an installation type and optionally choose your installation components, you advance to the confirmation dialog. Your installation type and installation path are displayed for you to review.
To install MySQL if you are satisfied with your settings, click the Install button. To change your settings, click the Back button. To exit the MySQL Installation Wizard without installing MySQL, click the Cancel button.
After installation is complete, you will be given the option of registering with the MySQL web site. Registration will give you access to post in the MySQL forums at forums.mysql.com, along with the ability to report bugs at bugs.mysql.com and subscribe to the newsletter. The final screen of the installer provides a summary of the installation and gives you the option to launch the MySQL Configuration Wizard, which you can use to create a configuration file, install the MySQL service, and configure security.
Once you click the Install button, the MySQL Installation Wizard begins the installation process and makes certain changes to your system which are described in the sections that follow.
Changes to the Registry
The MySQL Installation Wizard creates one Windows registry key in a typical
install situation, located in
HKEY_LOCAL_MACHINE\SOFTWARE\MySQL AB
.
The MySQL Installation Wizard creates a key named after the major version of
the server that is being installed, such as MySQL Server
4.1
. It contains two string values,
Location
and Version
. The
Location
string contains the path to the
installation directory. In a default installation it contains
C:\Program Files\MySQL\MySQL Server 4.1\
. The
Version
string contains the release number. For
example, for an installation of MySQL Server 4.1.5 the key contains
a value of 4.1.5
.
These registry keys are used to help external tools identify the
installed location of the MySQL server, preventing a complete scan
of the hard-disk to determine the installation path of the MySQL
server. The registry keys are not required to run the server and
when using the noinstall
Zip archive the registry
keys are not created.
Changes to the Start Menu
The MySQL Installation Wizard creates a new entry in the Windows Start menu under a common MySQL menu heading named after the major version of MySQL that you have installed. For example, if you install MySQL 4.1, the MySQL Installation Wizard creates a MySQL Server 4.1 section in the start menu.
The following entries are created within the new Start menu section:
MySQL Command Line Client
: This is a shortcut to
the mysql
command-line client and is configured
to connect as the root
user. The shortcut prompts for a root
user
password when connecting.
MySQL Server Instance Config Wizard
: This is a
shortcut to the MySQL Configuration Wizard. Use this shortcut to configure a
newly installed server, or to re-configure an existing server.
MySQL Documentation
: This is a link to the MySQL
server documentation that is stored locally in the MySQL server
installation directory. This option is not available when the MySQL
server is installed from the essential
installation package.
Changes to the File System
The MySQL Installation Wizard by default installs the MySQL server to
C:\Program Files\MySQL\MySQL
Server 4.1
, where
Program Files is the default location for
applications in your system, and 4.1 is
the major version of your MySQL server. This is the new recommended
location for the MySQL server, replacing the previous default
location of `c:\mysql'.
By default, all MySQL applications are stored in a common directory
at C:\Program
Files
\MySQL, where Program
Files is the default location for applications in your
Windows installation. A typical MySQL installation on a developer
machine may look like this:
C:\Program Files\MySQL\MySQL Server 4.1 C:\Program Files\MySQL\MySQL Server 5.0 C:\Program Files\MySQL\MySQL Administrator 1.0 C:\Program Files\MySQL\MySQL Query Browser 1.0
This approach makes it easier to manage and maintain all MySQL applications installed on a particular system.
From MySQL version 4.1.5, the new MySQL Installation Wizard can perform server upgrades automatically using the upgrade capabilities of MSI. That means you do not need to remove a previous installation manually before installing a new release. The installer automatically shuts down and removes the previous MySQL service before installing the new version.
Automatic upgrades are only available when upgrading between installations that have the same major and minor version numbers. For example, you can upgrade automatically from MySQL 4.1.5 to MySQL 4.1.6, but not from MySQL 4.1 to MySQL 5.0.
If you are upgrading MySQL version 4.1.4 or earlier to version 4.1.5 or later, you must first manually shut down and remove the older installation before upgrading. Be sure to back up your databases before performing such an upgrade, so that you can restore the databases after the upgrade is completed. It is always recommended that you back up your data before performing any upgrades.
See section 2.3.15 Upgrading MySQL on Windows.
The MySQL Configuration Wizard helps automate the process of configuring your server under Windows. The MySQL Configuration Wizard creates a custom `my.ini' file by asking you a series of questions and then applying your responses to a template to generate a `my.ini' file that is tuned to your installation.
The MySQL Configuration Wizard is included with the MySQL server starting with MySQL version 4.1.5, but is designed to work with MySQL servers versions 4.0 and higher. The MySQL Configuration Wizard is currently available for Windows users only.
MySQL Configuration Wizard is to a large extent the result of feedback MySQL AB has received from many users over a period of several years. However, if you find it's lacking some feature important to you, or if you discover a bug, please use our MySQL Bug System to request features or report problems.
The MySQL Configuration Wizard is typically launched from the MySQL Installation Wizard,
as the MySQL Installation Wizard exits. You can also launch the
MySQL Configuration Wizard by clicking the MySQL Server Instance Config
Wizard entry in the MySQL section of the
Start
menu.
In addition, you can navigate to the bin
directory
of your MySQL installation and launch the
`MySQLInstanceConfig.exe' file directly.
If the MySQL Configuration Wizard detects an existing `my.ini' file, you will have the option of either re-configuring your existing server, or removing the server instance by deleting the `my.ini' file and stopping and removing the MySQL service.
To reconfigure an existing server, choose the Re-configure
Instance
option and click the Next
button. Your existing `my.ini' file will be
renamed to my
timestamp.ini.bak
, where
timestamp is the date and time the
existing `my.ini' file was created. To remove the
existing server instance, choose the Remove
Instance
option and click the Next
button.
If you choose the Remove Instance
option, you
advance to a confirmation window. Click the
Execute button and the MySQL Configuration Wizard will
stop and remove the MySQL service and delete the
`my.ini' file. The server installation and its
data
folder will not be removed.
If you choose the Re-configure Instance
option,
you advance to the Configuration Type
dialog where
you can choose the type of installation you wish to configure.
When you start the MySQL Configuration Wizard for a new MySQL installation, or
choose the Re-configure Instance
option for an
existing installation, you advance to the Configuration
Type
dialog.
There are two configuration types available: Detailed
Configuration
and Standard
Configuration
. The Standard
Configuration
option is intended for new users who want to
get started with MySQL quickly without having to make a lot of
decisions in regards to server configuration. The Detailed
Configuration
option is intended for advanced users who
want more fine-grained control of server configuration.
If you are new to MySQL and need a server configured as a
single-user developer machine the Standard
Configuration
will suit your needs. Choosing the
Standard Configuration
option causes the
MySQL Configuration Wizard to automatically set all configuration options with
the exception of the Service Options
and
Security Options
.
The Standard Configuration
sets options that may
be incompatible with systems where there are existing MySQL
installations. If you have an existing MySQL installation on your
system in addition to the installation you wish to configure, the
Detailed Configuration
option is recommended.
To complete the Standard Configuration
, please refer to the sections
on Service Options
and Security Options
, located at
section 2.3.5.11 The Service Options Dialog and section 2.3.5.12 The Security Options Dialog
respectively.
There are three different server types available to choose from, and the server type you choose will affect the decisions the MySQL Configuration Wizard makes with regards to memory, disk, and processor usage.
Developer Machine
: Choose this option for a
typical desktop workstation where MySQL is intended only for
personal use. It is assumed that many other desktop applications
will be running. The MySQL server will be configured to use minimal
system resources.
Server Machine
: Choose this option for a server
machine where the MySQL server will be running alongside other
server applications such as FTP, email, and web servers. The MySQL
server will be configured to use a medium portion of the system
resources.
Dedicated MySQL Server Machine
: Choose this
option for a server machine that is intended to run only the MySQL
server. It is assumed that no other applications will be running.
The MySQL server will be configured to use all available system
resources.
The Database Usage
dialog allows you to indicate
the table handlers you expect to use when creating MySQL tables. The
option you choose will determine whether the InnoDB table handler is
available and what percentage of the server resources are available
to InnoDB.
Multifunctional Database
: This option enables
both the InnoDB and MyISAM table handlers and divides resources
evenly between the two. This option is recommended for users that
will use both table handlers on a regular basis.
Transactional Database Only
: This option enables
both the InnoDB and MyISAM table handlers but dedicates most server
resources toward the InnoDB table handler. This option is
recommended for users that will use InnoDB almost exclusively and
will make only minimal use of MyISAM.
Non-Transactional Database Only
: This option
disables the InnoDB table handler completely and dedicates all
server resources to the MyISAM table handler. This option is
recommended for users who will not be using InnoDB.
Some users may want to locate the InnoDB tablespace files in a different location than the MySQL server data directory. Placing the tablespace files in a separate location can be desirable if your system has a higher capacity or higher performance storage device available, such as a RAID storage system.
To change the default location for the InnoDB tablespace files, choose a new drive from the drop-down list of drive letters and choose a new path from the drop-down list of paths. To create a custom path, click the ... button.
If you are modifying the configuration of an existing server, you must click the Modify button before you change the path. In this situation you will have to manually move the existing tablespace files to the new location before starting the server.
It is important to set a limit to the number of concurrent
connections to the MySQL server that can be established to prevent
the server from running out of resources. The Concurrent
Connections
dialog allows you to choose the expected usage
of your server, and will set the limit for concurrent connections
accordingly. It is also possible to manually set the concurrent
connection limit.
Decision Support (DSS)/OLAP
: Choose this option
if your server will not require a large number of concurrent
connections. The maximum number of connections will be set at 100,
with an average of 20 concurrent connections assumed.
Online Transaction Processing (OLTP)
: Choose this
option if your server will require a large number of concurrent
connections. The maximum number of connections will be set at 500.
Manual Setting
: Choose this option to manually
set the maximum number of concurrent connections to the server.
Choose the number of concurrent connections from the drop-down box
provided, or type the maximum number of connections into the
drop-down box if the number you desire is not listed.
Use the Networking Options
dialog to enable or
disable TCP/IP networking and to configure the port number that is
used to connect to the MySQL server.
TCP/IP networking is enabled by default. To disable TCP/IP
networking, uncheck the box next to the Enable TCP/IP
Networking
option.
Port 3306 is used by default. To change the port used to access MySQL, choose a new port number from the drop-down box or type a new port number directly into the drop-down box. If the port number you choose is in use you will be prompted to confirm your choice of port number.
The MySQL server supports multiple character sets and it is possible
to set a default server character set that will be applied to all
tables, columns, and databases unless overridden. Use the
Character Set
dialog to change the default
character set of the MySQL server.
Standard Character Set
: Choose this option if you
want to use Latin1
as the default server
character set. Latin1
is used for English and
many Western European languages.
Best Support For Multilingualism
: Choose this
option if you want to use UTF8
as the default
server character set. UTF8
can store characters
from many different languages in a single character set.
Manual Selected Default Character Set /
Collation
: Choose this option if you want to pick the
server's default character set manually. Choose the desired
character set from the provided drop-down list.
On Windows NT based platforms, the MySQL server can be installed as a service. When installed as a service, the MySQL server can be started automatically during system startup, and even restarted automatically by Windows in the event of a service failure.
The MySQL Configuration Wizard will install the MySQL server as a service by
default, using the service name MySQL
. If you do
not wish to install the service, un-check the box next to the
Install As Windows Service
option. You can changed
the service name by picking a new service name from the drop-down box
provided or by typing a new service name into the drop-down box.
To install the MySQL server as a service but not have it started
automatically at startup, un-check the box next to the
Launch the MySQL Server automatically
option.
It is strongly recommended that you set a root
password for your
MySQL server, and the MySQL Configuration Wizard requires you set a root
password by default. If you do not wish to set a root
password,
un-check the box next to the Modify Security
Settings
option.
To set the root
password, type the desired password into both the
New root password
and Confirm
boxes. If you are re-configuring an existing server, you will also
need to enter the existing root
password into the Current
root password
box.
To prevent root
logins from across the network, check the box next to
the Root may only connect from localhost
option.
This will increase the security of your root
account.
To create an anonymous user account, check the box next to the
Create An Anonymous Account
option. Creating an
anonymous account can decrease server security and cause login and
permission difficulties and is not recommended.
The final dialog in the MySQL Configuration Wizard is the Confirmation
Dialog
. To start the configuration process, click the
Execute button. To return to a previous
dialog, click the Back button. To exit the
MySQL Configuration Wizard without configuring the server, click the
Cancel button.
After you click the Execute button, the MySQL Configuration Wizard will perform a series of tasks with progress displayed onscreen as the tasks are performed.
The MySQL Configuration Wizard will first determine various configuration file options based on your choices using a template prepared by MySQL AB developers and engineers. This template is named `my-template.ini' and is located in your server installation directory.
The MySQL Configuration Wizard will then write these options to a
`my.ini' file. The final location of the
`my.ini' file will be displayed next to the
Write configuration file
task.
If you chose to create a service for the MySQL server the MySQL Configuration Wizard will create the service and start it. If you are re-configuring an existing service, the MySQL Configuration Wizard will restart the service to apply your configuration changes.
If you chose to set a root
password, the MySQL Configuration Wizard will connect
to the server and set your new root
password and apply any other
security setting you may have selected.
After the MySQL Configuration Wizard has completed its tasks, a summary will be shown. Click the Finish button to exit the MySQL Configuration Wizard.
In MySQL installations prior to version 4.1.5 it was customary to name the server configuration file `my.cnf' or `my.ini' and locate the file either at `c:\my.cnf' or `c:\Windows\my.ini'.
The new MySQL Configuration Wizard places the `my.ini' file in the installation directory of the MySQL server. This helps associate configuration files with particular server instances.
To ensure that the MySQL server knows where to look for the
`my.ini' file, an argument similar to this is
passed to the MySQL server as part of the service installation:
--defaults-file="C:\Program Files\MySQL\MySQL
Server 4.1
\my.ini", where
C:\Program Files\MySQL\MySQL Server 4.1 is
replaced with the installation path to the MySQL Server.
The --defaults-file
instructs the MySQL server to
read the specified file for configuration options.
To modify the `my.ini' file, open it with a text editor and make any necessary changes. You can also modify the server configuration with the MySQL Administrator utility.
MySQL clients and utilities such as the mysql
command-line client and mysqldump
will not locate
the `my.ini' file located in the server
installation directory. To configure the client and utility
applications, create a new `my.ini' file in the
`c:\Windows' directory.
Users who are installing from the Noinstall package, or who are installing a version of MySQL prior to 4.1.5 can use the instructions in this section to manually install MySQL. If you are installing a version prior to 4.1.5 with an install package that includes a Setup program, substitute running the Setup program for extracting the archive.
The process for installing MySQL from a Zip archive is as follows:
This process is described in the sections that follow.
To install MySQL manually, do the following:
If you need to specify startup options when you run the server, you can indicate them on the command line or place them in an option file. For options that will be used every time the server starts, you will find it most convenient to use an option file to specify your MySQL configuration. This is true particularly under the following circumstances:
InnoDB
transactional tables in MySQL 3.23, you must manually add some extra lines
to the option file, as described in section 15.4 InnoDB
Configuration. (As of MySQL 4.0, InnoDB
creates its
data files and log files in the data directory by default. This means you
need not configure InnoDB
explicitly. You may still do so if you
wish, and an option file will be useful in this case, too.)
When the MySQL server starts on Windows, it looks for options in
two files: the `my.ini' file in the Windows directory, and
the `C:\my.cnf' file. The Windows directory typically is
named something like `C:\WINDOWS' or `C:\WinNT'. You
can determine its exact location from the value of the WINDIR
environment variable using the following command:
C:\> echo %WINDIR%
MySQL looks for options first in the `my.ini' file, then in
the `my.cnf' file. However, to avoid confusion, it's best if
you use only one file. If your PC uses a boot loader where the
C:
drive isn't the boot drive, your only option is to use
the `my.ini' file. Whichever option file you use, it must be a plain
text file.
You can also make use of the example option files included with your MySQL distribution. Look in your install directory for files such as my-small.cnf, my-medium.cnf, my-large.cnf, etc., which you can rename and copy to the appropriate location for use as a base configuration file.
An option file can be created and modified with any text editor,
such as the Notepad
program. For example, if MySQL is
installed at `E:\mysql' and the data directory is located at
`E:\mydata\data', you can create the option file and set up
a [mysqld]
section to specify values for the basedir
and datadir
parameters:
[mysqld] # set basedir to your installation path basedir=E:/mysql # set datadir to the location of your data directory datadir=E:/mydata/data
Note that Windows pathnames are specified in option files using forward slashes rather than backslashes. If you do use backslashes, you must double them:
[mysqld] # set basedir to your installation path basedir=E:\\mysql # set datadir to the location of your data directory datadir=E:\\mydata\\data
On Windows, the MySQL installer places the data directory directly under the directory where you install MySQL. If you would like to use a data directory in a different location, you should copy the entire contents of the `data' directory to the new location. For example, by default, the installer places MySQL in `C:\mysql' and the data directory in `C:\mysql\data'. If you want to use a data directory of `E:\mydata', you must do two things:
--datadir
option to specify the new data directory location
each time you start the server.
Starting with MySQL 3.23.38, the Windows distribution includes both the normal and the MySQL-Max server binaries.
Up through the early releases of MySQL 4.1, the servers included in Windows distributions are named like this:
Binary | Description |
mysqld | Compiled with full debugging and automatic memory allocation checking, symbolic links, and InnoDB and BDB tables.
|
mysqld-opt | Optimized binary. From version 4.0 on, InnoDB is enabled. Before 4.0, this server includes no transactional table support.
|
mysqld-nt | Optimized binary for Windows NT, 2000, and XP with support for named pipes. |
mysqld-max | Optimized binary with support for symbolic links, and InnoDB and BDB tables.
|
mysqld-max-nt | Like mysqld-max , but compiled with support for named pipes.
|
We have found that the server with the most generic name
(mysqld
) is the one that many users are likely to choose
by default. However, that is also the server that results in the
highest memory and CPU use due to the inclusion of full debugging
support. The server named mysqld-opt
is a better general-use
server choice to make instead if you don't need debugging support
and don't want the maximal feature set offered by the -max
servers or named pipe support offered by the -nt
servers.
To make it less likely that the debugging server would be chosen
inadvertently, some name changes were made from MySQL 4.1.2 to
4.1.4: mysqld
has been renamed to mysqld-debug
and mysqld-opt
has been renamed to mysqld
.
Thus, the server that includes debugging support indicates that in
its name, and the server named mysqld
is an efficient
default choice. The other servers still have their same names. The
resulting servers are named like this:
Binary | Description |
mysqld-debug | Compiled with full debugging and automatic memory allocation checking, symbolic links, and InnoDB and BDB tables.
|
mysqld | Optimized binary with InnoDB support.
|
mysqld-nt | Optimized binary for Windows NT, 2000, and XP with support for named pipes. |
mysqld-max | Optimized binary with support for symbolic links, and InnoDB and BDB tables.
|
mysqld-max-nt | Like mysqld-max , but compiled with support for named pipes.
|
The name changes were not both instituted at the same time. If you
have MySQL 4.1.2 or 4.1.3, it might be that you have a server named
mysqld-debug
but not one named mysqld
. In this
case, you should have a server mysqld-opt
, which you
should choose as your default server unless you need maximal features,
named pipes, or debugging support.
All of the preceding binaries are optimized for modern Intel processors, but should work on any Intel i386-class or higher processor.
MySQL supports TCP/IP on all Windows platforms. The mysqld-nt
and mysql-max-nt
servers support named pipes on Windows NT, 2000, XP, and 2003.
However, the default is to use TCP/IP regardless of the platform.
(Named pipes are slower than TCP/IP in many Windows configurations.)
Named pipe use is subject to these conditions:
--enable-named-pipe
option.
It is necessary to use this option explicitly because some users have
experienced problems shutting down the MySQL server when named pipes
were used.
mysqld-nt
or
mysqld-max-nt
servers, and only if the server is run on a version
of Windows that supports named pipes (NT, 2000, XP, 2003).
Note:
Most of the examples in reference manual use mysqld
as the
server name. If you choose to use a different server, such as
mysqld-nt
, make the appropriate substitutions in the commands that
are shown in the examples.
On Windows 95, 98, or Me, MySQL clients always connect to the server using TCP/IP. (This allows any machine on your network to connect to your MySQL server.) Because of this, you must make sure that TCP/IP support is installed on your machine before starting MySQL. You can find TCP/IP on your Windows CD-ROM.
Note that if you are using an old Windows 95 release (for example, OSR2), it's likely that you have an old Winsock package; MySQL requires Winsock 2! You can get the newest Winsock from http://www.microsoft.com/. Windows 98 has the new Winsock 2 library, so it is unnecessary to update the library.
On NT-based systems such as Windows NT, 2000, XP, or 2003, clients have two options. They can use TCP/IP, or they can use a named pipe if the server supports named pipe connections.
In MySQL versions 4.1 and higher, Windows servers also support shared-memory
connections if started with the --shared-memory
option. Clients can
connect through shared memory by using the --protocol=memory
option.
For information about which server binary to run, see section 2.3.9 Selecting a MySQL Server type.
This section gives a general overview of starting the MySQL server. The following sections provide more specific information for starting the MySQL server from the command line or as a Windows service.
The examples in these sections assume that MySQL is installed under the default location of `C:\mysql'. Adjust the pathnames shown in the examples if you have MySQL installed in a different location.
Testing is best done from a command prompt in a console window (a ``DOS window''). This way you can have the server display status messages in the window where they are easy to see. If something is wrong with your configuration, these messages make it easier for you to identify and fix any problems.
To start the server, enter this command:
C:\> C:\mysql\bin\mysqld --console
For servers that include InnoDB
support,
you should see the following messages as the server starts:
InnoDB: The first specified datafile c:\ibdata\ibdata1 did not exist: InnoDB: a new database to be created! InnoDB: Setting file c:\ibdata\ibdata1 size to 209715200 InnoDB: Database physically writes the file full: wait... InnoDB: Log file c:\iblogs\ib_logfile0 did not exist: new to be created InnoDB: Setting log file c:\iblogs\ib_logfile0 size to 31457280 InnoDB: Log file c:\iblogs\ib_logfile1 did not exist: new to be created InnoDB: Setting log file c:\iblogs\ib_logfile1 size to 31457280 InnoDB: Log file c:\iblogs\ib_logfile2 did not exist: new to be created InnoDB: Setting log file c:\iblogs\ib_logfile2 size to 31457280 InnoDB: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: creating foreign key constraint system tables InnoDB: foreign key constraint system tables created 011024 10:58:25 InnoDB: Started
When the server finishes its startup sequence, you should see something like this, which indicates that the server is ready to service client connections:
mysqld: ready for connections Version: '4.0.14-log' socket: '' port: 3306
The server will continue to write to the console any further diagnostic output it produces. You can open a new console window in which to run client programs.
If you omit the --console
option, the server writes diagnostic output
to the error log in the data directory (`C:\mysql\data' by default).
The error log is the file with the `.err' extension.
Note: The accounts that are listed in the MySQL grant tables initially have no passwords. After starting the server, you should set up passwords for them using the instructions in section 2.9 Post-Installation Setup and Testing.
The MySQL server can be started manually from the command line. This can be done on any version of Windows.
To start the mysqld
server from the command line, you should
start a console window (a ``DOS window'') and enter this command:
C:\> C:\Program Files\MySQL\MySQL Server 4.1\bin\mysqld
The path used in the preceding example may vary depending on the install location of MySQL on your system.
On non-NT versions of Windows, this will start mysqld
in the
background. That is, after the server starts, you should see another
command prompt. If you start the server this way on Windows NT, 2000, or XP,
the server will run in the foreground and no command prompt will appear
until the server exits. Because of this, you should open another console
window to run client programs while the server is running.
You can stop the MySQL server by executing this command:
C:\> C:\Program Files\MySQL\MySQL Server 4.1\bin\mysqladmin -u root shutdown
This invokes the MySQL administrative utility mysqladmin
to
connect to the server and tell it to shut down. The command connects
as root
, which is the default administrative account in the
MySQL grant system. Note that users in the MySQL grant system
are wholly independent from any login users under Windows.
If mysqld
doesn't start, check the error log to see whether the
server wrote any messages there to indicate the cause of the problem.
The error log is located in the `C:\mysql\data' directory. It is
the file with a suffix of `.err'. You can also try to start the
server as mysqld --console
; in this case, you may get some useful
information on the screen that may help solve the problem.
The last option is to start mysqld
with --standalone
--debug
. In this case, mysqld
writes a log file
`C:\mysqld.trace' that should contain the reason why mysqld
doesn't start. See section E.1.2 Creating Trace Files.
Use mysqld --verbose --help
to display all the options that
mysqld
understands. (Prior to MySQL 4.1, omit the
--verbose
option.)
On the NT family (Windows NT, 2000, XP, 2003), the recommended way to run
MySQL is to install it as a Windows service. When MySQL is installed as a
service, Windows starts and stops the MySQL server automatically when
Windows starts and stops. A server installed as a service can also be
controlled from the command line using NET
commands, or with the
graphical Services
utility.
The Services
utility (the Windows Service Control Manager
) can
be found in the Windows Control Panel
(under Administrative
Tools
on Windows 2000, XP, and Server 2003). It is advisable to close the
Services
utility while performing server installation or removal
operations from this command line. This prevents some odd errors.
To get MySQL to work with TCP/IP on Windows NT 4, you must install service pack 3 (or newer).
Before installing MySQL as a Windows service, you should first stop the current server if it is running by using the following command:
C:\> C:\mysql\bin\mysqladmin -u root shutdown
This invokes the MySQL administrative utility mysqladmin
to
connect to the server and tell it to shut down. The command connects
as root
, which is the default administrative account in the
MySQL grant system. Note that users in the MySQL grant system
are wholly independent from any login users under Windows.
Install the server as a service:
C:\> mysqld --install
If you have problems installing mysqld
as a
service using just the server name, try installing it using its full pathname:
C:\> C:\mysql\bin\mysqld --install
As of MySQL 4.0.2, you can specify a specific service name after the
--install
option. As of MySQL 4.0.3, you can in addition specify a
--defaults-file
option after the service name to indicate where the
server should obtain options when it starts. The rules that determine the
service name and option files the server uses are as follows:
MySQL
, the server uses
the default service name of MySQL
and the reads options from
the [mysqld]
group in the standard option files.
MySQL
after the
--install
option, the server reads options from the group that has
the same name as the service. The server reads options from the standard
option files.
As of MySQL 4.0.17, the server also reads options from the [mysqld]
group from the standard option files. This allows you to use the
[mysqld]
group for options that should be used by all MySQL services,
and an option group named after each service for use by the server installed
with that service name.
--defaults-file
option after the service name,
the server ignores the standard option files and reads options only from the
[mysqld]
group of the named file.
Note: Prior to MySQL 4.0.17, a server installed as a Windows service has problems starting if its pathname or the service name contains spaces. For this reason, with older versions, avoid installing MySQL in a directory such as `C:\Program Files' or using a service name containing spaces.
As a more complex example, consider the following command:
C:\> C:\mysql\bin\mysqld --install MySQL --defaults-file=C:\my-opts.cnf
Here, the default service name (MySQL
) is given after the
--install
option. If no --defaults-file
option had been given,
this command would have the effect of causing the server to read the
[mysqld]
group from the standard option files. However, because the
--defaults-file
option is present, the server reads options from the
[mysqld]
option group, but only from the named file.
You can also specify options as ``Start parameters
'' in the
Windows Services
utility before you start the MySQL service.
Once a MySQL server is installed as a service, Windows will start
the service automatically whenever Windows starts. The service also
can be started immediately from the Services
utility, or by
using the command NET START MySQL
. The NET
command
is not case sensitive.
When run as a service, mysqld
has no access
to a console window, so no messages can be seen there. If
mysqld
doesn't start, check the error log to see whether the
server wrote any messages there to indicate the cause of the problem.
The error log is located in the `C:\mysql\data' directory. It
is the file with a suffix of `.err'.
When mysqld
is running as a service, it can be stopped by
using the Services
utility, the command NET STOP
MySQL
, or the command mysqladmin shutdown
. If the service
is running when Windows shuts down, Windows will stop the server
automatically.
From MySQL 3.23.44 on, you have the choice of installing the
server as a Manual
service if you don't wish the service to
be started automatically during the boot process. To do this, use
the --install-manual
option rather than the --install
option:
C:\> C:\mysql\bin\mysqld --install-manual
To remove a server that is installed as a service, first stop it if it is
running. Then use the --remove
option to remove it:
C:\> C:\mysql\bin\mysqld --remove
For MySQL versions older than 3.23.49, one problem with automatic
MySQL service shutdown is that Windows waited only for a few
seconds for the shutdown to complete, then killed the database
server process if the time limit was exceeded. This had the potential
to cause problems. (For example, the InnoDB
storage engine
had to perform crash recovery at the next startup.) Starting from
MySQL 3.23.49, Windows waits longer for the MySQL server
shutdown to complete. If you notice this still is not enough for
your installation, it is safest not to run the MySQL server as a
service. Instead, start it from the command-line prompt, and stop
it with mysqladmin shutdown
.
This change to tell Windows to wait longer when stopping the MySQL server
works for Windows 2000 and XP. It does not work for Windows NT, where Windows
waits only 20 seconds for a service to shut down, and after that kills the
service process. You can increase this default by opening the Registry
Editor `\winnt\system32\regedt32.exe' and editing the value of
WaitToKillServiceTimeout
at
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
in the Registry tree. Specify the new larger value in milliseconds.
For example, the value 120000 tells Windows NT to wait up to 120 seconds.
If you don't want to start mysqld
as a service, you can start it
from the command line. For instructions, see section 2.3.11 Starting MySQL from the Windows Command Line.
Please see section 2.3.14 Troubleshooting a MySQL Installation Under Windows if you encounter difficulties during installation.
You can test whether the MySQL server is working by executing any of the following commands:
C:\> C:\mysql\bin\mysqlshow C:\> C:\mysql\bin\mysqlshow -u root mysql C:\> C:\mysql\bin\mysqladmin version status proc C:\> C:\mysql\bin\mysql test
If mysqld
is slow to respond to TCP/IP connections from client
programs on Windows 9x/Me, there is probably a problem with your DNS. In
this case, start mysqld
with the --skip-name-resolve
option
and use only localhost
and IP numbers in the Host
column of
the MySQL grant tables.
You can force a MySQL client to use a named pipe connection rather than
TCP/IP by specifying the --pipe
option or by specifying .
(period) as the host name. Use the --socket
option to specify the
name of the pipe. As of MySQL 4.1, you should use the
--protocol=PIPE
option.
There are two versions of the MySQL command-line tool:
Binary | Description |
mysql | Compiled on native Windows, offering limited text editing capabilities. |
mysqlc | Compiled with the Cygnus GNU compiler and
libraries, which offers readline editing. mysqlc was
intended for use primarily with Windows 9x/Me. It does not support the
updated authentication protocol used beginning with MySQL 4.1, and is
not supported in MySQL 4.1 and above. Beginning with MySQL 4.1.8, it is
no longer included in MySQL Windows distributions.
|
If you want to use mysqlc
, you must have a copy of the
`cygwinb19.dll' library installed somewhere that mysqlc
can find it. Current distributions of MySQL include this library
in the same directory as mysqlc
(the `bin' directory
under the base directory of your MySQL installation). If your
distribution does not have the cygwinb19.dll
library in the
`bin' directory, look for it in the lib
directory and
copy it to your Windows system directory
(`\Windows\system' or a similar place).
When installing and running MySQL for the first time, you may encounter certain errors that prevent the MySQL server from starting. The purpose of this section is to help you diagnose and correct some of these errors.
Your first resource when troubleshooting server issues is the error log. The MySQL server uses the error log to record information relevant to the error that is preventing the server from starting. The error log is located in the data directory specified in your `my.ini' file. The default data directory location is `C:\mysql\data'. See section 5.9.1 The Error Log.
Another source of information regarding possible errors is the console
messages displayed when the MySQL service is starting. Use the NET
START mysql
command from the command line after installing mysqld
as
a service to see any error messages regarding the starting of the MySQL
server as a service.
See section 2.3.12 Starting MySQL as a Windows Service.
The following are examples of some of the more common error messages you may encounter when installing MySQL and starting the server for the first time:
System error 1067 has occurred. Fatal error: Can't open privilege tables: Table 'mysql.host' doesn't exist
These messages occur when the MySQL server cannot find the mysql
privileges database or other critical files. This error is often encountered
when the MySQL base or data directories are installed in different
locations than the default locations (`C:\mysql' and
`C:\mysql\data', respectively).
If you have installed MySQL to a directory other than `C:\mysql' you
need to ensure that the MySQL server is aware of this through the use of a
configuration (my.ini
) file. The my.ini
file needs to be
located in your Windows directory, typically located at `C:\WinNT' or
`C:\WINDOWS'. You can determine its exact location from the value of
the WINDIR
environment variable by issuing the following command from
the command prompt:
C:\> echo %WINDIR%
An option file can be created and modified with any text editor,
such as the Notepad program. For example, if MySQL is installed at
`E:\mysql' and the data directory is located at `D:\MySQLdata',
you can create the option file and set up a [mysqld]
section to specify
values for the basedir and datadir parameters:
[mysqld] # set basedir to your installation path basedir=E:/mysql # set datadir to the location of your data directory datadir=D:/MySQLdata
Note that Windows pathnames are specified in option files using forward slashes rather than backslashes. If you do use backslashes, you must double them:
[mysqld] # set basedir to your installation path basedir=C:\\Program Files\\mysql # set datadir to the location of your data directory datadir=D:\\MySQLdata
See section 2.3.8 Creating an Option File.
This section lists some of the steps you should take when upgrading MySQL on Windows.
C:\> NET STOP MySQLIf you are not running the MySQL server as a service, use the following command to stop the server:
C:\> C:\mysql\bin\mysqladmin -u root shutdown
WinMySQLAdmin
program if it is running.
C:\> C:\mysql\bin\mysqld --removeIf you do not remove the existing service, the MySQL Installation Wizard may fail to properly install the new MySQL service.
C:\mysql4
. Overwriting the existing installation is recommended.
NET START MySQL
if you run MySQL
as a service, or invoke mysqld
directly otherwise.
MySQL for Windows has proven itself to be very stable. The Windows version of MySQL has the same features as the corresponding Unix version, with the following exceptions:
mysqld
for an extended time on Windows 95 if your server handles
many connections! Other versions of Windows don't suffer from this bug.
pread()
and pwrite()
calls to be
able to mix INSERT
and SELECT
. Currently we use mutexes
to emulate pread()
/pwrite()
. We will, in the long run,
replace the file level interface with a virtual interface so that we can
use the readfile()
/writefile()
interface on NT, 2000, and XP to
get more speed.
The current implementation limits the number of open files MySQL can use to
2,048 (1,024 before MySQL 4.0.19), which means that you will not be able to
run as many concurrent threads on NT, 2000, and XP as on Unix.
mysqladmin kill
will not work on a sleeping connection.
mysqladmin shutdown
can't abort as long as there are sleeping
connections.
ALTER TABLE
ALTER TABLE
statement, the table is locked
from being used by other threads. This has to do with the fact that on Windows,
you can't delete a file that is in use by another thread. In the future,
we may find some way to work around this problem.
DROP TABLE
DROP TABLE
on a table that is in use by a MERGE
table will
not work on Windows because the MERGE
handler 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.
DATA DIRECTORY
and INDEX DIRECTORY
DATA DIRECTORY
and INDEX DIRECTORY
options for
CREATE TABLE
are ignored on Windows, because Windows doesn't support
symbolic links. These options also are ignored on systems that have a
non-functional realpath()
call.
DROP DATABASE
mysqladmin shutdown
.
LOAD
DATA INFILE
or SELECT ... INTO OUTFILE
,
use Unix-style filenames with `/' characters:
mysql> LOAD DATA INFILE 'C:/tmp/skr.txt' INTO TABLE skr; mysql> SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;Alternatively, you must double the `\' character:
mysql> LOAD DATA INFILE 'C:\\tmp\\skr.txt' INTO TABLE skr; mysql> SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr;
^Z
/ CHAR(24)
, Windows will think it
has encountered end-of-file and abort the program.
This is mainly a problem when you try to apply a binary log as follows:
C:\> mysqlbinlog binary-log-name | mysql --user=rootIf you have a problem applying the log and suspect that it is because of a
^Z
/ CHAR(24)
character, you can use the following workaround:
C:\> mysqlbinlog binary-log-file --result-file=/tmp/bin.sql C:\> mysql --user=root --execute "source /tmp/bin.sql"The latter command also can be used to reliably read in any SQL file that may contain binary data.
Access denied for user
error
Access denied
for user 'some-user'@'unknown' to database 'mysql'
, this means
that MySQL cannot resolve your hostname properly.
To fix this, you should create a file named `\windows\hosts' containing
the following information:
127.0.0.1 localhost
Here are some open issues for anyone who might want to help us improve MySQL on Windows:
MYSQL.DLL
server. This should include everything in
a standard MySQL server, except thread creation. This will make
MySQL much easier to use in applications that don't need a true
client/server and don't need to access the server from other hosts.
mysqld
from the Task Manager
in Windows 95. For the moment, you must use mysqladmin shutdown
.
readline
to Windows for use in the mysql
command-line tool.
mysql
,
mysqlshow
, mysqladmin
, and mysqldump
) would be nice.
mysqladmin kill
on Windows.
The recommended way to install MySQL on Linux is by using the RPM
packages. The MySQL RPMs are currently built on a SuSE Linux 7.3
system, but should work on most versions of Linux that support rpm
and use glibc
.
To obtain RPM packages, see section 2.1.3 How to Get MySQL.
Note: RPM distributions of MySQL often are provided by other vendors. Be aware that they may differ in features and capabilities from those built by MySQL AB, and that the instructions in this manual do not necessarily apply to installing them. The vendor's instructions should be consulted instead.
If you have problems with an RPM file (for example, if you receive the error
``Sorry, the host 'xxxx' could not be looked up
''), see
section 2.12.1.2 Linux Binary Distribution Notes.
In most cases, you only need to install the MySQL-server
and
MySQL-client
packages to get a functional MySQL installation. The
other packages are not required for a standard installation.
If you want to run a MySQL-Max server that has additional capabilities,
you should also install the MySQL-Max
RPM. However, you should do so only
after installing the MySQL-server
RPM.
See section 5.1.2 The mysqld-max
Extended MySQL Server.
If you get a dependency failure when trying to install the MySQL 4.0
packages (for example, ``error: removing these packages would break dependencies:
libmysqlclient.so.10 is needed by ...
''), you should also install
the package MySQL-shared-compat
, which includes both the
shared libraries for backward compatibility (libmysqlclient.so.12
for MySQL 4.0 and libmysqlclient.so.10
for MySQL 3.23).
Many Linux distributions still ship with MySQL 3.23 and they usually link
applications dynamically to save disk space. If these shared libraries are
in a separate package (for example, MySQL-shared
), it is
sufficient to simply leave this package installed and just upgrade
the MySQL server and client packages (which are statically linked
and do not depend on the shared libraries). For distributions that
include the shared libraries in the same package as the MySQL server
(for example, Red Hat Linux), you could either install our 3.23
MySQL-shared
RPM, or use the MySQL-shared-compat
package instead.
The following RPM packages are available:
MySQL-server-VERSION.i386.rpm
The MySQL server. You will need this unless you only want to
connect to a MySQL server running on another machine. Note:
Server RPM files were called MySQL-VERSION.i386.rpm
before
MySQL 4.0.10. That is, they did not have -server
in the name.
MySQL-Max-VERSION.i386.rpm
The MySQL-Max server. This server has additional capabilities that the
one provided in the MySQL-server
RPM does not. You must install the
MySQL-server
RPM first, because the MySQL-Max
RPM depends on it.
MySQL-client-VERSION.i386.rpm
The standard MySQL client programs. You probably always want to
install this package.
MySQL-bench-VERSION.i386.rpm
Tests and benchmarks. Requires Perl and the DBD::mysql
module.
MySQL-devel-VERSION.i386.rpm
The libraries and include files that are needed if you want to compile other
MySQL clients, such as the Perl modules.
MySQL-shared-VERSION.i386.rpm
This package contains the shared libraries (libmysqlclient.so*
)
that certain languages and applications need to dynamically load and
use MySQL.
MySQL-shared-compat-VERSION.i386.rpm
This package includes the shared libraries for both MySQL 3.23 and
MySQL 4.0. Install this package instead of MySQL-shared
if you
have applications installed that are dynamically linked against MySQL
3.23 but you want to upgrade to MySQL 4.0 without breaking the library
dependencies. This package has been available since MySQL 4.0.13.
MySQL-embedded-VERSION.i386.rpm
The embedded MySQL server library (from MySQL 4.0).
MySQL-VERSION.src.rpm
This contains the source code for all of the previous packages. It can also
be used to rebuild the RPMs on other architectures (for example, Alpha or SPARC).
To see all files in an RPM package (for example, a MySQL-server
RPM), run:
shell> rpm -qpl MySQL-server-VERSION.i386.rpm
To perform a standard minimal installation, run:
shell> rpm -i MySQL-server-VERSION.i386.rpm shell> rpm -i MySQL-client-VERSION.i386.rpm
To install just the client package, run:
shell> rpm -i MySQL-client-VERSION.i386.rpm
RPM provides a feature to verify the integrity and authenticity of packages
before installing them. If you would like to learn more about this feature,
see section 2.1.4 Verifying Package Integrity Using MD5 Checksums or GnuPG
.
The server RPM places data under the `/var/lib/mysql' directory. The
RPM also creates a login account for a user named mysql
(if one does not
exist) to use for running the MySQL server, and
creates the appropriate entries in `/etc/init.d/' to start the
server automatically at boot time. (This means that if you have performed a
previous installation and have made changes to its startup script, you may
want to make a copy of the script so that you don't lose it when you install a
newer RPM.) See section 2.9.2.2 Starting and Stopping MySQL Automatically for more information on how MySQL can be
started automatically on system startup.
If you want to install the MySQL RPM on older Linux distributions that do not support initialization scripts in `/etc/init.d' (directly or via a symlink), you should create a symbolic link that points to the location where your initialization scripts actually are installed. For example, if that location is `/etc/rc.d/init.d', use these commands before installing the RPM to create `/etc/init.d' as a symbolic link that points there:
shell> cd /etc shell> ln -s rc.d/init.d .
However, all current major Linux distributions should support the new directory layout that uses `/etc/init.d', because it is required for LSB (Linux Standard Base) compliance.
If the RPM files that you install include MySQL-server
, the
mysqld
server should be up and running after installation.
You should be able to start using MySQL.
If something goes wrong, you can find more information in the binary installation section. See section 2.7 Installing MySQL on Other Unix-Like Systems.
Note: The accounts that are listed in the MySQL grant tables initially have no passwords. After starting the server, you should set up passwords for them using the instructions in section 2.9 Post-Installation Setup and Testing.
Beginning with MySQL 4.0.11, you can install MySQL on Mac OS X 10.2.x (``Jaguar'') and up using a Mac OS X binary package in PKG format instead of the binary tarball distribution. Please note that older versions of Mac OS X (for example, 10.1.x) are not supported by this package.
The package is located inside a disk image (.dmg
) file that you
first need to mount by double-clicking its icon in the Finder. It should
then mount the image and display its contents.
To obtain MySQL, see section 2.1.3 How to Get MySQL.
Note: Before proceeding with the installation, be sure to
shut down all running MySQL server instances by either
using the MySQL Manager Application (on Mac OS X Server) or via
mysqladmin shutdown
on the command line.
To actually install the MySQL PKG file, double-click on the package icon. This launches the Mac OS X Package Installer, which will guide you through the installation of MySQL.
Due to a bug in the Mac OS X package installer, you may see this error message in the destination disk selection dialog:
You cannot install this software on this disk. (null)
If this error occurs, simply click the Go Back
button once to return
to the previous screen. Then click Continue
to advance to the
destination disk selection again, and you should be able to choose the
destination disk correctly. We have reported this bug to Apple and it is
investigating this problem.
The Mac OS X PKG of MySQL will install itself into
`/usr/local/mysql-VERSION' and will also install a symbolic link,
`/usr/local/mysql', pointing to the new location. If a directory named
`/usr/local/mysql' exists, it will be renamed to
`/usr/local/mysql.bak' first. Additionally, the installer will create the
grant tables in the mysql
database by executing mysql_install_db
after the installation.
The installation layout is similar to that of a tar
file binary
distribution; all MySQL binaries are located in the directory
`/usr/local/mysql/bin'. The MySQL socket file is created as
`/tmp/mysql.sock' by default.
See section 2.1.5 Installation Layouts.
MySQL installation requires a Mac OS X user account named mysql
. A
user account with this name should exist by default on Mac OS X 10.2 and up.
If you are running Mac OS X Server, you have a version of MySQL installed. The versions of MySQL that ship with Mac OS X Server versions are shown in the following table:
Mac OS X Server Version | MySQL Version |
10.2-10.2.2 | 3.23.51 |
10.2.3-10.2.6 | 3.23.53 |
10.3 | 4.0.14 |
10.3.2 | 4.0.16 |
This manual section covers the installation of the official MySQL Mac OS X PKG only. Make sure to read Apple's help information about installing MySQL: Run the ``Help View'' application, select ``Mac OS X Server'' help, do a search for ``MySQL,'' and read the item entitled ``Installing MySQL.''
For pre-installed versions of MySQL on Mac OS X Server, note especially that
you should start mysqld
with safe_mysqld
instead of
mysqld_safe
if MySQL is older than version 4.0.
If you previously used Marc Liyanage's MySQL packages for Mac OS X from http://www.entropy.ch, you can simply follow the update instructions for packages using the binary installation layout as given on his pages.
If you are upgrading from Marc's 3.23.xx versions or from the Mac OS X Server version of MySQL to the official MySQL PKG, you also need to convert the existing MySQL privilege tables to the current format, because some new security privileges have been added. See section 2.10.7 Upgrading the Grant Tables.
If you would like to automatically start up MySQL during system startup, you
also need to install the MySQL Startup Item. Starting with MySQL 4.0.15, it
is part of the Mac OS X installation disk images as a separate installation
package. Simply double-click the MySQLStartupItem.pkg
icon and follow
the instructions to install it.
Note that the Startup Item need be installed only once! There is no need to install it each time you upgrade the MySQL package later.
The Startup Item will be installed into
`/Library/StartupItems/MySQLCOM'. (Before MySQL 4.1.2, the location
was `/Library/StartupItems/MySQL', but that collided with the MySQL
Startup Item installed by Mac OS X Server.) Startup Item installation
adds a variable MYSQLCOM=-YES-
to the system configuration file
`/etc/hostconfig'. If you would like to disable the automatic startup
of MySQL, simply change this variable to MYSQLCOM=-NO-
.
On Mac OS X Server, the default MySQL installation uses the variable
MYSQL
in the `/etc/hostconfig' file. The MySQL AB Startup Item
installer disables this variable by setting it to MYSQL=-NO-
. This
avoids boot time conflicts with the MYSQLCOM
variable used by the
MySQL AB Startup Item. However, it does not shut down a running
MySQL server. You should do that yourself.
After the installation, you can start up MySQL by running the following commands in a terminal window. You must have administrator privileges to perform this task.
If you have installed the Startup Item:
shell> sudo /Library/StartupItems/MySQLCOM/MySQLCOM start (Enter your password, if necessary) (Press Control-D or enter "exit" to exit the shell)
For versions of MySQL older than 4.1.3, substitute
/Library/StartupItems/MySQLCOM/MySQLCOM
with
/Library/StartupItems/MySQL/MySQL
above.
If you don't use the Startup Item, enter the following command sequence:
shell> cd /usr/local/mysql shell> sudo ./bin/mysqld_safe (Enter your password, if necessary) (Press Control-Z) shell> bg (Press Control-D or enter "exit" to exit the shell)
You should be able to connect to the MySQL server, for example, by running `/usr/local/mysql/bin/mysql'.
Note: The accounts that are listed in the MySQL grant tables initially have no passwords. After starting the server, you should set up passwords for them using the instructions in section 2.9 Post-Installation Setup and Testing.
You might want to add aliases to your shell's resource file to make it easier
to access commonly used programs such as mysql
and mysqladmin
from the command line. The syntax for tcsh
is:
alias mysql /usr/local/mysql/bin/mysql alias mysqladmin /usr/local/mysql/bin/mysqladmin
For bash
, use:
alias mysql=/usr/local/mysql/bin/mysql alias mysqladmin=/usr/local/mysql/bin/mysqladmin
Even better,
add /usr/local/mysql/bin
to
your PATH
environment variable. For example, add the following
line to your `$HOME/.tcshrc' file if your shell is tcsh
:
setenv PATH ${PATH}:/usr/local/mysql/bin
If no `.tcshrc' file exists in your home directory, create it with a text editor.
If you are upgrading an existing installation, please note that installing a new MySQL PKG does not remove the directory of an older installation. Unfortunately, the Mac OS X Installer does not yet offer the functionality required to properly upgrade previously installed packages.
To use your existing databases with the new installation, you'll need to copy the contents of the old data directory to the new data directory. Make sure that neither the old server nor the new one is running when you do this. After you have copied over the MySQL database files from the previous installation and have successfully started the new server, you should consider removing the old installation files to save disk space. Additionally, you should also remove older versions of the Package Receipt directories located in `/Library/Receipts/mysql-VERSION.pkg'.
Porting MySQL to NetWare was an effort spearheaded by Novell. Novell customers will be pleased to note that NetWare 6.5 ships with bundled MySQL binaries, complete with an automatic commercial use license for all servers running that version of NetWare.
MySQL for NetWare is compiled using a combination of Metrowerks
CodeWarrior for NetWare
and special cross-compilation versions of the
GNU autotools.
The latest binary packages for NetWare can be obtained at http://dev.mysql.com/downloads/. See section 2.1.3 How to Get MySQL.
In order to host MySQL, the NetWare server must meet these requirements:
To install MySQL for NetWare, use the following procedure:
SERVER: mysqladmin -u root shutdown
SERVER: SEARCH ADD SYS:MYSQL\BIN
mysql_install_db
at the server console.
mysqld_safe
at the server console.
autoexec.ncf
. For example, if your MySQL installation is in
`SYS:MYSQL' and you want MySQL to start automatically, you could
add these lines:
#Starts the MySQL 4.0.x database server SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFEIf you are running MySQL on NetWare 6.0, we strongly suggest that you use the
--skip-external-locking
option on the command line:
#Starts the MySQL 4.0.x database server SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE --skip-external-lockingIt will also be necessary to use
CHECK TABLE
and REPAIR
TABLE
instead of myisamchk
, because myisamchk
makes use
of external locking. External locking is known to have problems on
NetWare 6.0; the problem has been eliminated in NetWare 6.5.
mysqld_safe
on NetWare provides a screen presence. When you unload
(shut down) the mysqld_safe
NLM, the screen does not by default go
away. Instead, it prompts for user input:
*<NLM has terminated; Press any key to close the screen>*If you want NetWare to close the screen automatically instead, use the
--autoclose
option to mysqld_safe
. For example:
#Starts the MySQL 4.0.x database server SEARCH ADD SYS:MYSQL\BIN MYSQLD_SAFE --autoclose
The behavior of mysqld_safe
on NetWare is described further in
section 5.1.3 The mysqld_safe
Server Startup Script.
If there was an existing installation of MySQL on the server, be sure
to check for existing MySQL startup commands in autoexec.ncf
,
and edit or delete them as necessary.
Note: The accounts that are listed in the MySQL grant tables initially have no passwords. After starting the server, you should set up passwords for them using the instructions in section 2.9 Post-Installation Setup and Testing.
This section covers the installation of MySQL binary distributions that are
provided for various platforms in the form of compressed tar
files
(files with a .tar.gz
extension). See section 2.1.2.5 MySQL Binaries Compiled by MySQL AB for a
detailed list.
To obtain MySQL, see section 2.1.3 How to Get MySQL.
MySQL tar
file binary distributions have names of the form
`mysql-VERSION-OS.tar.gz', where VERSION
is a number (for
example, 4.0.17
), and OS indicates the type of operating
system for which the distribution is intended (for example,
pc-linux-i686
).
In addition to these generic packages, we also offer binaries in platform-specific package formats for selected platforms. See section 2.2 Standard MySQL Installation Using a Binary Distribution for more information on how to install these.
You need the following tools to install a MySQL tar
file binary
distribution:
gunzip
to uncompress the distribution.
tar
to unpack the distribution. GNU tar
is known
to work. Some operating systems come with a pre-installed version of
tar
that is known to have problems. For example, Mac OS X tar
and Sun tar
are known to have problems with long filenames. On Mac
OS X, you can use the pre-installed gnutar
program. On other systems
with a deficient tar
, you should install GNU tar
first.
If you run into problems, please always use mysqlbug
when
posting questions to a MySQL mailing list. Even if the problem
isn't a bug, mysqlbug
gathers system information that will help others
solve your problem. By not using mysqlbug
, you lessen the likelihood
of getting a solution to your problem. You will find mysqlbug
in the
`bin' directory after you unpack the distribution. See section 1.4.1.3 How to Report Bugs or Problems.
The basic commands you must execute to install and use a MySQL binary distribution are:
shell> groupadd mysql shell> useradd -g mysql mysql shell> cd /usr/local shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf - shell> ln -s full-path-to-mysql-VERSION-OS mysql shell> cd mysql shell> scripts/mysql_install_db --user=mysql shell> chown -R root . shell> chown -R mysql data shell> chgrp -R mysql . shell> bin/mysqld_safe --user=mysql &
For versions of MySQL older than 4.0, substitute bin/safe_mysqld
for bin/mysqld_safe
in the final command.
Note: This procedure does not set up any passwords for MySQL accounts. After following the procedure, proceed to section 2.9 Post-Installation Setup and Testing.
A more detailed version of the preceding description for installing a binary distribution follows:
mysqld
to run as:
shell> groupadd mysql shell> useradd -g mysql mysqlThese commands add the
mysql
group and the mysql
user. The
syntax for useradd
and groupadd
may differ slightly on different
versions of Unix. They may also be called adduser
and addgroup
.
You might want to call the user and group something else instead
of mysql
. If so, substitute the appropriate name in the
following steps.
root
.)
shell> cd /usr/local
shell> gunzip < /path/to/mysql-VERSION-OS.tar.gz | tar xvf - shell> ln -s full-path-to-mysql-VERSION-OS mysqlThe
tar
command creates a directory named
`mysql-VERSION-OS'. The
ln
command makes a symbolic link to that directory. This lets you refer
more easily to the installation directory as `/usr/local/mysql'.
With GNU tar
, no separate invocation of gunzip
is necessary.
You can replace the first line with the following
alternative command to uncompress and extract the distribution:
shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz
shell> cd mysqlYou will find several files and subdirectories in the
mysql
directory.
The most important for installation purposes are the `bin' and
`scripts' subdirectories.
PATH
environment variable so that your shell finds the MySQL
programs properly. See section F Environment Variables.
mysql_install_db
script used to initialize
the mysql
database containing the grant tables that store the server
access permissions.
shell> scripts/mysql_install_db --user=mysqlIf you run the command as
root
, you should use the --user
option as shown. The value of the option should be the name of the login
account that you created in the first step to use for running the server.
If you run the command while logged in as that user, you can omit the
--user
option.
Note that for MySQL versions older than 3.22.10,
mysql_install_db
left the server running after creating the grant
tables. This is no longer true; you will need to restart the server after
performing the remaining steps in this procedure.
root
and ownership of the
data directory to the user that you will run mysqld
as. Assuming
that you are located in the installation directory
(`/usr/local/mysql'), the commands look like this:
shell> chown -R root . shell> chown -R mysql data shell> chgrp -R mysql .The first command changes the owner attribute of the files to the
root
user. The second changes the owner attribute of the
data directory to the mysql
user. The third changes the
group attribute to the mysql
group.
support-files/mysql.server
to the location where
your system has its startup files. More information can be found in the
support-files/mysql.server
script itself and in
section 2.9.2.2 Starting and Stopping MySQL Automatically.
bin/mysql_setpermission
script if
you install the DBI
and DBD::mysql
Perl modules.
For instructions, see section 2.13 Perl Installation Notes.
mysqlaccess
and have the MySQL
distribution in some non-standard place, you must change the location where
mysqlaccess
expects to find the mysql
client. Edit the
`bin/mysqlaccess' script at approximately line 18. Search for a line
that looks like this:
$MYSQL = '/usr/local/bin/mysql'; # path to mysql executableChange the path to reflect the location where
mysql
actually is
stored on your system. If you do not do this, you will get a Broken
pipe
error when you run mysqlaccess
.
After everything has been unpacked and installed, you should test your distribution.
You can start the MySQL server with the following command:
shell> bin/mysqld_safe --user=mysql &
For versions of MySQL older than 4.0, substitute bin/safe_mysqld
for bin/mysqld_safe
in the command.
More information about mysqld_safe
is given in
section 5.1.3 The mysqld_safe
Server Startup Script.
Note: The accounts that are listed in the MySQL grant tables initially have no passwords. After starting the server, you should set up passwords for them using the instructions in section 2.9 Post-Installation Setup and Testing.
Before you proceed with the source installation, check first to see whether our binary is available for your platform and whether it will work for you. We put a lot of effort into making sure that our binaries are built with the best possible options.
To obtain a source distribution for MySQL, section 2.1.3 How to Get MySQL.
MySQL source distributions are provided as compressed tar
archives and have names of the form `mysql-VERSION.tar.gz', where
VERSION is a number like 4.1.10a
.
You need the following tools to build and install MySQL from source:
gunzip
to uncompress the distribution.
tar
to unpack the distribution. GNU tar
is known
to work. Some operating systems come with a pre-installed version of
tar
that is known to have problems. For example, Mac OS X tar
and Sun tar
are known to have problems with long filenames. On Mac
OS X, you can use the pre-installed gnutar
program. On other systems
with a deficient tar
, you should install GNU tar
first.
gcc
2.95.2 or later, egcs
1.0.2
or later or egcs 2.91.66
, SGI C++, and SunPro C++ are some of the
compilers that are known to work. libg++
is not needed when
using gcc
. gcc
2.7.x has a bug that makes it impossible
to compile some perfectly legal C++ files, such as
`sql/sql_base.cc'. If you have only gcc
2.7.x, you must
upgrade your gcc
to be able to compile MySQL. gcc
2.8.1 is also known to have problems on some platforms, so it should be
avoided if a new compiler exists for the platform.
gcc
2.95.2 or later is recommended when compiling MySQL
3.23.x.
make
program. GNU make
is always recommended and is
sometimes required. If you have problems, we recommend trying GNU
make
3.75 or newer.
If you are using a version of gcc
recent enough to understand the
-fno-exceptions
option, it is very important that you use
this option. Otherwise, you may compile a binary that crashes randomly. We also
recommend that you use -felide-constructors
and -fno-rtti
along
with -fno-exceptions
. When in doubt, do the following:
CFLAGS="-O3" CXX=gcc CXXFLAGS="-O3 -felide-constructors \ -fno-exceptions -fno-rtti" ./configure \ --prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-static
On most systems, this will give you a fast and stable binary.
If you run into problems, please always use mysqlbug
when
posting questions to a MySQL mailing list. Even if the problem
isn't a bug, mysqlbug
gathers system information that will help others
solve your problem. By not using mysqlbug
, you lessen the likelihood
of getting a solution to your problem. You will find mysqlbug
in the
`scripts' directory after you unpack the distribution.
See section 1.4.1.3 How to Report Bugs or Problems.
The basic commands you must execute to install a MySQL source distribution are:
shell> groupadd mysql shell> useradd -g mysql mysql shell> gunzip < mysql-VERSION.tar.gz | tar -xvf - shell> cd mysql-VERSION shell> ./configure --prefix=/usr/local/mysql shell> make shell> make install shell> cp support-files/my-medium.cnf /etc/my.cnf shell> cd /usr/local/mysql shell> bin/mysql_install_db --user=mysql shell> chown -R root . shell> chown -R mysql var shell> chgrp -R mysql . shell> bin/mysqld_safe --user=mysql &
For versions of MySQL older than 4.0, substitute bin/safe_mysqld
for bin/mysqld_safe
in the final command.
If you start from a source RPM, do the following:
shell> rpmbuild --rebuild --clean MySQL-VERSION.src.rpm
This will make a binary RPM that you can install. For older versions of RPM,
you may have to replace the command rpmbuild
with rpm
instead.
Note: This procedure does not set up any passwords for MySQL accounts. After following the procedure, proceed to section 2.9 Post-Installation Setup and Testing, for post-installation setup and testing.
A more detailed version of the preceding description for installing MySQL from a source distribution follows:
mysqld
to run as:
shell> groupadd mysql shell> useradd -g mysql mysqlThese commands add the
mysql
group and the mysql
user. The
syntax for useradd
and groupadd
may differ slightly on different
versions of Unix. They may also be called adduser
and addgroup
.
You might want to call the user and group something else instead
of mysql
. If so, substitute the appropriate name in the
following steps.
shell> gunzip < /path/to/mysql-VERSION.tar.gz | tar xvf -This command creates a directory named `mysql-VERSION'. With GNU
tar
, no separate invocation of gunzip
is necessary.
You can use the following alternative command to uncompress and extract
the distribution:
shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz
shell> cd mysql-VERSIONNote that currently you must configure and build MySQL from this top-level directory. You cannot build it in a different directory.
shell> ./configure --prefix=/usr/local/mysql shell> makeWhen you run
configure
, you might want to specify some options.
Run ./configure --help
for a list of options.
section 2.8.2 Typical configure
Options, discusses some of the
more useful options.
If configure
fails and you are going to send mail to a MySQL mailing
list to ask for assistance, please include any
lines from `config.log' that you think can help solve the problem. Also
include the last couple of lines of output from configure
.
Post the bug report using the mysqlbug
script. See section 1.4.1.3 How to Report Bugs or Problems.
If the compile fails, see section 2.8.4 Dealing with Problems Compiling MySQL for help.
shell> make installIf you want to set up an option file, use one of those present in the `support-files' directory as a template. For example:
shell> cp support-files/my-medium.cnf /etc/my.cnfYou might need to run these commands as
root
.
If you want to configure support for InnoDB
tables, you should edit the
/etc/my.cnf
file, remove the #
character before the
option lines that start with innodb_...
, and modify the option values
to be what you want.
See section 4.3.2 Using Option Files
and section 15.4 InnoDB
Configuration.
shell> cd /usr/local/mysql
shell> bin/mysql_install_db --user=mysqlIf you run the command as
root
, you should use the --user
option as shown. The value of the option should be the name of the login
account that you created in the first step to use for running the server.
If you run the command while logged in as that user, you can omit the
--user
option.
Note that for MySQL versions older than 3.22.10,
mysql_install_db
left the server running after creating the grant
tables. This is no longer true; you will need to restart the server after
performing the remaining steps in this procedure.
root
and ownership of the
data directory to the user that you will run mysqld
as. Assuming
that you are located in the installation directory
(`/usr/local/mysql'), the commands look like this:
shell> chown -R root . shell> chown -R mysql var shell> chgrp -R mysql .The first command changes the owner attribute of the files to the
root
user. The second changes the owner attribute of the
data directory to the mysql
user. The third changes the
group attribute to the mysql
group.
support-files/mysql.server
to the location where
your system has its startup files. More information can be found in the
support-files/mysql.server
script itself and in
section 2.9.2.2 Starting and Stopping MySQL Automatically.
bin/mysql_setpermission
script if
you install the DBI
and DBD::mysql
Perl modules.
For instructions, see section 2.13 Perl Installation Notes.
After everything has been installed, you should initialize and test your distribution using this command:
shell> /usr/local/mysql/bin/mysqld_safe --user=mysql &
For versions of MySQL older than 4.0, substitute safe_mysqld
for mysqld_safe
in the command.
If that command fails immediately and prints mysqld ended
, you can
find some information in the `host_name.err' file in the data directory.
More information about mysqld_safe
is given in
section 5.1.3 The mysqld_safe
Server Startup Script.
Note: The accounts that are listed in the MySQL grant tables initially have no passwords. After starting the server, you should set up passwords for them using the instructions in section 2.9 Post-Installation Setup and Testing.
configure
Options
The configure
script gives you a great deal of control over how
you configure a MySQL source distribution. Typically you do this
using options on the configure
command line. You can also affect
configure
using certain environment variables. See section F Environment Variables. For a list of options supported by configure
, run
this command:
shell> ./configure --help
Some of the more commonly used configure
options are described here:
--without-server
option:
shell> ./configure --without-serverIf you don't have a C++ compiler,
mysql
will not compile (it is the
one client program that requires C++). In this case,
you can remove the code in configure
that tests for the C++ compiler
and then run ./configure
with the --without-server
option. The
compile step will still try to build mysql
, but you can ignore any
warnings about `mysql.cc'. (If make
stops, try make -k
to tell it to continue with the rest of the build even if errors occur.)
libmysqld.a
) you should
use the --with-embedded-server
option.
configure
command something like one
of these:
shell> ./configure --prefix=/usr/local/mysql shell> ./configure --prefix=/usr/local \ --localstatedir=/usr/local/mysql/dataThe first command changes the installation prefix so that everything is installed under `/usr/local/mysql' rather than the default of `/usr/local'. The second command preserves the default installation prefix, but overrides the default location for database directories (normally `/usr/local/var') and changes it to
/usr/local/mysql/data
. After you have compiled MySQL, you can
change these options with option files. See section 4.3.2 Using Option Files.
configure
command like this:
shell> ./configure \ --with-unix-socket-path=/usr/local/mysql/tmp/mysql.sockThe socket filename must be an absolute pathname. You can also change the location of `mysql.sock' later by using a MySQL option file. See section A.4.5 How to Protect or Change the MySQL Socket File `/tmp/mysql.sock'.
configure
like this:
shell> ./configure --with-client-ldflags=-all-static \ --with-mysqld-ldflags=-all-static
gcc
and don't have libg++
or libstdc++
installed, you can tell configure
to use gcc
as your C++
compiler:
shell> CC=gcc CXX=gcc ./configureWhen you use
gcc
as your C++ compiler, it will not attempt to link in
libg++
or libstdc++
. This may be a good idea to do even if you
have these libraries installed, because some versions of them have
caused strange problems for MySQL users in the past.
The following list indicates some compilers and environment variable settings
that are commonly used with each one.
gcc
2.7.2:
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors"
egcs
1.0.3a:
CC=gcc CXX=gcc CXXFLAGS="-O3 -felide-constructors \ -fno-exceptions -fno-rtti"
gcc
2.95.2:
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ -felide-constructors -fno-exceptions -fno-rtti"
pgcc
2.90.29 or newer:
CFLAGS="-O3 -mpentiumpro -mstack-align-double" CXX=gcc \ CXXFLAGS="-O3 -mpentiumpro -mstack-align-double \ -felide-constructors -fno-exceptions -fno-rtti"
configure
line:
--prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-staticThe full
configure
line would, in other words, be something like the
following for all recent gcc
versions:
CFLAGS="-O3 -mpentiumpro" CXX=gcc CXXFLAGS="-O3 -mpentiumpro \ -felide-constructors -fno-exceptions -fno-rtti" ./configure \ --prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-staticThe binaries we provide on the MySQL Web site at http://www.mysql.com/ are all compiled with full optimization and should be perfect for most users. See section 2.1.2.5 MySQL Binaries Compiled by MySQL AB. There are some configuration settings you can tweak to make an even faster binary, but these are only for advanced users. See section 7.5.4 How Compiling and Linking Affects the Speed of MySQL. If the build fails and produces errors about your compiler or linker not being able to create the shared library `libmysqlclient.so.#' (where `#' is a version number), you can work around this problem by giving the
--disable-shared
option to configure
. In this case,
configure
will not build a shared `libmysqlclient.so.#' library.
latin1
(ISO-8859-1) character set. To
change the default set, use the --with-charset
option:
shell> ./configure --with-charset=CHARSETCHARSET may be one of
big5
, cp1251
, cp1257
,
czech
, danish
, dec8
, dos
, euc_kr
,
gb2312
, gbk
, german1
, hebrew
, hp8
,
hungarian
, koi8_ru
, koi8_ukr
, latin1
,
latin2
, sjis
, swe7
, tis620
, ujis
,
usa7
, or win1251ukr
.
See section 5.8.1 The Character Set Used for Data and Sorting.
As of MySQL 4.1.1, the default collation may also be specified. MySQL uses
the latin1_swedish_ci
collation. To change this, use the
--with-collation
option:
shell> ./configure --with-collation=COLLATIONTo change both the character set and the collation, use both the
--with-charset
and --with-collation
options.
The collation must be a legal collation for the character set.
(Use the SHOW COLLATION
statement to determine which collations are
available for each character set.)
If you want to convert characters between the server and the client,
you should take a look at the SET CHARACTER SET
statement.
See section 13.5.3 SET
Syntax.
Warning: If you change character sets after having created any
tables, you will have to run myisamchk -r -q --set-character-set=charset
on every table. Your
indexes may be sorted incorrectly otherwise. (This can happen if you
install MySQL, create some tables, then reconfigure
MySQL to use a different character set and reinstall it.)
With the configure
option --with-extra-charsets=LIST
, you can
define which additional character sets should be compiled into the server.
LIST is either a list of character set names separated by spaces,
complex
to include all character sets that can't be dynamically loaded,
or all
to include all character sets into the binaries.
--with-debug
option:
shell> ./configure --with-debugThis causes a safe memory allocator to be included that can find some errors and that provides output about what is happening. See section E.1 Debugging a MySQL Server.
--enable-thread-safe-client
configure option. This will create a
libmysqlclient_r
library with which you should link your threaded
applications. See section 22.2.15 How to Make a Threaded Client.
Caution: You should read this section only if you are interested in helping us test our new code. If you just want to get MySQL up and running on your system, you should use a standard release distribution (either a binary or source distribution will do).
To obtain our most recent development source tree, use these instructions:
shell> bk clone bk://mysql.bkbits.net/mysql-3.23 mysql-3.23To clone the 4.0 stable (production) branch, use this command:
shell> bk clone bk://mysql.bkbits.net/mysql-4.0 mysql-4.0To clone the 4.1 stable (production) branch, use this command:
shell> bk clone bk://mysql.bkbits.net/mysql-4.1 mysql-4.1To clone the 5.0 development branch, use this command:
shell> bk clone bk://mysql.bkbits.net/mysql-5.0 mysql-5.0In the preceding examples, the source tree will be set up in the `mysql-3.23/', `mysql-4.0/', `mysql-4.1/', or `mysql-5.0/' subdirectory of your current directory. If you are behind a firewall and can only initiate HTTP connections, you can also use BitKeeper via HTTP. If you are required to use a proxy server, set the environment variable
http_proxy
to point to your proxy:
shell> export http_proxy="http://your.proxy.server:8080/"Replace the
bk://
with http://
when doing
a clone. Example:
shell> bk clone http://mysql.bkbits.net/mysql-4.1 mysql-4.1The initial download of the source tree may take a while, depending on the speed of your connection. Please be patient.
make
, autoconf
2.58 (or newer),
automake
1.8, libtool
1.5, and m4
to run the next
set of commands. Even though many operating systems come with their
own implementation of make
, chances are high that the compilation
will fail with strange error messages. Therefore, it is highly recommended
that you use GNU make
(sometimes named gmake
) instead.
Fortunately, a large number of operating systems ship with the GNU
toolchain preinstalled or supply installable packages of these. In any case,
they can also be downloaded from the following locations:
bison
1.75 or later. Older versions of bison
may report this
error:
sql_yacc.yy:#####: fatal error: maximum table size (32767) exceededNote: The maximum table size is not actually exceeded; the error is caused by bugs in older versions of
bison
.
Versions of MySQL before version 4.1 may also compile with other
yacc
implementations (for example, BSD yacc
91.7.30). For later
versions, GNU bison
is required.
The following example shows the typical commands required to configure a
source tree. The first cd
command changes location into the top-level
directory of the tree; replace `mysql-4.0' with the appropriate directory
name.
shell> cd mysql-4.0 shell> bk -r edit shell> aclocal; autoheader; autoconf; automake shell> (cd innobase; aclocal; autoheader; autoconf; automake) shell> (cd bdb/dist; sh s_all) shell> ./configure # Add your favorite options here makeThe command lines that change directory into the `innobase' and `bdb/dist' directories are used to configure the
InnoDB
and
Berkeley DB (BDB
) storage engines. You can omit these command lines if
you to not require InnoDB
or BDB
support.
If you get some strange errors during this stage, verify that you really
have libtool
installed.
A collection of our standard configuration scripts is located in the
`BUILD/' subdirectory. You may find it more convenient to use the
`BUILD/compile-pentium-debug' script than the preceding set of
shell commands. To compile on a different architecture,
modify the script by removing flags that are Pentium-specific.
make install
. Be careful with this
on a production machine; the command may overwrite your live release
installation. If you have another installation of MySQL, we
recommend that you run ./configure
with different values for the
--prefix
, --with-tcp-port
, and --unix-socket-path
options
than those used for your production server.
make test
. See section 25.1.2 MySQL Test Suite.
make
stage and the distribution does
not compile, please report it in our bugs database at
http://bugs.mysql.com/. If you
have installed the latest versions of the required GNU tools, and they
crash trying to process our configuration files, please report that also.
However, if you execute aclocal
and get a command not found
error or a similar problem, do not report it. Instead, make sure that all
the necessary tools are installed and that your PATH
variable is
set correctly so that your shell can find them.
bk clone
operation to obtain the source tree, you
should run bk pull
periodically to get updates.
bk revtool
. If you see some funny diffs or code that you have a
question about, do not hesitate to send email to the MySQL internals
mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
Also, if you think you have a better idea
on how to do something, send an email message to the same address with a patch.
bk diffs
will produce a patch for you after you have made changes
to the source. If you do not have the time to code your idea, just send
a description.
bk helptool
.
bk ci
or bk citool
) will
trigger the posting of a message with the changeset to our internals
mailing list, as well as the usual openlogging.org submission with
just the changeset comments.
Generally, you wouldn't need to use commit (since the public tree will
not allow bk push
), but rather use the bk diffs
method
described previously.
You can also browse changesets, comments, and source code online. For example, to browse this information for MySQL 4.1, go to http://mysql.bkbits.net:8080/mysql-4.1.
The manual is in a separate tree that can be cloned with:
shell> bk clone bk://mysql.bkbits.net/mysqldoc mysqldoc
There are also public BitKeeper trees for MySQL Control Center and MyODBC. They can be cloned respectively as follows.
To clone MySQL Control center, use this command:
shell> bk clone http://mysql.bkbits.net/mysqlcc mysqlcc
To clone MyODBC, use this command:
shell> bk clone http://mysql.bkbits.net/myodbc3 myodbc3
To clone Connector/NET, use this command:
shell> bk clone http://mysql.bkbits.net/connector-net connector-net
All MySQL programs compile cleanly for us with no warnings on
Solaris or Linux using gcc
. On other systems, warnings may occur due to
differences in system include files. See section 2.8.5 MIT-pthreads Notes for warnings
that may occur when using MIT-pthreads. For other problems, check
the following list.
The solution to many problems involves reconfiguring. If you do need to reconfigure, take note of the following:
configure
is run after it has previously been run, it may use
information that was gathered during its previous invocation. This
information is stored in `config.cache'. When configure
starts
up, it looks for that file and reads its contents if it exists, on the
assumption that the information is still correct. That assumption is invalid
when you reconfigure.
configure
, you must run make
again
to recompile. However, you may want to remove old object files from previous
builds first because they were compiled using different configuration options.
To prevent old configuration information or object files from being used,
run these commands before re-running configure
:
shell> rm config.cache shell> make clean
Alternatively, you can run make distclean
.
The following list describes some of the problems when compiling MySQL that have been found to occur most often:
Internal compiler error: program cc1plus got fatal signal 11 Out of virtual memory Virtual memory exhaustedThe problem is that
gcc
requires a huge amount of memory to compile
`sql_yacc.cc' with inline functions. Try running configure
with
the --with-low-memory
option:
shell> ./configure --with-low-memoryThis option causes
-fno-inline
to be added to the compile line if you
are using gcc
and -O0
if you are using something else. You
should try the --with-low-memory
option even if you have so much
memory and swap space that you think you can't possibly have run out. This
problem has been observed to occur even on systems with generous hardware
configurations and the --with-low-memory
option usually fixes it.
configure
picks c++
as the compiler name and
GNU c++
links with -lg++
. If you are using gcc
,
that behavior can cause problems during configuration such as this:
configure: error: installation or configuration problem: C++ compiler cannot create executables.You might also observe problems during compilation related to
g++
, libg++
, or libstdc++
.
One cause of these problems is that you may not have g++
, or you may
have g++
but not libg++
, or libstdc++
. Take a look at
the `config.log' file. It should contain the exact reason why your C++
compiler didn't work. To work around these problems, you can use gcc
as your C++ compiler. Try setting the environment variable CXX
to
"gcc -O3"
. For example:
shell> CXX="gcc -O3" ./configureThis works because
gcc
compiles C++ sources as well as g++
does, but does not link in libg++
or libstdc++
by default.
Another way to fix these problems is to install g++
,
libg++
, and libstdc++
. We would, however, like to recommend
that you not use libg++
or libstdc++
with MySQL because this will
only increase the binary size of mysqld
without giving you any benefits.
Some versions of these libraries have also caused strange problems for
MySQL users in the past.
Using gcc
as the C++ compiler is also required if you want to
compile MySQL with RAID functionality (see section 13.2.6 CREATE TABLE
Syntax for more info
on RAID table type) and you are using GNU gcc
version 3 and above. If
you get errors like those following during the linking stage when you
configure MySQL to compile with the option --with-raid
, try to use
gcc
as your C++ compiler by defining the CXX
environment
variable:
gcc -O3 -DDBUG_OFF -rdynamic -o isamchk isamchk.o sort.o libnisam.a ../mysys/libmysys.a ../dbug/libdbug.a ../strings/libmystrings.a -lpthread -lz -lcrypt -lnsl -lm -lpthread ../mysys/libmysys.a(raid.o)(.text+0x79): In function `my_raid_create':: undefined reference to `operator new(unsigned)' ../mysys/libmysys.a(raid.o)(.text+0xdd): In function `my_raid_create':: undefined reference to `operator delete(void*)' ../mysys/libmysys.a(raid.o)(.text+0x129): In function `my_raid_open':: undefined reference to `operator new(unsigned)' ../mysys/libmysys.a(raid.o)(.text+0x189): In function `my_raid_open':: undefined reference to `operator delete(void*)' ../mysys/libmysys.a(raid.o)(.text+0x64b): In function `my_raid_close':: undefined reference to `operator delete(void*)' collect2: ld returned 1 exit status
make
to GNU make
:
making all in mit-pthreads make: Fatal error in reader: Makefile, line 18: Badly formed macro assignmentOr:
make: file `Makefile' line 18: Must be a separator (:Or:
pthread.h: No such file or directorySolaris and FreeBSD are known to have troublesome
make
programs.
GNU make
Version 3.75 is known to work.
CFLAGS
and CXXFLAGS
environment
variables. You can also specify the compiler names this way using CC
and CXX
. For example:
shell> CC=gcc shell> CFLAGS=-O3 shell> CXX=gcc shell> CXXFLAGS=-O3 shell> export CC CFLAGS CXX CXXFLAGSSee section 2.1.2.5 MySQL Binaries Compiled by MySQL AB, for a list of flag definitions that have been found to be useful on various systems.
gcc
compiler:
client/libmysql.c:273: parse error before `__attribute__'
gcc
2.8.1 is known to work, but we recommend using gcc
2.95.2 or
egcs
1.0.3a instead.
mysqld
,
configure
didn't correctly detect the type of the last argument to
accept()
, getsockname()
, or getpeername()
:
cxx: Error: mysqld.cc, line 645: In this statement, the referenced type of the pointer value ''length'' is ''unsigned long'', which is not compatible with ''int''. new_sock = accept(sock, (struct sockaddr *)&cAddr, &length);To fix this, edit the `config.h' file (which is generated by
configure
). Look for these lines:
/* Define as the base type of the last arg to accept */ #define SOCKET_SIZE_TYPE XXXChange
XXX
to size_t
or int
, depending on your
operating system. (Note that you will have to do this each time you run
configure
because configure
regenerates `config.h'.)
"sql_yacc.yy", line xxx fatal: default action causes potential...This is a sign that your version of
yacc
is deficient.
You probably need to install bison
(the GNU version of yacc
)
and use that instead.
gawk
instead of the default
mawk
if you want to compile MySQL 4.1 or higher with Berkeley DB
support.
mysqld
or a MySQL client, run
configure
with the --with-debug
option, then recompile and
link your clients with the new client library. See section E.2 Debugging a MySQL Client.
libmysql.c:1329: warning: passing arg 5 of `gethostbyname_r' from incompatible pointer type libmysql.c:1329: too few arguments to function `gethostbyname_r' libmysql.c:1329: warning: assignment makes pointer from integer without a cast make[2]: *** [libmysql.lo] Error 1By default, the
configure
script attempts to determine the correct
number of arguments by using g++
the GNU C++ compiler. This test
yields wrong results if g++
is not installed. There are two ways
to work around this problem:
g++
is installed. On some Linux
distributions, the required package is called gpp
; on others, it
is named gcc-c++
.
gcc
as your C++ compiler by setting the CXX
environment
variable to gcc
:
export CXX="gcc"
configure
again afterward.
This section describes some of the issues involved in using MIT-pthreads.
On Linux, you should not use MIT-pthreads. Use the installed LinuxThreads implementation instead. See section 2.12.1 Linux Notes.
If your system does not provide native thread support, you will need to build MySQL using the MIT-pthreads package. This includes older FreeBSD systems, SunOS 4.x, Solaris 2.4 and earlier, and some others. See section 2.1.1 Operating Systems Supported by MySQL.
Beginning with MySQL 4.0.2, MIT-pthreads is no longer part of the source distribution. If you require this package, you need to download it separately from http://www.mysql.com/Downloads/Contrib/pthreads-1_60_beta6-mysql.tar.gz
After downloading, extract this source archive into the top level of the
MySQL source directory. It will create a new subdirectory named
mit-pthreads
.
configure
with the --with-mit-threads
option:
shell> ./configure --with-mit-threadsBuilding in a non-source directory is not supported when using MIT-pthreads because we want to minimize our changes to this code.
--without-server
to build only the client code, clients will not know whether
MIT-pthreads is being used and will use Unix socket connections by default.
Because Unix socket files do not work under MIT-pthreads on some platforms, this
means you will need to use -h
or --host
when you run client
programs.
--external-locking
option. This is needed
only if you want to be able to run two MySQL servers against the same data
files, which is not recommended.
bind()
command fails to bind to a socket without
any error message (at least on Solaris). The result is that all connections
to the server fail. For example:
shell> mysqladmin version mysqladmin: connect to server at '' failed; error: 'Can't connect to mysql server on localhost (146)'The solution to this is to kill the
mysqld
server and restart it.
This has only happened to us when we have forced down the server and done
a restart immediately.
sleep()
system call isn't interruptible with
SIGINT
(break). This is only noticeable when you run
mysqladmin --sleep
. You must wait for the sleep()
call to
terminate before the interrupt is served and the process stops.
ld: warning: symbol `_iob' has differing sizes: (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; file /usr/lib/libc.so value=0x140); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken ld: warning: symbol `__iob' has differing sizes: (file /my/local/pthreads/lib/libpthread.a(findfp.o) value=0x4; file /usr/lib/libc.so value=0x140); /my/local/pthreads/lib/libpthread.a(findfp.o) definition taken
implicit declaration of function `int strtoll(...)' implicit declaration of function `int strtoul(...)'
readline
to work with MIT-pthreads. (This isn't
needed, but may be interesting for someone.)
These instructions describe how to build MySQL binaries from source for versions 4.1 and above on Windows. Instructions are provided for building binaries from a standard source distribution or from the BitKeeper tree that contains the latest development source.
Note: The instructions in this document are strictly for users who want to test MySQL on Windows from the latest source distribution or from the BitKeeper tree. For production use, MySQL AB does not advise using a MySQL server built by yourself from source. Normally, it is best to use precompiled binary distributions of MySQL that are built specifically for optimal performance on Windows by MySQL AB. Instructions for installing a binary distributions are available at section 2.3 Installing MySQL on Windows.
To build MySQL on Windows from source, you need the following compiler and resources available on your Windows system:
You'll also need a MySQL source distribution for Windows. There are two ways you can get a source distribution for MySQL version 4.1 and above:
If you are using a Windows source distribution, you can go directly to section 2.8.6.1 Building MySQL Using VC++. To build from the BitKeeper tree, proceed to section 2.8.6.2 Creating a Windows Source Package from the Latest Development Source.
If you find something not working as expected, or you have
suggestions about ways to improve the current build process
on Windows, please send a message to the win32
mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
Note: VC++ workspace files for MySQL 4.1 and above are compatible with Microsoft Visual Studio 6.0 and above (7.0/.NET) editions and tested by MySQL AB staff before each release.
Follow this procedure to build MySQL:
WinZip
or other Windows tool that can read `.zip' files.
File
menu, select Open Workspace
.
Build
menu,
select the Set Active Configuration
menu.
mysqld - Win32 Debug
and click OK.
F7
to begin the build of the debug server, libraries, and
some client applications.
Build All
option from the Build
menu.
--basedir
and --datadir
options, or place appropriate options in an option file (the `my.ini'
file in your Windows directory or `C:\my.cnf'). If you have
an existing data directory elsewhere that you want to use, you can
specify its pathname instead.
mysql
interactive command-line utility that exists in your `client_release'
or `client_debug' directory.
When you are satisfied that the programs you have built are working correctly, stop the server. Then install MySQL as follows:
C:\> mkdir C:\mysql C:\> mkdir C:\mysql\bin C:\> mkdir C:\mysql\data C:\> mkdir C:\mysql\share C:\> mkdir C:\mysql\scriptsIf you want to compile other clients and link them to MySQL, you should also create several additional directories:
C:\> mkdir C:\mysql\include C:\> mkdir C:\mysql\lib C:\> mkdir C:\mysql\lib\debug C:\> mkdir C:\mysql\lib\optIf you want to benchmark MySQL, create this directory:
C:\> mkdir C:\mysql\sql-benchBenchmarking requires Perl support.
C:\mysql
directory the
following directories:
C:\> cd \workdir C:\workdir> copy client_release\*.exe C:\mysql\bin C:\workdir> copy client_debug\mysqld.exe C:\mysql\bin\mysqld-debug.exe C:\workdir> xcopy scripts\*.* C:\mysql\scripts /E C:\workdir> xcopy share\*.* C:\mysql\share /EIf you want to compile other clients and link them to MySQL, you should also copy several libraries and header files:
C:\workdir> copy lib_debug\mysqlclient.lib C:\mysql\lib\debug C:\workdir> copy lib_debug\libmysql.* C:\mysql\lib\debug C:\workdir> copy lib_debug\zlib.* C:\mysql\lib\debug C:\workdir> copy lib_release\mysqlclient.lib C:\mysql\lib\opt C:\workdir> copy lib_release\libmysql.* C:\mysql\lib\opt C:\workdir> copy lib_release\zlib.* C:\mysql\lib\opt C:\workdir> copy include\*.h C:\mysql\include C:\workdir> copy libmysql\libmysql.def C:\mysql\includeIf you want to benchmark MySQL, you should also do this:
C:\workdir> xcopy sql-bench\*.* C:\mysql\bench /E
Set up and start the server in the same way as for the binary Windows distribution. See section 2.3 Installing MySQL on Windows.
To create a Windows source package from the current BitKeeper source tree, use the following instructions. Please note that this procedure must be performed on a system running a Unix or Unix-like operating system. For example, the procedure is known to work well on Linux.
shell> ./BUILD/compile-pentium-max
shell> ./scripts/make_win_src_distributionThis script creates a Windows source package to be used on your Windows system. You can supply different options to the script based on your needs. It accepts the following options:
--help
--debug
--tmp
--suffix
--dirname
--silent
--tar
make_win_src_distribution
creates a Zip-format
archive with the name `mysql-VERSION-win-src.zip', where
VERSION represents the version of your MySQL source tree.
In your source files, you should include `my_global.h' before `mysql.h':
#include <my_global.h> #include <mysql.h>
`my_global.h' includes any other files needed for Windows compatibility (such as `windows.h') if you compile your program on Windows.
You can either link your code with the dynamic `libmysql.lib' library, which is just a wrapper to load in `libmysql.dll' on demand, or link with the static `mysqlclient.lib' library.
The MySQL client libraries are compiled as threaded libraries, so you should also compile your code to be multi-threaded.
After installing MySQL, there are some issues you should address. For example, on Unix, you should initialize the data directory and create the MySQL grant tables. On all platforms, an important security concern is that the initial accounts in the grant tables have no passwords. You should assign passwords to prevent unauthorized access to the MySQL server. For MySQL 4.1.3 and up, you can create time zone tables to enable recognition of named time zones. (Currently, these tables can be populated only on Unix. This problem will be addressed soon for Windows.)
The following sections include post-installation procedures that are specific to Windows systems and to Unix systems. Another section, section 2.9.2.3 Starting and Troubleshooting the MySQL Server, applies to all platforms; it describes what to do if you have trouble getting the server to start. section 2.9.3 Securing the Initial MySQL Accounts also applies to all platforms. You should follow its instructions to make sure that you have properly protected your MySQL accounts by assigning passwords to them.
When you are ready to create additional user accounts, you can find information on the MySQL access control system and account management in section 5.5 The MySQL Access Privilege System and section 5.6 MySQL User Account Management.
On Windows, the data directory and the grant tables do not have to be
created. MySQL Windows distributions include the grant tables with a set of
preinitialized accounts in the mysql
database under the
data directory. You do not run the mysql_install_db
script that
is used on Unix. However, if you did not install MySQL using the Windows Installation Wizard,
you should assign passwords to the accounts. See section 2.3.4.1 Introduction.
The procedure for this is given in section 2.9.3 Securing the Initial MySQL Accounts.
Before setting up passwords, you might want to try running some client programs to make sure that you can connect to the server and that it is operating properly. Make sure the server is running (see section 2.3.10 Starting the Server for the First Time), then issue the following commands to verify that you can retrieve information from the server. The output should be similar to what is shown here:
C:\> C:\mysql\bin\mysqlshow +-----------+ | Databases | +-----------+ | mysql | | test | +-----------+ C:\> C:\mysql\bin\mysqlshow mysql Database: mysql +--------------+ | Tables | +--------------+ | columns_priv | | db | | func | | host | | tables_priv | | user | +--------------+ C:\> C:\mysql\bin\mysql -e "SELECT Host,Db,User FROM db" mysql +------+-------+------+ | host | db | user | +------+-------+------+ | % | test% | | +------+-------+------+
If you are running a version of Windows that supports services and you want the MySQL server to run automatically when Windows starts, see section 2.3.12 Starting MySQL as a Windows Service.
After installing MySQL on Unix, you need to initialize the grant tables, start the server, and make sure that the server works okay. You may also wish to arrange for the server to be started and stopped automatically when your system starts and stops. You should also assign passwords to the accounts in the grant tables.
On Unix, the grant tables are set up by the mysql_install_db
program.
For some installation methods, this program is run for you automatically:
mysql_install_db
.
mysql_install_db
.
Otherwise, you'll need to run mysql_install_db
yourself.
The following procedure describes how to initialize the grant tables (if that has not previously been done) and then start the server. It also suggests some commands that you can use to test whether the server is accessible and working properly. For information about starting and stopping the server automatically, see section 2.9.2.2 Starting and Stopping MySQL Automatically.
After you complete the procedure and have the server running, you should
assign passwords to the accounts created by mysql_install_db
.
Instructions for doing so are given in section 2.9.3 Securing the Initial MySQL Accounts.
In the examples shown here, the server runs under the user ID of the
mysql
login account. This assumes that such an account exists.
Either create the account if it does not exist, or substitute the name of a
different existing login account that you plan to use for running the
server.
shell> cd BASEDIRBASEDIR is likely to be something like `/usr/local/mysql' or `/usr/local'. The following steps assume that you are located in this directory.
mysql_install_db
program to set up the initial
MySQL grant tables containing the privileges that determine how users are
allowed to connect to the server. You'll need to do this if you used a
distribution type that doesn't run the program for you.
Typically, mysql_install_db
needs to be run only the first time you
install MySQL, so you can skip this step if you are upgrading an existing
installation, However, mysql_install_db
does not overwrite any
existing privilege tables, so it should be safe to run in any circumstances.
To initialize the grant tables, use one of the following commands,
depending on whether mysql_install_db
is located in the bin
or scripts
directory:
shell> bin/mysql_install_db --user=mysql shell> scripts/mysql_install_db --user=mysqlThe
mysql_install_db
script creates the data directory, the
mysql
database that holds all database privileges, and the test
database that you can use to test MySQL. The script also creates privilege
table entries for root
accounts and anonymous-user accounts.
The accounts have no passwords initially. A description of their initial
privileges is given in section 2.9.3 Securing the Initial MySQL Accounts. Briefly, these privileges
allow the MySQL root
user to do anything, and allow anybody to create
or use databases with a name of test
or starting with test_
.
It is important to make sure that the database directories and files are
owned by the mysql
login account so that the server has read and
write access to them when you run it later. To ensure this, the --user
option should be used as shown if you run mysql_install_db
as
root
. Otherwise, you should execute the script while logged in as
mysql
, in which case you can omit the --user
option from the
command.
mysql_install_db
creates several tables in the mysql
database:
user
, db
, host
, tables_priv
,
columns_priv
, func
, and possibly others depending on your
version of MySQL.
If you don't want to have the test
database, you can remove it with
mysqladmin -u root drop test
after starting the server.
If you have problems with mysql_install_db
, see
section 2.9.2.1 Problems Running mysql_install_db
.
There are some alternatives to running the mysql_install_db
script as it is provided in the MySQL distribution:
mysql_install_db
before you run it.
However, a preferable technique is to use GRANT
and REVOKE
to
change the privileges after the grant tables have been set up. In other
words, you can run mysql_install_db
, and then use mysql -u root
mysql
to connect to the server as the MySQL root
user so that you
can issue the GRANT
and REVOKE
statements.
If you want to install MySQL on a lot of machines with the
same privileges, you can put the GRANT
and REVOKE
statements in
a file and execute the file as a script using mysql
after running
mysql_install_db
. For example:
shell> bin/mysql_install_db --user=mysql shell> bin/mysql -u root < your_script_fileBy doing this, you can avoid having to issue the statements manually on each machine.
GRANT
and REVOKE
and have made so many modifications
after running mysql_install_db
that you want to wipe out the tables
and start over.
To re-create the grant tables, remove all the `.frm', `.MYI', and
`.MYD' files in the directory containing the mysql
database.
(This is the directory named `mysql' under the data directory, which is
listed as the datadir
value when you run mysqld --help
.) Then
run the mysql_install_db
script again.
Note: For MySQL versions older than 3.22.10, you should not
delete the `.frm' files. If you accidentally do this, you should copy
them back into the `mysql' directory from your MySQL distribution
before running mysql_install_db
.
mysqld
manually using the --skip-grant-tables
option and add the privilege information yourself using mysql
:
shell> bin/mysqld_safe --user=mysql --skip-grant-tables & shell> bin/mysql mysqlFrom
mysql
, manually execute the SQL commands contained in
mysql_install_db
. Make sure that you run mysqladmin
flush-privileges
or mysqladmin reload
afterward to tell the server to
reload the grant tables.
Note that by not using mysql_install_db
, you not only have to
populate the grant tables manually, you also have to create them first.
shell> bin/mysqld_safe --user=mysql &For versions of MySQL older than 4.0, substitute
bin/safe_mysqld
for bin/mysqld_safe
in this command.
It is important that the MySQL server be run using an unprivileged
(non-root
) login account. To ensure this, the --user
option should be used as shown if you run mysql_safe
as
root
. Otherwise, you should execute the script while logged in as
mysql
, in which case you can omit the --user
option from the
command.
Further instructions for running MySQL as an unprivileged user are given in
section A.3.2 How to Run MySQL as a Normal User.
If you neglected to create the grant tables before proceeding to this step,
the following message will appear in the error log file when you start the
server:
mysqld: Can't find file: 'host.frm'If you have other problems starting the server, see section 2.9.2.3 Starting and Troubleshooting the MySQL Server.
mysqladmin
to verify that the server is running. The following
commands provide simple tests to check whether the server is up and responding
to connections:
shell> bin/mysqladmin version shell> bin/mysqladmin variablesThe output from
mysqladmin version
varies slightly depending on your
platform and version of MySQL, but should be similar to that shown here:
shell> bin/mysqladmin version mysqladmin Ver 8.40 Distrib 4.0.18, for linux on i586 Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to modify and redistribute it under the GPL license Server version 4.0.18-log Protocol version 10 Connection Localhost via Unix socket TCP port 3306 UNIX socket /tmp/mysql.sock Uptime: 16 sec Threads: 1 Questions: 9 Slow queries: 0 Opens: 7 Flush tables: 2 Open tables: 0 Queries per second avg: 0.000 Memory in use: 132K Max memory used: 16773KTo see what else you can do with
mysqladmin
,
invoke it with the --help
option.
shell> bin/mysqladmin -u root shutdown
mysqld_safe
or
by invoking mysqld
directly. For example:
shell> bin/mysqld_safe --user=mysql --log &If
mysqld_safe
fails, see section 2.9.2.3 Starting and Troubleshooting the MySQL Server.
shell> bin/mysqlshow +-----------+ | Databases | +-----------+ | mysql | | test | +-----------+ shell> bin/mysqlshow mysql Database: mysql +--------------+ | Tables | +--------------+ | columns_priv | | db | | func | | host | | tables_priv | | user | +--------------+ shell> bin/mysql -e "SELECT Host,Db,User FROM db" mysql +------+--------+------+ | host | db | user | +------+--------+------+ | % | test | | | % | test_% | | +------+--------+------+
DBI DBD::mysql Data::Dumper Data::ShowTableThese modules can be obtained from CPAN (http://www.cpan.org/). See section 2.13.1 Installing Perl on Unix. The `sql-bench/Results' directory contains the results from many runs against different databases and platforms. To run all tests, execute these commands:
shell> cd sql-bench shell> perl run-all-testsIf you don't have the `sql-bench' directory, you probably installed MySQL using RPM files other than the source RPM. (The source RPM includes the `sql-bench' benchmark directory.) In this case, you must first install the benchmark suite before you can use it. Beginning with MySQL 3.22, there are separate benchmark RPM files named `mysql-bench-VERSION-i386.rpm' that contain benchmark code and data. If you have a source distribution, there are also tests in its `tests' subdirectory that you can run. For example, to run `auto_increment.tst', execute this command from the top-level directory of your source distribution:
shell> mysql -vvf test < ./tests/auto_increment.tstThe expected result of the test can be found in the `./tests/auto_increment.res' file.
As of MySQL 4.1.3, the installation procedure creates time zone tables
in the mysql
database. However, you must populate the tables manually.
Instructions to do this are given in section 5.8.8 MySQL Server Time Zone Support.
mysql_install_db
The purpose of the mysql_install_db
script is to generate new MySQL
privilege tables. It will not overwrite existing MySQL privilege tables,
and it will not affect any other data.
If you want to re-create your privilege tables, first stop
the mysqld
server if it's running. Then rename the `mysql'
directory under the data directory to save it, and then run
mysql_install_db
. For example:
shell> mv mysql-data-directory/mysql mysql-data-directory/mysql-old shell> mysql_install_db --user=mysql
This section lists problems you might encounter when you run
mysql_install_db
:
mysql_install_db
doesn't install the grant tables
mysql_install_db
fails to install the grant
tables and terminates after displaying the following messages:
Starting mysqld daemon with databases from XXXXXX mysqld endedIn this case, you should examine the error log file very carefully. The log should be located in the directory `XXXXXX' named by the error message, and should indicate why
mysqld
didn't start. If you don't understand
what happened, include the log when you post a bug report.
See section 1.4.1.3 How to Report Bugs or Problems.
mysqld
process running
mysql_install_db
at all because it need be run only once (when you
install MySQL the first time).
mysqld
server doesn't work when one server is running
Can't start server: Bind on TCP/IP port: Address already in use Can't start server: Bind on unix socket...For instructions on setting up multiple servers, see section 5.10 Running Multiple MySQL Servers on the Same Machine.
mysql_install_db
or the mysqld
server.
You can specify different temporary directory and Unix socket file locations
by executing these commands prior to starting mysql_install_db
or
mysqld
:
shell> TMPDIR=/some_tmp_dir/ shell> MYSQL_UNIX_PORT=/some_tmp_dir/mysql.sock shell> export TMPDIR MYSQL_UNIX_PORT`some_tmp_dir' should be the full pathname to some directory for which you have write permission. After this, you should be able to run
mysql_install_db
and start
the server with these commands:
shell> bin/mysql_install_db --user=mysql shell> bin/mysqld_safe --user=mysql &If
mysql_install_db
is located in the `scripts' directory,
modify the first command to use scripts/mysql_install_db
.
See section A.4.5 How to Protect or Change the MySQL Socket File `/tmp/mysql.sock'.
See section F Environment Variables.
Generally, you start the mysqld
server in one of these ways:
mysqld
directly. This works on any platform.
mysqld_safe
, which tries to determine the proper options
for mysqld
and then runs it with those options. This script is
used on systems based on BSD Unix.
See section 5.1.3 The mysqld_safe
Server Startup Script.
mysql.server
. This script is used primarily at
system startup and shutdown on systems that use System V-style run
directories, where it usually is installed under the name mysql
.
The mysql.server
script starts the server by invoking mysqld_safe
.
See section 5.1.4 The mysql.server
Server Startup Script.
mysql.server
.
See section 2.5 Installing MySQL on Mac OS X for details.
The mysql.server
and mysqld_safe
scripts and the Mac OS X
Startup Item can be used to start the server manually, or automatically at
system startup time. mysql.server
and the Startup Item also can be
used to stop the server.
To start or stop the server manually using the mysql.server
script,
invoke it with start
or stop
arguments:
shell> mysql.server start shell> mysql.server stop
Before mysql.server
starts the server, it changes location to the
MySQL installation directory, and then invokes mysqld_safe
. If you
want the server to run as some specific user, add an appropriate user
option to the [mysqld]
group of the `/etc/my.cnf' option file,
as shown later in this section.
(It is possible that you'll need to edit mysql.server
if you've installed a binary distribution of MySQL in a non-standard
location. Modify it to cd
into the proper directory before it runs
mysqld_safe
. If you do this, your modified version of
mysql.server
may be overwritten if you upgrade MySQL in the future,
so you should make a copy of your edited version that you can reinstall.)
mysql.server stop
brings down the server by sending a signal to it.
You can also stop the server manually by executing mysqladmin
shutdown
.
To start and stop MySQL automatically on your server, you need to add start and stop commands to the appropriate places in your `/etc/rc*' files.
If you use the Linux server RPM package (MySQL-server-VERSION.rpm
),
the mysql.server
script will have been installed in the
`/etc/init.d' directory with the name `mysql'. You need not
install it manually. See section 2.4 Installing MySQL on Linux for more information on the Linux
RPM packages.
Some vendors provide RPM packages that install a startup script under a
different name such as mysqld
.
If you install MySQL from a source distribution or using a binary
distribution format that does not install mysql.server
automatically,
you can install it manually. The script can be found in the
`support-files' directory under the MySQL installation directory or in
a MySQL source tree.
To install mysql.server
manually, copy it to the `/etc/init.d'
directory with the name mysql
, and then make it executable. Do this
by changing location into the appropriate directory where
mysql.server
is located and executing these commands:
shell> cp mysql.server /etc/init.d/mysql shell> chmod +x /etc/init.d/mysql
Older Red Hat systems use the `/etc/rc.d/init.d' directory rather than `/etc/init.d'. Adjust the preceding commands accordingly. Alternatively, first create `/etc/init.d' as a symbolic link that points to `/etc/rc.d/init.d':
shell> cd /etc shell> ln -s rc.d/init.d .
After installing the script, the commands needed to activate it to run
at system startup depend on your operating system. On Linux, you can use
chkconfig
:
shell> chkconfig --add mysql
On some Linux systems, the following command also seems to be necessary to
fully enable the mysql
script:
shell> chkconfig --level 345 mysql on
On FreeBSD, startup scripts generally should go in
`/usr/local/etc/rc.d/'. The rc(8)
manual page states that
scripts in this directory are executed only if their basename matches the
*.sh
shell filename pattern. Any other files or directories present
within the directory are silently ignored. In other words, on FreeBSD, you
should install the `mysql.server' script as
`/usr/local/etc/rc.d/mysql.server.sh' to enable automatic startup.
As an alternative to the preceding setup, some operating systems also use `/etc/rc.local' or `/etc/init.d/boot.local' to start additional services on startup. To start up MySQL using this method, you could append a command like the one following to the appropriate startup file:
/bin/sh -c 'cd /usr/local/mysql; ./bin/mysqld_safe --user=mysql &'
For other systems, consult your operating system documentation to see how to install startup scripts.
You can add options for mysql.server
in a global
`/etc/my.cnf' file. A typical `/etc/my.cnf' file might look like
this:
[mysqld] datadir=/usr/local/mysql/var socket=/var/tmp/mysql.sock port=3306 user=mysql [mysql.server] basedir=/usr/local/mysql
The mysql.server
script understands the following options:
basedir
, datadir
, and pid-file
. If specified, they
must be placed in an option file, not on the command line.
mysql.server
understands only start
and stop
as
command-line arguments.
The following table shows which option groups the server and each startup script read from option files:
Script | Option Groups |
mysqld | [mysqld] , [server] , [mysqld-major-version]
|
mysql.server | [mysqld] , [mysql.server]
|
mysqld_safe | [mysqld] , [server] , [mysqld_safe]
|
[mysqld-major-version]
means that groups with names like
[mysqld-4.0]
, [mysqld-4.1]
, and [mysqld-5.0]
will be
read by servers having versions 4.0.x, 4.1.x, 5.0.x, and so forth. This
feature was added in MySQL 4.0.14. It can be used to specify options that will
be read only by servers within a given release series.
For backward compatibility, mysql.server
also reads the
[mysql_server]
group and mysqld_safe
also reads the
[safe_mysqld]
group. However, you should update your option
files to use the [mysql.server]
and [mysqld_safe]
groups instead
when you begin using MySQL 4.0 or later.
See section 4.3.2 Using Option Files.
If you have problems starting the server, here are some things you can try:
Some storage engines have options that control their behavior.
You can create a `my.cnf' file and set startup options
for the engines you plan to use.
If you are going to use storage engines that support transactional tables
(InnoDB
, BDB
), be sure that you have them configured the
way you want before starting the server:
InnoDB
tables, refer to the InnoDB
-specific
startup options. In MySQL 3.23, you must configure InnoDB
explicitly
or the server will fail to start. From MySQL 4.0 on, InnoDB
uses default
values for its configuration options if you specify none.
See section 15.4 InnoDB
Configuration.
BDB
(Berkeley DB) tables, you should familiarize
yourself with the different BDB
-specific startup options.
See section 14.4.3 BDB
Startup Options.
When the mysqld
server starts, it changes location to the data
directory. This is where it expects to find databases and where it expects
to write log files. On Unix, the server also writes the pid (process ID)
file in the data directory.
The data directory location is hardwired in when the server is compiled.
This is where the server looks for the data directory by default. If
the data directory is located somewhere else on your system, the server will
not work properly. You can find out what the default path settings are by
invoking mysqld
with the --verbose
and --help
options.
(Prior to MySQL 4.1, omit the --verbose
option.)
If the defaults don't match the MySQL installation layout on your system,
you can override them by specifying options on the command line to
mysqld
or mysqld_safe
. You can also list the options in an
option file.
To specify the location of the data directory explicitly, use the
--datadir
option. However, normally you can tell mysqld
the
location of the base directory under which MySQL is installed and it will
look for the data directory there. You can do this with the --basedir
option.
To check the effect of specifying path options, invoke mysqld
with
those options followed by the --verbose
and --help
options.
For example, if you change location into the directory where mysqld
is
installed, and then run the following command, it
will show the effect of starting the server with a base
directory of `/usr/local':
shell> ./mysqld --basedir=/usr/local --verbose --help
You can specify other options such as --datadir
as well, but note
that --verbose
and --help
must be the last options. (Prior to
MySQL 4.1, omit the --verbose
option.)
Once you determine the path settings you want, start the server without
--verbose
and --help
.
If mysqld
is currently running, you can find out what path settings
it is using by executing this command:
shell> mysqladmin variables
Or:
shell> mysqladmin -h host_name variables
host_name is the name of the MySQL server host.
If you get Errcode 13
(which means Permission denied
) when
starting mysqld
, this means that the access privileges of the data
directory or its contents do not allow the server access. In this case, you
change the permissions for the involved files and directories so that the
server has the right to use them. You can also start the server as
root
, but this can raise security issues and should be avoided.
On Unix, change location into the data directory and check the ownership of the data directory and its contents to make sure the server has access. For example, if the data directory is `/usr/local/mysql/var', use this command:
shell> ls -la /usr/local/mysql/var
If the data directory or its files or subdirectories are not owned by the account that you use for running the server, change their ownership to that account:
shell> chown -R mysql /usr/local/mysql/var shell> chgrp -R mysql /usr/local/mysql/var
If the server fails to start up correctly, check the error log file to
see if you can find out why. Log files are located in the data directory
(typically `C:\mysql\data' on Windows, `/usr/local/mysql/data'
for a Unix binary distribution, and `/usr/local/var' for a Unix source
distribution). Look in the data directory for files with names of the form
`host_name.err' and `host_name.log', where host_name is the
name of your server host. (Older servers on Windows use `mysql.err'
as the error log name.) Then check the last few lines of these files.
On Unix, you can use tail
to display the last few lines:
shell> tail host_name.err shell> tail host_name.log
The error log contains information that indicates why the server couldn't start. For example, you might see something like this in the log:
000729 14:50:10 bdb: Recovery function for LSN 1 27595 failed 000729 14:50:10 bdb: warning: ./test/t1.db: No such file or directory 000729 14:50:10 Can't init databases
This means that you didn't start mysqld
with the
--bdb-no-recover
option and Berkeley DB found something wrong with
its own log files when it tried to recover your databases. To be able to
continue, you should move away the old Berkeley DB log files from the
database directory to some other place, where you can later examine them.
The BDB
log files are named in sequence beginning with
`log.0000000001', where the number increases over time.
If you are running mysqld
with BDB
table support and
mysqld
dumps core at startup, this could be due to problems with the
BDB
recovery log. In this case, you can try starting mysqld
with --bdb-no-recover
. If that helps, then you should remove
all BDB
log files from the data directory and try starting mysqld
again without the --bdb-no-recover
option.
If either of the following errors occur, it means that some other program
(perhaps another mysqld
server) is using the TCP/IP port or
Unix socket file that mysqld
is trying to use:
Can't start server: Bind on TCP/IP port: Address already in use Can't start server: Bind on unix socket...
Use ps
to determine whether you have another mysqld
server
running. If so, shut down the server before starting mysqld
again.
(If another server is running, and you really want to run multiple servers,
you can find information about how to do so in section 5.10 Running Multiple MySQL Servers on the Same Machine.)
If no other server is running, try to execute the command telnet
your-host-name tcp-ip-port-number
. (The default MySQL port number is
3306.) Then press Enter a couple of times. If you don't get an error
message like telnet: Unable to connect to remote host: Connection
refused
, some other program is using the TCP/IP port that mysqld
is
trying to use. You'll need to track down what program this is and disable
it, or else tell mysqld
to listen to a different port with the
--port
option. In this case, you'll also need to specify the port
number for client programs when connecting to the server via TCP/IP.
Another reason the port might be inaccessible is that you have a firewall running that blocks connections to it. If so, modify the firewall settings to allow access to the port.
If the server starts but you can't connect to it, you should make sure that you have an entry in `/etc/hosts' that looks like this:
127.0.0.1 localhost
This problem occurs only on systems that don't have a working thread library and for which MySQL must be configured to use MIT-pthreads.
If you can't get mysqld
to start, you can try to make a trace file
to find the problem by using the --debug
option.
See section E.1.2 Creating Trace Files.
See section 2.3.14 Troubleshooting a MySQL Installation Under Windows, for more information on troubleshooting Windows installations.
Part of the MySQL installation process is to set up the mysql
database
containing the grant tables:
mysql_install_db
program. Some installation methods run this program for you. Others require
that you execute it manually. For details, see section 2.9.2 Unix Post-Installation Procedures.
The grant tables define the initial MySQL user accounts and their access privileges. These accounts are set up as follows:
root
. These are
superuser accounts that can do anything. The initial root
account
passwords are empty, so anyone can connect to the MySQL server as root
without a password and be granted all privileges.
root
account is for connecting from the local host
and the other allows connections from any host.
root
accounts are for connections from the local host.
Connections must be made from the local host by specifying a hostname of
localhost
for one account, or the actual hostname or IP number for
the other.
root
accounts.
The other is for connections from any host and has all privileges for the
test
database or other databases with names that start with test
.
localhost
for one account, or the actual hostname or IP number for
the other. These accounts have all privileges for the test
database
or other databases with names that start with test_
.
As noted, none of the initial accounts have passwords. This means that your MySQL installation is unprotected until you do something about it:
root
accounts.
The following instructions describe how to set up passwords for the
initial MySQL accounts, first for the anonymous accounts and then for the
root
accounts. Replace ``newpwd'' in the examples with the
actual password that you want to use. The instructions also cover how
to remove the anonymous accounts, should you prefer not to allow anonymous
access at all.
You might want to defer setting the passwords until later, so that you don't need to specify them while you perform additional setup or testing. However, be sure to set them before using your installation for any real production work.
To assign passwords to the anonymous accounts, you can use either
SET PASSWORD
or UPDATE
. In both cases, be sure to encrypt the
password using the PASSWORD()
function.
To use SET PASSWORD
on Windows, do this:
shell> mysql -u root mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('newpwd'); mysql> SET PASSWORD FOR ''@'%' = PASSWORD('newpwd');
To use SET PASSWORD
on Unix, do this:
shell> mysql -u root mysql> SET PASSWORD FOR ''@'localhost' = PASSWORD('newpwd'); mysql> SET PASSWORD FOR ''@'host_name' = PASSWORD('newpwd');
In the second SET PASSWORD
statement, replace host_name
with the name of the server host. This is the name that is specified in
the Host
column of the non-localhost
record for root
in the user
table. If you don't know what hostname this is, issue
the following statement before using SET PASSWORD
:
mysql> SELECT Host, User FROM mysql.user;
Look for the record that has root
in the User
column and
something other than localhost
in the Host
column. Then use that
Host
value in the second SET PASSWORD
statement.
The other way to assign passwords to the anonymous accounts is by using
UPDATE
to modify the user
table directly. Connect to the
server as root
and issue an UPDATE
statement that assigns a
value to the Password
column of the appropriate user
table
records. The procedure is the same for Windows and Unix. The following
UPDATE
statement assigns a password to both anonymous accounts at
once:
shell> mysql -u root mysql> UPDATE mysql.user SET Password = PASSWORD('newpwd') -> WHERE User = ''; mysql> FLUSH PRIVILEGES;
After you update the passwords in the user
table directly using
UPDATE
, you must tell the server to re-read the grant tables with
FLUSH PRIVILEGES
. Otherwise, the change will go unnoticed until you
restart the server.
If you prefer to remove the anonymous accounts instead, do so as follows:
shell> mysql -u root mysql> DELETE FROM mysql.user WHERE User = ''; mysql> FLUSH PRIVILEGES;
The DELETE
statement applies both to Windows and to Unix.
On Windows, if you want to remove only the anonymous account that has the same
privileges as root
, do this instead:
shell> mysql -u root mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User=''; mysql> FLUSH PRIVILEGES;
This account allows anonymous access but has full privileges, so removing it improves security.
You can assign passwords to the root
accounts in several ways. The
following discussion demonstrates three methods:
SET PASSWORD
statement
mysqladmin
command-line client program
UPDATE
statement
To assign passwords using SET PASSWORD
, connect to the server as
root
and issue two SET PASSWORD
statements.
Be sure to encrypt the password using the PASSWORD()
function.
For Windows, do this:
shell> mysql -u root mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpwd'); mysql> SET PASSWORD FOR 'root'@'%' = PASSWORD('newpwd');
For Unix, do this:
shell> mysql -u root mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('newpwd'); mysql> SET PASSWORD FOR 'root'@'host_name' = PASSWORD('newpwd');
In the second SET PASSWORD
statement, replace host_name with
the name of the server host. This is the same hostname that you used when
you assigned the anonymous account passwords.
To assign passwords to the root
accounts using mysqladmin
,
execute the following commands:
shell> mysqladmin -u root password "newpwd" shell> mysqladmin -u root -h host_name password "newpwd"
These commands apply both to Windows and to Unix. In the second command, replace host_name with the name of the server host. The double quotes around the password are not always necessary, but you should use them if the password contains spaces or other characters that are special to your command interpreter.
If you are using a server from a very old version of MySQL, the
mysqladmin
commands to set the password will fail with the message
parse error near 'SET password'
. The solution to this problem is
to upgrade the server to a newer version of MySQL.
You can also use UPDATE
to modify the user
table directly.
The following UPDATE
statement assigns a password to both root
accounts at once:
shell> mysql -u root mysql> UPDATE mysql.user SET Password = PASSWORD('newpwd') -> WHERE User = 'root'; mysql> FLUSH PRIVILEGES;
The UPDATE
statement applies both to Windows and to Unix.
After the passwords have been set, you must supply the appropriate
password whenever you connect to the server.
For example, if you want to use mysqladmin
to shut
down the server, you can do so using this command:
shell> mysqladmin -u root -p shutdown Enter password: (enter root password here)
Note: If you forget your root
password after setting it up,
the procedure for resetting it is covered in section A.4.1 How to Reset the Root Password.
To set up new accounts, you can use the GRANT
statement. For
instructions, see section 5.6.2 Adding New User Accounts to MySQL.
As a general rule, we recommend that when upgrading from one release series to another, you should go to the next series rather than skipping a series. For example, if you currently are running MySQL 3.23 and wish to upgrade to a newer series, upgrade to MySQL 4.0 rather than to 4.1 or 5.0.
The following items form a checklist of things you should do whenever you perform an upgrade:
mysql
database. Occasionally new columns or tables are added to
support new features. To take advantage of these features, be sure that
your grant tables are up to date. The upgrade procedure is described in
section 2.10.7 Upgrading the Grant Tables.
mysqld-max
, then upgrade later to a non-Max version of MySQL,
mysqld_safe
will still attempt to run the old mysqld-max
server. If you perform such an upgrade, you should manually remove the old
mysqld-max
server to ensure that mysqld_safe
runs the new
mysqld
server.
You can always move the MySQL format files and data files between different
versions on the same architecture as long as you stay within versions for
the same release series of MySQL. The current production release series is
4.1. If you change the character set when running MySQL, you must run
myisamchk -r -q --set-character-set=charset
on all MyISAM
tables.
Otherwise, your indexes may not be ordered correctly, because changing the
character set may also change the sort order.
Normally you can upgrade MySQL to a newer MySQL version without having
to do any changes to your tables. Please confirm if the upgrade notes
to the particular version you are upgrading to tells you anything about
this. If there would be any incompatibilities you can use
mysqldump
to dump your tables before upgrading. After
upgrading, reload the dump file using mysql
or mysqlimport
to re-create your tables.
If you are cautious about using new versions, you can always rename your old
mysqld
before installing a newer one. For example, if you are using
MySQL 4.0.18 and want to upgrade to 4.1.1, rename your current server from
mysqld
to mysqld-4.0.18
. If your new mysqld
then does
something unexpected, you can simply shut it down and restart with your old
mysqld
.
If, after an upgrade, you experience problems with recompiled client programs,
such as Commands out of sync
or unexpected core dumps, you probably have
used old header or library files when compiling your programs. In this
case, you should check the date for your `mysql.h' file and
`libmysqlclient.a' library to verify that they are from the new
MySQL distribution. If not, recompile your programs with the new
headers and libraries.
If problems occur, such as that the new mysqld
server doesn't want to
start or that you can't connect without a password, verify that you don't
have some old `my.cnf' file from your previous installation. You can
check this with the --print-defaults
option (for example,
mysqld --print-defaults
). If this displays
anything other than the program name, you have an active `my.cnf'
file that affects server or client operation.
It is a good idea to rebuild and reinstall the Perl DBD::mysql
module whenever you install a new release of MySQL. The same applies to other
MySQL interfaces as well, such as the PHP mysql
extension and the
Python MySQLdb
module.
In general, you should do the following when upgrading to MySQL 5.0 from 4.1:
proc
table in the mysql
database.
To create this file, you should run the mysql_fix_privilege_tables
script as described in section 2.10.7 Upgrading the Grant Tables.
user
and db
tables in the mysql
database.
To create these columns, you should run the mysql_fix_privilege_tables
script as described in section 2.10.7 Upgrading the Grant Tables.
'2004-02-31'
, you should start
the server with --sql_mode=TRADITIONAL,ALLOW_INVALID_DATES
.
SCHEMA
and SCHEMAS
keywords are
accepted as synonyms for DATABASE
and DATABASES
.
The following list describes changes that may affect applications and that you should watch out for when upgrading to version 5.0:
SET @x = 0; SET @X = 1; SELECT @x;
creates two variables and
returns 0
. In MySQL 5.0, it creates one variable and returns
1
.
reconnect
flag in the MYSQL
structure is set
to 0 by mysql_real_connect()
. Only those client programs which didn't
explicitly set this flag to 0 or 1 after mysql_real_connect()
will
experience a change. Having automatic reconnection enabled by default was
considered too dangerous (after reconnection, table locks, temporary tables,
user and session variables are lost).
In general, you should do the following when upgrading to MySQL 4.1 from 4.0:
UTF8
. If you have
table names or column names that use characters outside of the standard 7-bit
US-ASCII range, you may have to do a mysqldump
of your tables
in MySQL 4.0 and restore them after upgrading to MySQL 4.1. The symptom for
this problem is that you get a table not found
error when trying to
access your tables. In this case, you should be able to downgrade back to
MySQL 4.0 and access your data.
Password
column that is needed for more secure handling of passwords.
The procedure uses mysql_fix_privilege_tables
and is described
in section 2.10.7 Upgrading the Grant Tables. If you don't do this, MySQL will not
use the new more secure protocol to authenticate. Implications of the
password-handling change for applications are given later in this section.
mysqldump
to dump your BDB
tables in text format and delete
all log.XXXXXXXXXX
files before you start MySQL 4.0 and reload
the data.
mysql
database.
For instructions, see section 2.9 Post-Installation Setup and Testing.
DBD-mysql
module
(Msql-MySQL-modules
) you have to upgrade to use the newer
DBD-mysql
module. Anything above DBD-mysql
2.xx should be fine.
If you don't upgrade, some methods (such as DBI->do()
) will not
notice error conditions correctly.
--defaults-file=option-file-name
option will give an error if
the option file doesn't exist.
Several visible behaviors have changed between MySQL 4.0 and MySQL 4.1 to fix some critical bugs and make MySQL more compatible with standard SQL. These changes may affect your applications.
Some of the 4.1 behaviors can be tested in 4.0 before performing
a full upgrade to 4.1. We have added to later MySQL 4.0 releases
(from 4.0.12 on) a --new
startup option for mysqld
.
See section 5.2.1 mysqld
Command-Line Options.
This option gives you the 4.1 behavior for the most critical changes.
You can also enable these behaviors for a given client connection with
the SET @@new=1
command, or turn them off if they are on with
SET @@new=0
.
If you believe that some of the 4.1 changes will affect you,
we recommend that before upgrading to 4.1, you download
the latest MySQL 4.0 version and run it with the --new
option by
adding the following to your config file:
[mysqld-4.0] new
That way you can test the new behaviors in 4.0 to make sure that your
applications work with them. This will help you have a smooth, painless
transition when you perform a full upgrade to 4.1 later. Putting the
--new
option in the [mysqld-4.0]
option group ensures
that you don't accidentally later run the 4.1
version with the --new
option.
The following lists describe changes that may affect applications and that you should watch out for when upgrading to version 4.1:
Server Changes:
SHOW CREATE TABLE
and mysqldump
.
(MySQL versions 4.0.6 and above can read the new dump files; older
versions cannot.)
This change should not affect applications that use only one character set.
mysqldump
and reload the dump file. Some items in the following list indicate
alternatives means for rebuilding.
InnoDB
tables with TIMESTAMP
columns in MySQL versions 4.1.0 to 4.1.3, you have to rebuild those tables
when you upgrade to MySQL 4.1.4 or later. The storage format in those
MySQL versions for a TIMESTAMP
column was incorrect. If you upgrade
from MySQL 4.0 to 4.1.4 or later, then no rebuild of tables with
TIMESTAMP
columns is needed.
InnoDB
uses the same character set
comparison functions as MySQL for non-latin1_swedish_ci
character
strings that are not BINARY
. This changes the sorting order of
space and characters with a code < ASCII(32) in those character sets.
For latin1_swedish_ci
character strings and BINARY
strings,
InnoDB
uses its own pad-spaces-at-end comparison method, which
stays unchanged. If you have an InnoDB
table created with MySQL
4.1.2 or earlier, with an index on a non-latin1
character set
(in the case of 4.1.0 and 4.1.1, with any character set) and the table
contains any CHAR
/VARCHAR
/or TEXT
columns that are
not BINARY
but may contain characters with a code < ASCII(32),
then you should do ALTER TABLE
or OPTIMIZE TABLE
on it to
regenerate the index, after upgrading to MySQL 4.1.3 or later.
Also, MyISAM
tables have to be rebuilt or repaired in these cases.
RENAME
TABLE
to overcome this if the accent character is in the table name or
the database name, or rebuild the table.
CHAR(N)
means N characters, not N
bytes.
For single-byte character sets, this change makes no difference. However,
if you upgrade to MySQL 4.1 and configure the server to use a multi-byte
character set, the apparent length of character columns will change. Suppose
that a 4.0 table contains a CHAR(8)
column used to store ujis
characters. Eight bytes can store from two to four ujis
characters.
If you upgrade to 4.1 and configure the server to use ujis
as its
default character set, the server interprets character column lengths
based on the maximum size of a ujis
character, which is three
bytes. The number of three-byte characters that fit in eight bytes is
two. Consequently, if you use SHOW CREATE TABLE
to view the table
definition, MySQL displays CHAR(2)
. You can retrieve existing
data from the table, but you will be able to store new values containing
only up to two characters. To correct this issue, use ALTER TABLE
to change the column definition. For example:
ALTER TABLE tbl_name MODIFY col_name CHAR(8);
mysqldump
.
See section 8.8 The mysqldump
Database Backup Program.
InnoDB
is not aware of multiple tablespaces.
timezone
system variable was renamed to system_time_zone
.
--shared-memory
option. If you are running
multiple servers this way on the same Windows machine, you should use a
different --shared-memory-base-name
option for each server.
xxx_clear()
function for each aggregate function XXX()
.
Client Changes:
mysqldump
has the --opt
and --quote-names
options
enabled by default. You can turn them off with --skip-opt
and
--skip-quote-names
.
SQL Changes:
Type
column in the output from SHOW TABLE
STATUS
was renamed to Engine
.
'a' > 'a\t'
,
which it wasn't before. If you have any tables where you
have a CHAR
or VARCHAR
column in which the last character in the
column may be less than ASCII(32)
, you should use REPAIR TABLE
or
myisamchk
to ensure that the table is correct.
DELETE
statements, you should use the
alias of the tables from which you want to delete, not the actual table name.
For example, instead of doing this:
DELETE test FROM test AS t1, test2 WHERE ...Do this:
DELETE t1 FROM test AS t1, test2 WHERE ...This corrects a problem that was present in MySQL 4.0.
TIMESTAMP
is returned as a string in 'YYYY-MM-DD HH:MM:SS'
format (from 4.0.12 the --new
option can be used to make a
4.0 server behave as 4.1 in this respect).
See section 11.3.1.2 TIMESTAMP
Properties as of MySQL 4.1.
If you want to have the value returned as a number (as MySQL 4.0 does) you
should add +0
to TIMESTAMP
columns when you retrieve them:
mysql> SELECT ts_col + 0 FROM tbl_name;Display widths for
TIMESTAMP
columns are no longer supported.
For example, if you declare a column as TIMESTAMP(10)
, the (10)
is ignored.
These changes were necessary for SQL standards compliance. In a future
version, a further change will be made (backward compatible with this
change), allowing the timestamp length to indicate the desired number of
digits for fractions of a second.
0xFFDF
are assumed to be strings instead of
numbers. This fixes some problems with character sets where it's
convenient to input a string as a binary value. With this change,
you should use CAST()
if you want to compare binary values
numerically as integers:
mysql> SELECT CAST(0xFEFF AS UNSIGNED INTEGER) -> < CAST(0xFF AS UNSIGNED INTEGER); -> 0If you don't use
CAST()
, a lexical string comparison will be done:
mysql> SELECT 0xFEFF < 0xFF; -> 1Using binary items in a numeric context or comparing them using the
=
operator should work as before. (The --new
option can
be used from 4.0.13 on to make a 4.0 server behave as 4.1 in this respect.)
DATE
, DATETIME
, or TIME
value, the result returned to the client is fixed up to have a temporal
type. For example, in MySQL 4.1, you get this result:
mysql> SELECT CAST('2001-1-1' AS DATETIME); -> '2001-01-01 00:00:00'In MySQL 4.0, the result is different:
mysql> SELECT CAST('2001-1-1' AS DATETIME); -> '2001-01-01'
DEFAULT
values no longer can be specified for AUTO_INCREMENT
columns. (In 4.0, a DEFAULT
value is silently ignored; in 4.1,
an error occurs.)
LIMIT
no longer accepts negative arguments.
Use some large number (maximum 18446744073709551615) instead of -1.
SERIALIZE
is no longer a valid mode value for the sql_mode
variable. You should use SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
instead. SERIALIZE
is no longer valid for the --sql-mode
option
for mysqld
, either. Use --transaction-isolation=SERIALIZABLE
instead.
INSERT INTO t (datetime_col) VALUES ('stuff 2005-02-11 10:17:01');As of MySQL 4.1.1, the parser is more strict and treats the string as an invalid date, so the preceding statement results in a warning.
C API Changes:
mysql_shutdown()
C API function has an extra parameter
as of MySQL 4.1.3: SHUTDOWN
-level. You should convert any
mysql_shutdown(X)
call you have in your application to
mysql_shutdown(X,SHUTDOWN_DEFAULT)
.
mysql_real_query()
return 1
on error,
not -1
. You may have to change some old applications if they use
constructs like this:
if (mysql_real_query(mysql_object, query, query_length) == -1) { printf("Got error"); }Change the call to test for a non-zero value instead:
if (mysql_real_query(mysql_object, query, query_length) != 0) { printf("Got error"); }
Password-Handling Changes:
The password hashing mechanism has changed in 4.1 to provide better security, but this may cause compatibility problems if you still have clients that use the client library from 4.0 or earlier. (It is very likely that you will have 4.0 clients in situations where clients connect from remote hosts that have not yet upgraded to 4.1.) The following list indicates some possible upgrade strategies. They represent various tradeoffs between the goal of compatibility with old clients and the goal of security.
mysql_fix_privilege_tables
script to
widen the Password
column in the user
table so that it can
hold long password hashes. But run the server with the
--old-passwords
option to provide backward compatibility that allows
pre-4.1 clients to continue to connect to their short-hash accounts.
Eventually, when all your clients are upgraded to 4.1, you can stop using
the --old-passwords
server option. You can also change the passwords
for your MySQL accounts to use the new more secure format. A pure-4.1
installation is the most secure.
Further background on password hashing with respect to client authentication
and password-changing operations may be found in section 5.5.9 Password Hashing in MySQL 4.1 and
section A.2.3 Client does not support authentication protocol
.
In general, you should do the following when upgrading to MySQL 4.0 from 3.23:
mysql_fix_privilege_tables
script and is described
in section 2.10.7 Upgrading the Grant Tables.
ISAM
files to MyISAM
files. One way to do this
is with the
mysql_convert_table_format
script. (This is a Perl script;
it requires that DBI be installed.) To convert the tables in a given database,
use this command:
shell> mysql_convert_table_format database db_nameNote that this should be used only if all tables in the given database are
ISAM
or MyISAM
tables. To avoid converting tables
of other types to MyISAM
, you can explicitly list the names
of your ISAM
tables after the database name on the command
line.
Individual tables can be changed to MyISAM
by using the following
ALTER TABLE
statement for each table to be converted:
mysql> ALTER TABLE tbl_name TYPE=MyISAM;If you are not sure of the table type for a given table, use this statement:
mysql> SHOW TABLE STATUS LIKE 'tbl_name';
DBD::mysql
module). If you do, you should recompile
them, because the data structures used in `libmysqlclient.so' have changed.
The same applies to other MySQL interfaces as well, such as the Python
MySQLdb
module.
MySQL 4.0 will work even if you don't perform the preceding actions, but you
will not be able to use the new security privileges in MySQL 4.0 and you
may run into problems when upgrading later to MySQL 4.1 or newer. The
ISAM
file format still works in MySQL 4.0, but is deprecated and
is not compiled in by default as of MySQL 4.1. MyISAM
tables should
be used instead.
Old clients should work with a MySQL 4.0 server without any problems.
Even if you perform the preceding actions, you can still downgrade to MySQL
3.23.52 or newer if you run into problems with the MySQL 4.0 series. In
this case, you must use mysqldump
to dump any tables that use
full-text indexes and reload the dump file into the 3.23 server. This is
necessary because 4.0 uses a new format for full-text indexing.
The following lists describe changes that may affect applications and that you should watch out for when upgrading to version 4.0:
Server Changes:
mysql.user
table.
See section 5.5.3 Privileges Provided by MySQL.
To get these new privileges to work, you must update the grant tables.
The procedure is described in section 2.10.7 Upgrading the Grant Tables.
Until you do this, all
accounts have the SHOW DATABASES
, CREATE TEMPORARY TABLES
,
and LOCK TABLES
privileges. SUPER
and EXECUTE
privileges take their value from PROCESS
.
REPLICATION SLAVE
and REPLICATION CLIENT
take their
values from FILE
.
If you have any scripts that create new MySQL user accounts, you may want to change
them to use the new privileges. If you are not using GRANT
commands in the scripts, this is a good time to change your scripts to use
GRANT
instead of modifying the grant tables directly.
From version 4.0.2 on, the option --safe-show-database
is deprecated
(and no longer does anything). See section 5.4.3 Startup Options for mysqld
Concerning Security.
If you get Access denied
errors for new users in version 4.0.2 and up, you
should check whether you need some of the new grants that you didn't need
before. In particular, you will need REPLICATION SLAVE
(instead of FILE
) for new slave servers.
safe_mysqld
has been renamed to mysqld_safe
. For backward
compatibility, binary distributions will for some time include
safe_mysqld
as a symlink to mysqld_safe
.
InnoDB
support is included by default in binary distributions.
If you build MySQL from source, InnoDB
is configured in by default.
If you do not use InnoDB
and want to save memory when running a
server that has InnoDB
support enabled, use the --skip-innodb
server startup option. To compile MySQL without InnoDB
support, run
configure
with the --without-innodb
option.
myisam_max_extra_sort_file_size
and
myisam_max_extra_sort_file_size
are given in bytes
(they were given in megabytes before 4.0.3).
mysqld
has the option --temp-pool
enabled by default
because this gives better performance with some operating systems (most
notably Linux).
mysqld
startup options --skip-locking
and
--enable-locking
were renamed to --skip-external-locking
and --external-locking
.
MyISAM
/ISAM
files is
turned off by default. You can turn this on with
--external-locking
. (However, this is never needed for most users.)
Old Name | New Name |
myisam_bulk_insert_tree_size | bulk_insert_buffer_size
|
query_cache_startup_type | query_cache_type
|
record_buffer | read_buffer_size
|
record_rnd_buffer | read_rnd_buffer_size
|
sort_buffer | sort_buffer_size
|
warnings | log-warnings
|
--err-log | --log-error (for mysqld_safe )
|
record_buffer
, sort_buffer
, and
warnings
will still work in MySQL 4.0 but are deprecated.
SQL Changes:
Old Name | New Name |
SQL_BIG_TABLES | BIG_TABLES
|
SQL_LOW_PRIORITY_UPDATES | LOW_PRIORITY_UPDATES
|
SQL_MAX_JOIN_SIZE | MAX_JOIN_SIZE
|
SQL_QUERY_CACHE_TYPE | QUERY_CACHE_TYPE
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=skip_count
instead of
SET SQL_SLAVE_SKIP_COUNTER=skip_count
.
SHOW MASTER STATUS
returns an empty set if binary logging is not
enabled.
SHOW SLAVE STATUS
returns an empty set if the slave is not
initialized.
SHOW INDEX
has two more columns than it had in 3.23 (Null
and
Index_type
).
SHOW OPEN TABLES
has changed.
ORDER BY col_name DESC
sorts NULL
values last, as of
MySQL 4.0.11. In 3.23 and in earlier 4.0 versions, this was not
always consistent.
CHECK
, LOCALTIME
, and LOCALTIMESTAMP
are reserved words.
DOUBLE
and FLOAT
columns honor the
UNSIGNED
flag on storage (before, UNSIGNED
was ignored for
these columns).
|
, &
, <<
,
>>
, and ~
) is unsigned. This may cause problems if you
are using them in a context where you want a signed result.
See section 12.7 Cast Functions and Operators.
Note: When you use subtraction between integer values where
one is of type UNSIGNED
, the result will be unsigned. In other
words, before upgrading to MySQL 4.0, you should check your application
for cases in which you are subtracting a value from an unsigned entity and
want a negative answer or subtracting an unsigned value from an
integer column. You can disable this behavior by using the
--sql-mode=NO_UNSIGNED_SUBTRACTION
option when starting
mysqld
. See section 5.2.2 The Server SQL Mode.
BIGINT
columns (instead
of using strings, as you did in MySQL 3.23). Using strings will still
work, but using integers is more efficient.
INSERT INTO ... SELECT
always had IGNORE
enabled.
As of 4.0.1, MySQL will stop (and possibly roll back) by default in case of
an error unless you specify IGNORE
.
TRUNCATE TABLE
when you want to delete all rows
from a table and you don't need to obtain a count of the number of rows
that were deleted. (DELETE FROM tbl_name
returns a row count in
4.0 and doesn't reset the AUTO_INCREMENT
counter, and
TRUNCATE TABLE
is faster.)
LOCK TABLES
statement when trying to execute TRUNCATE TABLE
or DROP
DATABASE
.
MATCH ... AGAINST (... IN BOOLEAN MODE)
full-text searches
with your tables, you must rebuild their indexes with REPAIR TABLE
tbl_name USE_FRM
. If you attempt a boolean full-text search without
rebuilding the indexes this way, the search will return incorrect results.
See section 12.6.4 Fine-Tuning MySQL Full-Text Search.
LOCATE()
and INSTR()
are case sensitive if one of the
arguments is a binary string. Otherwise they are case insensitive.
STRCMP()
uses the current character set when performing comparisons.
This makes the default comparison behavior not case sensitive unless
one or both of the operands are binary strings.
HEX(str)
returns the characters in str converted to
hexadecimal. If you want to convert a number to hexadecimal, you should
ensure that you call HEX()
with a numeric argument.
RAND(seed)
returns a different random number series in 4.0 than in
3.23; this was done to further differentiate RAND(seed)
and
RAND(seed+1)
.
IFNULL(A,B)
is set to be the
more ``general'' of the types of A
and B
. (The general-to-specific
order is string, REAL
, INTEGER
).
C API Changes:
mysql_drop_db()
, mysql_create_db()
, and
mysql_connect()
are no longer supported unless you compile
MySQL with CFLAGS=-DUSE_OLD_FUNCTIONS
. However, it is preferable
to change client programs to use the new 4.0 API instead.
MYSQL_FIELD
structure, length
and max_length
have
changed from unsigned int
to unsigned long
. This should not
cause any problems, except that they may generate warning messages when
used as arguments in the printf()
class of functions.
mysql_thread_init()
and
mysql_thread_end()
. See section 22.2.15 How to Make a Threaded Client.
Other Changes:
DBD::mysql
module, use a recent
version. Version 2.9003 is recommended. Versions older than 1.2218 should
not be used because they use the deprecated mysql_drop_db()
call.
MySQL 3.22 and 3.21 clients will work without any problems with a MySQL 3.23 server.
When upgrading to MySQL 3.23 from an earlier version, note the following changes:
Table Changes:
MyISAM
type and the old
ISAM
type. By default, all new tables are created with type
MyISAM
unless you start mysqld
with the
--default-table-type=isam
option. You don't have to convert your old
ISAM
tables to use them with MySQL 3.23. You can convert an
ISAM
table to MyISAM
format with ALTER TABLE tbl_name
TYPE=MyISAM
or the Perl script mysql_convert_table_format
.
tis620
character set must be fixed
with myisamchk -r
or REPAIR TABLE
.
german
character sort order for ISAM
tables, you must repair them with isamchk -r
, because we have made
some changes in the sort order.
Client Program Changes:
mysql
is by default started with the
--no-named-commands (-g)
option. 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. Long format commands still work from the first line.
mysqldump
files to be compatible between
MySQL 3.22 and 3.23, you should not use the
--opt
or --all
option to mysqldump
.
SQL Changes:
DROP DATABASE
on a symbolically linked database, both the
link and the original database are deleted. This didn't happen in MySQL 3.22
because configure
didn't detect the availability of the
readlink()
system call.
OPTIMIZE TABLE
works only for MyISAM
tables.
For other table types, you can use ALTER TABLE
to optimize the table.
During OPTIMIZE TABLE
, the table is locked to prevent it from being
used by other threads.
MONTH()
) will
return 0 for 0000-00-00
dates. In MySQL 3.22, these functions returned
NULL
.
IF()
depends on both arguments,
not just the first one.
AUTO_INCREMENT
columns should not be used to store negative
numbers. The reason for this is that negative numbers caused problems
when wrapping from -1 to 0. You should not store 0 in AUTO_INCREMENT
columns, either; CHECK TABLE
will complain about 0 values because
they may change if you dump and restore the table. AUTO_INCREMENT
for MyISAM
tables is handled at a lower level and is much
faster than before. In addition, for MyISAM
tables, old numbers
are not reused, even if you delete rows from the table.
CASE
, DELAYED
, ELSE
, END
, FULLTEXT
,
INNER
, RIGHT
, THEN
, and WHEN
are reserved words.
FLOAT(p)
is a true floating-point type and not a value with a
fixed number of decimals.
DECIMAL(length,dec)
type, the
length
argument no longer includes a place for the sign or the
decimal point.
TIME
string must be of one of the following formats:
[[[DAYS] [H]H:]MM:]SS[.fraction]
or
[[[[[H]H]H]H]MM]SS[.fraction]
.
LIKE
compares strings using the same character comparison rules
as for the =
operator. If you require the old behavior, you can
compile MySQL with the CXXFLAGS=-DLIKE_CMP_TOUPPER
flag.
REGEXP
is case insensitive if neither of the strings is a binary
string.
MyISAM
(`.MYI') tables, you should use
the CHECK TABLE
statement or the myisamchk
command. For
ISAM
(`.ISM') tables, use the isamchk
command.
DATE_FORMAT()
to make sure that there is a
`%' before each format character.
SELECT DISTINCT ...
was
almost always sorted. In MySQL 3.23, you must use GROUP BY
or
ORDER BY
to obtain sorted output.
SUM()
returns NULL
instead of 0 if
there are no matching rows. This is required by standard SQL.
AND
or OR
with NULL
values will return
NULL
instead of 0. This mostly affects queries that use NOT
on an AND/OR
expression as NOT NULL
= NULL
.
LPAD()
and RPAD()
shorten the result string if it's longer
than the length argument.
C API Changes:
mysql_fetch_fields_direct()
is a function instead of a macro.
It returns a pointer to a MYSQL_FIELD
instead of a
MYSQL_FIELD
.
mysql_num_fields()
cannot be used on a MYSQL*
object (it's
a function that takes a MYSQL_RES*
value as an argument). With a
MYSQL*
object, you should use mysql_field_count()
instead.
Nothing that affects compatibility has changed between versions 3.21 and 3.22.
The only pitfall is that new tables that are created with DATE
type
columns will use the new way to store the date. You can't access these new
columns from an old version of mysqld
.
When upgrading to MySQL 3.23 from an earlier version, note the following changes:
mysql_fix_privilege_tables
script. This will add the
new privileges that you need to use the GRANT
command. If you forget
this, you will get Access denied
when you try to use ALTER
TABLE
, CREATE INDEX
, or DROP INDEX
. The procedure for updating
the grant tables is described in section 2.10.7 Upgrading the Grant Tables.
mysql_real_connect()
has changed. If you have
an old client program that calls this function, you must pass a 0
for
the new db
argument (or recode the client to send the db
element for faster connections). You must also call mysql_init()
before calling mysql_real_connect()
. This change was done to allow
the new mysql_options()
function to save options in the MYSQL
handler structure.
mysqld
variable key_buffer
has been renamed to
key_buffer_size
, but you can still use the old name in your
startup files.
If you are running a version older than Version 3.20.28 and want to switch to Version 3.21, you need to do the following:
You can start the mysqld
Version 3.21 server with the
--old-protocol
option to use it with clients from a Version 3.20
distribution. In this case, the server uses the old pre-3.21
password()
checking rather than the new method. Also, the new client
function mysql_errno()
will not return any server error, only
CR_UNKNOWN_ERROR
. The function does work for client errors.
If you are not using the --old-protocol
option to
mysqld
, you will need to make the following changes:
scripts/add_long_password
script must be run to convert the
Password
field in the mysql.user
table to CHAR(16)
.
mysql.user
table to get 62-bit
rather than 31-bit passwords.
MySQL 3.20.28 and above can handle the new user
table
format without affecting clients. If you have a MySQL version earlier
than 3.20.28, passwords will no longer work with it if you convert the
user
table. So to be safe, you should first upgrade to at least Version
3.20.28 and then upgrade to Version 3.21.
The new client code works with a 3.20.x mysqld
server, so
if you experience problems with 3.21.x, you can use the old 3.20.x server
without having to recompile the clients again.
If you are not using the --old-protocol
option to mysqld
,
old clients will be unable to connect and will issue the following error
message:
ERROR: Protocol mismatch. Server Version = 10 Client Version = 9
The Perl DBI interface also supports the old
mysqlperl
interface. The only change you have to make if you use
mysqlperl
is to change the arguments to the connect()
function.
The new arguments are: host
, database
, user
,
and password
(note that the user
and password
arguments
have changed places).
The following changes may affect queries in old applications:
HAVING
must be specified before any ORDER BY
clause.
LOCATE()
have been swapped.
DATE
,
TIME
, and TIMESTAMP
.
Some releases introduce changes to the structure of the grant tables
(the tables in the mysql
database)
to add new privileges or features. To make sure that your grant tables
are current when you update to a new version of MySQL, you should update
your grant tables as well.
On Unix or Unix-like systems, update the grant tables by running the
mysql_fix_privilege_tables
script:
shell> mysql_fix_privilege_tables
You must run this script while the server is running. It attempts to
connect to the server running on the local host as root
.
If your root
account requires a password, indicate the password
on the command line. For MySQL 4.1 and up, specify the password like this:
shell> mysql_fix_privilege_tables --password=root_password
Prior to MySQL 4.1, specify the password like this:
shell> mysql_fix_privilege_tables root_password
The mysql_fix_privilege_tables
script performs any actions
necessary to convert your grant tables to the current format. You
might see some Duplicate column name
warnings as it runs; you can
ignore them.
After running the script, stop the server and restart it.
On Windows systems, there isn't an easy way to update the grant tables
until MySQL 4.0.15. From version 4.0.15 on, MySQL distributions include a
`mysql_fix_privilege_tables.sql' SQL script that you can run using
the mysql
client. If your MySQL installation is located at
`C:\mysql', the commands look like this:
C:\> C:\mysql\bin\mysql -u root -p mysql mysql> SOURCE C:\mysql\scripts\mysql_fix_privilege_tables.sql
If your installation is located in some other directory, adjust the pathnames appropriately.
The mysql
command will prompt you for the root
password; enter it
when prompted.
As with the Unix procedure, you might see some Duplicate column name
warnings as mysql
processes the statements in the
`mysql_fix_privilege_tables.sql' script; you can ignore them.
After running the script, stop the server and restart it.
If you are upgrading to MySQL 5.0.1 or later, the grant table upgrade
procedure just described will add view-related columns for the
CREATE VIEW
and SHOW VIEW
privileges. These privileges
exist at the global and database levels. Their initial values are assigned
as follows:
mysql_fix_privilege_tables
copies the Create_priv
value in the user
table to the
Create_view_priv
and Show_view_priv
columns.
GRANT
to give them to accounts
that should have them. To deal with this, first connect to the server as
root
and issue the following statements to give the privileges to
the root
accounts manually with UPDATE
:
mysql> UPDATE mysql.user SET Show_view_priv = 'Y', Create_view_priv = 'Y' -> WHERE User = 'root'; mysql> FLUSH PRIVILEGES;After this,
root
can use GRANT
to give the view privileges
to other accounts. Note: You should issue the statements just shown,
GRANT ALL
will not work at the global and database levels, because
GRANT ALL
requires that you actually possess all privileges.
If you are using MySQL 3.23 or later, you can copy the `.frm',
`.MYI', and `.MYD' files for MyISAM
tables between different
architectures that support the same floating-point format. (MySQL takes care
of any byte-swapping issues.)
See section 14.1 The MyISAM
Storage Engine.
The MySQL ISAM
data and index files (`.ISD' and `*.ISM',
respectively) are architecture dependent and in some cases operating
system dependent. If you want to move your applications to another
machine that has a different architecture or operating system than your
current machine, you should not try to move a database by simply copying
the files to the other machine. Use mysqldump
instead.
By default, mysqldump
will create a file containing SQL statements.
You can then transfer the file to the other machine and feed it as input
to the mysql
client.
Try mysqldump --help
to see what options are available.
If you are moving the data to a newer version of MySQL, you should use
mysqldump --opt
to take advantage of any optimizations that result
in a dump file that is smaller and can be processed faster.
The easiest (although not the fastest) way to move a database between two machines is to run the following commands on the machine on which the database is located:
shell> mysqladmin -h 'other_hostname' create db_name shell> mysqldump --opt db_name | mysql -h 'other_hostname' db_name
If you want to copy a database from a remote machine over a slow network, you can use:
shell> mysqladmin create db_name shell> mysqldump -h 'other_hostname' --opt --compress db_name | mysql db_name
You can also store the result in a file, then transfer the file to the target machine and load the file into the database there. For example, you can dump a database to a file on the source machine like this:
shell> mysqldump --quick db_name | gzip > db_name.contents.gz
(The file created in this example is compressed.) Transfer the file containing the database contents to the target machine and run these commands there:
shell> mysqladmin create db_name shell> gunzip < db_name.contents.gz | mysql db_name
You can also use mysqldump
and mysqlimport
to transfer
the database.
For big tables, this is much faster than simply using mysqldump
.
In the following commands, DUMPDIR
represents the full pathname
of the directory you use to store the output from mysqldump
.
First, create the directory for the output files and dump the database:
shell> mkdir DUMPDIR shell> mysqldump --tab=DUMPDIR db_name
Then transfer the files in the DUMPDIR
directory to some corresponding
directory on the target machine and load the files into MySQL
there:
shell> mysqladmin create db_name # create database shell> cat DUMPDIR/*.sql | mysql db_name # create tables in database shell> mysqlimport db_name DUMPDIR/*.txt # load data into tables
Also, don't forget to copy the mysql
database because that is
where the user
, db
, and host
grant tables are stored.
You might have to run commands as the MySQL root
user on the new
machine until you have the mysql
database in place.
After you import the mysql
database on the new machine, execute
mysqladmin flush-privileges
so that the server reloads the grant table
information.
This section describes what you should do if you are downgrading to an older MySQL version in the unlikely case that the previous version worked better than the new one.
If you are downgrading within the same release series (for example, from 4.0.20 to 4.0.19) the general rule is that you just have to install the new binaries on top of the old ones. There is no need to do anything with the databases. As always, however, it's always a good idea to make a backup.
The following items form a checklist of things you should do whenever you perform an downgrade:
You can always move the MySQL format files and data files between different versions on the same architecture as long as you stay within versions for the same release series of MySQL. The current production release series is 4.1.
If you downgrade from one release series to another, there may be
incompatibilities in table storage formats. In this case, you can use
mysqldump
to dump your tables before dowgnrading. After
downgrading, reload the dump file using mysql
or mysqlimport
to re-create your tables. See section 2.10.8 Copying MySQL Databases to Another Machine for examples.
The normal symptom of a downward-incompatible table format change when you downgrade is that you can't open tables. In that case, use the following procedure:
mysqldump
to create a dump file.
The table format in 4.1 changed to include more and new character set
information. Because of this, you must use mysqldump
to dump any tables
you have created with the newer MySQL server. For example, if all the tables
in a particular database need to be dumped to be reverted back to MySQL 4.0
format, use this command:
shell> mysqldump --create-options --compatible=mysql40 db_name > dump_file
Then stop the newer server, restart the older server, and read in the dump file:
shell> mysql db_name < dump_file
In the special case that you're downgrading MyISAM
tables, no special
treatment is necessary if all columns in the tables contain only numeric
columns or string columns (CHAR
, VARCHAR
, TEXT
, and so
forth) that contain only latin1
data. Your
4.1 tables should be directly usable with a 4.0 server.
If you used the mysql_fix_privilege_tables
script to upgrade the
grant tables, you can either use the preceding method to convert them to back to
MySQL 4.0 or do the following in MySQL 4.1 (or above):
ALTER TABLE mysql.user CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci; ALTER TABLE mysql.db CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci; ALTER TABLE mysql.host CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci; ALTER TABLE mysql.tables_priv CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci; ALTER TABLE mysql.columns_priv CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci; ALTER TABLE mysql.func CONVERT TO CHARACTER SET latin1 COLLATE latin1_swedish_ci;
This section discusses issues that have been found to occur on Linux. The first few subsections describe general operating system-related issues, problems that can occur when using binary or source distributions, and post-installation issues. The remaining subsections discuss problems that occur with Linux on specific platforms.
Note that most of these problems occur on older versions of Linux. If you are running a recent version, you likely will see none of them.
MySQL needs at least Linux Version 2.0.
Warning: We have seen some strange problems with Linux 2.2.14 and MySQL on SMP systems. We also have reports from some MySQL users that they have encountered serious stability problems using MySQL with kernel 2.2.14. If you are using this kernel, you should upgrade to 2.2.19 (or newer) or to a 2.4 kernel. If you have a multiple-CPU box, then you should seriously consider using 2.4 because it will give you a significant speed boost. Your system also will be more stable.
When using LinuxThreads, you will see a minimum of three mysqld
processes
running. These are in fact threads. There will be one thread for the
LinuxThreads manager, one thread to handle connections, and one thread
to handle alarms and signals.
The Linux-Intel binary and RPM releases of MySQL are configured for the highest possible speed. We are always trying to use the fastest stable compiler available.
The binary release is linked with -static
, which means you do not
normally need to worry about which version of the system libraries you
have. You need not install LinuxThreads, either. A program linked with
-static
is slightly larger than a dynamically linked program,
but also slightly faster (3-5%). However, one problem with a statically
linked program is that you can't use user-defined functions (UDFs).
If you are going to write or use UDFs (this is something for C or C++
programmers only), you must compile MySQL yourself using dynamic linking.
A known issue with binary distributions is that on older Linux
systems that use libc
(such as Red Hat 4.x or Slackware), you will get
some non-fatal problems with hostname resolution. If your system uses
libc
rather than glibc2
,
you probably will encounter some difficulties with hostname resolution and
getpwnam()
. This happens because glibc
unfortunately depends on some external libraries to implement hostname
resolution and getpwent()
, even when compiled with -static
.
These problems manifest themselves in two ways:
mysql_install_db
:
Sorry, the host 'xxxx' could not be looked upYou can deal with this by executing
mysql_install_db --force
, which will not execute the
resolveip
test in mysql_install_db
. The downside is that
you can't use hostnames in the grant tables: Except for localhost
,
you must use IP numbers instead. If you are using an old version of MySQL
that doesn't support --force
, you must manually remove the
resolveip
test in mysql_install
using an editor.
mysqld
with the --user
option:
getpwnam: No such file or directoryTo work around this, start
mysqld
by using
the su
command rather than by specifying the --user
option. This causes the system itself to change the user ID of the
mysqld
process so that mysqld
need not do so.
Another solution, which solves both problems, is to not use a binary
distribution. Get a MySQL source distribution (in RPM or tar.gz
format) and install that instead.
On some Linux 2.2 versions, you may get the error Resource
temporarily unavailable
when clients make a lot of new connections to
a mysqld
server over TCP/IP. The problem is that Linux has a
delay between the time that you close a TCP/IP socket and the time that
the system actually frees it. There is room for only a finite number
of TCP/IP slots, so you will encounter the resource-unavailable error if
clients attempt too many new TCP/IP connections during a short time. For
example, you may see the error when you run the MySQL `test-connect'
benchmark over TCP/IP.
We have inquired about this problem a few times on different Linux mailing lists but have never been able to find a suitable resolution. The only known ``fix'' is for the clients to use persistent connections, or, if you are running the database server and clients on the same machine, to use Unix socket file connections rather than TCP/IP connections.
The following notes regarding glibc
apply only to the situation
when you build MySQL
yourself. If you are running Linux on an x86 machine, in most cases it is
much better for you to just use our binary. We link our binaries against
the best patched version of glibc
we can come up with and with the
best compiler options, in an attempt to make it suitable for a high-load
server. For a typical user, even for setups with a lot of concurrent
connections or tables exceeding the 2GB limit, our binary is
the best choice in most cases. After reading the following text, if you
are in doubt about what to do, try our binary first to see whether it meets
your needs. If you discover that it is not good enough, then
you may want to try your own build. In that case, we would appreciate
a note about it so that we can build a better binary next time.
MySQL uses LinuxThreads on Linux. If you are using an old
Linux version that doesn't have glibc2
, you must install
LinuxThreads before trying to compile MySQL. You can get
LinuxThreads at http://dev.mysql.com/downloads/os-linux.html.
Note that glibc
versions before and including Version 2.1.1 have
a fatal bug in pthread_mutex_timedwait()
handling, which is used
when you issue INSERT DELAYED
statements. We recommend that you not use
INSERT DELAYED
before upgrading glibc
.
Note that Linux kernel and the LinuxThread library can by default only have 1,024 threads. If you plan to have more than 1,000 concurrent connections, you will need to make some changes to LinuxThreads:
PTHREAD_THREADS_MAX
in
`sysdeps/unix/sysv/linux/bits/local_lim.h' to 4096 and decrease
STACK_SIZE
in `linuxthreads/internals.h' to 256KB. The
paths are relative to the root of glibc
. (Note that MySQL will
not be stable with around 600-1000 connections if STACK_SIZE
is the default of 2MB.)
The page http://www.volano.com/linuxnotes.html contains additional information about circumventing thread limits in LinuxThreads.
There is another issue that greatly hurts MySQL performance, especially on
SMP systems. The mutex implementation in LinuxThreads in glibc
2.1 is very bad for programs with many threads that hold the mutex
only for a short time. This produces a paradoxical result: If you link
MySQL against an unmodified LinuxThreads, removing processors from an
SMP actually improves MySQL performance in many cases. We have made a
patch available for glibc
2.1.3 to correct this behavior
(http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch).
With glibc
2.2.2,
MySQL 3.23.36 will use the adaptive mutex, which is much
better than even the patched one in glibc
2.1.3. Be warned, however,
that under some conditions, the current mutex code in glibc
2.2.2
overspins, which hurts MySQL performance. The likelihood that this condition
will occur can be reduced by renicing the mysqld
process to the highest
priority. We have also been able to correct the overspin behavior with
a patch, available at
http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch.
It combines the correction of overspin, maximum number of
threads, and stack spacing all in one. You will need to apply it in the
linuxthreads
directory with
patch -p0 </tmp/linuxthreads-2.2.2.patch
.
We hope it will be included in
some form in future releases of glibc
2.2. In any case, if
you link against glibc
2.2.2, you still need to correct
STACK_SIZE
and PTHREAD_THREADS_MAX
. We hope that the defaults
will be corrected to some more acceptable values for high-load
MySQL setup in the future, so that the commands needed to produce
your own build can be reduced to ./configure; make; make install
.
We recommend that you use these patches to build a special static
version of libpthread.a
and use it only for statically linking
against MySQL. We know that the patches are safe for MySQL
and significantly improve its performance, but we cannot say anything
about other applications. If you link other applications that require
LinuxThreads against the
patched static version of the library, or build a patched shared version and
install it on your system, you do so at your own risk.
If you experience any strange problems during the installation of MySQL, or with some common utilities hanging, it is very likely that they are either library or compiler related. If this is the case, using our binary will resolve them.
If you link your own MySQL client programs, you may see the following error at runtime:
ld.so.1: fatal: libmysqlclient.so.#: open failed: No such file or directory
This problem can be avoided by one of the following methods:
-Wl,r/full/path/to/libmysqlclient.so
flag rather than with -Lpath
).
libmysqclient.so
to `/usr/lib'.
LD_RUN_PATH
environment variable before running your client.
If you are using the Fujitsu compiler (fcc/FCC
), you will have
some problems compiling MySQL because the Linux header files are very
gcc
oriented.
The following configure
line should work with fcc/FCC
:
CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE \ -DCONST=const -DNO_STRTOLL_PROTO" \ CXX=FCC CXXFLAGS="-O -K fast -K lib \ -K omitfp -K preex --no_exceptions --no_rtti -D_GNU_SOURCE \ -DCONST=const -Dalloca=__builtin_alloca -DNO_STRTOLL_PROTO \ '-D_EXTERN_INLINE=static __inline'" \ ./configure \ --prefix=/usr/local/mysql --enable-assembler \ --with-mysqld-ldflags=-all-static --disable-shared \ --with-low-memory
mysql.server
can be found in the `support-files' directory under
the MySQL installation directory or in a MySQL source tree. You can install
it as `/etc/init.d/mysql' for automatic MySQL startup and shutdown.
See section 2.9.2.2 Starting and Stopping MySQL Automatically.
If MySQL can't open enough files or connections, it may be that you haven't configured Linux to handle enough files.
In Linux 2.2 and onward, you can check the number of allocated file handles as follows:
shell> cat /proc/sys/fs/file-max shell> cat /proc/sys/fs/dquot-max shell> cat /proc/sys/fs/super-max
If you have more than 16MB of memory, you should add something like the following to your init scripts (for example, `/etc/init.d/boot.local' on SuSE Linux):
echo 65536 > /proc/sys/fs/file-max echo 8192 > /proc/sys/fs/dquot-max echo 1024 > /proc/sys/fs/super-max
You can also run the echo
commands from the command line as root
,
but these settings will be lost the next time your computer restarts.
Alternatively, you can set these parameters on startup by using the
sysctl
tool, which is used by many Linux distributions (SuSE has
added it as well, beginning with SuSE Linux 8.0). Just put the following
values into a file named `/etc/sysctl.conf':
# Increase some values for MySQL fs.file-max = 65536 fs.dquot-max = 8192 fs.super-max = 1024
You should also add the following to `/etc/my.cnf':
[mysqld_safe] open-files-limit=8192
This should allow the server a limit of 8,192 for the combined number of connections and open files.
The STACK_SIZE
constant in LinuxThreads controls the spacing of thread
stacks in the address space. It needs to be large enough so that there will
be plenty of room for each individual thread stack, but small enough
to keep the stack of some threads from running into the global mysqld
data. Unfortunately, as we have experimentally discovered, the Linux
implementation of mmap()
will successfully unmap a mapped
region if you ask it to map out an address currently in use, zeroing out the data
on the entire page instead of returning an error. So, the safety of
mysqld
or any other threaded application depends on ``gentlemanly''
behavior of the code that creates threads. The user must take measures to
make sure that the number of running threads at any time is sufficiently low for
thread stacks to stay away from the global heap. With mysqld
, you
should enforce this behavior by setting a reasonable value for
the max_connections
variable.
If you build MySQL yourself, you can patch LinuxThreads for better stack use.
See section 2.12.1.3 Linux Source Distribution Notes.
If you do not want to patch
LinuxThreads, you should set max_connections
to a value no higher
than 500. It should be even less if you have a large key buffer, large
heap tables, or some other things that make mysqld
allocate a lot
of memory, or if you are running a 2.2 kernel with a 2GB patch. If you are
using our binary or RPM version 3.23.25 or later, you can safely set
max_connections
at 1500, assuming no large key buffer or heap tables
with lots of data. The more you reduce STACK_SIZE
in LinuxThreads
the more threads you can safely create. We recommend values between
128KB and 256KB.
If you use a lot of concurrent connections, you may suffer from a ``feature'' in the 2.2 kernel that attempts to prevent fork bomb attacks by penalizing a process for forking or cloning a child. This causes MySQL not to scale well as you increase the number of concurrent clients. On single-CPU systems, we have seen this manifested as very slow thread creation: It may take a long time to connect to MySQL (as long as one minute), and it may take just as long to shut it down. On multiple-CPU systems, we have observed a gradual drop in query speed as the number of clients increases. In the process of trying to find a solution, we have received a kernel patch from one of our users who claimed it made a lot of difference for his site. The patch is available at http://www.mysql.com/Downloads/Patches/linux-fork.patch. We have done rather extensive testing of this patch on both development and production systems. It has significantly improved MySQL performance without causing any problems and we recommend it to our users who still run high-load servers on 2.2 kernels.
This issue has been fixed in the 2.4 kernel, so if you are not satisfied with the current performance of your system, rather than patching your 2.2 kernel, it might be easier to upgrade to 2.4. On SMP systems, upgrading also will give you a nice SMP boost in addition to fixing the fairness bug.
We have tested MySQL on the 2.4 kernel on a two-CPU machine and found MySQL scales much better. There was virtually no slowdown on query throughput all the way up to 1,000 clients, and the MySQL scaling factor (computed as the ratio of maximum throughput to the throughput for one client) was 180%. We have observed similar results on a four-CPU system: Virtually no slowdown as the number of clients was increased up to 1,000, and a 300% scaling factor. Based on these results, for a high-load SMP server using a 2.2 kernel, we definitely recommend upgrading to the 2.4 kernel at this point.
We have discovered that it is essential to run the mysqld
process
with the highest possible priority on the 2.4 kernel to achieve maximum
performance. This can be done by adding a renice -20 $$
command
to mysqld_safe
. In our testing on a four-CPU machine, increasing
the priority resulted in a 60% throughput increase with 400 clients.
We are currently also trying to collect more information on how well MySQL performs with a 2.4 kernel on four-way and eight-way systems. If you have access such a system and have done some benchmarks, please send an email message to benchmarks@mysql.com with the results. We will review them for inclusion in the manual.
If you see a dead mysqld
server process with ps
, this usually
means that you have found a bug in MySQL or you have a corrupted
table. See section A.4.2 What to Do If MySQL Keeps Crashing.
To get a core dump on Linux if mysqld
dies with a SIGSEGV
signal,
you can start mysqld
with the --core-file
option. Note
that you also probably need to raise the core file size by adding
ulimit -c 1000000
to mysqld_safe
or starting
mysqld_safe
with --core-file-size=1000000
.
See section 5.1.3 The mysqld_safe
Server Startup Script.
MySQL requires libc
Version 5.4.12 or newer. It's known to
work with libc
5.4.46. glibc
Version 2.0.6 and later should
also work. There have been some problems with the glibc
RPMs from
Red Hat, so if you have problems, check whether there are any updates.
The glibc
2.0.7-19 and 2.0.7-29 RPMs are known to work.
If you are using Red Hat 8.0 or a new glibc
2.2.x library, you may see
mysqld
die in gethostbyaddr()
. This happens because the new
glibc
library requires a stack size greater than 128KB for this call.
To fix the problem, start mysqld
with the --thread-stack=192K
option. (Use -O thread_stack=192K
before MySQL 4.)
This stack size is the default on MySQL 4.0.10 and above, so you should
not see the problem.
If you are using gcc
3.0 and above to compile MySQL, you must install
the libstdc++v3
library before compiling MySQL; if you don't do
this, you will get an error about a missing __cxa_pure_virtual
symbol during linking.
On some older Linux distributions, configure
may produce an error
like this:
Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual.
Just do what the error message says. Add an extra underscore to the
_P
macro name that has only one underscore, then try again.
You may get some warnings when compiling. Those shown here can be ignored:
mysqld.cc -o objs-thread/mysqld.o mysqld.cc: In function `void init_signals()': mysqld.cc:315: warning: assignment of negative value `-1' to `long unsigned int' mysqld.cc: In function `void * signal_hand(void *)': mysqld.cc:346: warning: assignment of negative value `-1' to `long unsigned int'
If mysqld
always dumps core when it starts, the problem may be that
you have an old `/lib/libc.a'. Try renaming it, then remove
`sql/mysqld' and do a new make install
and try again. This
problem has been reported on some Slackware installations.
If you get the following error when linking mysqld
,
it means that your `libg++.a' is not installed correctly:
/usr/lib/libc.a(putc.o): In function `_IO_putc': putc.o(.text+0x0): multiple definition of `_IO_putc'
You can avoid using `libg++.a' by running configure
like this:
shell> CXX=gcc ./configure
If mysqld
crashes immediately and you are running Red Hat Version 5.0
with a version of glibc
older than 2.0.7-5, you should make sure that
you have installed all glibc
patches. There is a lot of information
about this in the MySQL mail archives, available online at
http://lists.mysql.com/.
In some implementations, readdir_r()
is broken. The symptom is
that the SHOW DATABASES
statement always returns an empty set.
This can be fixed by removing HAVE_READDIR_R
from `config.h'
after configuring and before compiling.
MySQL 3.23.12 is the first MySQL version that is tested on Linux-Alpha. If you plan to use MySQL on Linux-Alpha, you should ensure that you have this version or newer.
We have tested MySQL on Alpha with our benchmarks and test suite, and it appears to work nicely.
We currently build the MySQL binary packages on SuSE Linux 7.0 for AXP, kernel 2.4.4-SMP, Compaq C compiler (V6.2-505) and Compaq C++ compiler (V6.3-006) on a Compaq DS20 machine with an Alpha EV6 processor.
You can find the preceding compilers at
http://www.support.compaq.com/alpha-tools/. By using these compilers
rather than gcc
, we get about 9-14% better MySQL performance.
Note that until MySQL version 3.23.52 and 4.0.2, we optimized the binary for
the current CPU only (by using the -fast
compile option). This means
that for older versions, you can use our Alpha binaries only if you have an
Alpha EV6 processor.
For all following releases, we added the -arch generic
flag
to our compile options, which makes sure that the binary runs on all Alpha
processors. We also compile statically to avoid library problems.
The configure
command looks like this:
CC=ccc CFLAGS="-fast -arch generic" CXX=cxx \ CXXFLAGS="-fast -arch generic -noexceptions -nortti" \ ./configure --prefix=/usr/local/mysql --disable-shared \ --with-extra-charsets=complex --enable-thread-safe-client \ --with-mysqld-ldflags=-non_shared --with-client-ldflags=-non_shared
If you want to use egcs
, the following configure
line worked
for us:
CFLAGS="-O3 -fomit-frame-pointer" CXX=gcc \ CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql --disable-shared
Some known problems when running MySQL on Linux-Alpha:
gdb 4.18
. You should use gdb
5.1 instead.
mysqld
statically when using gcc
, the
resulting image will dump core at startup time. In other words, do not
use --with-mysqld-ldflags=-all-static
with gcc
.
MySQL should work on MkLinux with the newest glibc
package
(tested with glibc
2.0.7).
To get MySQL to work on Qube2 (Linux Mips), you need the
newest glibc
libraries. glibc-2.0.7-29C2
is known to
work. You must also use the egcs
C++ compiler
(egcs
1.0.2-9, gcc
2.95.2 or newer).
To get MySQL to compile on Linux IA-64, we use the following configure
command for building with gcc
2.96:
CC=gcc \ CFLAGS="-O3 -fno-omit-frame-pointer" \ CXX=gcc \ CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql \ "--with-comment=Official MySQL binary" \ --with-extra-charsets=complex
On IA-64, the MySQL client binaries use shared libraries. This means
that if you install our binary distribution at a location other than
`/usr/local/mysql', you need to add the path of the directory
where you have `libmysqlclient.so' installed either to the
`/etc/ld.so.conf' file or to the value of your LD_LIBRARY_PATH
environment variable.
See section A.3.1 Problems Linking to the MySQL Client Library.
On Mac OS X, tar
cannot handle long filenames. If you need to unpack a
`.tar.gz' distribution, use gnutar
instead.
MySQL should work without any problems on Mac OS X 10.x (Darwin).
Our binary for Mac OS X is compiled on Darwin 6.3 with the following
configure
line:
CC=gcc CFLAGS="-O3 -fno-omit-frame-pointer" CXX=gcc \ CXXFLAGS="-O3 -fno-omit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql \ --with-extra-charsets=complex --enable-thread-safe-client \ --enable-local-infile --disable-shared
See section 2.5 Installing MySQL on Mac OS X.
For current versions of Mac OS X Server, no operating system changes are necessary before compiling MySQL. Compiling for the Server platform is the same as for the client version of Mac OS X. (However, note that MySQL comes preinstalled on Mac OS X Server, so you need not build it yourself.)
For older versions (Mac OS X Server 1.2, a.k.a. Rhapsody), you must first install a pthread package before trying to configure MySQL.
See section 2.5 Installing MySQL on Mac OS X.
On Solaris, you may run into trouble even before you get the MySQL
distribution unpacked! Solaris tar
can't handle long filenames, so
you may see an error like this when you unpack MySQL:
x mysql-3.22.12-beta/bench/Results/ATIS-mysql_odbc-NT_4.0-cmp-db2, informix,ms-sql,mysql,oracle,solid,sybase, 0 bytes, 0 tape blocks tar: directory checksum error
In this case, you must use GNU tar
(gtar
) to unpack the
distribution. You can find a precompiled copy for Solaris at
http://dev.mysql.com/downloads/os-solaris.html.
Sun native threads work only on Solaris 2.5 and higher. For Version 2.4 and earlier, MySQL automatically uses MIT-pthreads. See section 2.8.5 MIT-pthreads Notes.
If you get the following error from configure
,
it means that you have something wrong with your compiler installation:
checking for restartable system calls... configure: error can not run test programs while cross compiling
In this case, you should upgrade your compiler to a newer version. You may also be able to solve this problem by inserting the following row into the `config.cache' file:
ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
If you are using Solaris on a SPARC, the recommended compiler is
gcc
2.95.2 or 3.2. You can find this at http://gcc.gnu.org/.
Note that egcs
1.1.1 and gcc
2.8.1 don't work reliably on
SPARC!
The recommended configure
line when using gcc
2.95.2 is:
CC=gcc CFLAGS="-O3" \ CXX=gcc CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql --with-low-memory \ --enable-assembler
If you have an UltraSPARC system, you can get 4% better performance by adding
-mcpu=v8 -Wa,-xarch=v8plusa
to the CFLAGS
and CXXFLAGS
environment variables.
If you have Sun's Forte 5.0 (or newer) compiler, you can
run configure
like this:
CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt" \ CXX=CC CXXFLAGS="-noex -mt" \ ./configure --prefix=/usr/local/mysql --enable-assembler
To create a 64-bit binary with Sun's Forte compiler, use the following configuration options:
CC=cc CFLAGS="-Xa -fast -native -xstrconst -mt -xarch=v9" \ CXX=CC CXXFLAGS="-noex -mt -xarch=v9" ASFLAGS="-xarch=v9" \ ./configure --prefix=/usr/local/mysql --enable-assembler
To create a 64-bit Solaris binary using gcc
, add -m64
to
CFLAGS
and CXXFLAGS
and remove --enable-assembler
from
the configure
line. This works only with MySQL
4.0 and up; MySQL 3.23 does not include the required modifications to
support this.
In the MySQL benchmarks, we got a 4% speedup on an UltraSPARC when using
Forte 5.0 in 32-bit mode compared to using gcc
3.2 with the -mcpu
flag.
If you create a 64-bit mysqld
binary, it is 4% slower than the 32-bit
binary, but can handle more threads and memory.
If you get a problem with fdatasync
or sched_yield
,
you can fix this by adding LIBS=-lrt
to the configure
line
For compilers older than WorkShop 5.3, you might have to edit the
configure
script. Change this line:
#if !defined(__STDC__) || __STDC__ != 1
To this:
#if !defined(__STDC__)
If you turn on __STDC__
with the -Xc
option, the Sun compiler
can't compile with the Solaris `pthread.h' header file. This is a Sun
bug (broken compiler or broken include file).
If mysqld
issues the following error message when you run it, you have
tried to compile MySQL with the Sun compiler without enabling the -mt
multi-thread option:
libc internal error: _rmutex_unlock: rmutex not held
Add -mt
to CFLAGS
and CXXFLAGS
and recompile.
If you are using the SFW version of gcc
(which comes with Solaris 8),
you must add `/opt/sfw/lib' to the environment variable
LD_LIBRARY_PATH
before running configure
.
If you are using the gcc
available from sunfreeware.com
, you may
have many problems. To avoid this, you should recompile gcc
and GNU
binutils
on the machine where you will be running them.
If you get the following error when compiling MySQL with gcc
,
it means that your gcc
is not configured for your version of Solaris:
shell> gcc -O3 -g -O2 -DDBUG_OFF -o thr_alarm ... ./thr_alarm.c: In function `signal_hand': ./thr_alarm.c:556: too many arguments to function `sigwait'
The proper thing to do in this case is to get the newest version of
gcc
and compile it with your current gcc
compiler. At
least for Solaris 2.5, almost all binary versions of gcc
have
old, unusable include files that will break all programs that use
threads, and possibly other programs!
Solaris doesn't provide static versions of all system libraries
(libpthreads
and libdl
), so you can't compile MySQL
with --static
. If you try to do so, you will get one of the following
errors:
ld: fatal: library -ldl: not found undefined reference to `dlopen' cannot find -lrt
If you link your own MySQL client programs, you may see the following error at runtime:
ld.so.1: fatal: libmysqlclient.so.#: open failed: No such file or directory
This problem can be avoided by one of the following methods:
-Wl,r/full/path/to/libmysqlclient.so
flag rather than with -Lpath
).
libmysqclient.so
to `/usr/lib'.
LD_RUN_PATH
environment variable before running your client.
If you have problems with configure
trying to link with -lz
when
you don't have zlib
installed, you have two options:
zlib
from ftp.gnu.org
.
configure
with the --with-named-z-libs=no
option when
building MySQL.
If you are using gcc
and have problems with loading user-defined
functions (UDFs) into MySQL, try adding -lgcc
to the link line
for the UDF.
If you would like MySQL to start automatically, you can copy `support-files/mysql.server' to `/etc/init.d' and create a symbolic link to it named `/etc/rc3.d/S99mysql.server'.
If too many processes try to connect very rapidly to mysqld
, you will
see this error in the MySQL log:
Error in accept: Protocol error
You might try starting the server with the --back_log=50
option as a workaround for this. (Use -O back_log=50
before MySQL 4.)
Solaris doesn't support core files for setuid()
applications, so
you can't get a core file from mysqld
if you are using the
--user
option.
Normally, you can use a Solaris 2.6 binary on Solaris 2.7 and 2.8. Most of the Solaris 2.6 issues also apply for Solaris 2.7 and 2.8.
MySQL 3.23.4 and above should be able to detect new versions of Solaris automatically and enable workarounds for the following problems.
Solaris 2.7 / 2.8 has some bugs in the include files. You may see the
following error when you use gcc
:
/usr/include/widec.h:42: warning: `getwc' redefined /usr/include/wchar.h:326: warning: this is the location of the previous definition
If this occurs, you can fix the problem by copying
/usr/include/widec.h
to
.../lib/gcc-lib/os/gcc-version/include
and changing line 41 from this:
#if !defined(lint) && !defined(__lint)
To this:
#if !defined(lint) && !defined(__lint) && !defined(getwc)
Alternatively, you can edit `/usr/include/widec.h' directly. Either
way, after you make the fix, you should remove `config.cache' and run
configure
again.
If you get the following errors when you run make
, it's because
configure
didn't detect the `curses.h' file (probably
because of the error in `/usr/include/widec.h'):
In file included from mysql.cc:50: /usr/include/term.h:1060: syntax error before `,' /usr/include/term.h:1081: syntax error before `;'
The solution to this problem is to do one of the following:
CFLAGS=-DHAVE_CURSES_H CXXFLAGS=-DHAVE_CURSES_H ./configure
.
configure
.
#define HAVE_TERM
line from the `config.h' file and
run make
again.
If your linker can't find -lz
when linking
client programs, the problem is probably that your `libz.so' file is
installed in `/usr/local/lib'. You can fix this problem by one of the
following methods:
LD_LIBRARY_PATH
.
zlib
from your
Solaris 8 CD distribution.
configure
with the --with-named-z-libs=no
option when
building MySQL.
On Solaris 8 on x86, mysqld
will dump core if you remove the
debug symbols using strip
.
If you are using gcc
or egcs
on Solaris x86 and you
experience problems with core dumps under load, you should use the
following configure
command:
CC=gcc CFLAGS="-O3 -fomit-frame-pointer -DHAVE_CURSES_H" \ CXX=gcc \ CXXFLAGS="-O3 -fomit-frame-pointer -felide-constructors \ -fno-exceptions -fno-rtti -DHAVE_CURSES_H" \ ./configure --prefix=/usr/local/mysql
This will avoid problems with the libstdc++
library and with C++
exceptions.
If this doesn't help, you should compile a debug version and run
it with a trace file or under gdb
.
See section E.1.3 Debugging mysqld
under gdb
.
This section provides information about using MySQL on variants of BSD Unix.
FreeBSD 4.x or newer is recommended for running MySQL, because the thread
package is much more integrated.
To get a secure and stable system, you should use only FreeBSD kernels
that are marked -RELEASE
.
The easiest (and preferred) way to install MySQL is to use the
mysql-server
and mysql-client
ports available at
http://www.freebsd.org/.
Using these ports gives you the following benefits:
pkg_info -L
to see which files are installed.
pkg_delete
to remove MySQL if you no longer want it
on your machine.
It is recommended you use MIT-pthreads on FreeBSD 2.x, and native threads on
Versions 3 and up. It is possible to run with native threads on some late
2.2.x versions, but you may encounter problems shutting down mysqld
.
Unfortunately, certain function calls on FreeBSD are not yet fully thread-safe.
Most notably, this includes the gethostbyname()
function, which is
used by MySQL to convert hostnames into IP addresses. Under certain
circumstances, the mysqld
process will suddenly cause 100%
CPU load and will be unresponsive. If you encounter this problem, try to start
MySQL using the --skip-name-resolve
option.
Alternatively, you can link MySQL on FreeBSD 4.x against the LinuxThreads library, which avoids a few of the problems that the native FreeBSD thread implementation has. For a very good comparison of LinuxThreads versus native threads, see Jeremy Zawodny's article FreeBSD or Linux for your MySQL Server? at http://jeremy.zawodny.com/blog/archives/000697.html.
A known problem when using LinuxThreads on FreeBSD is that the
wait_timeout
value is not honored (probably a signal handling problem in
FreeBSD/LinuxThreads). This is supposed to be fixed in FreeBSD 5.0.
The symptom is that persistent connections can hang for a very long
time without getting closed down.
The MySQL build process requires GNU make (gmake
) to work. If
GNU make
is not available, you must install it first before compiling
MySQL.
The recommended way to compile and install MySQL on FreeBSD with
gcc
(2.95.2 and up) is:
CC=gcc CFLAGS="-O2 -fno-strength-reduce" \ CXX=gcc CXXFLAGS="-O2 -fno-rtti -fno-exceptions \ -felide-constructors -fno-strength-reduce" \ ./configure --prefix=/usr/local/mysql --enable-assembler gmake gmake install cd /usr/local/mysql bin/mysql_install_db --user=mysql bin/mysqld_safe &
If you notice that configure
will use MIT-pthreads, you should read
the MIT-pthreads notes. See section 2.8.5 MIT-pthreads Notes.
If you get an error from make install
that it can't find
`/usr/include/pthreads', configure
didn't detect that you need
MIT-pthreads. To fix this problem, remove `config.cache', then re-run
configure
with the --with-mit-threads
option.
Be sure that your name resolver setup is correct. Otherwise, you may
experience resolver delays or failures when connecting to mysqld
.
Also make sure that the localhost
entry in the `/etc/hosts' file is
correct. The file should start with a line similar to this:
127.0.0.1 localhost localhost.your.domain
FreeBSD is known to have a very low default file handle limit.
See section A.2.17 File Not Found. Start the server by using the
--open-files-limit
option for mysqld_safe
, or raise
the limits for the mysqld
user in `/etc/login.conf' and
rebuild it with cap_mkdb /etc/login.conf
. Also be sure that you set
the appropriate class for this user in the password file if you are not
using the default (use chpass mysqld-user-name
).
See section 5.1.3 The mysqld_safe
Server Startup Script.
If you have a lot of memory, you should consider rebuilding
the kernel to allow MySQL to use more than 512MB of RAM.
Take a look at option MAXDSIZ
in the LINT config
file for more information.
If you get problems with the current date in MySQL, setting the
TZ
variable will probably help. See section F Environment Variables.
To compile on NetBSD, you need GNU make
. Otherwise, the build process will
fail when make
tries to run lint
on C++ files.
On OpenBSD Version 2.5, you can compile MySQL with native threads with the following options:
CFLAGS=-pthread CXXFLAGS=-pthread ./configure --with-mit-threads=no
Our users have reported that OpenBSD 2.8 has a threading bug that causes problems with MySQL. The OpenBSD Developers have fixed the problem, but as of January 25, 2001, it's only available in the ``-current'' branch. The symptoms of this threading bug are slow response, high load, high CPU usage, and crashes.
If you get an error like Error in accept:: Bad file descriptor
or
error 9 when trying to open tables or directories, the problem is probably
that you have not allocated enough file descriptors for MySQL.
In this case, try starting mysqld_safe
as root
with the following
options:
mysqld_safe --user=mysql --open-files-limit=2048 &
If you get the following error when compiling MySQL, your
ulimit
value for virtual memory is too low:
item_func.h: In method `Item_func_ge::Item_func_ge(const Item_func_ge &)': item_func.h:28: virtual memory exhausted make[2]: *** [item_func.o] Error 1
Try using ulimit -v 80000
and run make
again. If this
doesn't work and you are using bash
, try switching to csh
or sh
; some BSDI users have reported problems with bash
and ulimit
.
If you are using gcc
, you may also use have to use the
--with-low-memory
flag for configure
to be able to compile
`sql_yacc.cc'.
If you get problems with the current date in MySQL, setting the
TZ
variable will probably help. See section F Environment Variables.
Upgrade to BSD/OS Version 3.1. If that is not possible, install BSDIpatch M300-038.
Use the following command when configuring MySQL:
env CXX=shlicc++ CC=shlicc2 \ ./configure \ --prefix=/usr/local/mysql \ --localstatedir=/var/mysql \ --without-perl \ --with-unix-socket-path=/var/mysql/mysql.sock
The following is also known to work:
env CC=gcc CXX=gcc CXXFLAGS=-O3 \ ./configure \ --prefix=/usr/local/mysql \ --with-unix-socket-path=/var/mysql/mysql.sock
You can change the directory locations if you wish, or just use the defaults by not specifying any locations.
If you have problems with performance under heavy load, try using the
--skip-thread-priority
option to mysqld
! This will run
all threads with the same priority. On BSDI Version 3.1, this gives better
performance, at least until BSDI fixes its thread scheduler.
If you get the error virtual memory exhausted
while compiling,
you should try using ulimit -v 80000
and running make
again.
If this doesn't work and you are using bash
, try switching to
csh
or sh
; some BSDI users have reported problems with
bash
and ulimit
.
BSDI Version 4.x has some thread-related bugs. If you want to use MySQL on this, you should install all thread-related patches. At least M400-023 should be installed.
On some BSDI Version 4.x systems, you may get problems with shared libraries.
The symptom is that you can't execute any client programs, for example,
mysqladmin
. In this case, you need to reconfigure not to use
shared libraries with the --disable-shared
option to configure.
Some customers have had problems on BSDI 4.0.1 that the mysqld
binary after a while can't open tables. This is because some
library/system-related bug causes mysqld
to change current
directory without having asked for that to happen.
The fix is to either upgrade MySQL to at least version 3.23.34 or, after
running configure
, remove the line #define HAVE_REALPATH
from
config.h
before running make
.
Note that this means that you can't symbolically link a database directories to another database directory or symbolic link a table to another database on BSDI. (Making a symbolic link to another disk is okay).
There are a couple of small problems when compiling MySQL on
HP-UX. We recommend that you use gcc
instead of the HP-UX native
compiler, because gcc
produces better code.
We recommend using gcc
2.95 on HP-UX. Don't use high optimization
flags (such as -O6
) because they may not be safe on HP-UX.
The following configure
line should work with gcc
2.95:
CFLAGS="-I/opt/dce/include -fpic" \ CXXFLAGS="-I/opt/dce/include -felide-constructors -fno-exceptions \ -fno-rtti" \ CXX=gcc \ ./configure --with-pthread \ --with-named-thread-libs='-ldce' \ --prefix=/usr/local/mysql --disable-shared
The following configure
line should work with gcc
3.1:
CFLAGS="-DHPUX -I/opt/dce/include -O3 -fPIC" CXX=gcc \ CXXFLAGS="-DHPUX -I/opt/dce/include -felide-constructors \ -fno-exceptions -fno-rtti -O3 -fPIC" \ ./configure --prefix=/usr/local/mysql \ --with-extra-charsets=complex --enable-thread-safe-client \ --enable-local-infile --with-pthread \ --with-named-thread-libs=-ldce --with-lib-ccflags=-fPIC --disable-shared
For HP-UX Version 11.x, we recommend MySQL 3.23.15 or later.
Because of some critical bugs in the standard HP-UX libraries, you should install the following patches before trying to run MySQL on HP-UX 11.0:
PHKL_22840 Streams cumulative PHNE_22397 ARPA cumulative
This will solve the problem of getting EWOULDBLOCK
from recv()
and EBADF
from accept()
in threaded applications.
If you are using gcc
2.95.1 on an unpatched HP-UX 11.x system,
you will get the error:
In file included from /usr/include/unistd.h:11, from ../include/global.h:125, from mysql_priv.h:15, from item.cc:19: /usr/include/sys/unistd.h:184: declaration of C function ... /usr/include/sys/pthread.h:440: previous declaration ... In file included from item.h:306, from mysql_priv.h:158, from item.cc:19:
The problem is that HP-UX doesn't define pthreads_atfork()
consistently.
It has conflicting prototypes in
`/usr/include/sys/unistd.h':184 and
`/usr/include/sys/pthread.h':440.
One solution is to copy `/usr/include/sys/unistd.h' into `mysql/include' and edit `unistd.h' and change it to match the definition in `pthread.h'. Look for this line:
extern int pthread_atfork(void (*prepare)(), void (*parent)(), void (*child)());
Change it to look like this:
extern int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
After making the change, the following configure
line should work:
CFLAGS="-fomit-frame-pointer -O3 -fpic" CXX=gcc \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -O3" \ ./configure --prefix=/usr/local/mysql --disable-shared
If you are using MySQL 4.0.5 with the HP-UX compiler, you can use the following
command (which has been tested with cc
B.11.11.04):
CC=cc CXX=aCC CFLAGS=+DD64 CXXFLAGS=+DD64 ./configure \ --with-extra-character-set=complex
You can ignore any errors of the following type:
aCC: warning 901: unknown option: `-3': use +help for online documentation
If you get the following error from configure
,
verify that you don't have the path to the K&R compiler before the path
to the HP-UX C and C++ compiler:
checking for cc option to accept ANSI C... no configure: error: MySQL requires an ANSI C compiler (and a C++ compiler). Try gcc. See the Installation chapter in the Reference Manual.
Another reason for not being able to compile is that you didn't define
the +DD64
flags as just described.
Another possibility for HP-UX 11 is to use MySQL binaries for HP-UX 10.20. We have received reports from some users that these binaries work fine on HP-UX 11.00. If you encounter problems, be sure to check your HP-UX patch level.
Automatic detection of xlC
is missing from Autoconf, so a number of
variables need to be set before running configure
. The following
example uses the IBM compiler:
export CC="xlc_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192 " export CXX="xlC_r -ma -O3 -qstrict -qoptimize=3 -qmaxmem=8192" export CFLAGS="-I /usr/local/include" export LDFLAGS="-L /usr/local/lib" export CPPFLAGS=$CFLAGS export CXXFLAGS=$CFLAGS ./configure --prefix=/usr/local \ --localstatedir=/var/mysql \ --sbindir='/usr/local/bin' \ --libexecdir='/usr/local/bin' \ --enable-thread-safe-client \ --enable-large-files
The preceding options are used to compile the MySQL distribution that can be found at http://www-frec.bull.com/.
If you change the -O3
to -O2
in the preceding configure
line, you must also remove the -qstrict
option. This is a limitation in
the IBM C compiler.
If you are using gcc
or egcs
to compile MySQL, you
must use the -fno-exceptions
flag, because the exception
handling in gcc
/egcs
is not thread-safe! (This is tested with
egcs
1.1.) There are also some known problems with IBM's assembler
that may cause it to generate bad code when used with gcc
.
We recommend the following configure
line with egcs
and
gcc
2.95 on AIX:
CC="gcc -pipe -mcpu=power -Wa,-many" \ CXX="gcc -pipe -mcpu=power -Wa,-many" \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" \ ./configure --prefix=/usr/local/mysql --with-low-memory
The -Wa,-many
option is necessary for the compile to be successful.
IBM is aware of this problem but is in no hurry to fix it because of the
workaround that is available. We don't know if the -fno-exceptions
is required with gcc
2.95, but because MySQL doesn't use exceptions
and the option generates faster code, we recommend that you should always
use it with egcs
/ gcc
.
If you get a problem with assembler code, try changing the -mcpu=xxx
option to match your CPU. Typically power2
, power
, or
powerpc
may need to be used. Alternatively, you might need to use
604
or 604e
. We are not positive but suspect that
power
would likely be safe most of the time, even on
a power2 machine.
If you don't know what your CPU is, execute a uname -m
command. It
will produce a string that looks like 000514676700
, with a format of
xxyyyyyymmss
where xx
and ss
are always 00
,
yyyyyy
is a unique system ID and mm
is the ID of the CPU Planar.
A chart of these values can be found at
http://www16.boulder.ibm.com/pseries/en_US/cmds/aixcmds5/uname.htm.
This will give you a machine type and a machine model you can use to
determine what type of CPU you have.
If you have problems with signals (MySQL dies unexpectedly under high load), you may have found an OS bug with threads and signals. In this case, you can tell MySQL not to use signals by configuring as follows:
CFLAGS=-DDONT_USE_THR_ALARM CXX=gcc \ CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti \ -DDONT_USE_THR_ALARM" \ ./configure --prefix=/usr/local/mysql --with-debug \ --with-low-memory
This doesn't affect the performance of MySQL, but has the side
effect that you can't kill clients that are ``sleeping'' on a connection with
mysqladmin kill
or mysqladmin shutdown
. Instead, the client
will die when it issues its next command.
On some versions of AIX, linking with libbind.a
makes
getservbyname()
dump core. This is an AIX bug and should be reported
to IBM.
For AIX 4.2.1 and gcc
, you have to make the following changes.
After configuring, edit `config.h' and `include/my_config.h' and change the line that says this:
#define HAVE_SNPRINTF 1
to this:
#undef HAVE_SNPRINTF
And finally, in `mysqld.cc', you need to add a prototype for
initgroups()
.
#ifdef _AIX41 extern "C" int initgroups(const char *,int); #endif
If you need to allocate a lot of memory to the mysqld
process, it's not
enough to just use ulimit -d unlimited
. You may also have to modify
mysqld_safe
to add a line something like this:
export LDR_CNTRL='MAXDATA=0x80000000'
You can find more information about using a lot of memory at http://publib16.boulder.ibm.com/pseries/en_US/aixprggd/genprogc/lrg_prg_support.htm.
On SunOS 4, MIT-pthreads is needed to compile MySQL. This in turn
means you will need GNU make
.
Some SunOS 4 systems have problems with dynamic libraries and libtool
.
You can use the following configure
line to avoid this problem:
./configure --disable-shared --with-mysqld-ldflags=-all-static
When compiling readline
, you may get warnings about duplicate defines.
These can be ignored.
When compiling mysqld
, there will be some implicit declaration
of function
warnings. These can be ignored.
If you are using egcs
1.1.2 on Digital Unix, you should upgrade to
gcc
2.95.2, because egcs
on DEC has some serious bugs!
When compiling threaded programs under Digital Unix, the documentation
recommends using the -pthread
option for cc
and cxx
and
the -lmach -lexc
libraries (in addition to -lpthread
). You
should run configure
something like this:
CC="cc -pthread" CXX="cxx -pthread -O" \ ./configure --with-named-thread-libs="-lpthread -lmach -lexc -lc"
When compiling mysqld
, you may see a couple of warnings like this:
mysqld.cc: In function void handle_connections()': mysqld.cc:626: passing long unsigned int *' as argument 3 of accept(int,sockadddr *, int *)'
You can safely ignore these warnings. They occur because configure
can detect only errors, not warnings.
If you start the server directly from the command line, you may have problems
with it dying when you log out. (When you log out, your outstanding processes
receive a SIGHUP
signal.) If so, try starting the server like this:
nohup mysqld [options] &
nohup
causes the command following it to ignore any SIGHUP
signal sent from the terminal. Alternatively, start the server by running
mysqld_safe
, which invokes mysqld
using nohup
for you.
See section 5.1.3 The mysqld_safe
Server Startup Script.
If you get a problem when compiling `mysys/get_opt.c', just remove the
#define _NO_PROTO
line from the start of that file.
If you are using Compaq's CC compiler, the following configure
line
should work:
CC="cc -pthread" CFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all -arch host" CXX="cxx -pthread" CXXFLAGS="-O4 -ansi_alias -ansi_args -fast -inline speed all \ -arch host -noexceptions -nortti" export CC CFLAGS CXX CXXFLAGS ./configure \ --prefix=/usr/local/mysql \ --with-low-memory \ --enable-large-files \ --enable-shared=yes \ --with-named-thread-libs="-lpthread -lmach -lexc -lc" gnumake
If you get a problem with libtool
when compiling with shared libraries
as just shown, when linking mysql
, you should be able to get around
this by issuing these commands:
cd mysql /bin/sh ../libtool --mode=link cxx -pthread -O3 -DDBUG_OFF \ -O4 -ansi_alias -ansi_args -fast -inline speed \ -speculate all \ -arch host -DUNDEF_HAVE_GETHOSTBYNAME_R \ -o mysql mysql.o readline.o sql_string.o completion_hash.o \ ../readline/libreadline.a -lcurses \ ../libmysql/.libs/libmysqlclient.so -lm cd .. gnumake gnumake install scripts/mysql_install_db
If you have problems compiling and have DEC CC
and gcc
installed, try running configure
like this:
CC=cc CFLAGS=-O CXX=gcc CXXFLAGS=-O3 \ ./configure --prefix=/usr/local/mysql
If you get problems with the `c_asm.h' file, you can create and use a 'dummy' `c_asm.h' file with:
touch include/c_asm.h CC=gcc CFLAGS=-I./include \ CXX=gcc CXXFLAGS=-O3 \ ./configure --prefix=/usr/local/mysql
Note that the following problems with the ld
program can be fixed
by downloading the latest DEC (Compaq) patch kit from:
http://ftp.support.compaq.com/public/unix/.
On OSF/1 V4.0D and compiler "DEC C V5.6-071 on Digital Unix V4.0 (Rev. 878),"
the compiler had some strange behavior (undefined asm
symbols).
/bin/ld
also appears to be broken (problems with _exit
undefined
errors occurring while linking mysqld
). On this system, we
have managed to compile MySQL with the following configure
line, after replacing /bin/ld
with the version from OSF 4.0C:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql
With the Digital compiler "C++ V6.1-029," the following should work:
CC=cc -pthread CFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed \ -speculate all -arch host CXX=cxx -pthread CXXFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed \ -speculate all -arch host -noexceptions -nortti export CC CFLAGS CXX CXXFLAGS ./configure --prefix=/usr/mysql/mysql \ --with-mysqld-ldflags=-all-static --disable-shared \ --with-named-thread-libs="-lmach -lexc -lc"
In some versions of OSF/1, the alloca()
function is broken. Fix
this by removing the line in `config.h' that defines 'HAVE_ALLOCA'
.
The alloca()
function also may have an incorrect prototype in
/usr/include/alloca.h
. This warning resulting from this can be ignored.
configure
will use the following thread libraries automatically:
--with-named-thread-libs="-lpthread -lmach -lexc -lc"
.
When using gcc
, you can also try running configure
like this:
CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ...
If you have problems with signals (MySQL dies unexpectedly under high load), you may have found an OS bug with threads and signals. In this case, you can tell MySQL not to use signals by configuring with:
CFLAGS=-DDONT_USE_THR_ALARM \ CXXFLAGS=-DDONT_USE_THR_ALARM \ ./configure ...
This doesn't affect the performance of MySQL, but has the side
effect that you can't kill clients that are ``sleeping'' on a connection with
mysqladmin kill
or mysqladmin shutdown
. Instead, the client
will die when it issues its next command.
With gcc
2.95.2, you will probably run into the following compile error:
sql_acl.cc:1456: Internal compiler error in `scan_region', at except.c:2566 Please submit a full bug report.
To fix this, you should change to the sql
directory and do a
cut-and-paste of the last gcc
line, but change -O3
to
-O0
(or add -O0
immediately after gcc
if you don't
have any -O
option on your compile line). After this is done, you
can just change back to the top-level directory and run make
again.
If you are using Irix Version 6.5.3 or newer, mysqld
will be able to
create threads only if you run it as a user that has CAP_SCHED_MGT
privileges (such as root
) or give the mysqld
server this privilege
with the following shell command:
chcap "CAP_SCHED_MGT+epi" /opt/mysql/libexec/mysqld
You may have to undefine some symbols in `config.h' after running
configure
and before compiling.
In some Irix implementations, the alloca()
function is broken. If the
mysqld
server dies on some SELECT
statements, remove the lines
from `config.h' that define HAVE_ALLOC
and HAVE_ALLOCA_H
.
If mysqladmin create
doesn't work, remove the line from `config.h'
that defines HAVE_READDIR_R
. You may have to remove the
HAVE_TERM_H
line as well.
SGI recommends that you install all the patches on this page as a set: http://support.sgi.com/surfzone/patches/patchset/6.2_indigo.rps.html
At the very minimum, you should install the latest kernel rollup, the
latest rld
rollup, and the latest libc
rollup.
You definitely need all the POSIX patches on this page, for pthreads support:
http://support.sgi.com/surfzone/patches/patchset/6.2_posix.rps.html
If you get the something like the following error when compiling `mysql.cc':
"/usr/include/curses.h", line 82: error(1084): invalid combination of type
Type the following in the top-level directory of your MySQL source tree:
extra/replace bool curses_bool < /usr/include/curses.h > include/curses.h make
There have also been reports of scheduling problems. If only one thread is running, performance is slow. Avoid this by starting another client. This may lead to a two-to-tenfold increase in execution speed thereafter for the other thread. This is a poorly understood problem with Irix threads; you may have to improvise to find solutions until this can be fixed.
If you are compiling with gcc
, you can use the following
configure
command:
CC=gcc CXX=gcc CXXFLAGS=-O3 \ ./configure --prefix=/usr/local/mysql --enable-thread-safe-client \ --with-named-thread-libs=-lpthread
On Irix 6.5.11 with native Irix C and C++ compilers ver. 7.3.1.2, the following is reported to work
CC=cc CXX=CC CFLAGS='-O3 -n32 -TARG:platform=IP22 -I/usr/local/include \ -L/usr/local/lib' CXXFLAGS='-O3 -n32 -TARG:platform=IP22 \ -I/usr/local/include -L/usr/local/lib' \ ./configure --prefix=/usr/local/mysql --with-innodb --with-berkeley-db \ --with-libwrap=/usr/local \ --with-named-curses-libs=/usr/local/lib/libncurses.a
The current port is tested only on ``sco3.2v5.0.5,'' ``sco3.2v5.0.6,'' and ``sco3.2v5.0.7'' systems. There has also been a lot of progress on a port to ``sco 3.2v4.2.'' Open Server 5.0.8(Legend) will have native threads and allow files greater than 2GB. The current maximum file size is 2GB.
We have been able to compile MySQL with the following configure
command on OpenServer with gcc
2.95.3.
CC=gcc CXX=gcc ./configure --prefix=/usr/local/mysql \ --enable-thread-safe-client --with-innodb \ --with-openssl --with-vio --with-extra-charsets=complex
gcc
is available at
ftp://ftp.sco.com/pub/openserver5/opensrc/gnutools-5.0.7Kj.
This development system requires the OpenServer Execution Environment Supplement oss646B on OpenServer 5.0.6 and oss656B and The OpenSource libraries found in gwxlibs. All OpenSource tools are in the `opensrc' directory. They are available at ftp://ftp.sco.com/pub/openserver5/opensrc/.
We recommend using the latest production release of MySQL.
SCO provides operating system patches at ftp://ftp.sco.com/pub/openserver5 for OpenServer 5.0.[0-6] and ftp://ftp.sco.com/pub/openserverv5/507 for OpenServer 5.0.7.
SCO provides information about security fixes at ftp://ftp.sco.com/pub/security/OpenServer for OpenServer 5.0.x.
The maximum file size on an OpenSever 5.0.x system is 2GB.
The total memory which could be allocated for streams buffers, clists and lock records cannot exceed 60MB on OpenServer 5.0.x.
Streams buffers are allocated in units of 4096 byte pages, clists are 70 bytes each, and lock records are 64 bytes each, so:
(NSTRPAGES * 4096) + (NCLIST * 70) + (MAX_FLCKREC * 64) <= 62914560
Follow this procedure to configure the Database Services option. If you are unsure whether an application requires this, see the documentation provided with the application.
root
.
N
in the second field to a Y
.
mkdev aio
or the Hardware/Kernel Manager to enable support for
asynchronous I/O and relink the kernel. To allow users to lock down memory
for use with this type of I/O, update the aiomemlock(F) file. This file
should be updated to include the names of users that can use AIO and the
maximum amounts of memory they can lock down.
After you complete this process, reboot the system to create a new kernel incorporating these changes.
By default, the entries in `/etc/conf/cf.d/mtune' are set as follows:
Value Default Min Max ----- ------- -- --- NBUF 0 24 450000 NHBUF 0 32 524288 NMPBUF 0 12 512 MAX_INODE 0 100 64000 MAX_FILE 0 100 64000 CTBUFSIZE 128 0 256 MAX_PROC 0 50 16000 MAX_REGION 0 500 160000 NCLIST 170 120 16640 MAXUP 100 15 16000 NOFILES 110 60 11000 NHINODE 128 64 8192 NAUTOUP 10 0 60 NGROUPS 8 0 128 BDFLUSHR 30 1 300 MAX_FLCKREC 0 50 16000 PUTBUFSZ 8000 2000 20000 MAXSLICE 100 25 100 ULIMIT 4194303 2048 4194303 * Streams Parameters NSTREAM 64 1 32768 NSTRPUSH 9 9 9 NMUXLINK 192 1 4096 STRMSGSZ 16384 4096 524288 STRCTLSZ 1024 1024 1024 STRMAXBLK 524288 4096 524288 NSTRPAGES 500 0 8000 STRSPLITFRAC 80 50 100 NLOG 3 3 3 NUMSP 64 1 256 NUMTIM 16 1 8192 NUMTRW 16 1 8192 * Semaphore Parameters SEMMAP 10 10 8192 SEMMNI 10 10 8192 SEMMNS 60 60 8192 SEMMNU 30 10 8192 SEMMSL 25 25 150 SEMOPM 10 10 1024 SEMUME 10 10 25 SEMVMX 32767 32767 32767 SEMAEM 16384 16384 16384 * Shared Memory Parameters SHMMAX 524288 131072 2147483647 SHMMIN 1 1 1 SHMMNI 100 100 2000 FILE 0 100 64000 NMOUNT 0 4 256 NPROC 0 50 16000 NREGION 0 500 160000
We recommend setting these values as follows:
NOFILES
should be 4096 or 2048.
MAXUP
should be 2048.
To make changes to the kernel, cd
to `/etc/conf/bin' and
use ./idtune
name parameter to make the changes. For example,
to change SEMMS
to 200
, execute these commands as root
:
# cd /etc/conf/bin # ./idtune SEMMNS 200
We recommend tuning the system, but the proper parameter values to use depend on the number of users accessing the application or database and size the of the database (that is, the used buffer pool). The following will affect the following kernel parameters defined in `/etc/conf/cf.d/stune':
SHMMAX
(recommended setting: 128MB) and SHMSEG
(recommended
setting: 15).
These parameters have influence on the MySQL database engine to create
user buffer pools.
NOFILES
and MAXUP
should be at to at least 2048.
MAXPROC
should be set to at least 3000/4000 (depends on number of users)
or more.
Also is recommended to use following formula to count value for SEMMSL
,
SEMMNS
and SEMMNU
:
SEMMSL = 13
The 13 is what has been found to be the best for both Progress and MySQL.
SEMMNS
= SEMMSL
* number of db servers to be run on the system.
Set SEMMNS
to the value of SEMMSL
multiplied by the number of
db servers (maximum) that you will be running on the system at one time.
SEMMNU = SEMMNS
Set the value of SEMMNU
to equal the value of SEMMNS
. You
could probably set this to 75% of SEMMNS
, but this is a conservative
estimate.
You need to at least install the "SCO OpenServer Linker and Application
Development Libraries" or the OpenServer Development System to use gcc
.
You cannot just use the GCC Dev system without installing one of these.
You should get the FSU Pthreads package and install it first. This can be found at http://moss.csc.ncsu.edu/~mueller/ftp/pub/PART/pthreads.tar.gz. You can also get a precompiled package from ftp://ftp.zenez.com/pub/zenez/prgms/FSU-threads-3.14.tar.gz.
FSU Pthreads can be compiled with SCO Unix 4.2 with tcpip, or using OpenServer 3.0 or Open Desktop 3.0 (OS 3.0 ODT 3.0) with the SCO Development System installed using a good port of GCC 2.5.x. For ODT or OS 3.0, you will need a good port of GCC 2.5.x. There are a lot of problems without a good port. The port for this product requires the SCO Unix Development system. Without it, you are missing the libraries and the linker that is needed. You will also need `SCO-3.2v4.2-includes.tar.gz'. This file contains the changes to the SCO Development include files that are needed to get MySQL to build. You need to replace the existing system include files with these modified header files. They can be obtained from ftp://ftp.zenez.com/pub/zenez/prgms/SCO-3.2v4.2-includes.tar.gz.
To build FSU Pthreads on your system,
all you should need to do is run GNU make
. The `Makefile' in
FSU-threads-3.14.tar.gz is set up to make FSU-threads.
You can run ./configure
in the `threads/src' directory and
select the SCO OpenServer option. This command copies `Makefile.SCO5' to
`Makefile'. Then run make
.
To install in the default `/usr/include' directory, log in as
root
, then cd
to the `thread/src' directory and run
make install
.
Remember that you must use GNU make
when making MySQL.
Note: If you don't start mysqld_safe
as root
, you
probably will get only the default 110 open files per process. mysqld
will write a note about this in the log file.
With SCO 3.2V4.2, you should use FSU Pthreads version 3.14 or newer.
The following configure
command should work:
CFLAGS="-D_XOPEN_XPG4" CXX=gcc CXXFLAGS="-D_XOPEN_XPG4" \ ./configure \ --prefix=/usr/local/mysql \ --with-named-thread-libs="-lgthreads -lsocket -lgen -lgthreads" \ --with-named-curses-libs="-lcurses"
You may get some problems with some include files. In this case, you can find new SCO-specific include files at ftp://ftp.zenez.com/pub/zenez/prgms/SCO-3.2v4.2-includes.tar.gz.
You should unpack this file in the `include' directory of your MySQL source tree.
SCO development notes:
mysqld
with
-lgthreads -lsocket -lgthreads
.
malloc
. If you encounter problems with memory usage,
make sure that `gmalloc.o' is included in `libgthreads.a' and
`libgthreads.so'.
read()
, write()
, getmsg()
, connect()
,
accept(),
select()
, and wait()
.
mysqld
unstable. You have to remove this one if you want to run
mysqld
on an OpenServer 5.0.6 machine.
libsocket.so.2
at
ftp://ftp.sco.com/pub/security/OpenServer and
ftp://ftp.sco.com/pub/security/sse for OpenServer 5.0.x.
telnetd
fix at
ftp://stage.caldera.com/pub/security/openserver/ or
ftp://stage.caldera.com/pub/security/openserver/CSSA-2001-SCO.10/ as
both `libsocket.so.2' and `libresolv.so.1' with instructions for
installing on pre-OSR506 systems.
It's probably a good idea to install these
patches before trying to compile/use MySQL.
Beginning with Legend, OpenServer will have native threads and no 2GB file size limit.
We recommend using the latest production release of MySQL. Currently this is MySQL 4.0.x. Should you choose to use an older release of MySQL on UnixWare 7.1.x, you must use a version of MySQL at least as recent as 3.22.13 to get fixes for some portability and OS problems.
We have been able to compile MySQL with the following configure
command on UnixWare Version 7.1.x:
CC="cc" CFLAGS="-I/usr/local/include" \ CXX="CC" CXXFLAGS="-I/usr/local/include" \ ./configure --prefix=/usr/local/mysql \ --enable-thread-safe-client --with-berkeley-db=./bdb \ --with-innodb --with-openssl --with-extra-charsets=complex
If you want to use gcc
, you must use gcc
2.95.3 or newer.
CC=gcc CXX=g++ ./configure --prefix=/usr/local/mysql
SCO provides operating system patches at ftp://ftp.sco.com/pub/unixware7 for UnixWare 7.1.1, ftp://ftp.sco.com/pub/unixware7/713/ for UnixWare 7.1.3, ftp://ftp.sco.com/pub/unixware7/714/ for UnixWare 7.1.4, and ftp://ftp.sco.com/pub/openunix8 for OpenUNIX 8.0.0.
SCO provides information about security fixes at ftp://ftp.sco.com/pub/security/OpenUNIX for OpenUNIX and ftp://ftp.sco.com/pub/security/UnixWare for UnixWare.
By default, the maximum file size on a UnixWare 7 system is 1GB. Many OS utilities have a limitation of 2GB. The maximum possible file size on UnixWare 7 is 1TB with VXFS.
To enable large file support on UnixWare 7.1.x, run fsadm
.
# fsadm -Fvxfs -o largefiles / # fsadm / * Note # ulimit unlimited # cd /etc/conf/bin # ./idtune SFSZLIM 0x7FFFFFFF ** Note # ./idtune HFSZLIM 0x7FFFFFFF ** Note # ./idbuild -B * This should report "largefiles". ** 0x7FFFFFFF represents infinity for these values.
Reboot the system using shutdown
.
By default, the entries in `/etc/conf/cf.d/mtune' are set to:
Value Default Min Max ----- ------- -- --- SVMMLIM 0x9000000 0x1000000 0x7FFFFFFF HVMMLIM 0x9000000 0x1000000 0x7FFFFFFF SSTKLIM 0x1000000 0x2000 0x7FFFFFFF HSTKLIM 0x1000000 0x2000 0x7FFFFFFF
We recommend setting these values as follows:
SDATLIM 0x7FFFFFFF HDATLIM 0x7FFFFFFF SSTKLIM 0x7FFFFFFF HSTKLIM 0x7FFFFFFF SVMMLIM 0x7FFFFFFF HVMMLIM 0x7FFFFFFF SFNOLIM 2048 HFNOLIM 2048
We recommend tuning the system, but the proper parameter values to use depend on the number of users accessing the application or database and size the of the database (that is, the used buffer pool). The following will affect the following kernel parameters defined in `/etc/conf/cf.d/stune':
SHMMAX
(recommended setting: 128MB) and SHMSEG
(recommended
setting: 15).
These parameters have influence on the MySQL database engine to create
user buffer pools.
SFNOLIM
and HFNOLIM
should be at maximum 2048.
NPROC
should be set to at least 3000/4000 (depends on number of users).
Also is recommended to use following formula to count value for SEMMSL
,
SEMMNS
, and SEMMNU
:
SEMMSL = 13
13 is what has been found to be the best for both Progress and MySQL.
SEMMNS
= SEMMSL
* number of db servers to be run on the system.
Set SEMMNS
to the value of SEMMSL
multiplied by the number
of db servers (maximum) that you will be running on the system at one time.
SEMMNU
= SEMMNS
Set the value of SEMMNU
to equal the value of SEMMNS
. You
could probably set this to 75% of SEMMNS
, but this is a conservative estimate.
MySQL uses quite a few open files. Because of this, you should add something like the following to your `CONFIG.SYS' file:
SET EMXOPT=-c -n -h1024
If you don't do this, you will probably run into the following error:
File 'xxxx' not found (Errcode: 24)
When using MySQL with OS/2 Warp 3, FixPack 29 or above is required. With OS/2 Warp 4, FixPack 4 or above is required. This is a requirement of the Pthreads library. MySQL must be installed on a partition with a type that supports long filenames, such as HPFS, FAT32, and so on.
The `INSTALL.CMD' script must be run from OS/2's own `CMD.EXE' and may not work with replacement shells such as `4OS2.EXE'.
The `scripts/mysql-install-db' script has been renamed. It is called `install.cmd' and is a REXX script, which will set up the default MySQL security settings and create the WorkPlace Shell icons for MySQL.
Dynamic module support is compiled in but not fully tested. Dynamic modules should be compiled using the Pthreads runtime library.
gcc -Zdll -Zmt -Zcrtdll=pthrdrtl -I../include -I../regex -I.. \ -o example udf_example.cc -L../lib -lmysqlclient udf_example.def mv example.dll example.udf
Note: Due to limitations in OS/2, UDF module name stems must not
exceed eight characters. Modules are stored in the `/mysql2/udf'
directory; the safe-mysqld.cmd
script will put this directory in
the BEGINLIBPATH
environment variable. When using UDF modules,
specified extensions are ignored--it is assumed to be `.udf'.
For example, in Unix, the shared module might be named `example.so'
and you would load a function from it like this:
mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME 'example.so';
In OS/2, the module would be named `example.udf', but you would not specify the module extension:
mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME 'example';
We have in the past talked with some BeOS developers who have said that MySQL is 80% ported to BeOS, but we haven't heard from them in a while.
Perl support for MySQL is provided by means of the DBI
/DBD
client interface. The interface requires Perl Version 5.6.0 or later.
It will not work if you have an older version of Perl.
If you want to use transactions with Perl DBI, you need to have
DBD::mysql
version 1.2216 or newer. Version 2.9003 or newer
is recommended.
If you are using the MySQL 4.1 client library, you must use
DBD::mysql
2.9003 or newer.
As of MySQL 3.22.8, Perl support is no longer included with MySQL
distributions. You can obtain the necessary modules from
http://search.cpan.org for Unix, or by using the ActiveState
ppm
program on Windows. The following sections describe how to do
this.
Perl support for MySQL must be installed if you want to run the MySQL benchmark scripts. See section 7.1.4 The MySQL Benchmark Suite.
MySQL Perl support requires that you've installed MySQL client programming support (libraries and header files). Most installation methods install the necessary files. However, if you installed MySQL from RPM files on Linux, be sure that you've installed the developer RPM. The client programs are in the client RPM, but client programming support is in the developer RPM.
If you want to install Perl support, the files you will need can be obtained from the CPAN (Comprehensive Perl Archive Network) at http://search.cpan.org.
The easiest way to install Perl modules on Unix is to use the CPAN
module. For example:
shell> perl -MCPAN -e shell cpan> install DBI cpan> install DBD::mysql
The DBD::mysql
installation runs a number of tests.
These tests require being able to connect to the local MySQL server
as the anonymous user with no password. If you have removed anonymous
accounts or assigned them passwords, the tests fail. You can use force
install DBD::mysql
to ignore the failed tests.
DBI
requires the Data::Dumper
module. It may be
installed; if not, you should install it before installing DBI
.
It is also possible to download the module distributions in the form of
compressed tar
archives and build the modules manually. For example,
to unpack and build a DBI distribution, use a procedure such as this:
shell> gunzip < DBI-VERSION.tar.gz | tar xvf -This command creates a directory named `DBI-VERSION'.
shell> cd DBI-VERSION
shell> perl Makefile.PL shell> make shell> make test shell> make install
The make test
command is important because it verifies that the
module is working. Note that when you run that command during the
DBD::mysql
installation to exercise the interface code, the
MySQL server must be running or the test will fail.
It is a good idea to rebuild and reinstall the DBD::mysql
distribution whenever you install a new release of MySQL,
particularly if you notice symptoms such as that all your DBI
scripts
fail after you upgrade MySQL.
If you don't have access rights to install Perl modules in the system directory or if you want to install local Perl modules, the following reference may be useful: http://servers.digitaldaze.com/extensions/perl/modules.html#modules
Look under the heading ``Installing New Modules that Require Locally Installed Modules.''
On Windows, you should do the following to install the MySQL
DBD
module with ActiveState Perl:
HTTP_proxy
variable. For example, you might try:
set HTTP_proxy=my.proxy.com:3128
C:\> C:\perl\bin\ppm.pl
DBI
:
ppm> install DBI
install \ ftp://ftp.de.uu.net/pub/CPAN/authors/id/JWIED/DBD-mysql-1.2212.x86.ppd
This procedure should work at least with ActiveState Perl Version 5.6.
If you can't get the procedure to work, you should instead install the MyODBC driver and connect to the MySQL server through ODBC:
use DBI; $dbh= DBI->connect("DBI:ODBC:$dsn",$user,$password) || die "Got error $DBI::errstr when connecting to $dsn\n";
DBI
/DBD
InterfaceIf Perl reports that it can't find the `../mysql/mysql.so' module, then the problem is probably that Perl can't locate the shared library `libmysqlclient.so'.
You should be able to fix this by one of the following methods:
DBD::mysql
distribution with perl
Makefile.PL -static -config
rather than perl Makefile.PL
.
-L
options used to compile DBD::mysql
to reflect
the actual location of `libmysqlclient.so'.
LD_RUN_PATH
environment variable. Some systems use
LD_LIBRARY_PATH
instead.
Note that you may also need to modify the -L
options if there are
other libraries that the linker fails to find. For example, if the linker
cannot find libc
because it is in `/lib' and the link command
specifies -L/usr/lib
, change the -L
option to -L/lib
or add -L/lib
to the existing link command.
If you get the following errors from DBD::mysql
,
you are probably using gcc
(or using an old binary compiled with
gcc
):
/usr/bin/perl: can't resolve symbol '__moddi3' /usr/bin/perl: can't resolve symbol '__divdi3'
Add -L/usr/lib/gcc-lib/... -lgcc
to the link command when the
`mysql.so' library gets built (check the output from make
for
`mysql.so' when you compile the Perl client). The -L
option
should specify the pathname of the directory where `libgcc.a' is located
on your system.
Another cause of this problem may be that Perl and MySQL aren't both
compiled with gcc
. In this case, you can solve the mismatch by
compiling both with gcc
.
You may see the following error from DBD::mysql
when you run the tests:
t/00base............install_driver(mysql) failed: Can't load '../blib/arch/auto/DBD/mysql/mysql.so' for module DBD::mysql: ../blib/arch/auto/DBD/mysql/mysql.so: undefined symbol: uncompress at /usr/lib/perl5/5.00503/i586-linux/DynaLoader.pm line 169.
This means that you need to include the -lz
compression library on the
link line. That can be done by changing the following line in the file
`lib/DBD/mysql/Install.pm':
$sysliblist .= " -lm";
Change that line to:
$sysliblist .= " -lm -lz";
After this, you must run make realclean
and then
proceed with the installation from the beginning.
If you want to install DBI on SCO, you have to edit the
`Makefile' in DBI-xxx and each subdirectory.
Note that the following assumes gcc
2.95.2 or newer:
OLD: NEW: CC = cc CC = gcc CCCDLFLAGS = -KPIC -W1,-Bexport CCCDLFLAGS = -fpic CCDLFLAGS = -wl,-Bexport CCDLFLAGS = LD = ld LD = gcc -G -fpic LDDLFLAGS = -G -L/usr/local/lib LDDLFLAGS = -L/usr/local/lib LDFLAGS = -belf -L/usr/local/lib LDFLAGS = -L/usr/local/lib LD = ld LD = gcc -G -fpic OPTIMISE = -Od OPTIMISE = -O1 OLD: CCCFLAGS = -belf -dy -w0 -U M_XENIX -DPERL_SCO5 -I/usr/local/include NEW: CCFLAGS = -U M_XENIX -DPERL_SCO5 -I/usr/local/include
These changes are necessary
because the Perl dynaloader will not load the DBI
modules
if they were compiled with icc
or cc
.
If you want to use the Perl module on a system that doesn't support
dynamic linking (such as SCO), you can generate a static version of
Perl that includes DBI
and DBD::mysql
. The way this works
is that you generate a version of Perl with the DBI
code linked
in and install it on top of your current Perl. Then you use that to
build a version of Perl that additionally has the DBD
code linked
in, and install that.
On SCO, you must have the following environment variables set:
LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/progressive/lib
Or:
LD_LIBRARY_PATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ /usr/progressive/lib:/usr/skunk/lib LIBPATH=/usr/lib:/lib:/usr/local/lib:/usr/ccs/lib:\ /usr/progressive/lib:/usr/skunk/lib MANPATH=scohelp:/usr/man:/usr/local1/man:/usr/local/man:\ /usr/skunk/man:
First, create a Perl that includes a statically linked DBI
module by
running these commands in the directory where your DBI
distribution is
located:
shell> perl Makefile.PL -static -config shell> make shell> make install shell> make perl
Then you must install the new Perl. The output of make perl
will
indicate the exact make
command you will need to execute to perform
the installation. On SCO, this is
make -f Makefile.aperl inst_perl MAP_TARGET=perl
.
Next, use the just-created Perl to create another Perl that also includes a
statically linked DBD::mysql
by running these commands in the
directory where your DBD::mysql
distribution is located:
shell> perl Makefile.PL -static -config shell> make shell> make install shell> make perl
Finally, you should install this new Perl. Again, the output of make
perl
indicates the command to use.
This chapter provides a tutorial introduction to MySQL by showing
how to use the mysql
client program to create and use a simple
database. mysql
(sometimes referred to as the ``terminal monitor'' or
just ``monitor'') is an interactive program that allows you to connect to a
MySQL server, run queries, and view the results. mysql
may
also be used in batch mode: you place your queries in a file beforehand, then
tell mysql
to execute the contents of the file. Both ways of using
mysql
are covered here.
To see a list of options provided by mysql
, invoke it with
the --help
option:
shell> mysql --help
This chapter assumes that mysql
is installed on your machine and that
a MySQL server is available to which you can connect. If this is
not true, contact your MySQL administrator. (If you are the
administrator, you will need to consult other sections of this manual.)
This chapter describes the entire process of setting up and using a database. If you are interested only in accessing an existing database, you may want to skip over the sections that describe how to create the database and the tables it contains.
Because this chapter is tutorial in nature, many details are necessarily omitted. Consult the relevant sections of the manual for more information on the topics covered here.
To connect to the server, you'll usually need to provide a MySQL
username when you invoke mysql
and, most likely, a password. If the
server runs on a machine other than the one where you log in, you'll also
need to specify a hostname. Contact your administrator to find out what
connection parameters you should use to connect (that is, what host, username,
and password to use). Once you know the proper parameters, you should be
able to connect like this:
shell> mysql -h host -u user -p Enter password: ********
host
and user
represent the hostname where your MySQL server is
running and the username of your MySQL account. Substitute appropriate values
for your setup.
The ********
represents your password; enter it when mysql
displays the Enter password:
prompt.
If that works, you should see some introductory information followed by a
mysql>
prompt:
shell> mysql -h host -u user -p Enter password: ******** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 25338 to server version: 4.0.14-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql>
The prompt tells you that mysql
is ready for you to enter commands.
Some MySQL installations allow users to connect as the anonymous
(unnamed) user to the server running on the local host. If this is the case
on your machine, you should be able to connect to that server by invoking
mysql
without any options:
shell> mysql
After you have connected successfully, you can disconnect any time by typing
QUIT
(or \q
) at the mysql>
prompt:
mysql> QUIT Bye
On Unix, you can also disconnect by pressing Control-D.
Most examples in the following sections assume that you are connected to the
server. They indicate this by the mysql>
prompt.
Make sure that you are connected to the server, as discussed in the previous
section. Doing so will not in itself select any database to work with, but
that's okay. At this point, it's more important to find out a little about
how to issue queries than to jump right in creating tables, loading data
into them, and retrieving data from them. This section describes the basic
principles of entering commands, using several queries you can try out to
familiarize yourself with how mysql
works.
Here's a simple command that asks the server to tell you its version number
and the current date. Type it in as shown here following the mysql>
prompt and press Enter:
mysql> SELECT VERSION(), CURRENT_DATE; +--------------+--------------+ | VERSION() | CURRENT_DATE | +--------------+--------------+ | 3.22.20a-log | 1999-03-19 | +--------------+--------------+ 1 row in set (0.01 sec) mysql>
This query illustrates several things about mysql
:
QUIT
,
mentioned earlier, is one of them. We'll get to others later.)
mysql
sends it to the server for execution
and displays the results, then prints another mysql>
prompt to indicate
that it is ready for another command.
mysql
displays query output in tabular form (rows and columns). The
first row contains labels for the columns. The rows following are the query
results. Normally, column labels are the names of the columns you fetch from
database tables. If you're retrieving the value of an expression rather than
a table column (as in the example just shown), mysql
labels the column
using the expression itself.
mysql
shows how many rows were returned and how long the query took
to execute, which gives you a rough idea of server performance. These values
are imprecise because they represent wall clock time (not CPU or machine
time), and because they are affected by factors such as server load and
network latency. (For brevity, the ``rows in set'' line is not shown in
the remaining examples in this chapter.)
Keywords may be entered in any lettercase. The following queries are equivalent:
mysql> SELECT VERSION(), CURRENT_DATE; mysql> select version(), current_date; mysql> SeLeCt vErSiOn(), current_DATE;
Here's another query. It demonstrates that you can use mysql
as a
simple calculator:
mysql> SELECT SIN(PI()/4), (4+1)*5; +-------------+---------+ | SIN(PI()/4) | (4+1)*5 | +-------------+---------+ | 0.707107 | 25 | +-------------+---------+
The queries shown thus far have been relatively short, single-line statements. You can even enter multiple statements on a single line. Just end each one with a semicolon:
mysql> SELECT VERSION(); SELECT NOW(); +--------------+ | VERSION() | +--------------+ | 3.22.20a-log | +--------------+ +---------------------+ | NOW() | +---------------------+ | 1999-03-19 00:15:33 | +---------------------+
A command need not be given all on a single line, so lengthy commands that
require several lines are not a problem. mysql
determines where your
statement ends by looking for the terminating semicolon, not by looking for
the end of the input line. (In other words, mysql
accepts free-format input: it collects input lines but does not execute them
until it sees the semicolon.)
Here's a simple multiple-line statement:
mysql> SELECT -> USER() -> , -> CURRENT_DATE; +--------------------+--------------+ | USER() | CURRENT_DATE | +--------------------+--------------+ | joesmith@localhost | 1999-03-18 | +--------------------+--------------+
In this example, notice how the prompt changes from mysql>
to
->
after you enter the first line of a multiple-line query. This is
how mysql
indicates that it hasn't seen a complete statement and is
waiting for the rest. The prompt is your friend, because it provides
valuable feedback. If you use that feedback, you will always be aware of
what mysql
is waiting for.
If you decide you don't want to execute a command that you are in the
process of entering, cancel it by typing \c
:
mysql> SELECT -> USER() -> \c mysql>
Here, too, notice the prompt. It switches back to mysql>
after you
type \c
, providing feedback to indicate that mysql
is ready
for a new command.
The following table shows each of the prompts you may see and summarizes what
they mean about the state that mysql
is in:
Prompt | Meaning |
mysql> | Ready for new command. |
-> | Waiting for next line of multiple-line command. |
'> | Waiting for next line, collecting a string that begins with a single quote (`''). |
"> | Waiting for next line, collecting a string that begins with a double quote (`"'). |
`> | Waiting for next line, collecting an identifier that begins with a backtick (``'). |
Multiple-line statements commonly occur by accident when you intend to
issue a command on a single line, but forget the terminating semicolon. In
this case, mysql
waits for more input:
mysql> SELECT USER() ->
If this happens to you (you think you've entered a statement but the only
response is a ->
prompt), most likely mysql
is waiting for the
semicolon. If you don't notice what the prompt is telling you, you might sit
there for a while before realizing what you need to do. Enter a semicolon to
complete the statement, and mysql
will execute it:
mysql> SELECT USER() -> ; +--------------------+ | USER() | +--------------------+ | joesmith@localhost | +--------------------+
The '>
and ">
prompts occur during string collection.
In MySQL, you can write strings surrounded by either `''
or `"' characters (for example, 'hello'
or "goodbye"
),
and mysql
lets you enter strings that span multiple lines. When you
see a '>
or ">
prompt, it means that you've entered a line
containing a string that begins with a `'' or `"' quote character,
but have not yet entered the matching quote that terminates the string.
That's fine if you really are entering a multiple-line string, but how likely
is that? Not very. More often, the '>
and ">
prompts indicate
that you've inadvertently left out a quote character. For example:
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30; '>
If you enter this SELECT
statement, then press Enter and wait for the
result, nothing will happen. Instead of wondering why this
query takes so long, notice the clue provided by the '>
prompt. It
tells you that mysql
expects to see the rest of an unterminated
string. (Do you see the error in the statement? The string 'Smith
is
missing the second quote.)
At this point, what do you do? The simplest thing is to cancel the command.
However, you cannot just type \c
in this case, because mysql
interprets it as part of the string that it is collecting! Instead, enter
the closing quote character (so mysql
knows you've finished the
string), then type \c
:
mysql> SELECT * FROM my_table WHERE name = 'Smith AND age < 30; '> '\c mysql>
The prompt changes back to mysql>
, indicating that mysql
is ready for a new command.
The `>
prompt is similar to th '>
and ">
prompts,
but indicates that you have begun but not completed a backtick-quoted
identifier.
It's important to know what the '>
, ">
, and `>
prompts signify,
because if you mistakenly enter an unterminated string, any further lines you
type will appear to be ignored by mysql
---including a line
containing QUIT
! This can be quite confusing, especially if you
don't know that you need to supply the terminating quote before you can
cancel the current command.
Once you know how to enter commands, it's time to access a database.
Suppose that you have several pets in your home (your menagerie) and you'd like to keep track of various types of information about them. You can do so by creating tables to hold your data and loading them with the desired information. Then you can answer different sorts of questions about your animals by retrieving data from the tables. This section shows you how to:
The menagerie database will be simple (deliberately), but it is not difficult
to think of real-world situations in which a similar type of database might
be used. For example, a database like this could be used by a farmer to keep
track of livestock, or by a veterinarian to keep track of patient records.
A menagerie distribution containing some of the queries and sample data used
in the following sections can be obtained from the MySQL Web site.
It's available in either compressed tar
format
(http://www.mysql.com/Downloads/Contrib/Examples/menagerie.tar.gz)
or Zip format
(http://www.mysql.com/Downloads/Contrib/Examples/menagerie.zip).
Use the SHOW
statement to find out what databases currently exist
on the server:
mysql> SHOW DATABASES; +----------+ | Database | +----------+ | mysql | | test | | tmp | +----------+
The list of databases is probably different on your machine, but the
mysql
and test
databases are likely to be among them. The
mysql
database is required because it describes user access
privileges. The test
database is often provided as a workspace for
users to try things out.
Note that you may not see all databases if you don't have the
SHOW DATABASES
privilege. See section 13.5.1.3 GRANT
and REVOKE
Syntax.
If the test
database exists, try to access it:
mysql> USE test Database changed
Note that USE
, like QUIT
, does not require a semicolon. (You
can terminate such statements with a semicolon if you like; it does no harm.)
The USE
statement is special in another way, too: it must be given on
a single line.
You can use the test
database (if you have access to it) for the
examples that follow, but anything you create in that database can be
removed by anyone else with access to it. For this reason, you should
probably ask your MySQL administrator for permission to use a
database of your own. Suppose that you want to call yours menagerie
. The
administrator needs to execute a command like this:
mysql> GRANT ALL ON menagerie.* TO 'your_mysql_name'@'your_client_host';
where your_mysql_name
is the MySQL username assigned to
you and your_client_host
is the host from which you connect to the
server.
If the administrator creates your database for you when setting up your permissions, you can begin using it. Otherwise, you need to create it yourself:
mysql> CREATE DATABASE menagerie;
Under Unix, database names are case sensitive (unlike SQL keywords), so you
must always refer to your database as menagerie
, not as
Menagerie
, MENAGERIE
, or some other variant. This is also true
for table names. (Under Windows, this restriction does not apply, although
you must refer to databases and tables using the same lettercase throughout a
given query.)
Creating a database does not select it for use; you must do that explicitly.
To make menagerie
the current database, use this command:
mysql> USE menagerie Database changed
Your database needs to be created only once, but you must select it for use
each time you begin a mysql
session. You can do this by issuing a
USE
statement as shown in the example. Alternatively, you can select the
database on the command line when you invoke mysql
. Just specify its
name after any connection parameters that you might need to provide. For
example:
shell> mysql -h host -u user -p menagerie Enter password: ********
Note that menagerie
is not your password on the command just shown.
If you want to supply your password on the command line after the -p
option, you must do so with no intervening space (for example, as
-pmypassword
, not as -p mypassword
). However, putting your
password on the command line is not recommended, because doing so exposes it
to snooping by other users logged in on your machine.
Creating the database is the easy part, but at this point it's empty, as
SHOW TABLES
will tell you:
mysql> SHOW TABLES; Empty set (0.00 sec)
The harder part is deciding what the structure of your database should be: what tables you will need and what columns will be in each of them.
You'll want a table that contains a record for each of your pets. This can
be called the pet
table, and it should contain, as a bare minimum,
each animal's name. Because the name by itself is not very interesting, the
table should contain other information. For example, if more than one person
in your family keeps pets, you might want to list each animal's owner. You
might also want to record some basic descriptive information such as species
and sex.
How about age? That might be of interest, but it's not a good thing to store in a database. Age changes as time passes, which means you'd have to update your records often. Instead, it's better to store a fixed value such as date of birth. Then, whenever you need age, you can calculate it as the difference between the current date and the birth date. MySQL provides functions for doing date arithmetic, so this is not difficult. Storing birth date rather than age has other advantages, too:
You can probably think of other types of information that would be useful in
the pet
table, but the ones identified so far are sufficient:
name, owner, species, sex, birth, and death.
Use a CREATE TABLE
statement to specify the layout of your table:
mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20), -> species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
VARCHAR
is a good choice for the name
, owner
, and
species
columns because the column values will vary in length. The
lengths of those columns need not all be the same, and need not be
20
. You can pick any length from 1
to 255
, whatever
seems most reasonable to you. (If you make a poor choice and it turns
out later that you need a longer field, MySQL provides an
ALTER TABLE
statement.)
Several types of values can be chosen to represent sex in animal records,
such as 'm'
and 'f'
, or perhaps 'male'
and 'female'
. It's simplest
to use the single characters 'm'
and 'f'
.
The use of the DATE
data type for the birth
and death
columns is a fairly obvious choice.
Once you have created a table, SHOW TABLES
should produce some
output:
mysql> SHOW TABLES; +---------------------+ | Tables in menagerie | +---------------------+ | pet | +---------------------+
To verify that your table was created the way you expected, use
a DESCRIBE
statement:
mysql> DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | name | varchar(20) | YES | | NULL | | | owner | varchar(20) | YES | | NULL | | | species | varchar(20) | YES | | NULL | | | sex | char(1) | YES | | NULL | | | birth | date | YES | | NULL | | | death | date | YES | | NULL | | +---------+-------------+------+-----+---------+-------+
You can use DESCRIBE
any time, for example, if you forget the names of
the columns in your table or what types they have.
After creating your table, you need to populate it. The LOAD DATA
and
INSERT
statements are useful for this.
Suppose that your pet records can be described as shown here.
(Observe that MySQL expects dates in 'YYYY-MM-DD'
format;
this may be different from what you are used to.)
name | owner | species | sex | birth | death |
Fluffy | Harold | cat | f | 1993-02-04 | |
Claws | Gwen | cat | m | 1994-03-17 | |
Buffy | Harold | dog | f | 1989-05-13 | |
Fang | Benny | dog | m | 1990-08-27 | |
Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 |
Chirpy | Gwen | bird | f | 1998-09-11 | |
Whistler | Gwen | bird | 1997-12-09 | ||
Slim | Benny | snake | m | 1996-04-29 |
Because you are beginning with an empty table, an easy way to populate it is to create a text file containing a row for each of your animals, then load the contents of the file into the table with a single statement.
You could create a text file `pet.txt' containing one record per line,
with values separated by tabs, and given in the order in which the columns
were listed in the CREATE TABLE
statement. For missing values (such
as unknown sexes or death dates for animals that are still living), you can
use NULL
values. To represent these in your text file, use
\N
(backslash, capital-N). For example, the record for Whistler the
bird would look like
this (where the whitespace between values is a single tab character):
name | owner | species | sex | birth | death |
Whistler | Gwen | bird | \N | 1997-12-09 | \N
|
To load the text file `pet.txt' into the pet
table, use this
command:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet;
Note that if you created the file on Windows with an editor that uses
\r\n
as a line terminator, you should use:
mysql> LOAD DATA LOCAL INFILE '/path/pet.txt' INTO TABLE pet -> LINES TERMINATED BY '\r\n';
You can specify the column value separator and end of line marker explicitly
in the LOAD DATA
statement if you wish, but the defaults are tab and
linefeed. These are sufficient for the statement to read the file
`pet.txt' properly.
If the statement fails, it is likely that your MySQL installation does not
have local file capability enabled by default. See
section 5.4.4 Security Issues with LOAD DATA LOCAL
for information on how to
change this.
When you want to add new records one at a time, the INSERT
statement
is useful. In its simplest form, you supply values for each column, in the
order in which the columns were listed in the CREATE TABLE
statement.
Suppose that Diane gets a new hamster named Puffball. You could add a new record
using an INSERT
statement like this:
mysql> INSERT INTO pet -> VALUES ('Puffball','Diane','hamster','f','1999-03-30',NULL);
Note that string and date values are specified as quoted strings here. Also,
with INSERT
, you can insert NULL
directly to represent a
missing value. You do not use \N
like you do with LOAD DATA
.
From this example, you should be able to see that there would be a lot more
typing involved to load
your records initially using several INSERT
statements rather
than a single LOAD DATA
statement.
The SELECT
statement is used to pull information from a table.
The general form of the statement is:
SELECT what_to_select FROM which_table WHERE conditions_to_satisfy;
what_to_select
indicates what you want to see. This can be a list of
columns, or *
to indicate ``all columns.'' which_table
indicates the table from which you want to retrieve data. The WHERE
clause is optional. If it's present, conditions_to_satisfy
specifies
conditions that rows must satisfy to qualify for retrieval.
The simplest form of SELECT
retrieves everything from a table:
mysql> SELECT * FROM pet; +----------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+--------+---------+------+------------+------------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Fang | Benny | dog | m | 1990-08-27 | NULL | | Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 | | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+--------+---------+------+------------+------------+
This form of SELECT
is useful if you want to review your entire table,
for example, after you've just loaded it with your initial dataset. For
example, you may happen to think that the birth date for Bowser doesn't seem
quite right. Consulting your original pedigree
papers, you find that the correct birth year should be 1989, not 1979.
There are least a couple of ways to fix this:
DELETE
and LOAD DATA
:
mysql> DELETE FROM pet; mysql> LOAD DATA LOCAL INFILE 'pet.txt' INTO TABLE pet;However, if you do this, you must also re-enter the record for Puffball.
UPDATE
statement:
mysql> UPDATE pet SET birth = '1989-08-31' WHERE name = 'Bowser';The
UPDATE
changes only the record in question and does not require you
to reload the table.
As shown in the preceding section, it is easy to retrieve an entire table.
Just omit the WHERE
clause from the SELECT
statement.
But typically you don't want
to see the entire table, particularly when it becomes large. Instead,
you're usually more interested in answering a particular question, in which
case you specify some constraints on the information you want. Let's look at
some selection queries in terms of questions about your pets that they
answer.
You can select only particular rows from your table. For example, if you want to verify the change that you made to Bowser's birth date, select Bowser's record like this:
mysql> SELECT * FROM pet WHERE name = 'Bowser'; +--------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+-------+---------+------+------------+------------+ | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+-------+---------+------+------------+------------+
The output confirms that the year is correctly recorded as 1989, not 1979.
String comparisons normally are case-insensitive, so you can specify the
name as 'bowser'
, 'BOWSER'
, etc. The query result will be
the same.
You can specify conditions on any column, not just name
. For example,
if you want to know which animals were born after 1998, test the birth
column:
mysql> SELECT * FROM pet WHERE birth >= '1998-1-1'; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Puffball | Diane | hamster | f | 1999-03-30 | NULL | +----------+-------+---------+------+------------+-------+
You can combine conditions, for example, to locate female dogs:
mysql> SELECT * FROM pet WHERE species = 'dog' AND sex = 'f'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
The preceding query uses the AND
logical operator. There is also an
OR
operator:
mysql> SELECT * FROM pet WHERE species = 'snake' OR species = 'bird'; +----------+-------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+-------+ | Chirpy | Gwen | bird | f | 1998-09-11 | NULL | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | | Slim | Benny | snake | m | 1996-04-29 | NULL | +----------+-------+---------+------+------------+-------+
AND
and OR
may be intermixed, although AND
has higher
precedence than OR
. If you use both operators, it's a good idea
to use parentheses to indicate explicitly how conditions should be grouped:
mysql> SELECT * FROM pet WHERE (species = 'cat' AND sex = 'm') -> OR (species = 'dog' AND sex = 'f'); +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
If you don't want to see entire rows from your table, just name the columns
in which you're interested, separated by commas. For example, if you want to
know when your animals were born, select the name
and birth
columns:
mysql> SELECT name, birth FROM pet; +----------+------------+ | name | birth | +----------+------------+ | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Buffy | 1989-05-13 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Puffball | 1999-03-30 | +----------+------------+
To find out who owns pets, use this query:
mysql> SELECT owner FROM pet; +--------+ | owner | +--------+ | Harold | | Gwen | | Harold | | Benny | | Diane | | Gwen | | Gwen | | Benny | | Diane | +--------+
However, notice that the query simply retrieves the owner
field from
each record, and some of them appear more than once. To minimize the output,
retrieve each unique output record just once by adding the keyword
DISTINCT
:
mysql> SELECT DISTINCT owner FROM pet; +--------+ | owner | +--------+ | Benny | | Diane | | Gwen | | Harold | +--------+
You can use a WHERE
clause to combine row selection with column
selection. For example, to get birth dates for dogs and cats only,
use this query:
mysql> SELECT name, species, birth FROM pet -> WHERE species = 'dog' OR species = 'cat'; +--------+---------+------------+ | name | species | birth | +--------+---------+------------+ | Fluffy | cat | 1993-02-04 | | Claws | cat | 1994-03-17 | | Buffy | dog | 1989-05-13 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | +--------+---------+------------+
You may have noticed in the preceding examples that the result rows are
displayed in no particular order. It's often easier to examine
query output when the rows are sorted in some meaningful way. To sort a
result, use an ORDER BY
clause.
Here are animal birthdays, sorted by date:
mysql> SELECT name, birth FROM pet ORDER BY birth; +----------+------------+ | name | birth | +----------+------------+ | Buffy | 1989-05-13 | | Bowser | 1989-08-31 | | Fang | 1990-08-27 | | Fluffy | 1993-02-04 | | Claws | 1994-03-17 | | Slim | 1996-04-29 | | Whistler | 1997-12-09 | | Chirpy | 1998-09-11 | | Puffball | 1999-03-30 | +----------+------------+
On character type columns, sorting--like all other comparison
operations--is normally performed in a case-insensitive fashion.
This means that the order will be undefined for columns that are identical
except for their case. You can force a case-sensitive sort for a column
by using the BINARY
cast: ORDER BY BINARY col_name
.
The default sort order is ascending, with smallest values first.
To sort in reverse (descending) order, add the DESC
keyword to the
name of the column you are sorting by:
mysql> SELECT name, birth FROM pet ORDER BY birth DESC; +----------+------------+ | name | birth | +----------+------------+ | Puffball | 1999-03-30 | | Chirpy | 1998-09-11 | | Whistler | 1997-12-09 | | Slim | 1996-04-29 | | Claws | 1994-03-17 | | Fluffy | 1993-02-04 | | Fang | 1990-08-27 | | Bowser | 1989-08-31 | | Buffy | 1989-05-13 | +----------+------------+
You can sort on multiple columns, and you can sort columns in different directions. For example, to sort by type of animal in ascending order, then by birth date within animal type in descending order (youngest animals first), use the following query:
mysql> SELECT name, species, birth FROM pet -> ORDER BY species, birth DESC; +----------+---------+------------+ | name | species | birth | +----------+---------+------------+ | Chirpy | bird | 1998-09-11 | | Whistler | bird | 1997-12-09 | | Claws | cat | 1994-03-17 | | Fluffy | cat | 1993-02-04 | | Fang | dog | 1990-08-27 | | Bowser | dog | 1989-08-31 | | Buffy | dog | 1989-05-13 | | Puffball | hamster | 1999-03-30 | | Slim | snake | 1996-04-29 | +----------+---------+------------+
Note that the DESC
keyword applies only to the column name immediately
preceding it (birth
); it does not affect the species
column sort
order.
MySQL provides several functions that you can use to perform calculations on dates, for example, to calculate ages or extract parts of dates.
To determine how many years old each of your pets is, compute the difference in the year part of the current date and the birth date, then subtract one if the current date occurs earlier in the calendar year than the birth date. The following query shows, for each pet, the birth date, the current date, and the age in years.
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | +----------+------------+------------+------+
Here, YEAR()
pulls out the year part of a date and RIGHT()
pulls off the rightmost five characters that represent the MM-DD
(calendar year) part of the date. The part of the expression that
compares the MM-DD
values evaluates to 1 or 0, which adjusts the
year difference down a year if CURDATE()
occurs earlier in
the year than birth
. The full expression is somewhat ungainly,
so an alias (age
) is used to make the output column label more
meaningful.
The query works, but the result could be scanned more easily if the rows
were presented in some order. This can be done by adding an ORDER
BY name
clause to sort the output by name:
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet ORDER BY name; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | +----------+------------+------------+------+
To sort the output by age
rather than name
, just use a
different ORDER BY
clause:
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet ORDER BY age; +----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | +----------+------------+------------+------+
A similar query can be used to determine age at death for animals that have
died. You determine which animals these are by checking whether the
death
value is NULL
. Then, for those with non-NULL
values, compute the difference between the death
and birth
values:
mysql> SELECT name, birth, death, -> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5)) -> AS age -> FROM pet WHERE death IS NOT NULL ORDER BY age; +--------+------------+------------+------+ | name | birth | death | age | +--------+------------+------------+------+ | Bowser | 1989-08-31 | 1995-07-29 | 5 | +--------+------------+------------+------+
The query uses death IS NOT NULL
rather than death <> NULL
because NULL
is a special value that cannot be compared using the usual
comparison operators. This is discussed later.
See section 3.3.4.6 Working with NULL
Values.
What if you want to know which animals have birthdays next month? For this
type of calculation, year and day are irrelevant; you simply want to extract
the month part of the birth
column. MySQL provides several
date-part extraction functions, such as YEAR()
, MONTH()
, and
DAYOFMONTH()
. MONTH()
is the appropriate function here. To
see how it works, run a simple query that displays the value of both
birth
and MONTH(birth)
:
mysql> SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+ | name | birth | MONTH(birth) | +----------+------------+--------------+ | Fluffy | 1993-02-04 | 2 | | Claws | 1994-03-17 | 3 | | Buffy | 1989-05-13 | 5 | | Fang | 1990-08-27 | 8 | | Bowser | 1989-08-31 | 8 | | Chirpy | 1998-09-11 | 9 | | Whistler | 1997-12-09 | 12 | | Slim | 1996-04-29 | 4 | | Puffball | 1999-03-30 | 3 | +----------+------------+--------------+
Finding animals with birthdays in the upcoming month is easy, too. Suppose
that the current month is April. Then the month value is 4
and you look
for animals born in May (month 5
) like this:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+ | name | birth | +-------+------------+ | Buffy | 1989-05-13 | +-------+------------+
There is a small complication if the current month is December.
You don't just add one to the month number (12
) and look for animals
born in month 13
, because there is no such month. Instead, you look for
animals born in January (month 1
).
You can even write the query so that it works no matter what the current
month is. That way you don't have to use a particular month number
in the query. DATE_ADD()
allows you to add a time interval to a
given date. If you add a month to the value of CURDATE()
, then extract
the month part with MONTH()
, the result produces the month in which to
look for birthdays:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
A different way to accomplish the same task is to add 1
to get the
next month after the current one (after using the modulo function (MOD
)
to wrap around the month value to 0
if it is currently
12
):
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
Note that MONTH
returns a number between 1
and 12
. And
MOD(something,12)
returns a number between 0
and 11
. So the
addition has to be after the MOD()
, otherwise we would go from
November (11
) to January (1
).
NULL
Values
The NULL
value can be surprising until you get used to it.
Conceptually, NULL
means missing value or unknown value and it
is treated somewhat differently than other values. To test for NULL
,
you cannot use the arithmetic comparison operators such as =
, <
,
or <>
. To demonstrate this for yourself, try the following query:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL; +----------+-----------+----------+----------+ | 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL | +----------+-----------+----------+----------+ | NULL | NULL | NULL | NULL | +----------+-----------+----------+----------+
Clearly you get no meaningful results from these comparisons. Use
the IS NULL
and IS NOT NULL
operators instead:
mysql> SELECT 1 IS NULL, 1 IS NOT NULL; +-----------+---------------+ | 1 IS NULL | 1 IS NOT NULL | +-----------+---------------+ | 0 | 1 | +-----------+---------------+
Note that in MySQL, 0
or NULL
means false and anything else means
true. The default truth value from a boolean operation is 1
.
This special treatment of NULL
is why, in the previous section, it
was necessary to determine which animals are no longer alive using
death IS NOT NULL
instead of death <> NULL
.
Two NULL
values are regarded as equal in a GROUP BY
.
When doing an ORDER BY
, NULL
values are presented first if you
do ORDER BY ... ASC
and last if you do ORDER BY ... DESC
.
Note that MySQL 4.0.2 to 4.0.10 incorrectly always sorts NULL
values
first regardless of the sort direction.
MySQL provides standard SQL pattern matching as well as a form of
pattern matching based on extended regular expressions similar to those used
by Unix utilities such as vi
, grep
, and sed
.
SQL pattern matching allows you to use `_' to match any single
character and `%' to match an arbitrary number of characters (including
zero characters). In MySQL, SQL patterns are case-insensitive by
default. Some examples are shown here. Note that you do not use =
or <>
when you use SQL patterns; use the LIKE
or NOT
LIKE
comparison operators instead.
To find names beginning with `b':
mysql> SELECT * FROM pet WHERE name LIKE 'b%'; +--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+
To find names ending with `fy':
mysql> SELECT * FROM pet WHERE name LIKE '%fy'; +--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+
To find names containing a `w':
mysql> SELECT * FROM pet WHERE name LIKE '%w%'; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+
To find names containing exactly five characters, use five instances of the `_' pattern character:
mysql> SELECT * FROM pet WHERE name LIKE '_____'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
The other type of pattern matching provided by MySQL uses extended
regular expressions. When you test for a match for this type of pattern, use
the REGEXP
and NOT REGEXP
operators (or RLIKE
and
NOT RLIKE
, which are synonyms).
Some characteristics of extended regular expressions are:
REGEXP
pattern match succeed if
the pattern matches anywhere in the value being tested.
(This differs from a LIKE
pattern match, which succeeds only if the
pattern matches the entire value.)
To demonstrate how extended regular expressions work, the LIKE
queries
shown previously are rewritten here to use REGEXP
.
To find names beginning with `b', use `^' to match the beginning of the name:
mysql> SELECT * FROM pet WHERE name REGEXP '^b'; +--------+--------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+------------+ | Buffy | Harold | dog | f | 1989-05-13 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | +--------+--------+---------+------+------------+------------+
Prior to MySQL Version 3.23.4, REGEXP
is case sensitive,
and the previous query will return no rows. In this case, to match either
lowercase or uppercase `b', use this query instead:
mysql> SELECT * FROM pet WHERE name REGEXP '^[bB]';
From MySQL 3.23.4 on, if you really want to force a REGEXP
comparison to
be case sensitive, use the BINARY
keyword to make one of the
strings a binary string. This query will match only lowercase `b'
at the beginning of a name:
mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b';
To find names ending with `fy', use `$' to match the end of the name:
mysql> SELECT * FROM pet WHERE name REGEXP 'fy$'; +--------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +--------+--------+---------+------+------------+-------+ | Fluffy | Harold | cat | f | 1993-02-04 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +--------+--------+---------+------+------------+-------+
To find names containing a `w', use this query:
mysql> SELECT * FROM pet WHERE name REGEXP 'w'; +----------+-------+---------+------+------------+------------+ | name | owner | species | sex | birth | death | +----------+-------+---------+------+------------+------------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 | | Whistler | Gwen | bird | NULL | 1997-12-09 | NULL | +----------+-------+---------+------+------------+------------+
Because a regular expression pattern matches if it occurs anywhere in the value, it is not necessary in the previous query to put a wildcard on either side of the pattern to get it to match the entire value like it would be if you used an SQL pattern.
To find names containing exactly five characters, use `^' and `$' to match the beginning and end of the name, and five instances of `.' in between:
mysql> SELECT * FROM pet WHERE name REGEXP '^.....$'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
You could also write the previous query using the `{n}'
``repeat-n
-times'' operator:
mysql> SELECT * FROM pet WHERE name REGEXP '^.{5}$'; +-------+--------+---------+------+------------+-------+ | name | owner | species | sex | birth | death | +-------+--------+---------+------+------------+-------+ | Claws | Gwen | cat | m | 1994-03-17 | NULL | | Buffy | Harold | dog | f | 1989-05-13 | NULL | +-------+--------+---------+------+------------+-------+
Databases are often used to answer the question, ``How often does a certain type of data occur in a table?'' For example, you might want to know how many pets you have, or how many pets each owner has, or you might want to perform various kinds of census operations on your animals.
Counting the total number of animals you have is the same question as ``How
many rows are in the pet
table?'' because there is one record per pet.
COUNT(*)
counts the number of rows, so
the query to count your animals looks like this:
mysql> SELECT COUNT(*) FROM pet; +----------+ | COUNT(*) | +----------+ | 9 | +----------+
Earlier, you retrieved the names of the people who owned pets. You can
use COUNT()
if you want to find out how many pets each owner has:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+ | owner | COUNT(*) | +--------+----------+ | Benny | 2 | | Diane | 2 | | Gwen | 3 | | Harold | 2 | +--------+----------+
Note the use of GROUP BY
to group together all records for each
owner
. Without it, all you get is an error message:
mysql> SELECT owner, COUNT(*) FROM pet; ERROR 1140: Mixing of GROUP columns (MIN(),MAX(),COUNT()...) with no GROUP columns is illegal if there is no GROUP BY clause
COUNT()
and GROUP BY
are useful for characterizing your
data in various ways. The following examples show different ways to
perform animal census operations.
Number of animals per species:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species; +---------+----------+ | species | COUNT(*) | +---------+----------+ | bird | 2 | | cat | 2 | | dog | 3 | | hamster | 1 | | snake | 1 | +---------+----------+
Number of animals per sex:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+ | sex | COUNT(*) | +------+----------+ | NULL | 1 | | f | 4 | | m | 4 | +------+----------+
(In this output, NULL
indicates that the sex is unknown.)
Number of animals per combination of species and sex:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | bird | NULL | 1 | | bird | f | 1 | | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | | hamster | f | 1 | | snake | m | 1 | +---------+------+----------+
You need not retrieve an entire table when you use COUNT()
. For
example, the previous query, when performed just on dogs and cats, looks like
this:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE species = 'dog' OR species = 'cat' -> GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | +---------+------+----------+
Or, if you wanted the number of animals per sex only for known-sex animals:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE sex IS NOT NULL -> GROUP BY species, sex; +---------+------+----------+ | species | sex | COUNT(*) | +---------+------+----------+ | bird | f | 1 | | cat | f | 1 | | cat | m | 1 | | dog | f | 1 | | dog | m | 2 | | hamster | f | 1 | | snake | m | 1 | +---------+------+----------+
The pet
table keeps track of which pets you have. If you want to
record other information about them, such as events in their lives like
visits to the vet or when litters are born, you need another table. What
should this table look like? It needs:
Given these considerations, the CREATE TABLE
statement for the
event
table might look like this:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, -> type VARCHAR(15), remark VARCHAR(255));
As with the pet
table, it's easiest to load the initial records
by creating a tab-delimited text file containing the information:
name | date | type | remark |
Fluffy | 1995-05-15 | litter | 4 kittens, 3 female, 1 male |
Buffy | 1993-06-23 | litter | 5 puppies, 2 female, 3 male |
Buffy | 1994-06-19 | litter | 3 puppies, 3 female |
Chirpy | 1999-03-21 | vet | needed beak straightened |
Slim | 1997-08-03 | vet | broken rib |
Bowser | 1991-10-12 | kennel | |
Fang | 1991-10-12 | kennel | |
Fang | 1998-08-28 | birthday | Gave him a new chew toy |
Claws | 1998-03-17 | birthday | Gave him a new flea collar |
Whistler | 1998-12-09 | birthday | First birthday |
Load the records like this:
mysql> LOAD DATA LOCAL INFILE 'event.txt' INTO TABLE event;
Based on what you've learned from the queries you've run on the pet
table, you should be able to perform retrievals on the records in the
event
table; the principles are the same. But when is the
event
table by itself insufficient to answer questions you might ask?
Suppose that you want to find out the ages at which each pet had its
litters. We saw earlier how to calculate ages from two dates.
The litter date of the mother is in the
event
table, but to calculate her age on that date you need her
birth date, which is stored in the pet
table.
This means the query requires both tables:
mysql> SELECT pet.name, -> (YEAR(date)-YEAR(birth)) - (RIGHT(date,5)<RIGHT(birth,5)) AS age, -> remark -> FROM pet, event -> WHERE pet.name = event.name AND type = 'litter'; +--------+------+-----------------------------+ | name | age | remark | +--------+------+-----------------------------+ | Fluffy | 2 | 4 kittens, 3 female, 1 male | | Buffy | 4 | 5 puppies, 2 female, 3 male | | Buffy | 5 | 3 puppies, 3 female | +--------+------+-----------------------------+
There are several things to note about this query:
FROM
clause lists two tables because the query needs to pull
information from both of them.
name
column. The query uses
WHERE
clause to match up records in the two tables based on the
name
values.
name
column occurs in both tables, you must be specific
about which table you mean when referring to the column. This is done
by prepending the table name to the column name.
You need not have two different tables to perform a join. Sometimes it is
useful to join a table to itself, if you want to compare records in a table
to other records in that same table. For example, to find breeding pairs
among your pets, you can join the pet
table with itself to produce
candidate pairs of males and females of like species:
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species -> FROM pet AS p1, pet AS p2 -> WHERE p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm'; +--------+------+--------+------+---------+ | name | sex | name | sex | species | +--------+------+--------+------+---------+ | Fluffy | f | Claws | m | cat | | Buffy | f | Fang | m | dog | | Buffy | f | Bowser | m | dog | +--------+------+--------+------+---------+
In this query, we specify aliases for the table name in order to refer to the columns and keep straight which instance of the table each column reference is associated with.
What if you forget the name of a database or table, or what the structure of a given table is (for example, what its columns are called)? MySQL addresses this problem through several statements that provide information about the databases and tables it supports.
You have previously seen SHOW DATABASES
, which lists the databases
managed by the server. To find out which database is currently selected,
use the DATABASE()
function:
mysql> SELECT DATABASE(); +------------+ | DATABASE() | +------------+ | menagerie | +------------+
If you haven't selected any database yet, the result is NULL
(or the empty string before MySQL 4.1.1).
To find out what tables the current database contains (for example, when you're not sure about the name of a table), use this command:
mysql> SHOW TABLES; +---------------------+ | Tables in menagerie | +---------------------+ | event | | pet | +---------------------+
If you want to find out about the structure of a table, the DESCRIBE
command is useful; it displays information about each of a table's columns:
mysql> DESCRIBE pet; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | name | varchar(20) | YES | | NULL | | | owner | varchar(20) | YES | | NULL | | | species | varchar(20) | YES | | NULL | | | sex | char(1) | YES | | NULL | | | birth | date | YES | | NULL | | | death | date | YES | | NULL | | +---------+-------------+------+-----+---------+-------+
Field
indicates the column name, Type
is the data type for
the column, NULL
indicates whether the column can contain
NULL
values, Key
indicates whether the column is
indexed, and Default
specifies the column's default value.
If you have indexes on a table,
SHOW INDEX FROM tbl_name
produces information about them.
mysql
in Batch Mode
In the previous sections, you used mysql
interactively to enter
queries and view the results. You can also run mysql
in batch
mode. To do this, put the commands you want to run in a file, then
tell mysql
to read its input from the file:
shell> mysql < batch-file
If you are running mysql
under Windows and have some special
characters in the file that cause problems, you can do this:
C:\> mysql -e "source batch-file"
If you need to specify connection parameters on the command line, the command might look like this:
shell> mysql -h host -u user -p < batch-file Enter password: ********
When you use mysql
this way, you are creating a script file, then
executing the script.
If you want the script to continue even if some of the statements in it
produce errors, you should
use the --force
command-line option.
Why use a script? Here are a few reasons:
mysql
to execute it again.
shell> mysql < batch-file | more
shell> mysql < batch-file > mysql.out
cron
job. In this case, you must use batch mode.
The default output format is different (more concise) when you run
mysql
in batch mode than when you use it interactively. For
example, the output of SELECT DISTINCT species FROM pet
looks like
this when mysql
is run interactively:
+---------+ | species | +---------+ | bird | | cat | | dog | | hamster | | snake | +---------+
In batch mode, the output looks like this instead:
species bird cat dog hamster snake
If you want to get the interactive output format in batch mode, use
mysql -t
. To echo to the output the commands that are executed, use
mysql -vvv
.
You can also use scripts from the mysql
prompt by
using the source
or \.
command:
mysql> source filename; mysql> \. filename
Here are examples of how to solve some common problems with MySQL.
Some of the examples use the table shop
to hold the price of each
article (item number) for certain traders (dealers). Supposing that each
trader has a single fixed price per article, then (article
,
dealer
) is a primary key for the records.
Start the command-line tool mysql
and select a database:
shell> mysql your-database-name
(In most MySQL installations, you can use the database name test
).
You can create and populate the example table with these statements:
mysql> CREATE TABLE shop ( -> article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, -> dealer CHAR(20) DEFAULT '' NOT NULL, -> price DOUBLE(16,2) DEFAULT '0.00' NOT NULL, -> PRIMARY KEY(article, dealer)); mysql> INSERT INTO shop VALUES -> (1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45), -> (3,'C',1.69),(3,'D',1.25),(4,'D',19.95);
After issuing the statements, the table should have the following contents:
mysql> SELECT * FROM shop; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0001 | A | 3.45 | | 0001 | B | 3.99 | | 0002 | A | 10.99 | | 0003 | B | 1.45 | | 0003 | C | 1.69 | | 0003 | D | 1.25 | | 0004 | D | 19.95 | +---------+--------+-------+
``What's the highest item number?''
SELECT MAX(article) AS article FROM shop; +---------+ | article | +---------+ | 4 | +---------+
``Find number, dealer, and price of the most expensive article.''
In standard SQL (and as of MySQL 4.1), this is easily done with a subquery:
SELECT article, dealer, price FROM shop WHERE price=(SELECT MAX(price) FROM shop);
In MySQL versions prior to 4.1, just do it in two steps:
SELECT
statement.
mysql> SELECT MAX(price) FROM shop; +------------+ | MAX(price) | +------------+ | 19.95 | +------------+
mysql> SELECT article, dealer, price -> FROM shop -> WHERE price=19.95; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0004 | D | 19.95 | +---------+--------+-------+
Another solution is to sort all rows descending by price and only
get the first row using the MySQL-specific LIMIT
clause:
SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1;
Note: If there were several most expensive articles, each with a
price of 19.95, the LIMIT
solution would show only one of them!
``What's the highest price per article?''
SELECT article, MAX(price) AS price FROM shop GROUP BY article +---------+-------+ | article | price | +---------+-------+ | 0001 | 3.99 | | 0002 | 10.99 | | 0003 | 1.69 | | 0004 | 19.95 | +---------+-------+
``For each article, find the dealer or dealers with the most expensive price.''
In standard SQL (and as of MySQL 4.1), the problem can be solved with a subquery like this:
SELECT article, dealer, price FROM shop s1 WHERE price=(SELECT MAX(s2.price) FROM shop s2 WHERE s1.article = s2.article);
In MySQL versions prior to 4.1, it's best do it in several steps:
This can easily be done with a temporary table and a join:
CREATE TEMPORARY TABLE tmp ( article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL, price DOUBLE(16,2) DEFAULT '0.00' NOT NULL); LOCK TABLES shop READ; INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article; SELECT shop.article, dealer, shop.price FROM shop, tmp WHERE shop.article=tmp.article AND shop.price=tmp.price; UNLOCK TABLES; DROP TABLE tmp;
If you don't use a TEMPORARY
table, you must also lock the tmp
table.
``Can it be done with a single query?''
Yes, but only by using a quite inefficient trick called the ``MAX-CONCAT trick'':
SELECT article, SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer, 0.00+LEFT( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price FROM shop GROUP BY article; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0001 | B | 3.99 | | 0002 | A | 10.99 | | 0003 | C | 1.69 | | 0004 | D | 19.95 | +---------+--------+-------+
The last example can be made a bit more efficient by doing the splitting of the concatenated column in the client.
You can use MySQL user variables to remember results without having to store them in temporary variables in the client. See section 9.3 User Variables.
For example, to find the articles with the highest and lowest price you can do this:
mysql> SELECT @min_price:=MIN(price),@max_price:=MAX(price) FROM shop; mysql> SELECT * FROM shop WHERE price=@min_price OR price=@max_price; +---------+--------+-------+ | article | dealer | price | +---------+--------+-------+ | 0003 | D | 1.25 | | 0004 | D | 19.95 | +---------+--------+-------+
In MySQL 3.23.44 and up, InnoDB
tables support checking of
foreign key constraints. See section 15 The InnoDB
Storage Engine.
See also section 1.5.5.5 Foreign Keys.
You don't actually need foreign keys to join two tables.
For table types other than InnoDB
,
the only things MySQL currently doesn't do are 1)
CHECK
to make sure that the keys you use
really exist in the table or tables you're referencing and 2)
automatically delete rows from a table with a foreign key
definition. Using your keys to join tables will work just fine:
CREATE TABLE person ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, name CHAR(60) NOT NULL, PRIMARY KEY (id) ); CREATE TABLE shirt ( id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, style ENUM('t-shirt', 'polo', 'dress') NOT NULL, color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL, owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id), PRIMARY KEY (id) ); INSERT INTO person VALUES (NULL, 'Antonio Paz'); SELECT @last := LAST_INSERT_ID(); INSERT INTO shirt VALUES (NULL, 'polo', 'blue', @last), (NULL, 'dress', 'white', @last), (NULL, 't-shirt', 'blue', @last); INSERT INTO person VALUES (NULL, 'Lilliana Angelovska'); SELECT @last := LAST_INSERT_ID(); INSERT INTO shirt VALUES (NULL, 'dress', 'orange', @last), (NULL, 'polo', 'red', @last), (NULL, 'dress', 'blue', @last), (NULL, 't-shirt', 'white', @last); SELECT * FROM person; +----+---------------------+ | id | name | +----+---------------------+ | 1 | Antonio Paz | | 2 | Lilliana Angelovska | +----+---------------------+ SELECT * FROM shirt; +----+---------+--------+-------+ | id | style | color | owner | +----+---------+--------+-------+ | 1 | polo | blue | 1 | | 2 | dress | white | 1 | | 3 | t-shirt | blue | 1 | | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | | 7 | t-shirt | white | 2 | +----+---------+--------+-------+ SELECT s.* FROM person p, shirt s WHERE p.name LIKE 'Lilliana%' AND s.owner = p.id AND s.color <> 'white'; +----+-------+--------+-------+ | id | style | color | owner | +----+-------+--------+-------+ | 4 | dress | orange | 2 | | 5 | polo | red | 2 | | 6 | dress | blue | 2 | +----+-------+--------+-------+
An OR
using a single key is well optimized, as is the handling
of AND
.
The one tricky case is that of searching on two different keys
combined with OR
:
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1' OR field2_index = '1'
This case is optimized from MySQL 5.0.0. See section 7.2.6 Index Merge Optimization.
In MySQL 4.0 and up, you can also solve the problem efficiently by
using a UNION
that combines the output of two separate
SELECT
statements.
See section 13.1.7.2 UNION
Syntax.
Each SELECT
searches only one key and can be optimized:
SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1' UNION SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1';
Prior to MySQL 4.0, you can achieve the same effect by using a
TEMPORARY
table and separate SELECT
statements.
This type of optimization is also very good if
you are using very complicated queries where the SQL server does the
optimizations in the wrong order.
CREATE TEMPORARY TABLE tmp SELECT field1_index, field2_index FROM test_table WHERE field1_index = '1'; INSERT INTO tmp SELECT field1_index, field2_index FROM test_table WHERE field2_index = '1'; SELECT * from tmp; DROP TABLE tmp;
This method of solving the problem is in effect a UNION
of two queries.
The following example shows how you can use the bit group functions to calculate the number of days per month a user has visited a Web page.
CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, day INT(2) UNSIGNED ZEROFILL); INSERT INTO t1 VALUES(2000,1,1),(2000,1,20),(2000,1,30),(2000,2,2), (2000,2,23),(2000,2,23);
The example table contains year-month-day values representing visits by users to the page. To determine how many different days in each month these visits occur, use this query:
SELECT year,month,BIT_COUNT(BIT_OR(1<<day)) AS days FROM t1 GROUP BY year,month;
Which returns:
+------+-------+------+ | year | month | days | +------+-------+------+ | 2000 | 01 | 3 | | 2000 | 02 | 2 | +------+-------+------+
The query calculates how many different days appear in the table for each year/month combination, with automatic removal of duplicate entries.
AUTO_INCREMENT
The AUTO_INCREMENT
attribute can be used to generate a unique
identity for new rows:
CREATE TABLE animals ( id MEDIUMINT NOT NULL AUTO_INCREMENT, name CHAR(30) NOT NULL, PRIMARY KEY (id) ); INSERT INTO animals (name) VALUES ('dog'),('cat'),('penguin'), ('lax'),('whale'),('ostrich'); SELECT * FROM animals;
Which returns:
+----+---------+ | id | name | +----+---------+ | 1 | dog | | 2 | cat | | 3 | penguin | | 4 | lax | | 5 | whale | | 6 | ostrich | +----+---------+
You can retrieve the most recent AUTO_INCREMENT
value with the
LAST_INSERT_ID()
SQL function or the mysql_insert_id()
C API
function. These functions are connection-specific, so their return value
is not affected by another connection also doing inserts.
Note: For a multiple-row insert,
LAST_INSERT_ID()
/mysql_insert_id()
will actually return the
AUTO_INCREMENT
key from the first of the inserted rows.
This allows multiple-row inserts to be reproduced correctly on other servers
in a replication setup.
For MyISAM
and BDB
tables you can specify AUTO_INCREMENT
on a secondary column in a multiple-column index. In this case, the generated
value for the AUTO_INCREMENT
column is calculated as
MAX(auto_increment_column)+1 WHERE prefix=given-prefix
. This is
useful when you want to put data into ordered groups.
CREATE TABLE animals ( grp ENUM('fish','mammal','bird') NOT NULL, id MEDIUMINT NOT NULL AUTO_INCREMENT, name CHAR(30) NOT NULL, PRIMARY KEY (grp,id) ); INSERT INTO animals (grp,name) VALUES('mammal','dog'),('mammal','cat'), ('bird','penguin'),('fish','lax'),('mammal','whale'), ('bird','ostrich'); SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+ | grp | id | name | +--------+----+---------+ | fish | 1 | lax | | mammal | 1 | dog | | mammal | 2 | cat | | mammal | 3 | whale | | bird | 1 | penguin | | bird | 2 | ostrich | +--------+----+---------+
Note that in this case (when the AUTO_INCREMENT
column is part of a
multiple-column index), AUTO_INCREMENT
values will be reused if you
delete the row with the biggest AUTO_INCREMENT
value in any group.
This happens even for MyISAM
tables, for which AUTO_INCREMENT
values normally are not reused.)
At Analytikerna and Lentus, we have been doing the systems and field work for a big research project. This project is a collaboration between the Institute of Environmental Medicine at Karolinska Institutet Stockholm and the Section on Clinical Research in Aging and Psychology at the University of Southern California.
The project involves a screening part where all twins in Sweden older than 65 years are interviewed by telephone. Twins who meet certain criteria are passed on to the next stage. In this latter stage, twins who want to participate are visited by a doctor/nurse team. Some of the examinations include physical and neuropsychological examination, laboratory testing, neuroimaging, psychological status assessment, and family history collection. In addition, data are collected on medical and environmental risk factors.
More information about Twin studies can be found at: http://www.mep.ki.se/twinreg/index_en.html
The latter part of the project is administered with a Web interface written using Perl and MySQL.
Each night all data from the interviews is moved into a MySQL database.
The following query is used to determine who goes into the second part of the project:
SELECT CONCAT(p1.id, p1.tvab) + 0 AS tvid, CONCAT(p1.christian_name, ' ', p1.surname) AS Name, p1.postal_code AS Code, p1.city AS City, pg.abrev AS Area, IF(td.participation = 'Aborted', 'A', ' ') AS A, p1.dead AS dead1, l.event AS event1, td.suspect AS tsuspect1, id.suspect AS isuspect1, td.severe AS tsevere1, id.severe AS isevere1, p2.dead AS dead2, l2.event AS event2, h2.nurse AS nurse2, h2.doctor AS doctor2, td2.suspect AS tsuspect2, id2.suspect AS isuspect2, td2.severe AS tsevere2, id2.severe AS isevere2, l.finish_date FROM twin_project AS tp /* For Twin 1 */ LEFT JOIN twin_data AS td ON tp.id = td.id AND tp.tvab = td.tvab LEFT JOIN informant_data AS id ON tp.id = id.id AND tp.tvab = id.tvab LEFT JOIN harmony AS h ON tp.id = h.id AND tp.tvab = h.tvab LEFT JOIN lentus AS l ON tp.id = l.id AND tp.tvab = l.tvab /* For Twin 2 */ LEFT JOIN twin_data AS td2 ON p2.id = td2.id AND p2.tvab = td2.tvab LEFT JOIN informant_data AS id2 ON p2.id = id2.id AND p2.tvab = id2.tvab LEFT JOIN harmony AS h2 ON p2.id = h2.id AND p2.tvab = h2.tvab LEFT JOIN lentus AS l2 ON p2.id = l2.id AND p2.tvab = l2.tvab, person_data AS p1, person_data AS p2, postal_groups AS pg WHERE /* p1 gets main twin and p2 gets his/her twin. */ /* ptvab is a field inverted from tvab */ p1.id = tp.id AND p1.tvab = tp.tvab AND p2.id = p1.id AND p2.ptvab = p1.tvab AND /* Just the screening survey */ tp.survey_no = 5 AND /* Skip if partner died before 65 but allow emigration (dead=9) */ (p2.dead = 0 OR p2.dead = 9 OR (p2.dead = 1 AND (p2.death_date = 0 OR (((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365) >= 65)))) AND ( /* Twin is suspect */ (td.future_contact = 'Yes' AND td.suspect = 2) OR /* Twin is suspect - Informant is Blessed */ (td.future_contact = 'Yes' AND td.suspect = 1 AND id.suspect = 1) OR /* No twin - Informant is Blessed */ (ISNULL(td.suspect) AND id.suspect = 1 AND id.future_contact = 'Yes') OR /* Twin broken off - Informant is Blessed */ (td.participation = 'Aborted' AND id.suspect = 1 AND id.future_contact = 'Yes') OR /* Twin broken off - No inform - Have partner */ (td.participation = 'Aborted' AND ISNULL(id.suspect) AND p2.dead = 0)) AND l.event = 'Finished' /* Get at area code */ AND SUBSTRING(p1.postal_code, 1, 2) = pg.code /* Not already distributed */ AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00) /* Has not refused or been aborted */ AND NOT (h.status = 'Refused' OR h.status = 'Aborted' OR h.status = 'Died' OR h.status = 'Other') ORDER BY tvid;
Some explanations:
CONCAT(p1.id, p1.tvab) + 0 AS tvid
id
and tvab
in
numerical order. Adding 0
to the result causes MySQL to
treat the result as a number.
id
tvab
1
or 2
.
ptvab
tvab
. When tvab
is 1
this is
2
, and vice versa. It exists to save typing and to make it easier for
MySQL to optimize the query.
This query demonstrates, among other things, how to do lookups on a table
from the same table with a join (p1
and p2
). In the example,
this is used to check whether a twin's partner died before the age of 65. If
so, the row is not returned.
All of the above exist in all tables with twin-related information. We
have a key on both id,tvab
(all tables), and id,ptvab
(person_data
) to make queries faster.
On our production machine (A 200MHz UltraSPARC), this query returns about 150-200 rows and takes less than one second.
The current number of records in the tables used in the query:
Table | Rows |
person_data | 71074 |
lentus | 5291 |
twin_project | 5286 |
twin_data | 2012 |
informant_data | 663 |
harmony | 381 |
postal_groups | 100 |
Each interview ends with a status code called event
. The query
shown here is used to display a table over all twin pairs combined by
event. This indicates in how many pairs both twins are finished, in how many
pairs one twin is finished and the other refused, and so on.
SELECT t1.event, t2.event, COUNT(*) FROM lentus AS t1, lentus AS t2, twin_project AS tp WHERE /* We are looking at one pair at a time */ t1.id = tp.id AND t1.tvab=tp.tvab AND t1.id = t2.id /* Just the screening survey */ AND tp.survey_no = 5 /* This makes each pair only appear once */ AND t1.tvab='1' AND t2.tvab='2' GROUP BY t1.event, t2.event;
There are programs that let you authenticate your users from a MySQL database and also let you write your log files into a MySQL table.
You can change the Apache logging format to be easily readable by MySQL by putting the following into the Apache configuration file:
LogFormat \ "\"%h\",%{%Y%m%d%H%M%S}t,%>s,\"%b\",\"%{Content-Type}o\", \ \"%U\",\"%{Referer}i\",\"%{User-Agent}i\""
To load a log file in that format into MySQL, you can use a statement something like this:
LOAD DATA INFILE '/local/access_log' INTO TABLE tbl_name FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\'
The named table should be created to have columns that correspond to those
that the LogFormat
line writes to the log file.
This chapter provides a brief overview of the programs provided by MySQL AB and discusses how to specify options when you run these programs. Most programs have options that are specific to their own operation, but the syntax for specifying options is similar for all of them. Later chapters provide more detailed descriptions of individual programs, including which options they recognize.
MySQL AB provides several types of programs:
mysqld
is the MySQL server
mysqld_safe
, mysql.server
, and mysqld_multi
are server
startup scripts
mysql_install_db
initializes the data directory and the initial
databases
mysql
is a command-line client for executing SQL statements interactively
or in batch mode
mysqlcc
(MySQL Control Center) is an interactive graphical tool for
executing SQL statements and administration
mysqladmin
is an administrative client
mysqlcheck
performs table maintenance operations
mysqldump
and mysqlhotcopy
make database backups
mysqlimport
imports data files
mysqlshow
displays information about databases and tables
myisamchk
performs table maintenance operations
myisampack
produces compressed, read-only tables
mysqlbinlog
is a tool for processing binary log files
perror
displays error code meanings
myisamchk
is discussed further in section 5 Database Administration.
The other programs are further in section 8 MySQL Client and Utility Programs.
Most MySQL distributions include all of these programs, except for those programs that are platform-specific. (For example, the server startup scripts are not used on Windows.) The exception is that RPM distributions are more specialized. There is one RPM for the server, another for the client programs, and so forth. If you appear to be missing one or more programs, see section 2 Installing MySQL for information on types of distributions and what they contain. It may be that you need to install something else.
To invoke a MySQL program at the command line (that is, from your shell or
command prompt), enter the program name followed by any options or other
arguments needed to instruct the program what you want it to do. The following
commands show some sample program invocations. ``shell>
'' represents
the prompt for your command interpreter; it is not part of what you type.
The particular prompt you will see depends on your command interpreter.
Typical prompts are $
for sh
or bash
, %
for
csh
or tcsh
, and C:\>
for Windows
command.com
or cmd.exe
.
shell> mysql test shell> mysqladmin extended-status variables shell> mysqlshow --help shell> mysqldump --user=root personnel
Arguments that begin with a dash are option arguments. They typically specify the type of connection a program should make to the server or affect its operational mode. Options have a syntax that is described in section 4.3 Specifying Program Options.
Non-option arguments (arguments with no leading dash) provide additional
information to the program. For example, the mysql
program interprets
the first non-option argument as a database name, so the command
mysql test
indicates that you want to use the test
database.
Later sections that describe individual programs indicate which options a program understands and describe the meaning of any additional non-option arguments.
Some options are common to a number of programs. The most common of these are
the --host
, --user
, and --password
options that specify
connection parameters. They indicate the host where the MySQL server is
running, and the username and password of your MySQL account. All MySQL client
programs understand these options; they allow you to specify which server to
connect to and the account to use on that server.
You may find it necessary to invoke MySQL programs using the
pathname to the `bin' directory in which they are installed. This is
likely to be the case if you get a ``program not found'' error whenever
you attempt to run a MySQL program from any directory other than the
`bin' directory. To make it more convenient to use MySQL, you
can add the pathname of the `bin' directory to your PATH
environment variable setting. Then to run a program you need only type
its name, not its entire pathname.
Consult the documentation for your command interpreter for instructions on
setting your PATH
. The syntax for setting environment variables is
interpreter-specific.
You can provide options for MySQL programs in several ways:
MySQL programs determine which options are given first by examining environment variables, then option files, and then the command line. If an option is specified multiple times, the last occurrence takes precedence. This means that environment variables have the lowest precedence and command-line options the highest.
You can take advantage of the way that MySQL programs process options by specifying the default values for a program's options in an option file. Then you need not type them each time you run the program, but can override the defaults if necessary by using command-line options.
Program options specified on the command line follow these rules:
-?
and --help
are the short and long forms
of the option that instructs a MySQL program to display a help message.
-v
and -V
are both legal and
have different meanings. (They are the corresponding short forms of the
--verbose
and --version
options.)
-h localhost
or --host=localhost
indicate
the MySQL server host to a client program. The option value
tells the program the name of the host where the MySQL server is running.
-hlocalhost
and -h localhost
are equivalent.)
An exception to this rule is the option for specifying your MySQL password.
This option can be given in long form as --password=pass_val
or as
--password
. In the latter case (with no password value given), the
program will prompt you for the password.
The password option also may be given in short form as -ppass_val
or as
-p
. However, for the short form, if the password value is given, it
must follow the option letter with no intervening space. The reason for
this is that if a space follows the option letter, the program has no way to
tell whether a following argument is supposed to be the password value or some
other kind of argument. Consequently, the following two commands have two
completely different meanings:
shell> mysql -ptest shell> mysql -p testThe first command instructs
mysql
to use a password value of
test
, but specifies no default database.
The second instructs mysql
to prompt for the password value
and to use test
as the default database.
MySQL 4.0 introduced some additional flexibility in the way you specify options. These changes were made in MySQL 4.0.2. Some of them relate to the way you specify options that have ``enabled'' and ``disabled'' states, and to the use of options that might be present in one version of MySQL but not another. Those capabilities are discussed in this section. Another change pertains to the way you use options to set program variables. section 4.3.4 Using Options to Set Program Variables discusses that topic further.
Some options control behavior that can be turned on or off. For example,
the mysql
client supports a --column-names
option that
determines whether or not to display a row of column names at the beginning
of query results. By default, this option is enabled. However, you may
want to disable it in some instances, such as when sending the output
of mysql
into another program that expects to see only data and
not an initial header line.
To disable column names, you can specify the option using any of these forms:
--disable-column-names --skip-column-names --column-names=0
The --disable
and --skip
prefixes and the =0
suffix
all have the same effect: They turn the option off.
The ``enabled'' form of the option may be specified in any of these ways:
--column-names --enable-column-names --column-names=1
Another change to option processing introduced in MySQL 4.0 is that you
can use the --loose
prefix for command-line options. If an option
is prefixed by --loose
, the program will not exit with
an error if it does not recognize the option, but instead will issue
only a warning:
shell> mysql --loose-no-such-option mysql: WARNING: unknown option '--no-such-option'
The --loose
prefix can be useful when you run programs from
multiple installations of MySQL on the same machine, at least if all the
versions are as recent as 4.0.2. This prefix is particularly useful when you
list options in an option file. An option that may not be recognized by all
versions of a program can be given using the --loose
prefix (or loose
in an option file). Versions of the program that do
not recognize the option will issue a warning and ignore it. This
strategy requires that versions involved be 4.0.2 or later, because
earlier versions know nothing of the --loose
convention.
MySQL programs can read startup options from option files (also sometimes called configuration files). Option files provide a convenient way to specify commonly used options so that they need not be entered on the command line each time you run a program. Option file capability is available from MySQL 3.22 on.
The following programs support option files:
myisamchk
,
myisampack
,
mysql
,
mysql.server
,
mysqladmin
,
mysqlbinlog
,
mysqlcc
,
mysqlcheck
,
mysqld_safe
,
mysqldump
,
mysqld
,
mysqlhotcopy
,
mysqlimport
, and
mysqlshow
.
On Windows, MySQL programs read startup options from the following files:
Filename | Purpose |
WINDIR\my.ini | Global options |
C:\my.cnf | Global options |
WINDIR represents the location of your Windows directory. This is
commonly `C:\Windows' or `C:\WinNT'. You can determine its
exact location from the value of the WINDIR
environment variable
using the following command:
C:\> echo %WINDIR%
On Unix, MySQL programs read startup options from the following files:
Filename | Purpose |
/etc/my.cnf | Global options |
DATADIR/my.cnf | Server-specific options |
defaults-extra-file | The file specified with --defaults-extra-file=path , if any
|
~/.my.cnf | User-specific options |
DATADIR represents the location of the MySQL data directory. Typically
this is `/usr/local/mysql/data' for a binary installation or
`/usr/local/var' for a source installation. Note that this is the data
directory location that was specified at configuration time, not the
one specified with --datadir
when mysqld
starts.
Use of --datadir
at runtime has no effect on where the server
looks for option files, because it looks for them before processing any
command-line arguments.
MySQL looks for option files in the order just described and reads any that exist. If an option file that you want to use does not exist, create it with a plain text editor. If multiple option files exist, an option specified in a file read later takes precedence over the same option specified in a file read earlier.
Any long option that may be given on the command line when running a
MySQL program can be given in an option file as well. To get the list
of available options for a program, run it with the --help
option.
The syntax for
specifying options in an option file is similar to command-line syntax, except
that you omit the leading two dashes. For example, --quick
or
--host=localhost
on the command line should be specified as
quick
or host=localhost
in an option file.
To specify an option of the form --loose-opt_name
in an option file, write it as loose-opt_name
.
Empty lines in option files are ignored. Non-empty lines can take any of the following forms:
#comment
;comment
[group]
set-variable
lines
apply to the named group until the end of the option file or another group
line is given.
opt_name
--opt_name
on the command line.
opt_name=value
--opt_name=value
on the command line.
In an option file, you can have spaces around the `=' character,
something that is not true on the command line.
As of
MySQL 4.0.16, you can quote the value with double quotes or single quotes.
This is useful if the value contains a `#' comment character or whitespace.
set-variable = var_name=value
--set-variable=var_name=value
on the
command line.
Spaces are allowed around the first `=' character but not around
the second.
This syntax is deprecated as of MySQL 4.0.
See section 4.3.4 Using Options to Set Program Variables for more information on setting program variables.
Leading and trailing blanks are automatically deleted from option names and values. You may use the escape sequences `\b', `\t', `\n', `\r', `\\', and `\s' in option values to represent the backspace, tab, newline, carriage return, and space characters.
On Windows, if an option value represents a pathname, you should specify the value using `/' rather than `\' as the pathname separator. If you use `\', you must double it as `\\', because `\' is the escape character in MySQL.
If an option group name is the same as a program name, options in the group apply specifically to that program.
The [client]
option group is read by all client programs (but not
by mysqld
). This allows you to specify options that apply to every
client. For example, [client]
is the perfect group to use to specify
the password that you use to connect to the server. (But make sure that
the option file is readable and writable only by yourself, so that other
people cannot find out your password.) Be sure not to put an option in the
[client]
group unless it is recognized by all client programs
that you use. Programs that do not understand the option will quit after
displaying an error message if you try to run them.
As of MySQL 4.0.14, if you want to create option groups that should be
read only by one specific mysqld
server release series, you can do this by
using groups with names of [mysqld-4.0]
, [mysqld-4.1]
, and so
forth. The following group indicates that the --new
option should be
used only by MySQL servers with 4.0.x version numbers:
[mysqld-4.0] new
Here is a typical global option file:
[client] port=3306 socket=/tmp/mysql.sock [mysqld] port=3306 socket=/tmp/mysql.sock key_buffer_size=16M max_allowed_packet=8M [mysqldump] quick
The preceding option file uses var_name=value
syntax for the
lines that set the key_buffer_size
and max_allowed_packet
variables. Prior to MySQL 4.0.2, you would need to use set-variable
syntax instead (described earlier in this section).
Here is a typical user option file:
[client] # The following password will be sent to all standard MySQL clients password="my_password" [mysql] no-auto-rehash set-variable = connect_timeout=2 [mysqlhotcopy] interactive-timeout
This option file uses set-variable
syntax to set the
connect_timeout
variable. For MySQL 4.0.2 and up, you can also set
the variable using just connect_timeout=2
.
If you have a source distribution, you will find sample option files named `my-xxxx.cnf' in the `support-files' directory. If you have a binary distribution, look in the `support-files' directory under your MySQL installation directory (typically `C:\mysql' on Windows or `/usr/local/mysql' on Unix). On Windows the sample option files may also be located in the MySQL installation directory. Currently there are sample option files for small, medium, large, and very large systems. To experiment with one of these files, copy it to `C:\my.cnf' on Windows or to `.my.cnf' in your home directory on Unix.
Note: On Windows, the `.cnf' option file extension might not be displayed.
All MySQL programs that support option files handle the following command-line options:
--no-defaults
--print-defaults
--defaults-file=path_name
--defaults-extra-file=path_name
To work properly, each of these options must immediately
follow the command name on the command line, with the exception
that --print-defaults
may be used immediately after
--defaults-file
or --defaults-extra-file
.
In shell scripts, you can use the my_print_defaults
program to parse
option files. The following example shows the output that
my_print_defaults
might produce when asked to show the options found in
the [client]
and [mysql]
groups:
shell> my_print_defaults client mysql --port=3306 --socket=/tmp/mysql.sock --no-auto-rehash
Note for developers: Option file handling is implemented in the C client library simply by processing all matching options (that is, options in the appropriate group) before any command-line arguments. This works nicely for programs that use the last instance of an option that is specified multiple times. If you have a C or C++ program that handles multiply specified options this way but doesn't read option files, you need add only two lines to give it that capability. Check the source code of any of the standard MySQL clients to see how to do this.
Several other language interfaces to MySQL are based on the C client library, and some of them provide a way to access option file contents. These include Perl and Python. See the documentation for your preferred interface for details.
To specify an option using an environment variable, set the variable using the
syntax appropriate for your comment processor. For example, on Windows or
NetWare,
you can set the USER
variable to specify your MySQL account name.
To do so, use this syntax:
SET USER=your_name
The syntax on Unix depends on your shell. Suppose that you want to specify the
TCP/IP port number using the MYSQL_TCP_PORT
variable. The syntax for
Bourne shell and variants (sh
, bash
, zsh
, etc.) is:
MYSQL_TCP_PORT=3306
For csh
and tcsh
, use this syntax:
setenv MYSQL_TCP_PORT 3306
The commands to set environment variables can be executed at your command
prompt to take effect immediately. These settings persist until you log out.
To have the settings take effect each time you log in,
place the appropriate command or commands in a startup file that your
command interpreter reads each time it starts. Typical startup files are
`AUTOEXEC.BAT' for Windows, `.bash_profile' for bash
, or
`.tcshrc' for tcsh
. Consult the documentation for your command
interpreter for specific details.
section F Environment Variables lists all environment variables that affect MySQL program operation.
Many MySQL programs have internal variables that can be set at runtime.
As of MySQL 4.0.2, program
variables are set the same way as any other long option that takes a value.
For example, mysql
has a max_allowed_packet
variable that
controls the maximum size of its communication buffer.
To set the max_allowed_packet
variable for mysql
to a value of
16MB, use either of the following commands:
shell> mysql --max_allowed_packet=16777216 shell> mysql --max_allowed_packet=16M
The first command specifies the value in bytes. The second specifies the value
in megabytes. Variable values can have a suffix of K
, M
, or
G
(either uppercase or lowercase) to indicate units of kilobytes,
megabytes, or gigabytes.
In an option file, the variable setting is given without the leading dashes:
[mysql] max_allowed_packet=16777216
Or:
[mysql] max_allowed_packet=16M
If you like, underscores in a variable name can be specified as dashes.
Prior to MySQL 4.0.2, program variable names are not recognized as option
names.
Instead, use the --set-variable
option to assign a value to a variable:
shell> mysql --set-variable=max_allowed_packet=16777216 shell> mysql --set-variable=max_allowed_packet=16M
In an option file, omit the leading dashes:
[mysql] set-variable = max_allowed_packet=16777216
Or:
[mysql] set-variable = max_allowed_packet=16M
With --set-variable
, underscores in variable names cannot be given as
dashes for versions of MySQL older than 4.0.2.
The --set-variable
option is still recognized in MySQL 4.0.2 and up,
but is deprecated.
Some server variables can be set at runtime. For details, see section 5.2.3.1 Dynamic System Variables.
This chapter covers topics that deal with administering a MySQL installation, such as configuring the server, managing user accounts, and performing backups.
The MySQL server, mysqld
, is the main program that does most of the
work in a MySQL installation. The server is accompanied by several related
scripts that perform setup operations when you install MySQL or that are
helper programs to assist you in starting and stopping the server.
This section provides an overview of the server and related programs, and information about server startup scripts. Information about configuring the server itself is given in section 5.2 Configuring the MySQL Server.
All MySQL programs take many different options. However, every
MySQL program provides a --help
option that you can use
to get a description of the program's options. For example, try
mysqld --help
.
You can override default options for all standard programs by specifying options on the command line or in an option file. section 4.3 Specifying Program Options.
The following list briefly describes the MySQL server and server-related programs:
mysqld
mysqld-max
mysqld-max
Extended MySQL Server.
mysqld_safe
mysqld_safe
attempts to start mysqld-max
if it exists, and
mysqld
otherwise.
See section 5.1.3 The mysqld_safe
Server Startup Script.
mysql.server
mysqld_safe
to start the MySQL server.
See section 5.1.4 The mysql.server
Server Startup Script.
mysqld_multi
mysqld_multi
Program for Managing Multiple MySQL Servers.
mysql_install_db
mysql_fix_privilege_tables
There are several other programs that also are run on the server host:
myisamchk
MyISAM
tables.
myisamchk
is described in
section 5.7.3 Table Maintenance and Crash Recovery.
make_binary_distribution
ftp.mysql.com
for the
convenience of other MySQL users.
mysqlbug
mysqld-max
Extended MySQL Server
A MySQL-Max server is a version of the mysqld
MySQL server that
has been built to include additional features.
The distribution to use depends on your platform:
mysqld.exe
) and the MySQL-Max server (mysqld-max.exe
), so you
need not get a special distribution. Just use a regular Windows
distribution, available at
http://dev.mysql.com/downloads/.
See section 2.3 Installing MySQL on Windows.
MySQL-server
RPM first to install a standard server named
mysqld
. Then use the MySQL-Max
RPM to install a server named
mysqld-max
. The MySQL-Max
RPM presupposes that you have
installed the regular server RPM. See section 2.4 Installing MySQL on Linux for more
information on the Linux RPM packages.
mysqld
but that has the additional features included.
You can find the MySQL-Max binaries on the MySQL AB Web site at http://dev.mysql.com/downloads/mysql-4.0.html.
MySQL AB builds the MySQL-Max servers by using the following
configure
options:
--with-server-suffix=-max
-max
suffix to the mysqld
version string.
--with-innodb
InnoDB
storage engine. MySQL-Max
servers always include InnoDB
support, but this option actually is
needed only for MySQL 3.23. From MySQL 4 on, InnoDB
is included by
default in binary distributions, so you do not need a MySQL-Max server to
obtain InnoDB
support.
--with-bdb
BDB
) storage engine.
USE_SYMDIR
MySQL-Max binary distributions are a convenience for those who wish to install precompiled programs. If you build MySQL using a source distribution, you can build your own Max-like server by enabling the same features at configuration time that the MySQL-Max binary distributions are built with.
MySQL-Max servers include the BerkeleyDB (BDB
) storage engine
whenever possible, but not all platforms support BDB
. The following
table shows which platforms allow MySQL-Max binaries to include BDB
:
System | BDB Support
|
AIX 4.3 | N |
HP-UX 11.0 | N |
Linux-Alpha | N |
Linux-IA-64 | N |
Linux-Intel | Y |
Mac OS X | N |
NetWare | N |
SCO OSR5 | Y |
Solaris-Intel | N |
Solaris-SPARC | Y |
UnixWare | Y |
Windows/NT | Y |
To find out which storage engines your server supports, issue the following statement:
mysql> SHOW ENGINES;
Before MySQL 4.1.2, SHOW ENGINES
is unavailable. Use the following
statement instead and check the value of the variable for the storage engine
in which you are interested:
mysql> SHOW VARIABLES LIKE 'have_%'; +------------------+----------+ | Variable_name | Value | +------------------+----------+ | have_bdb | NO | | have_crypt | YES | | have_innodb | YES | | have_isam | NO | | have_raid | NO | | have_symlink | DISABLED | | have_openssl | NO | | have_query_cache | YES | +------------------+----------+
The values in the second column indicate the server's level of support for each feature:
Value | Meaning |
YES | The feature is supported and is active. |
NO | The feature is not supported. |
DISABLED | The feature is supported but has been disabled. |
A value of NO
means that the server was compiled without support
for the feature, so it cannot be activated at runtime.
A value of DISABLED
occurs either because the server was
started with an option that disables the feature, or because not
all options required to enable it were given. In the latter case, the
host_name.err
error log file should contain a reason indicating why
the option is disabled.
One situation in which you might see DISABLED
occurs with MySQL 3.23
when the InnoDB
storage engine is compiled in. In MySQL 3.23, you
must supply at least the innodb_data_file_path
option at runtime to
set up the InnoDB
tablespace. Without this option, InnoDB
disables itself.
See section 15.3 InnoDB
in MySQL 3.23.
You can specify configuration options for the BDB
storage engine, too,
but BDB
will not disable itself if you do not provide them.
See section 14.4.3 BDB
Startup Options.
You might also see DISABLED
for the InnoDB
, BDB
, or
ISAM
storage engines if the server was compiled to support them, but
was started with the --skip-innodb
, --skip-bdb
, or
--skip-isam
options at runtime.
As of Version 3.23, all MySQL servers support MyISAM
tables, because
MyISAM
is the default storage engine.
mysqld_safe
Server Startup Script
mysqld_safe
is the recommended way to start a mysqld
server on Unix and NetWare. mysqld_safe
adds some safety features
such as restarting the server when an error occurs and logging runtime
information to an error log file. NetWare-specific behaviors are listed
later in this section.
Note:
Before MySQL 4.0, mysqld_safe
is named safe_mysqld
.
To preserve backward compatibility, MySQL binary distributions for
some time will include safe_mysqld
as a symbolic link to
mysqld_safe
.
By default, mysqld_safe
tries to start an executable named
mysqld-max
if it exists, or mysqld
otherwise.
Be aware of the implications of this behavior:
MySQL-Max
RPM relies on this mysqld_safe
behavior. The RPM installs an executable named mysqld-max
, which
causes mysqld_safe
to automatically use that executable from that
point on.
mysqld-max
, then upgrade later to a non-Max version of MySQL,
mysqld_safe
will still attempt to run the old mysqld-max
server. If you perform such an upgrade, you should manually remove the old
mysqld-max
server to ensure that mysqld_safe
runs the new
mysqld
server.
To override the default behavior and specify explicitly which server you
want to run, specify a --mysqld
or --mysqld-version
option to
mysqld_safe
.
Many of the options to mysqld_safe
are the same as the options to
mysqld
. See section 5.2.1 mysqld
Command-Line Options.
All options specified to mysqld_safe
on the command line are
passed to mysqld
. If you want to use any options that are specific
to mysqld_safe
and that mysqld
doesn't support, do not specify
them on the command line. Instead, list them in the [mysqld_safe]
group
of an option file.
See section 4.3.2 Using Option Files.
mysqld_safe
reads all options from the [mysqld]
,
[server]
, and [mysqld_safe]
sections in option files.
For backward compatibility, it also reads [safe_mysqld]
sections, although you should rename such sections to [mysqld_safe]
when you begin using MySQL 4.0 or later.
mysqld_safe
supports the following options:
--help
--basedir=path
--core-file-size=size
mysqld
should be able to create. The option
value is passed to ulimit -c
.
--datadir=path
--defaults-extra-file=path
--defaults-file=path
--err-log=path
--log-error
option, to be used before MySQL 4.0.
--ledir=path
mysqld
program.
Use this option to explicitly indicate the location of the server.
--log-error=path
--mysqld=prog_name
ledir
directory) that you
want to start. This option is needed if you use the MySQL binary distribution
but have the data directory outside of the binary distribution.
--mysqld-version=suffix
--mysqld
option, but you specify only
the suffix for the server program name. The basename is assumed to be
mysqld
. For example, if you use --mysqld-version=max
,
mysqld_safe
will start the mysqld-max
program in the
ledir
directory. If the argument to --mysqld-version
is
empty, mysqld_safe
uses mysqld
in the ledir
directory.
--nice=priority
nice
program to set the server's scheduling priority to the
given value. This option was added in MySQL 4.0.14.
--no-defaults
--open-files-limit=count
mysqld
should be able to open. The option value
is passed to ulimit -n
. Note that you need to start
mysqld_safe
as root
for this to work properly!
--pid-file=path
--port=port_num
--socket=path
--timezone=zone
TZ
time zone environment variable to the given option value.
Consult your operating system documentation for legal time zone
specification formats.
--user={user_name | user_id}
mysqld
server as the user having the name user_name or
the numeric user ID user_id.
(``User'' in this context refers to a system login account, not a MySQL user
listed in the grant tables.)
The mysqld_safe
script is written so that it normally can start a
server that was installed from either a source or a binary distribution of
MySQL, even though these types of distributions typically install the server
in slightly different locations.
(See section 2.1.5 Installation Layouts.)
mysqld_safe
expects one of the following conditions to be true:
mysqld_safe
is invoked. For binary distributions, mysqld_safe
looks under its working directory for `bin' and `data'
directories. For source distributions, it looks for `libexec' and
`var' directories. This condition should be met if you execute
mysqld_safe
from your MySQL installation directory (for example,
`/usr/local/mysql' for a binary distribution).
mysqld_safe
attempts to locate them by absolute pathnames.
Typical locations are `/usr/local/libexec' and `/usr/local/var'.
The actual locations are determined from the values configured into the
distribution at the time it was built. They should be correct if MySQL
is installed in the location specified at configuration time.
Because mysqld_safe
will try to find the server and databases relative
to its own working directory, you can install a binary distribution of
MySQL anywhere, as long as you run mysqld_safe
from the
MySQL installation directory:
shell> cd mysql_installation_directory shell> bin/mysqld_safe &
If mysqld_safe
fails, even when invoked from the MySQL
installation directory, you can specify the --ledir
and
--datadir
options to indicate the directories in which the server and
databases are located on your system.
Normally, you should not edit the mysqld_safe
script. Instead,
configure mysqld_safe
by using command-line options or options in the
[mysqld_safe]
section of a `my.cnf' option file. In rare cases,
it might be necessary to edit mysqld_safe
to get it to start the server
properly. However, if you do this, your modified version of
mysqld_safe
might be overwritten if you upgrade MySQL in the future, so
you should make a copy of your edited version that you can reinstall.
On NetWare, mysqld_safe
is a NetWare Loadable Module (NLM) that is
ported from the original Unix shell script. It does the following:
MyISAM
and ISAM
tables.
mysqld
, monitors it, and restarts it if it terminates in error.
mysqld
to the `host_name.err' file in the
data directory.
mysqld_safe
screen output to the `host_name.safe' file in the
data directory.
mysql.server
Server Startup Script
MySQL distributions on Unix include a script named mysql.server
.
It can be used on systems such as Linux and Solaris that use System V-style
run directories to start and stop system services. It is also used by the Mac
OS X Startup Item for MySQL.
mysql.server
can be found in the `support-files' directory under
your MySQL installation directory or in a MySQL source tree.
If you use the Linux server RPM package (MySQL-server-VERSION.rpm
),
the mysql.server
script will have been installed in the
`/etc/init.d' directory with the name `mysql'. You need not
install it manually. See section 2.4 Installing MySQL on Linux for more information on the Linux
RPM packages.
Some vendors provide RPM packages that install a startup script under a
different name such as mysqld
.
If you install MySQL from a source distribution or using a binary distribution
format that does not install mysql.server
automatically, you can
install it manually. Instructions are provided in section 2.9.2.2 Starting and Stopping MySQL Automatically.
mysql.server
reads options from the [mysql.server]
and
[mysqld]
sections of option files. (For backward compatibility,
it also reads [mysql_server]
sections, although you should rename such
sections to [mysql.server]
when you begin using MySQL 4.0 or later.)
mysqld_multi
Program for Managing Multiple MySQL Servers
mysqld_multi
is meant for managing several mysqld
processes that listen for connections on different Unix socket files and
TCP/IP ports. It can start or stop servers, or report their current status.
The program searches for groups named [mysqld#]
in `my.cnf' (or
in the file named by the --config-file
option). #
can be any
positive integer. This number is referred to in the following discussion as
the option group number, or GNR. Group numbers distinguish option groups
from one another and are used as arguments to mysqld_multi
to specify
which servers you want to start, stop, or obtain a status report for.
Options listed in these groups are the same that you would use in the
[mysqld]
group used for starting mysqld
. (See, for example,
section 2.9.2.2 Starting and Stopping MySQL Automatically.) However, when using multiple servers it is necessary
that each one use its own value for options such as the Unix socket file and
TCP/IP port number. For more information on which options must be unique per
server in a multiple-server environment, see section 5.10 Running Multiple MySQL Servers on the Same Machine.
To invoke mysqld_multi
, use the following syntax:
shell> mysqld_multi [options] {start|stop|report} [GNR[,GNR]...]
start
, stop
, and report
indicate which operation you
want to perform. You can perform the designated operation on a single server
or multiple servers, depending on the GNR list that follows the option name.
If there is no list, mysqld_multi
performs the operation for all
servers in the option file.
Each GNR value represents an option group number or range of group numbers.
The value should be the number at the end of the group name in the
option file. For example, the GNR for a group named [mysqld17]
is 17
. To specify a range of numbers, separate the first and last
numbers by a dash. The GNR value 10-13
represents groups
[mysqld10]
through [mysqld13]
. Multiple groups or group
ranges can be specified on the command line, separated by commas. There
must be no whitespace characters (spaces or tabs) in the GNR list; anything
after a whitespace character is ignored.
This command starts a single server using option group [mysqld17]
:
shell> mysqld_multi start 17
This command stops several servers, using option groups [mysql8]
and [mysqld10]
through [mysqld13]
:
shell> mysqld_multi stop 8,10-13
For an example of how you might set up an option file, use this command:
shell> mysqld_multi --example
mysqld_multi
supports the following options:
--config-file=name
mysqld_multi
looks for [mysqld#]
option groups. Without this
option, all options are read from the usual `my.cnf' file. The option
does not affect where mysqld_multi
reads its own options, which are
always taken from the [mysqld_multi]
group in the usual `my.cnf'
file.
--example
--help
--log=name
--mysqladmin=prog_name
mysqladmin
binary to be used to stop servers.
--mysqld=prog_name
mysqld
binary to be used. Note that you can specify
mysqld_safe
as the value for this option also. The options are passed
to mysqld
. Just make sure that you have the directory where mysqld
is
located in your PATH
environment variable setting or fix mysqld_safe
.
--no-log
--password=password
mysqladmin
.
Note that the password value is not optional for this option, unlike for other
MySQL programs.
--silent
--tcp-ip
stop
and
report
operations.
--user=user_name
mysqladmin
.
--verbose
--version
Some notes about mysqld_multi
:
mysqld
servers
(with the mysqladmin
program) has the same username and password for
each server. Also, make sure that the account has the SHUTDOWN
privilege. If the servers that you want to manage have many different
usernames or passwords for the administrative accounts, you might want to
create an account on each server that has the same username and password.
For example, you might set up a common multi_admin
account by
executing the following commands for each server:
shell> mysql -u root -S /tmp/mysql.sock -proot_password mysql> GRANT SHUTDOWN ON *.* -> TO 'multi_admin'@'localhost' IDENTIFIED BY 'multipass';See section 5.5.2 How the Privilege System Works. You will have to do this for each
mysqld
server. Change the
connection parameters appropriately when connecting to each one. Note that
the host part of the account name must allow you to connect as
multi_admin
from the host where you want to run mysqld_multi
.
--pid-file
option is very important if you are using mysqld_safe
to start mysqld
(for example, --mysqld=mysqld_safe
) Every
mysqld
should have its own process ID file. The advantage of
using mysqld_safe
instead of mysqld
is
that mysqld_safe
``guards'' its mysqld
process and will
restart it if the process terminates due to a signal
sent using kill -9
, or for other reasons, such as a segmentation
fault. Please note that the
mysqld_safe
script might require that you start it from a certain
place. This means that you might have to change location to a certain directory
before running mysqld_multi
. If you have problems starting,
please see the mysqld_safe
script. Check especially the lines:
---------------------------------------------------------------- MY_PWD=`pwd` # Check if we are starting this relative (for the binary release) if test -d $MY_PWD/data/mysql -a -f ./share/mysql/english/errmsg.sys -a \ -x ./bin/mysqld ----------------------------------------------------------------See section 5.1.3 The
mysqld_safe
Server Startup Script.
The test performed by these lines should be successful, or you might encounter
problems.
mysqld
.
--user
option for mysqld
, but in order
to do this you need to run the mysqld_multi
script as the Unix
root
user. Having the option in the option file doesn't matter; you
will just get a warning, if you are not the superuser and the mysqld
processes are started under your own Unix account.
mysqld
process is started as. Do not use the
Unix root account for this, unless you know what you are doing.
mysqld_multi
be sure that you
understand the meanings of the options that are passed to the mysqld
servers and why you would want to have separate mysqld
processes. Beware of the dangers of using multiple mysqld
servers
with the same data directory. Use separate data directories, unless you
know what you are doing. Starting multiple servers with the same
data directory will not give you extra performance in a threaded
system.
See section 5.10 Running Multiple MySQL Servers on the Same Machine.
The following example shows how you might set up an option file for use with
mysqld_multi
. The first and fifth [mysqld#]
group were
intentionally left out from the example to illustrate that you can have
``gaps'' in the option file. This gives you more flexibility. The order in
which the mysqld
programs are started or stopped depends on the order
in which they appear in the option file.
# This file should probably be in your home dir (~/.my.cnf) # or /etc/my.cnf # Version 2.1 by Jani Tolonen [mysqld_multi] mysqld = /usr/local/bin/mysqld_safe mysqladmin = /usr/local/bin/mysqladmin user = multi_admin password = multipass [mysqld2] socket = /tmp/mysql.sock2 port = 3307 pid-file = /usr/local/mysql/var2/hostname.pid2 datadir = /usr/local/mysql/var2 language = /usr/local/share/mysql/english user = john [mysqld3] socket = /tmp/mysql.sock3 port = 3308 pid-file = /usr/local/mysql/var3/hostname.pid3 datadir = /usr/local/mysql/var3 language = /usr/local/share/mysql/swedish user = monty [mysqld4] socket = /tmp/mysql.sock4 port = 3309 pid-file = /usr/local/mysql/var4/hostname.pid4 datadir = /usr/local/mysql/var4 language = /usr/local/share/mysql/estonia user = tonu [mysqld6] socket = /tmp/mysql.sock6 port = 3311 pid-file = /usr/local/mysql/var6/hostname.pid6 datadir = /usr/local/mysql/var6 language = /usr/local/share/mysql/japanese user = jani
See section 4.3.2 Using Option Files.
This section discusses MySQL server configuration topics:
mysqld
Command-Line Options
When you start the mysqld
server, you can specify program options
using any of the methods described in section 4.3 Specifying Program Options. The most
common methods are to provide options in an option file or on the command
line. However, in most cases it is desirable to make sure that the server uses
the same options each time it runs. The best way to ensure this is to
list them in an option file.
See section 4.3.2 Using Option Files.
mysqld
reads options from the [mysqld]
and [server]
groups. mysqld_safe
reads options from the [mysqld]
,
[server]
, [mysqld_safe]
, and [safe_mysqld]
groups. mysql.server
reads options from the [mysqld]
and [mysql.server]
groups. An embedded MySQL server usually reads
options from the [server]
, [embedded]
, and [xxxxx_SERVER]
groups, where xxxxx is the name of the application into which the
server is embedded.
mysqld
accepts many command-line options.
For a list, execute mysqld --help
. Before MySQL 4.1.1, --help
prints the full help message. As of 4.1.1, it prints a brief message; to see
the full list, use mysqld --verbose --help
.
The following list shows some of the most common server options. Additional options are described elsewhere:
mysqld
Concerning Security.
MyISAM
Startup Options,
section 14.4.3 BDB
Startup Options,
section 15.5 InnoDB
Startup Options.
You can also set the value of a server system variable by using the variable name as an option, as described later in this section.
--help, -?
--help
displays the full help message.
As of 4.1.1, it displays an abbreviated message only. Use both the
--verbose
and --help
options to see the full message.
--ansi
--sql-mode
option instead.
--basedir=path, -b path
--big-tables
--bind-address=IP
--console
--log-error
is specified. On Windows, mysqld
will not close the console screen if
this option is used.
--character-sets-dir=path
--chroot=path
mysqld
server in a closed environment during startup by using the
chroot()
system call. This is a recommended security measure as of
MySQL 4.0. (MySQL 3.23 is not able to provide a chroot()
jail that is
100% closed.) Note that use of this option somewhat limits LOAD
DATA INFILE
and SELECT ... INTO OUTFILE
.
--character-set-server=charset
--core-file
mysqld
dies. For some systems, you must also
specify the --core-file-size
option to mysqld_safe
.
See section 5.1.3 The mysqld_safe
Server Startup Script.
Note that on some systems, such as Solaris, you will
not get a core file if you are also using the --user
option.
--collation-server=collation
--datadir=path, -h path
--debug[=debug_options], -# [debug_options]
--with-debug
, you can use this
option to get a trace file of what mysqld
is doing.
The debug_options string often is 'd:t:o,file_name'
.
See section E.1.2 Creating Trace Files.
--default-character-set=charset
--character-set-server
as of MySQL 4.1.3.
See section 5.8.1 The Character Set Used for Data and Sorting.
--default-collation=collation
--collation-server
as of MySQL 4.1.3.
See section 5.8.1 The Character Set Used for Data and Sorting.
--default-storage-engine=type
--default-table-type
.
It is available as of MySQL 4.1.2.
--default-table-type=type
--default-time-zone=type
time_zone
system variable. If this option is not given, the default
time zone will be the same as the system time zone (given by the value of
the system_time_zone
system variable.
This option is available as of MySQL 4.1.3.
--delay-key-write[= OFF | ON | ALL]
DELAYED KEYS
option should be used.
Delayed key writing causes key buffers not to be flushed between writes for
MyISAM
tables.
OFF
disables delayed key writes.
ON
enables delayed key writes for those tables that were created with
the DELAYED KEYS
option.
ALL
delays key writes for all MyISAM
tables.
Available as of MySQL 4.0.3.
See section 7.5.2 Tuning Server Parameters. See section 14.1.1 MyISAM
Startup Options.
Note: If you set this variable to ALL
, you should not use
MyISAM
tables from within another program (such as from another MySQL server or
with myisamchk
) when the table is in use. Doing so will lead to index
corruption.
--delay-key-write-for-all-tables
--delay-key-write=ALL
for use prior to MySQL 4.0.3.
As of 4.0.3, use --delay-key-write
instead.
--des-key-file=file_name
DES_ENCRYPT()
and DES_DECRYPT()
from this file.
--enable-named-pipe
mysqld-nt
and mysqld-max-nt
servers that support
named pipe connections.
--exit-info[=flags], -T [flags]
mysqld
server. Do not use this option unless you know
exactly what it does!
--external-locking
lockd
does not fully work (as on Linux), you will easily get
mysqld
to deadlock.
This option previously was named --enable-locking
.
Note: If you use this option to enable updates to MyISAM
tables from many MySQL processes, you have to ensure that these conditions are
satisfied:
--delay-key-write=ALL
or DELAY_KEY_WRITE=1
on any shared tables.
--external-locking
together with --delay-key-write=OFF --query-cache-size=0
.
(This is not done by default because in many setups it's useful to have a
mixture of the above options.)
--flush
--init-file=file
--innodb-safe-binlog
InnoDB
tables and
the binary log.
See section 5.9.4 The Binary Log.
--language=lang_name, -L lang_name
--large-pages
--log[=file], -l [file]
host_name.log
as the filename.
--log-bin=[file]
host_name-bin
as the log file basename.
--log-bin-index[=file]
--log-bin
, MySQL will use host_name-bin.index
as the
filename.
--log-error[=file]
host_name.err
as the filename.
--log-isam[=file]
ISAM
/MyISAM
changes to this file (used only when
debugging ISAM
/MyISAM
).
--log-long-format
--log-slow-queries
and --log-long-format
,
queries that are not using indexes also are logged to the slow query log.
--log-long-format
is deprecated as of MySQL version 4.1, when
--log-short-format
was introduced. (Long log format is the
default setting since version 4.1.) Also note that starting with MySQL
4.1, the --log-queries-not-using-indexes
option is available for
the purpose of logging queries that do not use indexes to the slow query log.
--log-queries-not-using-indexes
--log-slow-queries
, then
queries that are not using indexes also are logged to the slow query log. This
option is available as of MySQL 4.1. See section 5.9.5 The Slow Query Log.
--log-short-format
--log-slow-queries[=file]
long_query_time
seconds
to execute to this file.
See section 5.9.5 The Slow Query Log.
Note that the default for the amount of information
logged has changed in MySQL 4.1. See the --log-long-format
and
--log-short-format
options for details.
--log-update[=file]
--log-bin
). See section 5.9.4 The Binary Log. Starting from version 5.0.0,
using --log-update
will just turn on the binary log instead
(see section D.1.4 Changes in release 5.0.0 (22 Dec 2003: Alpha)).
--log-warnings, -W
Aborted connection...
to the error log.
Enabling this option is recommended, for example, if you
use replication (you will get more information about what is happening,
such as messages about network failures and reconnections).
This option is enabled by default as of MySQL 4.0.19 and 4.1.2; to disable it,
use --skip-log-warnings
.
As of MySQL 4.0.21 and 4.1.3, aborted connections are not logged to the error
log unless the value is greater than 1.
See section A.2.10 Communication Errors and Aborted Connections.
This option was named --warnings
before MySQL 4.0.
--low-priority-updates
INSERT
, REPLACE
, DELETE
, UPDATE
)
will have lower priority than selects. This can also be done via
{INSERT | REPLACE | DELETE | UPDATE} LOW_PRIORITY ...
to lower
the priority of only one query, or by
SET LOW_PRIORITY_UPDATES=1
to change the priority in one
thread. See section 7.3.2 Table Locking Issues.
--memlock
mysqld
process in memory. This works on systems such as
Solaris that support the mlockall()
system call. This
might help if you have a problem where the operating system is causing
mysqld
to swap on disk.
Note that use of this option requires that you run the server as root
,
which is normally not a good idea for security reasons.
--myisam-recover [=option[,option...]]]
MyISAM
storage engine recovery mode.
The option value is any combination of the values
of DEFAULT
, BACKUP
, FORCE
, or QUICK
.
If you specify multiple values, separate them by commas.
You can also use a value of ""
to disable this
option. If this option is used, mysqld
will, when it opens a
MyISAM
table, open check whether the
table is marked as crashed or wasn't closed properly.
(The last option works only if you are running with
--skip-external-locking
.) If this is the case, mysqld
will run
a check on the table. If the table was corrupted, mysqld
will
attempt to repair it.
The following options affect how the repair works:
Option | Description |
DEFAULT | The same as not giving any option to
--myisam-recover .
|
BACKUP | If the data file was changed during recovery, save a backup of the `tbl_name.MYD' file as `tbl_name-datetime.BAK'. |
FORCE | Run recovery even if we will lose more than one row from the `.MYD' file. |
QUICK | Don't check the rows in the table if there aren't any delete blocks. |
BACKUP,FORCE
. This will force a repair of a table even if some rows
would be deleted, but it will keep the old data file as a backup so that
you can later examine what happened.
This option is available as of MySQL 3.23.25.
--ndb-connectstring=connect_string
NDB
storage engine, it is possible to point out the
management server that distributes the cluster configuration by setting the
connect string option. See section 16.3.4.2 The MySQL Cluster connectstring
for syntax.
--ndbcluster
NDB Cluster
storage engine
(from version 4.1.3, the MySQL-Max binaries are built with NDB Cluster
enabled)
the default disabling of support for the NDB Cluster
storage engine can be
overruled by using this option. Using the NDB Cluster
storage engine is
necessary for using MySQL Cluster.
See section 16 MySQL Cluster.
--new
--new
option can be used to make the server
behave as 4.1 in certain respects, easing a 4.0 to 4.1 upgrade:
0xFF
are treated as strings by
default rather than as numbers. (Works in 4.0.12 and up.)
TIMESTAMP
is returned as a string with the format
'YYYY-MM-DD HH:MM:SS'
. (Works in 4.0.13 and up.)
See section 11 Column Types.
--old-passwords
--old-protocol, -o
--one-thread
--open-files-limit=count
mysqld
.
If this is not set or set to 0, then mysqld
will use this value
to reserve file descriptors to use with setrlimit()
. If this
value is 0 then mysqld
will reserve max_connections*5
or
max_connections + table_cache*2
(whichever is larger) number of
files. You should try increasing this if mysqld
gives you the
error "Too many open files."
--pid-file=path
mysqld_safe
.
--port=port_num, -P port_num
--safe-mode
--safe-show-database
SHOW DATABASES
statement displays only the names
of those databases for which the user has some kind of privilege.
As of MySQL 4.0.2, this option is deprecated and doesn't do anything
(it is enabled by default), because there is a SHOW DATABASES
privilege that can be used to control access to database
names on a per-account basis.
See section 5.5.3 Privileges Provided by MySQL.
--safe-user-create
GRANT
statement, if the user doesn't have the INSERT
privilege for the
mysql.user
table or any column in the table.
--secure-auth
--shared-memory
--shared-memory-base-name=name
--skip-bdb
BDB
storage engine. This saves memory and might speed
up some operations.
Do not use this option if you require BDB
tables.
--skip-concurrent-insert
MyISAM
tables. (This is to be used only if you think you have found a bug in this
feature.)
--skip-delay-key-write
DELAY_KEY_WRITE
option for all tables.
As of MySQL 4.0.3, you should use --delay-key-write=OFF
instead.
See section 7.5.2 Tuning Server Parameters.
--skip-external-locking
isamchk
or myisamchk
,
you must shut down the server. See section 1.2.3 MySQL Stability. In MySQL 3.23, you
can use CHECK TABLE
and REPAIR TABLE
to check and repair
MyISAM
tables.
This option previously was named --skip-locking
.
--skip-grant-tables
mysqladmin
flush-privileges
or mysqladmin reload
command, or by issuing a
FLUSH PRIVILEGES
statement.)
--skip-host-cache
--skip-innodb
InnoDB
storage engine. This saves memory and disk
space and might speed up some operations.
Do not use this option if you require InnoDB
tables.
--skip-isam
ISAM
storage engine. As of MySQL 4.1, ISAM
is
disabled by default, so this option applies only if the server was configured
with support for ISAM
.
This option was added in MySQL 4.1.1.
--skip-name-resolve
Host
column values in the
grant tables must be IP numbers or localhost
. See section 7.5.6 How MySQL Uses DNS.
--skip-ndbcluster
NDB Cluster
storage engine. This is the default for binaries
that were built with NDB Cluster
storage engine support, this means that
the system will only allocate memory and other resources for this storage engine
if it is explicitly enabled.
--skip-networking
mysqld
must be made via named pipes or shared memory (on Windows) or Unix socket files
(on Unix). This option is highly recommended for systems where only local
clients are allowed. See section 7.5.6 How MySQL Uses DNS.
--skip-new
--skip-symlink
--skip-symbolic-links
, for use before MySQL
4.0.13.
--symbolic-links, --skip-symbolic-links
directory.sym
file that contains the path to the real directory.
See section 7.6.1.3 Using Symbolic Links for Databases on Windows.
MyISAM
index file or data file to another directory with
the INDEX DIRECTORY
or DATA DIRECTORY
options of the
CREATE TABLE
statement. If you delete or rename the table,
the files that its symbolic links point to also are deleted or
renamed. See section 13.2.6 CREATE TABLE
Syntax.
--skip-safemalloc
--with-debug=full
, all MySQL programs
check for memory overruns during each memory allocation and memory
freeing operation. This checking is very slow, so for the server you
can avoid it when you don't need it by using the --skip-safemalloc
option.
--skip-show-database
SHOW DATABASES
statement is allowed only to
users who have the SHOW DATABASES
privilege, and the statement
displays all database names. Without this option, SHOW DATABASES
is
allowed to all users, but displays each database name only if the user has
the SHOW DATABASES
privilege or some privilege for the database.
--skip-stack-trace
mysqld
under a debugger. On some systems, you also must use
this option to get a core file. See section E.1 Debugging a MySQL Server.
--skip-thread-priority
--socket=path
MySQL
.
--sql-mode=value[,value[,value...]]
--temp-pool
--transaction-isolation=level
READ-UNCOMMITTED
,
READ-COMMITTED
,
REPEATABLE-READ
, or
SERIALIZABLE
.
See section 13.4.6 SET TRANSACTION
Syntax.
--tmpdir=path, -t path
/tmp
directory resides on a partition that
is too small to hold temporary tables. Starting from MySQL 4.1, this
option accepts several paths that are used in round-robin fashion. Paths
should be separated by colon characters (`:') on Unix and semicolon
characters (`;') on Windows, NetWare, and OS/2.
If the MySQL server is acting as a replication slave, you should not set
--tmpdir
to point to a directory on a memory-based filesystem or to a
directory that is cleared when the server host restarts. A replication
slave needs some of its temporary files to survive a machine restart so that
it can replicate temporary tables or LOAD DATA INFILE
operations. If
files in the temporary file directory are lost when the server restarts,
replication will fail.
--user={user_name | user_id}, -u {user_name | user_id}
mysqld
server as the user having the name user_name or
the numeric user ID user_id.
(``User'' in this context refers to a system login account, not a MySQL user
listed in the grant tables.)
This option is mandatory when starting mysqld
as root
.
The server will change its user ID during its startup sequence, causing it
to run as that particular user rather than as root
.
See section 5.4.1 General Security Guidelines.
Starting from MySQL 3.23.56 and 4.0.12:
To avoid a possible security hole where a user adds a --user=root
option to some `my.cnf' file (thus causing the server to run as
root
), mysqld
uses only the first
--user
option specified and produces a warning if there are multiple
--user
options. Options in `/etc/my.cnf' and
`datadir/my.cnf' are processed before
command-line options, so it is recommended that you
put a --user
option in `/etc/my.cnf' and specify a value other than
root
. The option in `/etc/my.cnf' will be found before any other
--user
options, which ensures that the server runs as a user other
than root
, and that a warning results if any other --user
option
is found.
--version, -V
As of MySQL 4.0,
you can assign a value to a server system variable by using an option of
the form --var_name=value
. For example, --key_buffer_size=32M
sets the key_buffer_size
variable to a value of 32MB.
Note that when setting a variable to a value, MySQL might automatically correct it to stay within a given range, or adjust the value to the closest allowable value if only certain values are allowed.
It is also possible to set variables by using
--set-variable=var_name=value
or -O var_name=value
syntax. However, this syntax is deprecated as of MySQL 4.0.
You can find a full description for all variables in section 5.2.3 Server System Variables. The section on tuning server parameters includes information on how to optimize them. See section 7.5.2 Tuning Server Parameters.
You can change the values of most system variables for a running server with the
SET
statement. See section 13.5.3 SET
Syntax.
If you want to restrict the maximum value that a startup option can be set to
with SET
, you can define this by using the
--maximum-var_name
command-line option.
The MySQL server can operate in different SQL modes, and (as of MySQL 4.1) can apply these modes differentially for different clients. This allows an application to tailor server operation to its own requirements.
Modes define what SQL syntax MySQL should support and what kind of data validation checks it should perform. This makes it easier to use MySQL in different environments and to use MySQL together with other database servers.
You can set the default SQL mode by starting mysqld
with the
--sql-mode="modes"
option. The value also can be empty
(--sql-mode=""
) if you want to reset it.
Beginning with MySQL 4.1, you can also change the SQL mode after startup time
by setting the sql_mode
variable with a SET [SESSION|GLOBAL]
sql_mode='modes'
statement. Setting the GLOBAL
variable
requires the SUPER
privilege and affects the operation of all clients
that connect from that time on. Setting the SESSION
variable affects
only the current client. Any client can change its session sql_mode
value.
modes is a list of different modes separated
by comma (`,') characters. You can retrieve the current mode by
issuing a SELECT @@sql_mode
statement. The default value is empty
(no modes set).
The most important sql_mode
values are probably these:
ANSI
STRICT_TRANS_TABLES
TRADITIONAL
INSERT
/UPDATE
will abort as soon as the error is noticed.
This may not be what you want if you are using a non-transactional storage
engine, because data changes made prior to the error will not be rolled
back, resulting in a ``partially-done'' update. (New in MySQL 5.0.2)
When this manual refers to ``strict mode,'' it means a mode where at least
one of STRICT_TRANS_TABLES
or STRICT_ALL_TABLES
is enabled.
The following list describes all the supported modes:
ALLOW_INVALID_DATES
DATE
and DATETIME
columns. It does not apply TIMESTAMP
columns,
which always require a valid date.
This mode is new in MySQL 5.0.2. Before 5.0.2, this was the default MySQL
date-handling mode. As of 5.0.2, enabling strict mode causes the server to
require that month and day values be legal, not just in the range from 1
to 12 and 1 to 31. For example, '2004-04-31'
is legal with strict
mode disabled, but illegal with strict mode enabled. To allow such dates
in strict mode, enable ALLOW_INVALID_DATES
as well.
ANSI_QUOTES
ANSI_QUOTES
enabled, you cannot use double quotes to quote a literal string, because it
will be interpreted as an identifier.
(New in MySQL 4.0.0)
ERROR_FOR_DIVISION_BY_ZERO
MOD(X,0)
) during an INSERT
/
UPDATE
. If this mode is not given, MySQL instead returns
NULL
for divisions by zero. If used with IGNORE
, MySQL
generates a warning for divisions by zero, but the result of the operation is
NULL
.
(New in MySQL 5.0.2)
HIGH_NOT_PRECEDENCE
NOT
operator precedence is handled
so that expressions such as
NOT a BETWEEN b AND c
are parsed as
NOT (a BETWEEN b AND c)
.
Before MySQL 5.0.2, the expression is parsed as
(NOT a) BETWEEN b AND c
.
The old higher-precedence behavior can be obtained by enabling the
HIGH_NOT_PRECEDENCE
SQL mode.
(New in MySQL 5.0.2)
mysql> SET sql_mode = ''; mysql> SELECT NOT 1 BETWEEN -5 AND 5; -> 0 mysql> SET sql_mode = 'broken_not'; mysql> SELECT NOT 1 BETWEEN -5 AND 5; -> 1
IGNORE_SPACE
USER()
function, the
name of the user
table in the mysql
database and the User
column in that table become reserved, so you must quote them:
SELECT "User" FROM mysql."user";(New in MySQL 4.0.0)
NO_AUTO_CREATE_USER
GRANT
from automatically creating new users if it would
otherwise do so, unless a password also is specified.
(New in MySQL 5.0.2)
NO_AUTO_VALUE_ON_ZERO
NO_AUTO_VALUE_ON_ZERO
affects handling of AUTO_INCREMENT
columns. Normally, you generate the next sequence number for the column by
inserting either NULL
or 0
into it.
NO_AUTO_VALUE_ON_ZERO
suppresses this behavior for 0
so that
only NULL
generates the next sequence number.
(New in MySQL 4.1.1)
This mode can be useful if 0
has been stored in a table's
AUTO_INCREMENT
column. (This is not a recommended practice, by
the way.) For example, if you dump the table with mysqldump
and then reload it, MySQL normally generates new sequence numbers when
it encounters the 0
values, resulting in a table with different
contents than the one that was dumped. Enabling NO_AUTO_VALUE_ON_ZERO
before reloading the dump file solves this problem. As of MySQL 4.1.1,
mysqldump
automatically includes a statement in the dump output
to enable NO_AUTO_VALUE_ON_ZERO
.
NO_BACKSLASH_ESCAPES
NO_DIR_IN_CREATE
INDEX DIRECTORY
and DATA
DIRECTORY
directives. This option is useful on slave replication servers.
(New in MySQL 4.0.15)
NO_FIELD_OPTIONS
SHOW CREATE
TABLE
. This mode is used by mysqldump
in portability mode.
(New in MySQL 4.1.1)
NO_KEY_OPTIONS
SHOW CREATE
TABLE
. This mode is used by mysqldump
in portability mode.
(New in MySQL 4.1.1)
NO_TABLE_OPTIONS
ENGINE
) in the
output of SHOW CREATE TABLE
. This mode is used by mysqldump
in
portability mode.
(New in MySQL 4.1.1)
NO_UNSIGNED_SUBTRACTION
UNSIGNED
if one
of the operands is unsigned. Note that this makes UNSIGNED BIGINT
not
100% usable in all contexts. See section 12.7 Cast Functions and Operators.
(New in MySQL 4.0.2)
NO_ZERO_DATE
'0000-00-00'
as a valid date. You can still insert zero
dates with the IGNORE
option.
(New in MySQL 5.0.2)
NO_ZERO_IN_DATE
IGNORE
option, we insert a '0000-00-00'
date for any such date.
(New in MySQL 5.0.2)
ONLY_FULL_GROUP_BY
GROUP BY
part refer to a not
selected column.
(New in MySQL 4.0.0)
PIPES_AS_CONCAT
||
as a string concatenation operator (same as CONCAT()
)
rather than as a synonym for OR
.
(New in MySQL 4.0.0)
REAL_AS_FLOAT
REAL
as a synonym for FLOAT
rather than as a synonym for
DOUBLE
.
(New in MySQL 4.0.0)
STRICT_ALL_TABLES
STRICT_TRANS_TABLES
Strict mode controls how MySQL handles values that are invalid or missing. A
value can be invalid for several reasons. For example, it might have
the wrong data type for the column, or it might be out of range. A value
is missing when a new row to be inserted does not contain a value for a
column that has no explicit DEFAULT
clause in its definition.
For transactional tables, an error occurs for invalid or missing
values in a statement when either of the STRICT_ALL_TABLES
or
STRICT_TRANS_TABLES
modes are enabled. The statement is aborted
and rolled back.
For non-transactional tables, the behavior is the same for either mode, if the bad value occurs in the first row to be inserted or updated. The statement is aborted and the table remains unchanged. If the statement inserts or modifies multiple rows and the bad value occurs in the second or later row, the result depends on which strict option is enabled:
STRICT_ALL_TABLES
, MySQL returns an error and ignores the
rest of the rows. However, in this case, the earlier rows will
have been inserted or updated. This means that you might get a partial
update, which might not be what you want. To avoid this, it's best to
use single-row statements because these can be aborted without changing the
table.
STRICT_TRANS_TABLES
, MySQL converts an invalid value to the
closest valid value for the column and insert the adjusted value. If a
value is missing, MySQL inserts the implicit default value for the column
data type. In either case, MySQL generates a warning rather than an error
and continues processing the statement. Implicit defaults are described in
section 13.2.6 CREATE TABLE
Syntax.
Strict mode disallows invalid date values such as '2004-04-31'
.
It does not disallow dates with zero parts such as 2004-04-00'
or
``zero'' dates. To disallow these as well, enable the NO_ZERO_IN_DATE
and NO_ZERO_DATE
SQL modes in addition to strict mode.
If you are not using strict mode (that is, neither STRICT_TRANS_TABLES
nor STRICT_ALL_TABLES
is enabled), MySQL inserts adjusted values
for invalid or missing values and produces warnings. In strict mode, you can
produce this behavior by using INSERT IGNORE
or UPDATE IGNORE
.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
The following special modes are provided as shorthand for combinations of
mode values from the preceding list. All are available as of MySQL 4.1.1,
except TRADITIONAL
(5.0.2).
The descriptions include all mode values that are available in the most recent version of MySQL. For older versions, a combination mode does not include individual mode values that are not available except in newer versions.
ANSI
REAL_AS_FLOAT
, PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, ONLY_FULL_GROUP_BY
. See section 1.5.3 Running MySQL in ANSI Mode.
DB2
PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
.
MAXDB
PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
, NO_AUTO_CREATE_USER
.
MSSQL
PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
.
MYSQL323
NO_FIELD_OPTIONS
, HIGH_NOT_PRECEDENCE
.
MYSQL40
NO_FIELD_OPTIONS
, HIGH_NOT_PRECEDENCE
.
ORACLE
PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
, NO_AUTO_CREATE_USER
.
POSTGRESQL
PIPES_AS_CONCAT
, ANSI_QUOTES
, IGNORE_SPACE
, NO_KEY_OPTIONS
, NO_TABLE_OPTIONS
, NO_FIELD_OPTIONS
.
TRADITIONAL
STRICT_TRANS_TABLES
, STRICT_ALL_TABLES
, NO_ZERO_IN_DATE
, NO_ZERO_DATE
, ERROR_FOR_DIVISION_BY_ZERO
, NO_AUTO_CREATE_USER
.
The server maintains many system variables that indicate how it is configured.
All of them have default values. They can be set at server startup
using options on the command line or in option
files. Most of them can be set at runtime using the
SET
statement.
Beginning with MySQL 4.0.3,
the mysqld
server maintains two kinds of variables.
Global variables affect the overall operation of the server.
Session variables affect its operation for individual client connections.
When the server starts, it initializes all global variables to their default
values. These defaults can be changed by options specified in option files
or on the command line. After the server starts, those global variables
that are dynamic can be changed by connecting to the server and issuing
a SET GLOBAL var_name
statement. To change a global variable,
you must have the SUPER
privilege.
The server also maintains a set of session variables for each client
that connects. The client's session variables are initialized at connect
time using the current values of the corresponding global variables. For
those session variables that are dynamic, the client can change them
by issuing a SET SESSION var_name
statement. Setting a session
variable requires no special privilege, but a client can change only its
own session variables, not those of any other client.
A change to a global variable is visible to any client that accesses that
global variable. However, it affects the corresponding session variable
that is initialized from the global variable only for clients that connect
after the change. It does not affect the session variable for any client
that is currently connected (not even that of the client that issues the
SET GLOBAL
statement).
When setting a variable using a startup option, variable values can be given
with a suffix of K
, M
, or G
to indicate kilobytes,
megabytes, or gigabytes, respectively. For example, the following command
starts the server with a key buffer size of 16 megabytes:
mysqld --key_buffer_size=16M
Before MySQL 4.0, use this syntax instead:
mysqld --set-variable=key_buffer_size=16M
The lettercase of suffix letters does not matter; 16M
and 16m
are
equivalent.
At runtime, use the SET
statement to set system variables. In this
context, suffix letters cannot be used, but the value can take the form of an
expression:
mysql> SET sort_buffer_size = 10 * 1024 * 1024;
To specify explicitly whether to set the global or session variable, use the
GLOBAL
or SESSION
options:
mysql> SET GLOBAL sort_buffer_size = 10 * 1024 * 1024; mysql> SET SESSION sort_buffer_size = 10 * 1024 * 1024;
Without either option, the statement sets the session variable.
The variables that can be set at runtime are listed in section 5.2.3.1 Dynamic System Variables.
If you want to restrict the maximum value to which a system variable can
be set with the SET
statement, you can specify this maximum
by using an option of the form --maximum-var_name
at server
startup. For example, to prevent the value of query_cache_size
from being increased to more than 32MB at runtime, use the option
--maximum-query_cache_size=32M
. This feature is available as of MySQL
4.0.2.
You can view system variables and their values by using the
SHOW VARIABLES
statement.
See section 9.4 System Variables for more information.
mysql> SHOW VARIABLES; +---------------------------------+------------------------------+ | Variable_name | Value | +---------------------------------+------------------------------| | back_log | 50 | | basedir | /usr/local/mysql | | bdb_cache_size | 8388572 | | bdb_home | /usr/local/mysql | | bdb_log_buffer_size | 32768 | | bdb_logdir | | | bdb_max_lock | 10000 | | bdb_shared_data | OFF | | bdb_tmpdir | /tmp/ | | bdb_version | Sleepycat Software: ... | | binlog_cache_size | 32768 | | bulk_insert_buffer_size | 8388608 | | character_set | latin1 | | character_sets | latin1 big5 czech euc_kr | | concurrent_insert | ON | | connect_timeout | 5 | | convert_character_set | | | datadir | /usr/local/mysql/data/ | | default_week_format | 0 | | delay_key_write | ON | | delayed_insert_limit | 100 | | delayed_insert_timeout | 300 | | delayed_queue_size | 1000 | | flush | OFF | | flush_time | 0 | | ft_boolean_syntax | + -><()~*:""&| | | ft_max_word_len | 84 | | ft_min_word_len | 4 | | ft_query_expansion_limit | 20 | | ft_stopword_file | (built-in) | | have_bdb | YES | | have_innodb | YES | | have_isam | YES | | have_openssl | YES | | have_query_cache | YES | | have_raid | NO | | have_symlink | DISABLED | | init_file | | | innodb_additional_mem_pool_size | 1048576 | | innodb_buffer_pool_size | 8388608 | | innodb_data_file_path | ibdata1:10M:autoextend | | innodb_data_home_dir | | | innodb_fast_shutdown | ON | | innodb_file_io_threads | 4 | | innodb_flush_log_at_trx_commit | 1 | | innodb_flush_method | | | innodb_force_recovery | 0 | | innodb_lock_wait_timeout | 50 | | innodb_log_arch_dir | | | innodb_log_archive | OFF | | innodb_log_buffer_size | 1048576 | | innodb_log_file_size | 5242880 | | innodb_log_files_in_group | 2 | | innodb_log_group_home_dir | ./ | | innodb_mirrored_log_groups | 1 | | innodb_thread_concurrency | 8 | | interactive_timeout | 28800 | | join_buffer_size | 131072 | | key_buffer_size | 16773120 | | key_cache_age_threshold | 300 | | key_cache_block_size | 1024 | | key_cache_division_limit | 100 | | language | /usr/local/mysql/share/... | | large_files_support | ON | | local_infile | ON | | locked_in_memory | OFF | | log | OFF | | log_bin | OFF | | log_slave_updates | OFF | | log_slow_queries | OFF | | log_update | OFF | | log_warnings | 1 | | long_query_time | 10 | | low_priority_updates | OFF | | lower_case_table_names | 0 | | max_allowed_packet | 1047552 | | max_binlog_cache_size | 4294967295 | | max_binlog_size | 1073741824 | | max_connect_errors | 10 | | max_connections | 100 | | max_delayed_threads | 20 | | max_error_count | 64 | | max_heap_table_size | 16777216 | | max_join_size | 4294967295 | | max_relay_log_size | 0 | | max_sort_length | 1024 | | max_tmp_tables | 32 | | max_user_connections | 0 | | max_write_lock_count | 4294967295 | | myisam_max_extra_sort_file_size | 268435456 | | myisam_max_sort_file_size | 2147483647 | | myisam_recover_options | force | | myisam_repair_threads | 1 | | myisam_sort_buffer_size | 8388608 | | net_buffer_length | 16384 | | net_read_timeout | 30 | | net_retry_count | 10 | | net_write_timeout | 60 | | open_files_limit | 1024 | | pid_file | /usr/local/mysql/name.pid | | port | 3306 | | protocol_version | 10 | | query_cache_limit | 1048576 | | query_cache_size | 0 | | query_cache_type | ON | | read_buffer_size | 131072 | | read_rnd_buffer_size | 262144 | | rpl_recovery_rank | 0 | | server_id | 0 | | skip_external_locking | ON | | skip_networking | OFF | | skip_show_database | OFF | | slave_net_timeout | 3600 | | slow_launch_time | 2 | | socket | /tmp/mysql.sock | | sort_buffer_size | 2097116 | | sql_mode | | | table_cache | 64 | | table_type | MYISAM | | thread_cache_size | 3 | | thread_stack | 131072 | | timezone | EEST | | tmp_table_size | 33554432 | | tmpdir | /tmp/:/mnt/hd2/tmp/ | | tx_isolation | READ-COMMITTED | | version | 4.0.4-beta | | wait_timeout | 28800 | +---------------------------------+------------------------------+
Most system variables are described here. Variables with no version
indicated have been present since at least MySQL 3.22. InnoDB
system
variables are listed at
section 15.5 InnoDB
Startup Options.
Values for buffer sizes, lengths, and stack sizes are given in bytes unless otherwise specified.
Information on tuning these variables can be found in section 7.5.2 Tuning Server Parameters.
ansi_mode
ON
if mysqld
was started with --ansi
.
See section 1.5.3 Running MySQL in ANSI Mode.
This variable was added in MySQL 3.23.6 and removed in 3.23.41.
See the description for sql_mode
.
back_log
back_log
value indicates how many requests can be
stacked during this short time before MySQL momentarily stops
answering new requests. You need to increase this only if you expect a large
number of connections in a short period of time.
In other words, this value is the size of the listen queue for incoming
TCP/IP connections. Your operating system has its own limit on the size
of this queue. The manual page for the Unix listen()
system
call should have more details. Check your OS documentation for the
maximum value for this variable. Attempting to set back_log
higher than your operating system limit will be ineffective.
basedir
--basedir
option.
bdb_cache_size
BDB
tables. If you don't use BDB
tables, you should start
mysqld
with --skip-bdb
to not waste memory for this cache.
This variable was added in MySQL 3.23.14.
bdb_home
BDB
tables. This should be assigned the same
value as the datadir
variable.
This variable was added in MySQL 3.23.14.
bdb_log_buffer_size
BDB
tables. If you don't use BDB
tables, you should set this
to 0 or start mysqld
with --skip-bdb
to not waste memory for
this cache.
This variable was added in MySQL 3.23.31.
bdb_logdir
BDB
storage engine writes its log files.
This variable can be set with the --bdb-logdir
option.
This variable was added in MySQL 3.23.14.
bdb_max_lock
BDB
table
(10,000 by default). You should increase this if errors such as the
following occur when you perform long transactions or when mysqld
has
to examine many rows to calculate a query:
bdb: Lock table is out of available locks Got error 12 from ...This variable was added in MySQL 3.23.29.
bdb_shared_data
ON
if you are using --bdb-shared-data
.
This variable was added in MySQL 3.23.29.
bdb_tmpdir
--bdb-tmpdir
option.
This variable was added in MySQL 3.23.14.
bdb_version
version_bdb
.
binlog_cache_size
--log-bin
option). If you
often use big, multiple-statement transactions, you can increase this to get
more performance.
The Binlog_cache_use
and Binlog_cache_disk_use
status variables
can be useful for tuning the size of this variable.
This variable was added in MySQL 3.23.29.
See section 5.9.4 The Binary Log.
bulk_insert_buffer_size
MyISAM
uses a special tree-like cache to make bulk inserts faster for
INSERT ... SELECT
, INSERT ... VALUES (...), (...), ...
, and
LOAD DATA INFILE
. This variable limits
the size of the cache tree in bytes per thread. Setting it to 0
disables this optimization.
Note: This cache is used only when adding data to a non-empty table.
The default value is 8MB.
This variable was added in MySQL 4.0.3.
This variable previously was named myisam_bulk_insert_tree_size
.
character_set
character_set_xxx
variables.
character_set_client
character_set_connection
character_set_database
character_set_server
.
This variable was added in MySQL 4.1.1.
character_set_results
character_set_server
character_set_system
utf8
.
This variable was added in MySQL 4.1.1.
character_sets
SHOW CHARACTER SET
for a list of character sets.)
character_sets_dir
collation_connection
collation_database
collation_server
.
This variable was added in MySQL 4.1.1.
collation_server
concurrent_insert
ON
(the default), MySQL allows INSERT
and SELECT
statements to run concurrently for MyISAM
tables that have no free
blocks in the middle. You can turn this option off by starting
mysqld
with --safe
or --skip-new
.
This variable was added in MySQL 3.23.7.
connect_timeout
mysqld
server waits for a connect
packet before responding with Bad handshake
.
convert_character_set
SET CHARACTER SET
.
This variable was removed in MySQL 4.1.
datadir
--datadir
option.
default_week_format
WEEK()
function.
This variable is available as of MySQL 4.0.14.
delay_key_write
MyISAM
tables. It can have one of the
following values to affect handling of the DELAY_KEY_WRITE
table
option that can be used in CREATE TABLE
statements.
Option | Description |
OFF | DELAYED_KEY_WRITE is ignored.
|
ON | MySQL honors the DELAY_KEY_WRITE option
for CREATE TABLE . This is the default value.
|
ALL | All new opened tables are treated as if they were
created with the DELAY_KEY_WRITE option enabled.
|
DELAY_KEY_WRITE
is enabled, this means that the key buffer for
tables with this option are not flushed on every index update, but
only when a table is closed. This will speed up writes on keys a lot,
but if you use this feature, you should add automatic checking of all
MyISAM
tables by starting the server with the --myisam-recover
option (for example, --myisam-recover=BACKUP,FORCE
).
See section 5.2.1 mysqld
Command-Line Options and section 14.1.1 MyISAM
Startup Options.
Note that --external-locking
doesn't offer any protection against
index corruption for tables that use delayed key writes.
This variable was added in MySQL 3.23.8.
delayed_insert_limit
delayed_insert_limit
delayed rows, the INSERT
DELAYED
handler thread checks whether there are any SELECT
statements pending. If so, it allows them to execute before continuing to
insert delayed rows.
delayed_insert_timeout
INSERT DELAYED
handler thread should wait for
INSERT
statements before terminating.
delayed_queue_size
INSERT DELAYED
statements. If the queue becomes full, any client that issues an
INSERT DELAYED
statement will wait until there is room in the queue
again.
expire_logs_days
flush
ON
if you have started mysqld
with the --flush
option.
This variable was added in MySQL 3.22.9.
flush_time
flush_time
seconds to free up resources and sync unflushed data to
disk. We recommend this option only on Windows 9x or Me, or on systems
with minimal resources available.
This variable was added in MySQL 3.22.18.
ft_boolean_syntax
IN BOOLEAN MODE
.
This variable was added in MySQL 4.0.1.
See section 12.6.1 Boolean Full-Text Searches.
The default variable value is '+ -><()~*:""&|'
. The rules for
changing the value are as follows:
ft_max_word_len
FULLTEXT
index.
This variable was added in MySQL 4.0.0.
Note: FULLTEXT
indexes must be rebuilt after changing
this variable.
Use REPAIR TABLE tbl_name QUICK
.
ft_min_word_len
FULLTEXT
index.
This variable was added in MySQL 4.0.0.
Note: FULLTEXT
indexes must be rebuilt after changing
this variable.
Use REPAIR TABLE tbl_name QUICK
.
ft_query_expansion_limit
WITH QUERY EXPANSION
.
This variable was added in MySQL 4.1.1.
ft_stopword_file
''
) disables stopword filtering. This variable was added in
MySQL 4.0.10.
Note: FULLTEXT
indexes must be rebuilt after changing
this variable.
Use REPAIR TABLE tbl_name QUICK
.
group_concat_max_len
GROUP_CONCAT()
function.
This variable was added in MySQL 4.1.0.
have_archive
YES
if mysqld
supports ARCHIVE
tables, NO
if not. This variable was added in MySQL 4.1.3.
have_bdb
YES
if mysqld
supports BDB
tables. DISABLED
if --skip-bdb
is used.
This variable was added in MySQL 3.23.30.
have_compress
zlib
compression library is available to the server.
If not, the COMPRESS()
and UNCOMPRESS()
functions cannot be
used.
This variable was added in MySQL 4.1.1.
have_crypt
crypt()
system call is available to the server.
If not, the CRYPT()
function cannot be used.
This variable was added in MySQL 4.0.10.
have_csv
YES
if mysqld
supports ARCHIVE
tables, NO
if not. This variable was added in MySQL 4.1.4.
have_example_engine
YES
if mysqld
supports EXAMPLE
tables, NO
if not. This variable was added in MySQL 4.1.4.
have_geometry
have_innodb
YES
if mysqld
supports InnoDB
tables. DISABLED
if --skip-innodb
is used.
This variable was added in MySQL 3.23.37.
have_isam
YES
if mysqld
supports ISAM
tables. DISABLED
if --skip-isam
is used.
This variable was added in MySQL 3.23.30.
have_ndbcluster
YES
if mysqld
supports NDB Cluster
tables.
DISABLED
if --skip-ndbcluster
is used.
This variable was added in MySQL 4.1.2.
have_openssl
YES
if mysqld
supports SSL (encryption) of the client/server
protocol.
This variable was added in MySQL 3.23.43.
have_query_cache
YES
if mysqld
supports the query cache.
This variable was added in MySQL 4.0.2.
have_raid
YES
if mysqld
supports the RAID
option.
This variable was added in MySQL 3.23.30.
have_rtree_keys
RTREE
indexes are available. (These are used for spatial
indexed in MyISAM
tables.)
This variable was added in MySQL 4.1.3.
have_symlink
DATA DIRECTORY
and INDEX DIRECTORY
table options.
This variable was added in MySQL 4.0.0.
init_connect
init_connect
can be used to achieve the
same effect:
SET GLOBAL init_connect='SET AUTOCOMMIT=0';This variable can also be set on the command line or in an option file. To set the variable as just shown using an option file, include these lines:
[mysqld] init_connect='SET AUTOCOMMIT=0'Note that the content of
init_connect
is not executed for users having
the SUPER
privilege; this is in case that content has been wrongly set
(contains a wrong query, for example with a syntax error),
thus making all connections fail. Not executing it for SUPER
users
enables those to open a connection and fix init_connect
.
This variable was added in MySQL 4.1.2.
init_file
--init-file
option when you
start the server. This is a file containing SQL statements that you want
the server to execute when it starts.
Each statement must be on a single line and should not include comments.
This variable was added in MySQL 3.23.2.
init_slave
init_connect
, but is a string to be
executed by a slave server each time the SQL thread starts. The format of
the string is the same as for the init_connect
variable.
This variable was added in MySQL 4.1.2.
innodb_xxx
InnoDB
system variables are listed at
section 15.5 InnoDB
Startup Options.
interactive_timeout
CLIENT_INTERACTIVE
option to
mysql_real_connect()
. See also wait_timeout
.
join_buffer_size
join_buffer_size
to get a faster full join when
adding indexes is not possible. One join buffer is allocated for each full
join between two tables. For a complex join between several tables for which
indexes are not used, multiple join buffers might be necessary.
key_buffer_size
MyISAM
and ISAM
tables are buffered and are
shared by all threads. key_buffer_size
is the size of the buffer
used for index blocks. The key buffer is also known as the key cache.
The maximum allowable setting for key_buffer_size
is 4GB. The
effective maximum size might be less, depending on your available
physical RAM and per-process RAM limits imposed by your operating
system or hardware platform.
Increase the value to get better index handling (for all reads and multiple
writes) to as much as you can afford. Using a value that is 25% of total
memory on a machine that mainly runs MySQL is quite common. However, if you
make the value too large (for example, more than 50% of your total memory)
your system might start to page and become extremely slow. MySQL relies on
the operating system to perform filesystem caching for data reads, so you
must leave some room for the filesystem cache.
For even more speed when writing many rows at the same time, use
LOCK TABLES
. See section 13.4.5 LOCK TABLES
and UNLOCK TABLES
Syntax.
You can check the performance of the key buffer by issuing a SHOW
STATUS
statement and examining the Key_read_requests
,
Key_reads
, Key_write_requests
, and Key_writes
status
variables.
See section 13.5.4 SHOW
Syntax.
The Key_reads/Key_read_requests
ratio should normally be
less than 0.01. The Key_writes/Key_write_requests
ratio is usually
near 1 if you are using mostly updates and deletes, but might be much
smaller if you tend to do updates that affect many rows at the same time or
if you are using the DELAY_KEY_WRITE
table option.
The fraction of the key buffer in use can be determined using
key_buffer_size
in conjunction with the Key_blocks_unused
status
variable and the buffer block size. From MySQL 4.1.1 on, the buffer block
size is available from the key_cache_block_size
server variable. The
fraction of the buffer in use is:
1 - ((Key_blocks_unused * key_cache_block_size) / key_buffer_size)This value is an approximation because some space in the key buffer may be allocated internally for administrative structures. Before MySQL 4.1.1, key cache blocks are 1024 bytes, and before MySQL 4.1.2,
Key_blocks_unused
is unavailable. The Key_blocks_used
variable
can be used as follows to determine the fraction of the key buffer in use:
(Key_blocks_used * 1024) / key_buffer_sizeHowever,
Key_blocks_used
indicates the maximum number of blocks that
have ever been in use at once, so this formula does not necessary represent
the current fraction of the buffer that is in use.
See section 7.4.6 The MyISAM
Key Cache.
key_cache_age_threshold
MyISAM
Key Cache.
key_cache_block_size
MyISAM
Key Cache.
key_cache_division_limit
MyISAM
Key Cache.
language
large_file_support
mysqld
was compiled with options for large file support.
This variable was added in MySQL 3.23.28.
large_pages
license
local_infile
LOCAL
is supported for LOAD DATA INFILE
statements.
This variable was added in MySQL 4.0.3.
locked_in_memory
mysqld
was locked in memory with --memlock
.
This variable was added in MySQL 3.23.25.
log
log_bin
log_error
log_slave_updates
log_slow_queries
long_query_time
variable.
This variable was added in MySQL 4.0.2.
See section 5.9.5 The Slow Query Log.
log_update
log_warnings
long_query_time
Slow_queries
status variable is incremented. If you are using the
--log-slow-queries
option, the query is logged to the slow query log
file. This value is measured in real time, not CPU time, so a query that is
under the threshold on a lightly loaded system might be above the threshold
on a heavily loaded one.
See section 5.9.5 The Slow Query Log.
low_priority_updates
1
, all INSERT
, UPDATE
, DELETE
, and
LOCK TABLE WRITE
statements wait until there is no pending
SELECT
or LOCK TABLE READ
on the affected table.
This variable previously was named sql_low_priority_updates
.
It was added in MySQL 3.22.5.
lower_case_file_system
ON
means filenames are case
insensitive, OFF
means they are case sensitive. This variable was
added in MySQL 4.0.19.
lower_case_table_names
lower_case_table_names
to 2.
max_allowed_packet
net_buffer_length
bytes, but can grow up to max_allowed_packet
bytes when needed.
This value by default is small, to catch big (possibly wrong) packets.
You must increase this value if you are using big BLOB
columns or
long strings. It should be as big as the biggest BLOB
you want to
use. The protocol limit for max_allowed_packet
is 16MB before
MySQL 4.0 and 1GB thereafter.
max_binlog_cache_size
Multi-statement transaction required more than
'max_binlog_cache_size' bytes of storage
.
This variable was added in MySQL 3.23.29.
max_binlog_size
max_binlog_size
.
If max_relay_log_size
is 0, the value of max_binlog_size
applies to relay logs as well. max_relay_log_size
was added in
MySQL 4.0.14.
max_connect_errors
FLUSH HOSTS
statement.
max_connections
mysqld
requires. See
section 7.4.8 How MySQL Opens and Closes Tables for comments on file descriptor limits.
Also see section A.2.6 Too many connections
.
max_delayed_threads
INSERT DELAYED
statements. If you try to insert data into a new table after all INSERT
DELAYED
threads are in use, the row will be inserted as if the
DELAYED
attribute wasn't specified. If you set this to 0, MySQL
never creates a thread to handle DELAYED
rows; in effect, this
disables DELAYED
entirely.
This variable was added in MySQL 3.23.0.
max_error_count
SHOW ERRORS
or SHOW WARNINGS
.
This variable was added in MySQL 4.1.0.
max_heap_table_size
MEMORY
(HEAP
)
tables are allowed to grow. The value of the variable is used to calculate
MEMORY
table MAX_ROWS
values. Setting this variable has no
effect on any existing MEMORY
table, unless the table is re-created
with a statement such as CREATE TABLE
or TRUNCATE TABLE
, or
altered with ALTER TABLE
.
This variable was added in MySQL 3.23.0.
max_insert_delayed_threads
max_delayed_threads
.
It was added in MySQL 4.0.19.
max_join_size
SELECT
statements that probably will need to examine
more than max_join_size
row combinations or are likely to do more
than max_join_size
disk seeks. By setting this value, you can catch
SELECT
statements where keys are not used properly and that would
probably take a long time. Set it if your users tend to perform joins
that lack a WHERE
clause, that take a long time, or that return
millions of rows.
Setting this variable to a value other than DEFAULT
resets
the SQL_BIG_SELECTS
value to 0
. If you set the
SQL_BIG_SELECTS
value again, the max_join_size
variable
is ignored.
If a query result is in the query cache, no result size
check is performed, because the result has previously been computed and it does
not burden the server to send it to the client.
This variable previously was named sql_max_join_size
.
max_length_for_sort_data
filesort
algorithm to use.
See section 7.2.10 How MySQL Optimizes ORDER BY
.
This variable was added in MySQL 4.1.1
max_relay_log_size
max_binlog_size
for both binary logs and relay
logs. You must set max_relay_log_size
to between 4096 bytes and 1GB
(inclusive), or to 0. The default value is 0. This variable was added in
MySQL 4.0.14.
See section 6.3 Replication Implementation Details.
max_seeks_for_key
SHOW INDEX
Syntax). By setting this to a low value (100?), you can force
MySQL to prefer keys instead of table scans.
This variable was added in MySQL 4.0.14.
max_sort_length
BLOB
or TEXT
values. Only the first max_sort_length
bytes of each value
are used; the rest are ignored.
max_tmp_tables
max_user_connections
MAX_USER_CONNECTIONS
resource limit. In that case, the
session value reflects the account limit.
max_write_lock_count
multi_read_range
NDBCLUSTER
. This engine needs to send
the range requests to all nodes, and sending many of those requests at once
reduces the communication costs significantly. This variable was added in
MySQL 5.0.3.
myisam_data_pointer_size
CREATE TABLE
for
MyISAM
tables when no MAX_ROWS
option is specified. This
variable cannot be less than 2 or larger than 8. The default value is 4.
This variable was added in MySQL 4.1.2.
See section A.2.11 The table is full
.
myisam_max_extra_sort_file_size
MyISAM
index creation would be
larger than using the key cache by the amount specified here, prefer the key
cache method. This is mainly used to force long character keys in large
tables to use the slower key cache method to create the index.
This variable was added in MySQL 3.23.37.
Note: The value is given in megabytes before 4.0.3 and
in bytes thereafter.
myisam_max_sort_file_size
MyISAM
index (during REPAIR TABLE
, ALTER
TABLE
, or LOAD DATA INFILE
). If the file size would be bigger than
this value, the index will be created using the key cache instead, which is
slower.
This variable was added in MySQL 3.23.37.
Note: The value is given in megabytes before 4.0.3 and
in bytes thereafter.
myisam_recover_options
--myisam-recover
option.
This variable was added in MySQL 3.23.36.
myisam_repair_threads
MyISAM
table indexes are created in
parallel (each index in its own thread) during the Repair by sorting
process. The default value is 1. Note: Multi-threaded repair is
still alpha quality code.
This variable was added in MySQL 4.0.13.
myisam_sort_buffer_size
MyISAM
indexes during a
REPAIR TABLE
or when creating indexes with CREATE INDEX
or
ALTER TABLE
.
This variable was added in MySQL 3.23.16.
named_pipe
net_buffer_length
max_allowed_packet
bytes.
net_read_timeout
net_read_timeout
is the
timeout value controlling when to abort.
When the server is writing to the client, net_write_timeout
is the
timeout value controlling when to abort.
See also slave_net_timeout
.
This variable was added in MySQL 3.23.20.
net_retry_count
net_write_timeout
net_read_timeout
.
This variable was added in MySQL 3.23.20.
new
old_passwords
open_files_limit
mysqld
to open.
This is the real value allowed by the system and might be different from the
value you gave mysqld
as a startup option. The value is 0 on systems
where MySQL can't change the number of open files. This variable was added
in MySQL 3.23.20.
optimizer_prune_level
optimizer_search_depth
pid_file
--pid-file
option.
This variable was added in MySQL 3.23.23.
port
--port
option.
preload_buffer_size
protocol_version
query_alloc_block_size
query_cache_limit
query_cache_min_res_unit
query_cache_size
query_cache_type
is set to 0.
This variable was added in MySQL 4.0.1.
query_cache_type
GLOBAL
value sets the type for all
clients that connect thereafter. Individual clients can set the
SESSION
value to affect their own use of the query cache.
Option | Description |
0 or OFF | Don't cache or retrieve results.
Note that this will not deallocate the query cache buffer. To
do that, you should set query_cache_size to 0.
|
1 or ON | Cache all query results except for those that
begin with SELECT SQL_NO_CACHE .
|
2 or DEMAND | Cache results only for queries that
begin with SELECT SQL_CACHE .
|
query_cache_wlock_invalidate
WRITE
lock on a MyISAM
table, other clients are not blocked from issuing queries for the table if
the query results are present in the query cache. Setting this variable to
1 causes acquisition of a WRITE
lock for a table to invalidate
any queries in the query cache that refer to the table. This forces other
clients that attempt to access the table to wait while the lock is in effect.
This variable was added in MySQL 4.0.19.
query_prealloc_size
query_prealloc_size
value
might be helpful in improving performance, because it can reduce the need for
the server to perform memory allocation during query execution operations.
This variable was added in MySQL 4.0.16.
range_alloc_block_size
read_buffer_size
record_buffer
.
read_only
ON
for a replication slave server, it
causes the slave to allow no updates except from slave threads or from users
with the SUPER
privilege. This can be useful to ensure that a slave
server accepts no updates from clients.
This variable was added in MySQL 4.0.14.
relay_log_purge
read_rnd_buffer_size
ORDER BY
performance by a lot. However, this is a buffer
allocated for each client, so you should not set the global variable to a
large value. Instead, change the session variable only from within those
clients that need to run large queries.
This variable was added in MySQL 4.0.3.
Previously, it was named record_rnd_buffer
.
safe_show_database
skip_show_database
.
This variable was removed in MySQL 4.0.5. Instead, use the SHOW
DATABASES
privilege to control access by MySQL accounts to database names.
secure_auth
--secure-auth
option,
it blocks connections from all accounts that have passwords stored in the old
(pre-4.1) format. In that case, the value of this variable is ON
,
otherwise it is OFF
.
You should enable this option if you want to prevent all usage of passwords
in old format (and hence insecure communication over the network).
This variable was added in MySQL 4.1.1.
Server startup will fail with an error if this option is enabled
and the privilege tables are in pre-4.1 format.
When used as a client-side option, the client refuses to connect to a server
if the server requires a password in old format for the client account.
server_id
--server-id
option. It is used for master and slave
replication servers.
This variable was added in MySQL 3.23.26.
shared_memory
shared_memory_base_name
skip_external_locking
OFF
if mysqld
uses external locking.
This variable was added in MySQL 4.0.3.
Previously, it was named skip_locking
.
skip_networking
ON
if the server allows only local (non-TCP/IP) connections.
On Unix, local connections use a Unix socket file. On Windows, local
connections use a named pipe or shared memory. On NetWare, only TCP/IP connections are
supported, so do not set this variable to ON
.
This variable was added in MySQL 3.22.23.
skip_show_database
SHOW DATABASES
statement if they
don't have the SHOW DATABASES
privilege. This can improve security if
you're concerned about people being able to see what databases other users
have. See also safe_show_database
.
This variable was added in MySQL 3.23.4. As of MySQL 4.0.2, its effect also
depends on the SHOW DATABASES
privilege: If the variable value is
ON
, the SHOW DATABASES
statement is allowed only to users who
have the SHOW DATABASES
privilege, and the statement displays all
database names. If the value is OFF
, SHOW DATABASES
is
allowed to all users, but displays each database name only if the user has
the SHOW DATABASES
privilege or some privilege for the database.
slave_compressed_protocol
slave_net_timeout
slow_launch_time
Slow_launch_threads
status variable.
This variable was added in MySQL 3.23.15.
socket
sort_buffer_size
ORDER BY
or GROUP BY
operations.
See section A.4.4 Where MySQL Stores Temporary Files.
sql_mode
sql_slave_skip_counter
storage_engine
table_type
.
It was added in MySQL 4.1.2.
sync_binlog
fdatasync()
) after every sync_binlog
'th write to this binary
log. Note that there is one write to the binary log per statement if in
autocommit mode, and otherwise one write per transaction. The default value is
0 which does no sync'ing to disk. A value of 1 is the safest choice, because in
case of crash you will lose at most one statement/transaction from the binary
log; but it is also the slowest choice (unless the disk has a battery-backed
cache, which makes sync'ing very fast). This variable was added in MySQL 4.1.3.
sync_frm
fdatasync()
);
this is slower but safer in case of crash. Default is 1.
system_time_zone
system_time_zone
. Typically the time zone
is specified by the TZ
environment variable. It also can be specified
using the --timezone
option of the mysqld_safe
script.
This variable was added in MySQL 4.1.3.
table_cache
mysqld
requires.
You can check whether you need to increase the table cache by checking the
Opened_tables
status variable.
See section 5.2.4 Server Status Variables.
If the value of Opened_tables
is large and you don't do FLUSH
TABLES
a lot (which just forces all tables to be closed and reopened),
then you should increase the value of the table_cache
variable.
For more information about the table cache, see section 7.4.8 How MySQL Opens and Closes Tables.
table_type
--default-table-type
option.
This variable was added in MySQL 3.23.0.
See section 5.2.1 mysqld
Command-Line Options.
thread_cache_size
thread_cache_size
threads there. Requests for threads are
satisfied by reusing threads taken from the cache if possible, and only when
the cache is empty is a new thread created. This variable can be increased
to improve performance if you have a lot of new connections. (Normally this
doesn't give a notable performance improvement if you have a good thread
implementation.) By examining the difference between the Connections
and Threads_created
status variables (see section 5.2.4 Server Status Variables
for details) you can see how efficient the thread cache is.
This variable was added in MySQL 3.23.16.
thread_concurrency
mysqld
calls thr_setconcurrency()
with this value.
This function allows applications to give the threads system a hint about
the desired number of threads that should be run at the same time.
This variable was added in MySQL 3.23.7.
thread_stack
crash-me
test are dependent on this value. The default is
large enough for normal operation. See section 7.1.4 The MySQL Benchmark Suite.
time_zone
'SYSTEM'
(use the value of system_time_zone
), but can be specified
explicitly at server startup time with the --default-time-zone
option.
This variable was added in MySQL 4.1.3.
timezone
TZ
environment
variable when mysqld
is started. The time zone also can be set by
giving a --timezone
argument to mysqld_safe
.
This variable was added in MySQL 3.23.15. As of MySQL 4.1.3, it is obsolete
and has been replaced by the system_time_zone
variable.
See section A.4.6 Time Zone Problems.
tmp_table_size
MyISAM
table.
Increase the value of tmp_table_size
if you do many advanced
GROUP BY
queries and you have lots of memory.
tmpdir
tmpdir
to point to a directory on a memory-based filesystem or to a
directory that is cleared when the server host restarts. A replication
slave needs some of its temporary files to survive a machine restart so that
it can replicate temporary tables or LOAD DATA INFILE
operations. If
files in the temporary file directory are lost when the server restarts,
replication will fail.
This variable was added in MySQL 3.22.4.
transaction_alloc_block_size
transaction_prealloc_size
transaction_alloc_blocks
that
is not freed between queries. By making this big enough to fit all queries
in a common transaction, you can avoid a lot of malloc()
calls. This
variable was added in MySQL 4.0.16.
tx_isolation
updatable_views_with_limit
LIMIT
clause. (Such updates often are generated by GUI tools.)
An update is an UPDATE
or DELETE
statement. Primary key
here means a PRIMARY KEY
, or a UNIQUE
index in which no column
can contain NULL
.
The variable can have two values:
1
or YES
: Issue a warning only (not an error message).
This is the default value.
0
or NO
: Prohibit the update.
version
version_bdb
BDB
storage engine version.
This variable was added in MySQL 3.23.31 with the name bdb_version
and renamed to version_bdb
in MySQL 4.1.1.
version_comment
configure
script has a --with-comment
option that
allows a comment to be specified when building MySQL.
This variable contains the value of that comment.
This variable was added in MySQL 4.0.17.
version_compile_machine
version_compile_os
wait_timeout
wait_timeout
value is initialized from
the global wait_timeout
value or from the global
interactive_timeout
value, depending on the type of client (as
defined by the CLIENT_INTERACTIVE
connect option to
mysql_real_connect()
). See also interactive_timeout
.
Beginning with MySQL 4.0.3, many server system variables are dynamic and can
be set at runtime using SET GLOBAL
or SET SESSION
. You can also
select their values using SELECT
.
See section 9.4 System Variables.
The following table shows the full list of all dynamic system variables.
The last column indicates for each variable whether GLOBAL
or
SESSION
(or both) apply.
Variable Name | Value Type | Type |
autocommit | boolean | SESSION
|
big_tables | boolean | SESSION
|
binlog_cache_size | numeric | GLOBAL
|
bulk_insert_buffer_size | numeric | GLOBAL | SESSION
|
character_set_client | string | GLOBAL | SESSION
|
character_set_connection | string | GLOBAL | SESSION
|
character_set_results | string | GLOBAL | SESSION
|
character_set_server | string | GLOBAL | SESSION
|
collation_connection | string | GLOBAL | SESSION
|
collation_server | string | GLOBAL | SESSION
|
concurrent_insert | boolean | GLOBAL
|
connect_timeout | numeric | GLOBAL
|
convert_character_set | string | GLOBAL | SESSION
|
default_week_format | numeric | GLOBAL | SESSION
|
delay_key_write | OFF | ON | ALL | GLOBAL
|
delayed_insert_limit | numeric | GLOBAL
|
delayed_insert_timeout | numeric | GLOBAL
|
delayed_queue_size | numeric | GLOBAL
|
error_count | numeric | SESSION
|
expire_logs_days | numeric | GLOBAL
|
flush | boolean | GLOBAL
|
flush_time | numeric | GLOBAL
|
foreign_key_checks | boolean | SESSION
|
ft_boolean_syntax | numeric | GLOBAL
|
group_concat_max_len | numeric | GLOBAL | SESSION
|
identity | numeric | SESSION
|
innodb_autoextend_increment | numeric | GLOBAL
|
innodb_concurrency_tickets | numeric | GLOBAL
|
innodb_max_dirty_pages_pct | numeric | GLOBAL
|
innodb_max_purge_lag | numeric | GLOBAL
|
innodb_sync_spin_loops | numeric | GLOBAL
|
innodb_table_locks | boolean | GLOBAL | SESSION
|
innodb_thread_concurrency | numeric GLOBAL
| |
innodb_thread_sleep_delay | numeric GLOBAL
| |
insert_id | boolean | SESSION
|
interactive_timeout | numeric | GLOBAL | SESSION
|
join_buffer_size | numeric | GLOBAL | SESSION
|
key_buffer_size | numeric | GLOBAL
|
last_insert_id | numeric | SESSION
|
local_infile | boolean | GLOBAL
|
log_warnings | numeric | GLOBAL
|
long_query_time | numeric | GLOBAL | SESSION
|
low_priority_updates | boolean | GLOBAL | SESSION
|
max_allowed_packet | numeric | GLOBAL | SESSION
|
max_binlog_cache_size | numeric | GLOBAL
|
max_binlog_size | numeric | GLOBAL
|
max_connect_errors | numeric | GLOBAL
|
max_connections | numeric | GLOBAL
|
max_delayed_threads | numeric | GLOBAL
|
max_error_count | numeric | GLOBAL | SESSION
|
max_heap_table_size | numeric | GLOBAL | SESSION
|
max_insert_delayed_threads | numeric | GLOBAL
|
max_join_size | numeric | GLOBAL | SESSION
|
max_relay_log_size | numeric | GLOBAL
|
max_seeks_for_key | numeric | GLOBAL | SESSION
|
max_sort_length | numeric | GLOBAL | SESSION
|
max_tmp_tables | numeric | GLOBAL | SESSION
|
max_user_connections | numeric | GLOBAL
|
max_write_lock_count | numeric | GLOBAL
|
multi_read_range | numeric | GLOBAL | SESSION
|
myisam_data_pointer_size | numeric | GLOBAL
|
myisam_max_extra_sort_file_size | numeric | GLOBAL | SESSION
|
myisam_max_sort_file_size | numeric | GLOBAL | SESSION
|
myisam_repair_threads | numeric | GLOBAL | SESSION
|
myisam_sort_buffer_size | numeric | GLOBAL | SESSION
|
net_buffer_length | numeric | GLOBAL | SESSION
|
net_read_timeout | numeric | GLOBAL | SESSION
|
net_retry_count | numeric | GLOBAL | SESSION
|
net_write_timeout | numeric | GLOBAL | SESSION
|
old_passwords | numeric | GLOBAL | SESSION
|
optimizer_prune_level | numeric | GLOBAL | SESSION
|
optimizer_search_depth | numeric | GLOBAL | SESSION
|
preload_buffer_size | numeric | GLOBAL | SESSION
|
query_alloc_block_size | numeric | GLOBAL | SESSION
|
query_cache_limit | numeric | GLOBAL
|
query_cache_size | numeric | GLOBAL
|
query_cache_type | enumeration | GLOBAL | SESSION
|
query_cache_wlock_invalidate | boolean | GLOBAL | SESSION
|
query_prealloc_size | numeric | GLOBAL | SESSION
|
range_alloc_block_size | numeric | GLOBAL | SESSION
|
read_buffer_size | numeric | GLOBAL | SESSION
|
read_only | numeric | GLOBAL
|
read_rnd_buffer_size | numeric | GLOBAL | SESSION
|
rpl_recovery_rank | numeric | GLOBAL
|
safe_show_database | boolean | GLOBAL
|
secure_auth | boolean | GLOBAL
|
server_id | numeric | GLOBAL
|
slave_compressed_protocol | boolean | GLOBAL
|
slave_net_timeout | numeric | GLOBAL
|
slow_launch_time | numeric | GLOBAL
|
sort_buffer_size | numeric | GLOBAL | SESSION
|
sql_auto_is_null | boolean | SESSION
|
sql_big_selects | boolean | SESSION
|
sql_big_tables | boolean | SESSION
|
sql_buffer_result | boolean | SESSION
|
sql_log_bin | boolean | SESSION
|
sql_log_off | boolean | SESSION
|
sql_log_update | boolean | SESSION
|
sql_low_priority_updates | boolean | GLOBAL | SESSION
|
sql_max_join_size | numeric | GLOBAL | SESSION
|
sql_mode | enumeration | GLOBAL | SESSION
|
sql_quote_show_create | boolean | SESSION
|
sql_safe_updates | boolean | SESSION
|
sql_select_limit | numeric | SESSION
|
sql_slave_skip_counter | numeric | GLOBAL
|
updatable_views_with_limit | enumeration | GLOBAL | SESSION
|
sql_warnings | boolean | SESSION
|
sync_binlog | numeric | GLOBAL
|
sync_frm | boolean | GLOBAL
|
storage_engine | enumeration | GLOBAL | SESSION
|
table_cache | numeric | GLOBAL
|
table_type | enumeration | GLOBAL | SESSION
|
thread_cache_size | numeric | GLOBAL
|
time_zone | string | GLOBAL | SESSION
|
timestamp | boolean | SESSION
|
tmp_table_size | enumeration | GLOBAL | SESSION
|
transaction_alloc_block_size | numeric | GLOBAL | SESSION
|
transaction_prealloc_size | numeric | GLOBAL | SESSION
|
tx_isolation | enumeration | GLOBAL | SESSION
|
unique_checks | boolean | SESSION
|
wait_timeout | numeric | GLOBAL | SESSION
|
warning_count | numeric | SESSION
|
Variables that are marked as ``string'' take a string value. Variables that
are marked as ``numeric'' take a numeric value. Variables that are
marked as ``boolean'' can be set to 0, 1, ON
or OFF
. Variables
that are marked as ``enumeration'' normally should be set to one of the
available values for the variable, but can also be set to the number that
corresponds to the desired enumeration value. For enumeration-valued system
variables, the first enumeration value corresponds to 0. This differs
from ENUM
columns, for which the first enumeration value corresponds
to 1.
The server maintains many status variables that provide information about its
operations. You can view these variables and their values by using the
SHOW STATUS
statement:
mysql> SHOW STATUS; +--------------------------+------------+ | Variable_name | Value | +--------------------------+------------+ | Aborted_clients | 0 | | Aborted_connects | 0 | | Bytes_received | 155372598 | | Bytes_sent | 1176560426 | | Connections | 30023 | | Created_tmp_disk_tables | 0 | | Created_tmp_files | 60 | | Created_tmp_tables | 8340 | | Delayed_errors | 0 | | Delayed_insert_threads | 0 | | Delayed_writes | 0 | | Flush_commands | 1 | | Handler_delete | 462604 | | Handler_read_first | 105881 | | Handler_read_key | 27820558 | | Handler_read_next | 390681754 | | Handler_read_prev | 6022500 | | Handler_read_rnd | 30546748 | | Handler_read_rnd_next | 246216530 | | Handler_update | 16945404 | | Handler_write | 60356676 | | Key_blocks_used | 14955 | | Key_read_requests | 96854827 | | Key_reads | 162040 | | Key_write_requests | 7589728 | | Key_writes | 3813196 | | Max_used_connections | 0 | | Not_flushed_delayed_rows | 0 | | Not_flushed_key_blocks | 0 | | Open_files | 2 | | Open_streams | 0 | | Open_tables | 1 | | Opened_tables | 44600 | | Qcache_free_blocks | 36 | | Qcache_free_memory | 138488 | | Qcache_hits | 79570 | | Qcache_inserts | 27087 | | Qcache_lowmem_prunes | 3114 | | Qcache_not_cached | 22989 | | Qcache_queries_in_cache | 415 | | Qcache_total_blocks | 912 | | Questions | 2026873 | | Select_full_join | 0 | | Select_full_range_join | 0 | | Select_range | 99646 | | Select_range_check | 0 | | Select_scan | 30802 | | Slave_open_temp_tables | 0 | | Slave_running | OFF | | Slow_launch_threads | 0 | | Slow_queries | 0 | | Sort_merge_passes | 30 | | Sort_range | 500 | | Sort_rows | 30296250 | | Sort_scan | 4650 | | Table_locks_immediate | 1920382 | | Table_locks_waited | 0 | | Threads_cached | 0 | | Threads_connected | 1 | | Threads_created | 30022 | | Threads_running | 1 | | Uptime | 80380 | +--------------------------+------------+
Many status variables are reset to 0 by the FLUSH STATUS
statement.
The status variables have the following meanings. The Com_xxx
statement counter variables were added beginning with MySQL 3.23.47. The
Qcache_xxx
query cache variables were added beginning with MySQL
4.0.1. Otherwise, variables with no version indicated have been present since
at least MySQL 3.22.
Aborted_clients
Aborted_connects
Binlog_cache_disk_use
binlog_cache_size
and used a temporary file to
store statements from the transaction.
This variable was added in MySQL 4.1.2.
Binlog_cache_use
Bytes_received
Bytes_sent
Com_xxx
Com_delete
and Com_insert
count DELETE
and INSERT
statements.
Connections
Created_tmp_disk_tables
Created_tmp_files
mysqld
has created.
This variable was added in MySQL 3.23.28.
Created_tmp_tables
Created_tmp_disk_tables
is big, you may want to increase the
tmp_table_size
value to cause temporary tables to be memory-based
instead of disk-based.
Delayed_errors
INSERT DELAYED
for which some error
occurred (probably duplicate key
).
Delayed_insert_threads
INSERT DELAYED
handler threads in use.
Delayed_writes
INSERT DELAYED
rows written.
Flush_commands
FLUSH
statements.
Handler_commit
COMMIT
statements.
This variable was added in MySQL 4.0.2.
Handler_discover
NDB Cluster
storage engine if it knows about
a table with a given name. This is called discovery. Handler_discover
indicates the number of time tables have been discovered.
This variable was added in MySQL 4.1.2.
Handler_delete
Handler_read_first
SELECT col1 FROM foo
, assuming that col1
is indexed.
Handler_read_key
Handler_read_next
Handler_read_prev
ORDER BY ... DESC
.
This variable was added in MySQL 3.23.6.
Handler_read_rnd
Handler_read_rnd_next
Handler_rollback
ROLLBACK
statements.
This variable was added in MySQL 4.0.2.
Handler_update
Handler_write
Innodb_buffer_pool_pages_data
Innodb_buffer_pool_pages_dirty
Innodb_buffer_pool_pages_flushed
Innodb_buffer_pool_pages_free
Innodb_buffer_pool_pages_latched
InnoDB
buffer pool. These are pages
currently being read or written or that can't be flushed or removed
for some other reason.
Added in MySQL 5.0.2.
Innodb_buffer_pool_pages_misc
Innodb_buffer_pool_pages_total
- Innodb_buffer_pool_pages_free
- Innodb_buffer_pool_pages_data
.
Added in MySQL 5.0.2.
Innodb_buffer_pool_pages_total
Innodb_buffer_pool_read_ahead_rnd
InnoDB
initiated. This happens
when a query is to scan a large portion of a table but in random order.
Added in MySQL 5.0.2.
Innodb_buffer_pool_read_ahead_seq
InnoDB
initiated. This happens when
InnoDB
does a sequential full table scan.
Added in MySQL 5.0.2.
Innodb_buffer_pool_read_requests
InnoDB
has done.
Added in MySQL 5.0.2.
Innodb_buffer_pool_reads
InnoDB
could not satisfy from
buffer pool and had to do a single-page read.
Added in MySQL 5.0.2.
Innodb_buffer_pool_wait_free
InnoDB
buffer pool happen in the background.
However, if it's necessary to read or create a page and no clean pages are
available, it's necessary to wait for pages to be flushed first.
This counter counts instances of these waits.
If the buffer pool size was set properly, this value should be small.
Added in MySQL 5.0.2.
Innodb_buffer_pool_write_requests
InnoDB
buffer pool.
Added in MySQL 5.0.2.
Innodb_data_fsyncs
fsync()
operations so far.
Added in MySQL 5.0.2.
Innodb_data_pending_fsyncs
fsync()
operations.
Added in MySQL 5.0.2.
Innodb_data_pending_reads
Innodb_data_pending_writes
Innodb_data_read
Innodb_data_reads
Innodb_data_writes
Innodb_data_written
Innodb_dblwr_writes
Innodb_dblwr_pages_written
Innodb_log_waits
Innodb_log_write_requests
Innodb_log_writes
Innodb_os_log_fsyncs
Innodb_os_log_pending_fsyncs
Innodb_os_log_pending_writes
Innodb_os_log_written
Innodb_page_size
InnoDB
page size (default 16KB). Many values are
counted in pages; the page size allows them to be easily converted to bytes.
Added in MySQL 5.0.2.
Innodb_pages_created
Innodb_pages_read
Innodb_pages_written
Innodb_row_lock_current_waits
Innodb_row_lock_time
Innodb_row_lock_time_avg
Innodb_row_lock_time_max
Innodb_row_lock_waits
Innodb_rows_deleted
InnoDB
tables.
Added in MySQL 5.0.2.
Innodb_rows_inserted
InnoDB
tables.
Added in MySQL 5.0.2.
Innodb_rows_read
InnoDB
tables.
Added in MySQL 5.0.2.
Innodb_rows_updated
InnoDB
tables.
Added in MySQL 5.0.2.
Key_blocks_not_flushed
Not_flushed_key_blocks
.
Key_blocks_unused
key_buffer_size
in
section 5.2.3 Server System Variables.
This variable was added in MySQL 4.1.2.
section 5.2.3 Server System Variables.
Key_blocks_used
Key_read_requests
Key_reads
Key_reads
is big, then your key_buffer_size
value is
probably too small. The cache miss rate can be calculated as
Key_reads
/Key_read_requests
.
Key_write_requests
Key_writes
Last_query_cost
Max_used_connections
Not_flushed_delayed_rows
INSERT DELAY
queues.
Not_flushed_key_blocks
Key_blocks_not_flushed
before MySQL 4.1.1.
Open_files
Open_streams
Open_tables
Opened_tables
Opened_tables
is big, your table_cache
value is probably too small.
Qcache_free_blocks
Qcache_free_memory
Qcache_hits
Qcache_inserts
Qcache_lowmem_prunes
Qcache_not_cached
query_cache_type
).
Qcache_queries_in_cache
Qcache_total_blocks
Questions
Rpl_status
Select_full_join
Select_full_range_join
Select_range
Select_range_check
Select_scan
Slave_open_temp_tables
Slave_running
ON
if this server is a slave that is connected to a master.
This variable was added in MySQL 3.23.16.
Slow_launch_threads
slow_launch_time
seconds to create.
This variable was added in MySQL 3.23.15.
Slow_queries
long_query_time
seconds. See section 5.9.5 The Slow Query Log.
Sort_merge_passes
sort_buffer_size
system variable.
This variable was added in MySQL 3.23.28.
Sort_range
Sort_rows
Sort_scan
Ssl_xxx
Table_locks_immediate
Table_locks_waited
Threads_cached
Threads_connected
Threads_created
Threads_created
is big, you may want to increase the
thread_cache_size
value. The cache hit rate can be calculated
as Threads_created
/Connections
.
This variable was added in MySQL 3.23.31.
Threads_running
Uptime
The server shutdown process can be summarized like this:
A more detailed description of the process follows:
SHUTDOWN
privilege can execute a mysqladmin shutdown
command. mysqladmin
can be used on any platform supported by
MySQL. Other operating system-specific shutdown initiation methods are possible
as well: The server shuts down on Unix when it receives a SIGTERM
signal. A server running as a service on Windows shuts down when the services
manager tells it to.
SIGTERM
signal, the signal thread might handle shutdown itself, or it
might create a separate thread to do so. If the server tries to create a
shutdown thread and cannot (for example, if memory is exhausted), it issues a
diagnostic message that will appear in the error log:
Error: Can't create thread to kill server
KILL
Syntax, in particular for the
instructions about killed REPAIR TABLE
or OPTIMIZE TABLE
operations on MyISAM
tables.
For threads that have an open transaction, the transaction is rolled back.
Note that if a thread is updating a non-transactional table, an operation
such as a multiple-row UPDATE
or INSERT
may leave the table
partially updated, because the operation can terminate before completion.
If the server is a master replication server, threads associated with
currently connected slaves are treated like other client threads. That
is, each one is marked as killed and exits when it next checks its state.
If the server is a slave replication server, the I/O and SQL threads, if
active, are stopped before client threads are marked as killed. The SQL
thread is allowed to finish its current statement (to avoid causing
replication problems) then stops. If the SQL thread was in the middle
of a transaction at this point, the transaction is rolled back.
This section describes some general security issues to be aware of and what you can do to make your MySQL installation more secure against attack or misuse. For information specifically about the access control system that MySQL uses for setting up user accounts and checking database access, see section 5.5 The MySQL Access Privilege System.
Anyone using MySQL on a computer connected to the Internet should read this section to avoid the most common security mistakes.
In discussing security, we emphasize the necessity of fully protecting the entire server host (not just the MySQL server) against all types of applicable attacks: eavesdropping, altering, playback, and denial of service. We do not cover all aspects of availability and fault tolerance here.
MySQL uses security based on Access Control Lists (ACLs) for all connections, queries, and other operations that users can attempt to perform. There is also some support for SSL-encrypted connections between MySQL clients and servers. Many of the concepts discussed here are not specific to MySQL at all; the same general ideas apply to almost all applications.
When running MySQL, follow these guidelines whenever possible:
root
accounts) access
to the user
table in the mysql
database! This is critical.
The encrypted password is the real password in MySQL. Anyone who
knows the password that is listed in the user
table and has access
to the host listed for the account can easily log in as that user.
GRANT
and
REVOKE
statements are used for controlling access to MySQL. Do
not grant any more privileges than necessary. Never grant privileges to all
hosts.
Checklist:
mysql -u root
. If you are able to connect successfully to the
server without being asked for a password, you have problems. Anyone
can connect to your MySQL server as the MySQL
root
user with full privileges!
Review the MySQL installation instructions, paying particular
attention to the information about setting a root
password.
See section 2.9.3 Securing the Initial MySQL Accounts.
SHOW GRANTS
statement and check to see who has access to
what. Then use the REVOKE
statement to remove those privileges that
are not necessary.
MD5()
, SHA1()
, or
some other one-way hashing function.
nmap
. MySQL uses port 3306 by default. This port should
not be accessible from untrusted hosts. Another simple way to check whether
or not your MySQL port is open is to try the following command
from some remote machine, where server_host
is the host on which
your MySQL server runs:
shell> telnet server_host 3306If you get a connection and some garbage characters, the port is open, and should be closed on your firewall or router, unless you really have a good reason to keep it open. If
telnet
just hangs or the
connection is refused, everything is OK; the port is blocked.
; DROP
DATABASE mysql;
''. This is an extreme example, but large security leaks
and data loss might occur as a result of hackers using similar techniques,
if you do not prepare for them.
A common mistake is to protect only string data values. Remember to check
numeric data as well. If an application generates a query such as
SELECT * FROM table WHERE ID=234
when a user enters the value
234
, the user can enter the value 234 OR 1=1
to cause the
application to generate the query SELECT * FROM table WHERE ID=234 OR
1=1
. As a result, the server retrieves every record in the table. This
exposes every record and causes excessive server load. The simplest way to
protect from this type of attack is to use apostrophes around the numeric
constants: SELECT * FROM table WHERE ID='234'
. If the user enters
extra information, it all becomes part of the string. In numeric context,
MySQL automatically converts this string to a number and strips any trailing
non-numeric characters from it.
Sometimes people think that if a database contains only publicly available
data, it need not be protected. This is incorrect. Even if it is allowable
to display any record in the database, you should still protect against
denial of service attacks (for example, those that are based on the
technique in the preceding paragraph that causes the server to waste
resources). Otherwise, your server becomes unresponsive to legitimate users.
Checklist:
%22
(`"'), %23
(`#'), and %27
(`'') in the URL.
mysql_real_escape_string()
API call.
escape
and quote
modifiers for query streams.
mysql_escape_string()
function, which
is based on the function of the same name in the MySQL C API.
Prior to PHP 4.0.3, use addslashes()
instead.
quote()
method or use placeholders.
PreparedStatement
object and placeholders.
tcpdump
and strings
utilities. For most cases,
you can check whether MySQL data streams are unencrypted
by issuing a command like the following:
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings(This works under Linux and should work with small modifications under other systems.) Warning: If you do not see plaintext data, this doesn't always mean that the information actually is encrypted. If you need high security, you should consult with a security expert.
When you connect to a MySQL server, you should use a password. The password is not transmitted in clear text over the connection. Password handling during the client connection sequence was upgraded in MySQL 4.1.1 to be very secure. If you are using an older version of MySQL, or are still using pre-4.1.1-style passwords, the encryption algorithm is less strong and with some effort a clever attacker who can sniff the traffic between the client and the server can crack the password. (See section 5.5.9 Password Hashing in MySQL 4.1 for a discussion of the different password handling methods.) If the connection between the client and the server goes through an untrusted network, you should use an SSH tunnel to encrypt the communication.
All other information is transferred as text that can be read by anyone who is able to watch the connection. If you are concerned about this, you can use the compressed protocol (in MySQL 3.22 and above) to make traffic much more difficult to decipher. To make the connection even more secure, you should use SSH to get an encrypted TCP/IP connection between a MySQL server and a MySQL client. You can find an Open Source SSH client at http://www.openssh.org/, and a commercial SSH client at http://www.ssh.com/.
If you are using MySQL 4.0 or newer, you can also use internal OpenSSL support. See section 5.6.7 Using Secure Connections.
To make a MySQL system secure, you should strongly consider the following suggestions:
mysql
program to connect as any other
person simply by invoking it as mysql -u other_user db_name
if
other_user has no password. If all users have a password,
connecting using another user's account becomes much more difficult.
To change the password for a user, use the SET PASSWORD
statement.
It is also possible to update the user
table in the mysql
database directly. For example, to change the password of all MySQL accounts
that have a username of root
, do this:
shell> mysql -u root mysql> UPDATE mysql.user SET Password=PASSWORD('newpwd') -> WHERE User='root'; mysql> FLUSH PRIVILEGES;
root
user. This is
very dangerous, because any user with the FILE
privilege will be able
to create files as root
(for example, ~root/.bashrc
). To
prevent this, mysqld
refuses to run as root
unless that
is specified explicitly using a --user=root
option.
mysqld
can be run as an ordinary unprivileged user instead.
You can also create a separate Unix account named mysql
to make
everything even more secure. Use the account only for administering MySQL.
To start mysqld
as another Unix user, add a user
option that specifies the username 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=mysqlThis causes the server to start as the designated user whether you start it manually or by using
mysqld_safe
or mysql.server
.
For more details, see section A.3.2 How to Run MySQL as a Normal User.
Running mysqld
as a Unix user other than root
does not
mean that you need to change the root
username in the user
table. Usernames for MySQL accounts have nothing to do with usernames for Unix
accounts.
--skip-symbolic-links
option.) This is especially important if you run
mysqld
as root
, because anyone that has write access to the
server's data directory then could delete any file in the system!
See section 7.6.1.2 Using Symbolic Links for Tables on Unix.
mysqld
runs as.
PROCESS
or SUPER
privilege to non-administrative users.
The output of mysqladmin processlist
shows the text of the currently
executing queries, so any user who is allowed to execute that command
might be able to see if another user issues an UPDATE user SET
password=PASSWORD('not_secure')
query.
mysqld
reserves an extra connection for users who have the
SUPER
privilege (PROCESS
before MySQL 4.0.2), so that a MySQL
root
user can log in and check server activity even if all normal
connections are in use.
The SUPER
privilege
can be used to terminate client connections, change server operation by
changing the value of system variables, and control replication servers.
FILE
privilege to non-administrative users.
Any user that has this privilege can write a file anywhere in the
filesystem with the privileges of the mysqld
daemon! To make
this a bit safer, files generated with SELECT ... INTO OUTFILE
will not overwrite existing files and are writable by everyone.
The FILE
privilege may also be used to read any file that is
world-readable or accessible to the Unix user that the server runs as.
With this privilege, you can read any file into a database table.
This could be abused, for example, by using LOAD DATA
to load
`/etc/passwd' into a table, which then can be displayed with
SELECT
.
max_user_connections
variable in
mysqld
.
The GRANT
statement also supports resource control options for limiting
the extent of server use allowed to an account.
mysqld
Concerning Security
The following mysqld
options affect security:
--local-infile[={0|1}]
--local-infile=0
, clients cannot use
LOCAL
in LOAD DATA
statements.
See section 5.4.4 Security Issues with LOAD DATA LOCAL
.
--old-passwords
--safe-show-database
SHOW DATABASES
statement displays the names
of only those databases for which the user has some kind of privilege.
As of MySQL 4.0.2, this option is deprecated and doesn't do anything
(it is enabled by default), because there is a SHOW DATABASES
privilege that can be used to control access to database
names on a per-account basis. See section 13.5.1.3 GRANT
and REVOKE
Syntax.
--safe-user-create
GRANT
statement unless the user has the INSERT
privilege for the
mysql.user
table. If you want a user to have the ability to create
new users with those privileges that the user has right to grant, you should
grant the user the following privilege:
mysql> GRANT INSERT(user) ON mysql.user TO 'user_name'@'host_name';This will ensure that the user can't change any privilege columns directly, but has to use the
GRANT
statement to give privileges to other users.
--secure-auth
--skip-grant-tables
mysqladmin
flush-privileges
or mysqladmin reload
command, or by issuing a
FLUSH PRIVILEGES
statement.)
--skip-name-resolve
Host
column values in the grant
tables must be IP numbers or localhost
.
--skip-networking
mysqld
must be made via Unix socket files.
This option is unsuitable when using a MySQL version prior to 3.23.27 with
the MIT-pthreads package, because Unix socket files were not supported by
MIT-pthreads at that time.
--skip-show-database
SHOW DATABASES
statement is allowed only to
users who have the SHOW DATABASES
privilege, and the statement
displays all database names. Without this option, SHOW DATABASES
is
allowed to all users, but displays each database name only if the user has
the SHOW DATABASES
privilege or some privilege for the database.
LOAD DATA LOCAL
The LOAD DATA
statement can load a file that is located on the
server host, or it can load a file that is located on the client host when
the LOCAL
keyword is specified.
There are two potential security issues with supporting the LOCAL
version of LOAD DATA
statements:
LOAD DATA
statement. Such a
server could access any file on the client host to which the client user has
read access.
LOAD DATA LOCAL
to read any files
that the Web server process has read access to (assuming that a user could
run any command against the SQL server). In this environment, the client with
respect to the MySQL server actually is the Web server, not the program being
run by the user connecting to the Web server.
To deal with these problems, we changed how LOAD DATA
LOCAL
is handled as of MySQL 3.23.49 and MySQL 4.0.2 (4.0.13 on Windows):
--enable-local-infile
option, to be compatible
with MySQL 3.23.48 and before.
--enable-local-infile
option to configure
, LOAD DATA LOCAL
cannot be used
by any client unless it is written explicitly to invoke
mysql_options(... MYSQL_OPT_LOCAL_INFILE, 0)
.
See section 22.2.3.43 mysql_options()
.
LOAD DATA LOCAL
commands from the server side
by starting mysqld
with the --local-infile=0
option.
mysql
command-line client, LOAD DATA LOCAL
can be
enabled by specifying the --local-infile[=1]
option, or disabled with
the --local-infile=0
option. Similarly, for mysqlimport
,
the --local
or -L
option enables local data file loading. In
any case, successful use of a local loading operation requires that the
server is enabled to allow it.
LOAD DATA LOCAL
in Perl scripts or other programs that
read the [client]
group from option files, you can add the
local-infile=1
option to that group. However, to keep this from
causing problems for programs that do not understand local-infile
,
specify it using the loose-
prefix:
[client] loose-local-infile=1The
loose-
prefix can be used as of MySQL 4.0.2.
LOAD DATA LOCAL INFILE
is disabled, either in the server or
the client, a client that attempts to issue such a statement receives the
following error message:
ERROR 1148: The used command is not allowed with this MySQL version
MySQL has an advanced but non-standard security and privilege system. This section describes how it works.
The primary function of the MySQL privilege system is to
authenticate a user connecting from a given host, and to associate that user
with privileges on a database such as
SELECT
, INSERT
, UPDATE
, and DELETE
.
Additional functionality includes the ability to have anonymous users and
to grant privileges for MySQL-specific functions such as LOAD
DATA INFILE
and administrative operations.
The MySQL privilege system ensures that all users may perform only the operations allowed to them. As a user, when you connect to a MySQL server, your identity is determined by the host from which you connect and the username you specify. When you issue requests after connecting, the system grants privileges according to your identity and what you want to do.
MySQL considers both your hostname and username in identifying you
because there is little reason to assume that a given username belongs to
the same person everywhere on the Internet. For example, the user
joe
who connects from office.com
need not be the same
person as the user joe
who connects from elsewhere.com
.
MySQL handles this by allowing you to distinguish users on different
hosts that happen to have the same name: You can grant one set of
privileges for connections by joe
from office.com
, and a
different set of privileges for connections by joe
from
elsewhere.com
.
MySQL access control involves two stages:
SELECT
privilege for the table or the DROP
privilege for the database.
If your privileges are changed (either by yourself or someone else) while you are connected, those changes will not necessarily take effect immediately for the next statement you issue. See section 5.5.7 When Privilege Changes Take Effect for details.
The server stores privilege information in the grant tables of the
mysql
database (that is, in the database named mysql
).
The MySQL server reads the contents of these tables into memory when it
starts and re-reads them under the circumstances indicated in section 5.5.7 When Privilege Changes Take Effect. Access-control decisions are based on the in-memory copies of the
grant tables.
Normally, you manipulate the contents of the grant tables indirectly by using
the GRANT
and REVOKE
statements to set up accounts and control
the privileges available to each one.
See section 13.5.1.3 GRANT
and REVOKE
Syntax.
The discussion here describes the underlying structure of the grant tables and
how the server uses their contents when interacting with clients.
The server uses the user
, db
, and host
tables in the
mysql
database at both stages of access control. The columns in these
grant tables are shown here:
Table Name | user | db | host |
Scope columns | Host | Host | Host
|
User | Db | Db
| |
Password | User | ||
Privilege columns | Select_priv | Select_priv | Select_priv
|
Insert_priv | Insert_priv | Insert_priv
| |
Update_priv | Update_priv | Update_priv
| |
Delete_priv | Delete_priv | Delete_priv
| |
Index_priv | Index_priv | Index_priv
| |
Alter_priv | Alter_priv | Alter_priv
| |
Create_priv | Create_priv | Create_priv
| |
Drop_priv | Drop_priv | Drop_priv
| |
Grant_priv | Grant_priv | Grant_priv
| |
Create_view_priv | Create_view_priv | Create_view_priv
| |
Show_view_priv | Show_view_priv | Show_view_priv
| |
Create_routine_priv | Create_routine_priv | ||
Alter_routine_priv | Alter_routine_priv | ||
References_priv | References_priv | References_priv
| |
Reload_priv | |||
Shutdown_priv | |||
Process_priv | |||
File_priv | |||
Show_db_priv | |||
Super_priv | |||
Create_tmp_table_priv | Create_tmp_table_priv | Create_tmp_table_priv
| |
Lock_tables_priv | Lock_tables_priv | Lock_tables_priv
| |
Execute_priv | |||
Repl_slave_priv | |||
Repl_client_priv | |||
Security columns | ssl_type | @tab | |
ssl_cipher | |||
x509_issuer | |||
x509_subject | |||
Resource control columns | max_questions | @tab | |
max_updates | |||
max_connections | |||
max_user_connections |
The
ssl_type
,
ssl_cipher
,
x509_issuer
, and
x509_subject
columns were added in MySQL 4.0.0.
The
Create_tmp_table_priv
,
Execute_priv
,
Lock_tables_priv
,
Repl_client_priv
,
Repl_slave_priv
,
Show_db_priv
,
Super_priv
,
max_questions
,
max_updates
, and
max_connections
columns were added in MySQL 4.0.2.
Execute_priv
is not operational until MySQL 5.0.3, however.
The Create_view_priv
and Show_view_priv
columns were added in
MySQL 5.0.1.
The Create_routine_priv
, Alter_routine_priv
, and
max_user_connections
columns were added in MySQL 5.0.3.
During the second stage of access control, the server performs request
verification to make sure that each client has sufficient privileges for
each request that it issues. In addition to the user
, db
, and
host
grant tables, the server may also consult the tables_priv
and columns_priv
tables for requests that involve tables. The
tables_priv
and columns_priv
tables provide finer privilege
control at the table and column levels. They have the following columns:
Table Name | tables_priv | columns_priv |
Scope columns | Host | Host
|
Db | Db
| |
User | User
| |
Table_name | Table_name
| |
Column_name
| ||
Privilege columns | Table_priv | Column_priv
|
Column_priv | ||
Other columns | Timestamp | Timestamp
|
Grantor |
The Timestamp
and Grantor
columns currently are unused and are
discussed no further here.
For verification of requests that involve stored routines, the server may
consult the procs_priv
table. This table exists as of MySQL 5.0.3 and
has the following columns:
Table Name | procs_priv |
Scope columns | Host
|
Db
| |
User
| |
Routine_name
| |
Privilege columns | Proc_priv
|
Other columns | Timestamp
|
Grantor
|
The Timestamp
and Grantor
columns currently are unused and are
discussed no further here.
Each grant table contains scope columns and privilege columns:
user
table row
with Host
and User
values of 'thomas.loc.gov'
and
'bob'
would be used for authenticating connections made to the server
from the host thomas.loc.gov
by a client that specifies a username of
bob
. Similarly, a db
table row with Host
, User
, and Db
column values of
'thomas.loc.gov'
, 'bob'
and 'reports'
would be used when
bob
connects from the host thomas.loc.gov
to access the
reports
database. The tables_priv
and columns_priv
tables contain scope columns indicating tables or table/column combinations
to which each row applies. The procs_priv
scope columns indicate the
store routine to which each row applies.
Scope columns contain strings. They are declared as shown here; the default value for each is the empty string:
Column Name | Type |
Host | CHAR(60)
|
User | CHAR(16)
|
Password | CHAR(16)
|
Db | CHAR(64)
|
Table_name | CHAR(64)
|
Column_name | CHAR(64)
|
Routine_name | CHAR(64)
|
Before MySQL 3.23, the Db
column is CHAR(32)
in some tables
and CHAR(60)
in others.
For access-checking purposes, comparisons of Host
values are
case-insensitive. User
, Password
, Db
, and
Table_name
values are case sensitive. Column_name
values are
case insensitive in MySQL 3.22.12 or later.
In the user
, db
, and host
tables, each privilege
is listed in a separate column that is declared as
ENUM('N','Y') DEFAULT 'N'
. In other words, each privilege can be disabled
or enabled, with the default being disabled.
In the tables_priv
, columns_priv
, and procs_priv
tables, the privilege columns are declared as SET
columns. Values in
these columns can contain any combination of the privileges controlled by
the table:
Table Name | Column Name | Possible Set Elements |
tables_priv
| Table_priv
| 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
|
tables_priv
| Column_priv
| 'Select', 'Insert', 'Update', 'References'
|
columns_priv
| Column_priv
| 'Select', 'Insert', 'Update', 'References'
|
procs_priv
| Proc_priv
| 'Execute', 'Alter Routine', 'Grant'
|
Briefly, the server uses the grant tables as follows:
user
table scope columns determine whether to reject or allow
incoming connections. For allowed connections, any privileges granted in
the user
table indicate the user's global (superuser) privileges.
These privileges apply to all databases on the server.
db
table scope columns determine which users can access which
databases from which hosts. The privilege columns determine which operations
are allowed. A privilege granted at the database level applies to the database
and to all its tables.
host
table is used in conjunction with the db
table when you
want a given db
table row to apply to several hosts. For example,
if you want a user to be able to use a database from several hosts in
your network, leave the Host
value empty in the user's db
table
row, then populate the host
table with a row for each of those
hosts. This mechanism is described more detail in section 5.5.6 Access Control, Stage 2: Request Verification.
Note: The host
table is not affected by the GRANT
and
REVOKE
statements. Most MySQL installations need not use this table at
all.
tables_priv
and columns_priv
tables are similar to
the db
table, but are more fine-grained: They apply at the
table and column levels rather than at the database level.
A privilege granted at the table level applies to the table and to all its
columns.
A privilege granted at the column level applies only to a specific column.
procs_priv
table applies to stored routines. A privilege granted at
the routine level applies only to a single routine.
Administrative privileges (such as RELOAD
or SHUTDOWN
)
are specified only in the user
table. This is because
administrative operations are operations on the server itself and are not
database-specific, so there is no reason to list these privileges in the
other grant tables. In fact, to determine whether you can perform an
administrative operation, the server need consult only the user
table.
The FILE
privilege also is specified only in the user
table.
It is not an administrative privilege as such, but your ability to read or
write files on the server host is independent of the database you are
accessing.
The mysqld
server reads the contents of the grant tables into memory
when it starts. You can tell it to re-read the tables by issuing a FLUSH
PRIVILEGES
statement or executing a mysqladmin flush-privileges
or
mysqladmin reload
command.
Changes to the grant tables take effect as indicated in
section 5.5.7 When Privilege Changes Take Effect.
When you modify the contents of the grant tables, it is a good idea to make
sure that your changes set up privileges the way you want. To check
the privileges for a given account, use the SHOW GRANTS
statement.
For example, to determine the privileges that are granted to an account with
Host
and User
values of pc84.example.com
and bob
,
issue this statement:
mysql> SHOW GRANTS FOR 'bob'@'pc84.example.com';
A useful diagnostic tool is the mysqlaccess
script, which Yves
Carlier has provided for the MySQL distribution. Invoke
mysqlaccess
with the --help
option to find out how it
works. Note that mysqlaccess
checks access using only the
user
, db
, and host
tables. It does not check table,
column, or routine privileges specified in the tables_priv
,
columns_priv
, or procs_priv
tables.
For additional help in diagnosing privilege-related problems, see
section 5.5.8 Causes of Access denied
Errors. For general advice on security issues, see
section 5.4 General Security Issues.
Information about account privileges is stored in the user
,
db
, host
, tables_priv
, columns_priv
, and
procs_priv
tables in the mysql
database. The MySQL server
reads the contents of these tables into memory when it starts and re-reads
them under the circumstances indicated in section 5.5.7 When Privilege Changes Take Effect.
Access-control decisions are based on the in-memory copies of the grant
tables.
The names used in the GRANT
and REVOKE
statements to refer to
privileges are shown in the following table, along with the column name
associated with each privilege in the grant tables and the context in
which the privilege applies. Further information about the meaning of
each privilege may be found at section 13.5.1.3 GRANT
and REVOKE
Syntax.
Privilege | Column | Context |
CREATE | Create_priv | databases, tables, or indexes |
DROP | Drop_priv | databases or tables |
GRANT | Grant_priv | databases, tables, or stored routines |
REFERENCES | References_priv | databases or tables |
ALTER | Alter_priv | tables |
DELETE | Delete_priv | tables |
INDEX | Index_priv | tables |
INSERT | Insert_priv | tables |
SELECT | Select_priv | tables |
UPDATE | Update_priv | tables |
CREATE VIEW | Create_view_priv | views |
SHOW VIEW | Show_view_priv | views |
ALTER ROUTINE | Alter_routine_priv | stored routines |
CREATE ROUTINE | Create_routine_priv | stored routines |
EXECUTE | Execute_priv | stored routines |
CREATE TEMPORARY TABLES | Create_tmp_table_priv | server administration |
FILE | File_priv | file access on server host |
LOCK TABLES | Lock_tables_priv | server administration |
PROCESS | Process_priv | server administration |
RELOAD | Reload_priv | server administration |
REPLICATION CLIENT | Repl_client_priv | server administration |
REPLICATION SLAVE | Repl_slave_priv | server administration |
SHOW DATABASES | Show_db_priv | server administration |
SHUTDOWN | Shutdown_priv | server administration |
SUPER | Super_priv | server administration |
The CREATE TEMPORARY TABLES
, EXECUTE
, LOCK TABLES
,
REPLICATION CLIENT
, REPLICATION SLAVE
, SHOW DATABASES
,
and SUPER
privileges were added in MySQL 4.0.2. (EXECUTE
is
not operational until MySQL 5.0.3.) CREATE VIEW
and SHOW VIEW
were added in MySQL 5.0.1. CREATE ROUTINE
and ALTER ROUTINE
were added in MySQL 5.0.3. To use these privileges when upgrading from an
earlier version of MySQL that does not have them, , you must upgrade your
grant tables. See section 2.10.7 Upgrading the Grant Tables.
The CREATE
and DROP
privileges allow you to create new
databases and tables, or to drop (remove) existing databases and tables.
If you grant the DROP
privilege for the mysql
database to a user, that user can drop the database in which the
MySQL access privileges are stored!
The SELECT
, INSERT
, UPDATE
, and DELETE
privileges allow you to perform operations on rows in existing tables in
a database.
SELECT
statements require the SELECT
privilege only if they
actually retrieve rows from a table. Some SELECT
statements do not
access tables and can be executed without permission for any database.
For example, you can use the mysql
client as a simple calculator
to evaluate expressions that make no reference to tables:
mysql> SELECT 1+1; mysql> SELECT PI()*2;
The INDEX
privilege allows you to create or drop (remove) indexes.
INDEX
applies to existing tables.
If you have the CREATE
privilege for a table, you can include index
definitions in the CREATE TABLE
statement.
The ALTER
privilege allows you to use ALTER TABLE
to change the
structure of or rename tables.
The CREATE ROUTINE
privilege is needed for creating stored routines
(functions and procedures). ALTER ROUTINE
privilege is needed for
altering or dropping stored routines, and EXECUTE
is needed for
executing stored routines.
The GRANT
privilege allows you to give to other users those
privileges that you yourself possess. It can be used for databases, tables, and stored routines.
The FILE
privilege gives you permission to read and write files on
the server host using the LOAD DATA INFILE
and SELECT ... INTO
OUTFILE
statements. A user who has the FILE
privilege can read any
file on the server host that is either world-readable or readable by the MySQL
server. (This implies the user can read any file in any database
directory, because the server can access any of those files.)
The FILE
privilege also allows the user to create new files in any
directory where the MySQL server has write access. Existing files cannot be
overwritten.
The remaining privileges are used for administrative operations. Many of
them can be performed by using the mysqladmin
program or by
issuing SQL statements. The following table shows which mysqladmin
commands each administrative privilege allows you to execute:
Privilege | Commands Permitted to Privilege Holders |
RELOAD | flush-hosts , flush-logs , flush-privileges , flush-status , flush-tables , flush-threads , refresh , reload
|
SHUTDOWN | shutdown
|
PROCESS | processlist
|
SUPER | kill
|
The reload
command tells the server to re-read the grant tables
into memory. flush-privileges
is a synonym for reload
.
The refresh
command closes and reopens the log files and flushes
all tables. The other flush-xxx
commands perform functions similar to
refresh
, but are more specific and may be preferable in some instances.
For example, if you want to flush just the log files, flush-logs
is a better choice than refresh
.
The shutdown
command shuts down the server. This command can be issued
only from mysqladmin
. There is no corresponding SQL statement.
The processlist
command displays information about the threads
executing within the server (that is, about the statements being executed by
clients associated with other accounts).
The kill
command terminates server threads.
You can always display or kill your own threads, but you need the
PROCESS
privilege to display threads initiated by other users and
the SUPER
privilege to kill them.
See section 13.5.5.3 KILL
Syntax. Prior to MySQL 4.0.2 when SUPER
was
introduced, the PROCESS
privilege controls the ability to both see and
terminate threads for other clients.
The CREATE TEMPORARY TABLES
privilege allows the use of the keyword
TEMPORARY
in CREATE TABLE
statements.
The LOCK TABLES
privilege allows the use of explicit LOCK TABLES
statements to lock tables for which you have the SELECT
privilege.
This includes the use of write locks, which prevents anyone else from reading
the locked table.
The REPLICATION CLIENT
privilege allows the use of SHOW MASTER
STATUS
and SHOW SLAVE STATUS
.
The REPLICATION SLAVE
privilege should be granted to accounts that are
used by slave servers to connect to the current server as their master.
Without this privilege, the slave cannot request updates that have been made
to databases on the master server.
The SHOW DATABASES
privilege allows the account to see database names
by issuing the SHOW DATABASE
statement. Accounts that do not have this
privilege see only databases for which they have some privileges, and cannot
use the statement at all if the server was started with the
--skip-show-database
option.
It is a good idea in general to grant to an account only those privileges
that it needs. You should exercise particular caution in granting the
FILE
and administrative privileges:
FILE
privilege can be abused to read into a database table any
files that the MySQL server can read on the server host. This includes all
world-readable files and files in the server's data directory. The table
can then be accessed using SELECT
to transfer its contents to the
client host.
GRANT
privilege allows users to give their privileges to
other users. Two users with different privileges and with the GRANT
privilege are able to combine privileges.
ALTER
privilege may be used to subvert the privilege system
by renaming tables.
SHUTDOWN
privilege can be abused to deny service to other
users entirely by terminating the server.
PROCESS
privilege can be used to view the plain text of
currently executing queries, including queries that set or change passwords.
SUPER
privilege can be used to terminate other clients or change
how the server operates.
mysql
database itself can be used to
change passwords and other access privilege information. Passwords are
stored encrypted, so a malicious user cannot simply read them to know the
plain text password. However, a user with write access to the user
table Password
column can change an account's password, and then
connect to the MySQL server using that account.
There are some things that you cannot do with the MySQL privilege system:
MySQL client programs generally expect you to specify connection parameters when you want to access a MySQL server:
For example, the
mysql
client can be started as follows from a command-line prompt
(indicated here by shell>
):
shell> mysql -h host_name -u user_name -pyour_pass
Alternate forms of the -h
, -u
, and -p
options are
--host=host_name
, --user=user_name
, and
--password=your_pass
. Note that there is no space between
-p
or --password=
and the password following it.
If you use a -p
or --password
option but do not specify the
password value, the client program will prompt you to enter the password.
The password is not displayed as you enter it.
This is more secure than giving the password on the command line.
Any user on your system may be able to see a password specified on the command
line by executing a command such as ps auxww
.
See section 5.6.6 Keeping Your Password Secure.
MySQL client programs use default values for any connection parameter option that you do not specify:
localhost
.
ODBC
on Windows and your Unix login name
on Unix.
-p
is missing.
Thus, for a Unix user with a login name of joe
, all of the following
commands are equivalent:
shell> mysql -h localhost -u joe shell> mysql -h localhost shell> mysql -u joe shell> mysql
Other MySQL clients behave similarly.
You can specify different default values to be used when you make a connection so that you need not enter them on the command line each time you invoke a client program. This can be done in a couple of ways:
[client]
section of an
option file. The relevant section of the file might look like this:
[client] host=host_name user=user_name password=your_passOption files are discussed further in section 4.3.2 Using Option Files.
mysql
using MYSQL_HOST
. The
MySQL username can be specified using USER
(this is for
Windows and NetWare only). The password can be specified using
MYSQL_PWD
,
although this is insecure; see section 5.6.6 Keeping Your Password Secure.
For a list of variables, see section F Environment Variables.
When you attempt to connect to a MySQL server, the server accepts or rejects the connection based on your identity and whether you can verify your identity by supplying the correct password. If not, the server denies access to you completely. Otherwise, the server accepts the connection, then enters Stage 2 and waits for requests.
Your identity is based on two pieces of information:
Identity checking is performed using the three user
table scope columns
(Host
, User
, and Password
). The server accepts the
connection only if the Host
and User
columns in some
user
table record match the client hostname and username,
and the client supplies the password specified in that record.
Host
values in the user
table may be specified as follows:
Host
value may be a hostname or an IP number, or 'localhost'
to indicate the local host.
Host
column values.
These have the same meaning as for pattern-matching operations
performed with the LIKE
operator.
For example, a Host
value of '%'
matches any hostname, whereas a
value of '%.mysql.com'
matches any host in the mysql.com
domain.
Host
values specified as
IP numbers, you can specify a netmask indicating how many address bits to
use for the network number. For example:
mysql> GRANT ALL PRIVILEGES ON db.* -> TO david@'192.58.197.0/255.255.255.0';This allows
david
to connect from any client host having an IP number
client_ip
for which the following condition is true:
client_ip & netmask = host_ipThat is, for the
GRANT
statement just shown:
client_ip & 255.255.255.0 = 192.58.197.0IP numbers that satisfy this condition and can connect to the MySQL server are those that lie in the range from
192.58.197.0
to
192.58.197.255
.
Host
value in a db
table record means that its
privileges should be combined with those in the row in the host
table that matches the client hostname. The privileges are combined
using an AND (intersection) operation, not OR (union). You can find more
information about the host
table in section 5.5.6 Access Control, Stage 2: Request Verification.
A blank Host
value in the other grant tables is the same as '%'
.
Because you can use IP wildcard values in the Host
column
(for example, '144.155.166.%'
to match every host on a
subnet), someone could try to exploit this capability by naming a host
144.155.166.somewhere.com
. To foil such attempts, MySQL disallows
matching on hostnames that start with digits and a dot. Thus, if you have
a host named something like 1.2.foo.com
, its name will never match
the Host
column of the grant tables. An IP wildcard value can
match only IP numbers, not hostnames.
In the User
column, wildcard characters are not allowed, but you can
specify a blank value, which matches any name. If the user
table
row that matches an incoming connection has a blank username, the user is
considered to be an anonymous user with no name, not a user with the
name that the client actually specified. This means that a blank username
is used for all further access checking for the duration of the connection
(that is, during Stage 2).
The Password
column can be blank. This is not a wildcard and does
not mean that any password matches. It means that the user must connect
without specifying a password.
Non-blank Password
values in the user
table represent
encrypted passwords. MySQL does not store passwords in plaintext form for
anyone to see. Rather, the password supplied by a user who is attempting to
connect is encrypted (using the PASSWORD()
function). The encrypted
password then is used during the connection process when checking whether
the password is correct. (This is done without the encrypted password ever
traveling over the connection.) From MySQL's point of view, the
encrypted password is the REAL password, so you should not give anyone
access to it! In particular, don't give non-administrative users read
access to the tables in the mysql
database!
From version 4.1 on, MySQL employs a stronger authentication method that has
better password protection during the connection process than in earlier
versions. It is secure even if TCP/IP packets are sniffed or the
mysql
database is captured. Password encryption is discussed further
in section 5.5.9 Password Hashing in MySQL 4.1.
The following examples show how various combinations of Host
and
User
values in the user
table apply to incoming
connections:
Host Value | User Value | Connections Matched by Entry |
'thomas.loc.gov' | 'fred' | fred , connecting from thomas.loc.gov
|
'thomas.loc.gov' | '' | Any user, connecting from thomas.loc.gov
|
'%' | 'fred' | fred , connecting from any host
|
'%' | '' | Any user, connecting from any host |
'%.loc.gov' | 'fred' | fred , connecting from any host in the loc.gov domain
|
'x.y.%' | 'fred' | fred , connecting from x.y.net , x.y.com , x.y.edu , and so on. (this is probably not useful)
|
'144.155.166.177' | 'fred' | fred , connecting from the host with IP address 144.155.166.177
|
'144.155.166.%' | 'fred' | fred , connecting from any host in the 144.155.166 class C subnet
|
'144.155.166.0/255.255.255.0' | 'fred' | Same as previous example |
It is possible for the client hostname and username of
an incoming connection to match more than one row in the
user
table. The preceding set of examples demonstrates this:
Several of the entries shown match a connection from thomas.loc.gov
by
fred
.
When multiple matches are possible, the server must determine which of them to use. It resolves this issue as follows:
user
table into memory, it sorts the
entries.
To see how this works, suppose that the user
table looks like this:
+-----------+----------+- | Host | User | ... +-----------+----------+- | % | root | ... | % | jeffrey | ... | localhost | root | ... | localhost | | ... +-----------+----------+-
When the server reads in the table, it orders the entries with the
most-specific Host
values first. Literal hostnames and IP numbers
are the most specific. The pattern '%'
means ``any host'' and is
least specific. Entries with the same Host
value are ordered with
the most-specific User
values first (a blank User
value means
``any user'' and is least specific). For the user
table just shown,
the result after sorting looks like this:
+-----------+----------+- | Host | User | ... +-----------+----------+- | localhost | root | ... | localhost | | ... | % | jeffrey | ... | % | root | ... +-----------+----------+-
When a client attempts to connect, the server looks through the sorted entries
and uses the first match found. For a connection from localhost
by
jeffrey
, two of the entries in the table match:
the one with Host
and User
values of 'localhost'
and
''
, and the one with values of '%'
and 'jeffrey'
.
The 'localhost'
row appears first in sorted order, so that is the one
the server uses.
Here is another example. Suppose that the user
table looks like this:
+----------------+----------+- | Host | User | ... +----------------+----------+- | % | jeffrey | ... | thomas.loc.gov | | ... +----------------+----------+-
The sorted table looks like this:
+----------------+----------+- | Host | User | ... +----------------+----------+- | thomas.loc.gov | | ... | % | jeffrey | ... +----------------+----------+-
A connection by jeffrey
from thomas.loc.gov
is matched by the
first row, whereas a connection by jeffrey
from whitehouse.gov
is matched by the second.
It is a common misconception to think that, for a given username, all entries
that explicitly name that user will be used first when the server attempts to
find a match for the connection. This is simply not true. The previous
example illustrates this, where a connection from thomas.loc.gov
by
jeffrey
is first matched not by the row containing 'jeffrey'
as the User
column value, but by the row with no username!
As a result, jeffrey
will be authenticated as an anonymous user, even
though he specified a username when connecting.
If you are able to connect to the server, but your privileges are not
what you expect, you probably are being authenticated as some other
account. To find out what account the server used to authenticate
you, use the CURRENT_USER()
function. It returns a value in
user_name@host_name
format that indicates the User
and Host
values from the matching user
table record.
Suppose that jeffrey
connects and issues the following query:
mysql> SELECT CURRENT_USER(); +----------------+ | CURRENT_USER() | +----------------+ | @localhost | +----------------+
The result shown here indicates that the matching user
table row
had a blank User
column value. In other words, the server is
treating jeffrey
as an anonymous user.
The CURRENT_USER()
function is available as of MySQL 4.0.6.
See section 12.8.3 Information Functions.
Another thing you can do to diagnose authentication problems is to print
out the user
table and sort it by hand to see where the first
match is being made.
Once you establish a connection, the server enters Stage 2 of access
control. For each request that comes in on the connection, the server
determines what operation you want to perform, then checks whether you have
sufficient privileges to do so. This is where the privilege columns in the
grant tables come into play. These privileges can come from any of the
user
, db
, host
, tables_priv
, or
columns_priv
tables. (You may find it helpful to refer to
section 5.5.2 How the Privilege System Works, which lists the columns present in each of the grant
tables.)
The user
table grants privileges that are assigned to you on a global
basis and that apply no matter what the current database is. For example, if
the user
table grants you the DELETE
privilege, you can
delete rows from any table in any database on the server host! In other words,
user
table privileges are superuser privileges. It is wise to grant
privileges in the user
table only to superusers such as
database administrators. For other users, you should leave the privileges
in the user
table set to 'N'
and grant privileges at more
specific levels only. You can grant privileges for particular databases,
tables, or columns.
The db
and host
tables grant database-specific privileges.
Values in the scope columns of these tables can take the following forms:
Host
and Db
columns of either table. These have the same meaning as for
pattern-matching operations performed with the LIKE
operator. If you
want to use either character literally when granting privileges, you must
escape it with a backslash. For example, to include `_' character
as part of a database name, specify it as `\_' in the GRANT
statement.
'%'
Host
value in the db
table means ``any host.'' A
blank Host
value in the db
table means ``consult the
host
table for further information'' (a process that is described later
in this section).
'%'
or blank Host
value in the host
table means ``any
host.''
'%'
or blank Db
value in either table means ``any database.''
User
value in either table matches the anonymous user.
The server reads in and sorts the db
and host
tables at the
same time that it reads the user
table. The server sorts the db
table based on the Host
, Db
, and User
scope columns,
and sorts the host
table based on the Host
and Db
scope columns. As with the user
table, sorting puts the
most-specific values first and least-specific values last, and when the
server looks for matching entries, it uses the first match that it finds.
The tables_priv
and columns_priv
tables grant table-specific and
column-specific privileges. Values in the scope columns of these tables can
take the following form:
Host
column of either table. These have the same meaning as for pattern-matching
operations performed with the LIKE
operator.
'%'
or blank Host
value in either table means ``any host.''
Db
, Table_name
, and Column_name
columns cannot contain
wildcards or be blank in either table.
The server sorts the tables_priv
and columns_priv
tables based
on the Host
, Db
, and User
columns. This is similar to
db
table sorting, but simpler because only the Host
column can
contain wildcards.
The request verification process is described here. (If you are familiar with the access-checking source code, you will notice that the description here differs slightly from the algorithm used in the code. The description is equivalent to what the code actually does; it differs only to make the explanation simpler.)
For requests that require administrative privileges such as SHUTDOWN
or
RELOAD
, the
server checks only the user
table row because that is the only table
that specifies administrative privileges. Access is granted if the row
allows the requested operation and denied otherwise. For example, if you
want to execute mysqladmin shutdown
but your user
table row
doesn't grant the SHUTDOWN
privilege to you, the server denies access
without even checking the db
or host
tables. (They
contain no Shutdown_priv
column, so there is no need to do so.)
For database-related requests (INSERT
, UPDATE
, and so on), the
server first checks the user's global (superuser) privileges by looking in
the user
table row. If the row allows the requested operation,
access is granted. If the global privileges in the user
table are
insufficient, the server determines the user's database-specific privileges
by checking the db
and host
tables:
db
table for a match on the Host
,
Db
, and User
columns. The Host
and User
columns are
matched to the connecting user's hostname and MySQL username. The
Db
column is matched to the database that the user wants to access. If
there is no row for the Host
and User
, access is denied.
db
table row and its Host
column is
not blank, that row defines the user's database-specific privileges.
db
table row's Host
column is blank, it
signifies that the host
table enumerates which hosts should be allowed
access to the database. In this case, a further lookup is done in the
host
table to find a match on the Host
and Db
columns.
If no host
table row matches, access is denied. If there is a
match, the user's database-specific privileges are computed as the
intersection (not the union!) of the privileges in the db
and
host
table entries; that is, the privileges that are 'Y'
in both
entries. (This way you can grant general privileges in the db
table
row and then selectively restrict them on a host-by-host basis using the
host
table entries.)
After determining the database-specific privileges granted by the db
and host
table entries, the server adds them to the global privileges
granted by the user
table. If the result allows the requested
operation, access is granted. Otherwise, the server successively
checks the user's table and column privileges in the tables_priv
and columns_priv
tables, adds those to the user's privileges,
and allows or denies access based on the result.
Expressed in boolean terms, the preceding description of how a user's privileges are calculated may be summarized like this:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
It may not be apparent why, if the global user
row privileges are
initially found to be insufficient for the requested operation, the server
adds those privileges to the database, table, and column privileges
later. The reason is that a request might require more than one type of
privilege. For example, if you execute an INSERT INTO ... SELECT
statement, you need both the INSERT
and the SELECT
privileges.
Your privileges might be such that the user
table row grants one
privilege and the db
table row grants the other. In this case, you
have the necessary privileges to perform the request, but the server cannot
tell that from either table by itself; the privileges granted by the entries
in both tables must be combined.
The host
table is not affected by the GRANT
or REVOKE
statements, so it is unused in most MySQL installations. If you modify
it directly, you can use it for some specialized purposes, such as to
maintain a list of secure servers. For example, at TcX, the host
table contains a list of all machines on the local network. These are
granted all privileges.
You can also use the host
table to indicate hosts that are not
secure. Suppose that you have a machine public.your.domain
that is located
in a public area that you do not consider secure. You can allow access to
all hosts on your network except that machine by using host
table
entries
like this:
+--------------------+----+- | Host | Db | ... +--------------------+----+- | public.your.domain | % | ... (all privileges set to 'N') | %.your.domain | % | ... (all privileges set to 'Y') +--------------------+----+-
Naturally, you should always test your entries in the grant tables (for
example, by using SHOW GRANTS
or
mysqlaccess
) to make sure that your access privileges are
actually set up the way you think they are.
When mysqld
starts, all grant table contents are read into memory and
become effective for access control at that point.
When the server reloads the grant tables, privileges for existing client connections are affected as follows:
USE db_name
statement.
If you modify the grant tables using GRANT
, REVOKE
, or
SET PASSWORD
, the server notices these changes and reloads the
grant tables into memory again immediately.
If you modify the grant tables directly using statements such as
INSERT
, UPDATE
, or DELETE
, your changes have
no effect on privilege checking until you either restart the server
or tell it to reload the tables. To reload the grant tables manually,
issue a FLUSH PRIVILEGES
statement or execute a mysqladmin
flush-privileges
or mysqladmin reload
command.
If you change the grant tables directly but forget to reload them, your changes will have no effect until you restart the server. This may leave you wondering why your changes don't seem to make any difference!
Access denied
ErrorsIf you encounter problems when you try to connect to the MySQL server, the following items describe some courses of action you can take to correct the problem.
shell> mysql ERROR 2003: Can't connect to MySQL server on 'host_name' (111) shell> mysql ERROR 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (111)It might also be that the server is running, but you are trying to connect using a TCP/IP port, named pipe, or Unix socket file different from those on which the server is listening. To correct this when you invoke a client program, specify a
--port
option to indicate the proper port, or a
--socket
option to indicate the proper named pipe or Unix socket
file.
To find out what port is used, and where the socket is, you can do:
shell> netstat -l | grep mysql
mysql
database containing the grant tables. For
distributions that do not do this, you should initialize the grant tables
manually by running the mysql_install_db
script. For details, see
section 2.9.2 Unix Post-Installation Procedures.
One way to determine whether you need to initialize the grant tables is to
look for a `mysql' directory under the data directory. (The data
directory normally is named `data' or `var' and is located under
your MySQL installation directory.) Make sure that you have a file named
`user.MYD' in the `mysql' database directory. If you do not,
execute the mysql_install_db
script. After running this script and
starting the server, test the initial privileges by executing this command:
shell> mysql -u root testThe server should let you connect without error.
shell> mysql -u root mysqlThe server should let you connect because the MySQL
root
user
has no password initially. That is also a security risk, so setting the
password for the
root
accounts is something you should do while you're setting up
your other MySQL users.
For instructions on setting the initial passwords, see section 2.9.3 Securing the Initial MySQL Accounts.
mysql_fix_privilege_tables
script? If not, do so. The
structure of the grant tables changes occasionally when new capabilities are
added, so after an upgrade you should always make sure that your tables have
the current structure. For instructions, see section 2.10.7 Upgrading the Grant Tables.
shell> mysql Client does not support authentication protocol requested by server; consider upgrading MySQL clientFor information on how to deal with this, see section 5.5.9 Password Hashing in MySQL 4.1 and section A.2.3
Client does not support authentication protocol
.
root
and get the following error,
it means that you don't have an row in the user
table with a
User
column value of 'root'
and that mysqld
cannot
resolve the hostname for your client:
Access denied for user ''@'unknown' to database mysqlIn this case, you must restart the server with the
--skip-grant-tables
option and edit your `/etc/hosts' or `\windows\hosts' file to
add an entry for your host.
Access denied
when you run a client
without any options, make sure that you haven't specified an old password in
any of your option files!
You can suppress the use of option files by a client program by invoking it
with the --no-defaults
option. For example:
shell> mysqladmin --no-defaults -u root versionThe option files that clients use are listed in section 4.3.2 Using Option Files. Environment variables are listed in section F Environment Variables.
root
password:
shell> mysqladmin -u root -pxxxx ver Access denied for user 'root'@'localhost' (using password: YES)If the preceding error occurs even when you haven't specified a password, it means that you have an incorrect password listed in some option file. Try the
--no-defaults
option as described in the previous item.
For information on changing passwords, see section 5.6.5 Assigning Account Passwords.
If you have lost or forgotten the root
password, you can restart
mysqld
with --skip-grant-tables
to change the password.
See section A.4.1 How to Reset the Root Password.
SET PASSWORD
, INSERT
, or
UPDATE
, you must encrypt the password using the PASSWORD()
function. If you do not use PASSWORD()
for these statements,
the password will not work. For example, the following statement sets a
password, but fails to encrypt it, so the user will not be able to connect
afterward:
mysql> SET PASSWORD FOR 'abe'@'host_name' = 'eagle';Instead, set the password like this:
mysql> SET PASSWORD FOR 'abe'@'host_name' = PASSWORD('eagle');The
PASSWORD()
function is unnecessary when you specify a password
using the GRANT
statement or the mysqladmin password
command,
both of which automatically use PASSWORD()
to encrypt the password.
See section 5.6.5 Assigning Account Passwords.
localhost
is a synonym for your local hostname, and is also the
default host to which clients try to connect if you specify no host
explicitly. However, connections to localhost
on Unix systems
do not work if you are using a MySQL version older than 3.23.27 that uses
MIT-pthreads: localhost
connections are made using Unix socket files,
which were not supported by MIT-pthreads at that time.
To avoid this problem on such systems, you can use a --host=127.0.0.1
option to name the server host explicitly. This will make a TCP/IP
connection to the local mysqld
server. You can also use TCP/IP by
specifying a --host
option that uses the actual hostname of the
local host. In this case, the hostname must be specified in a user
table row on the server host, even though you are running the client
program on the same host as the server.
Access denied
error when trying to connect to the
database with mysql -u user_name
, you may have a problem
with the user
table. Check this by executing mysql -u root
mysql
and issuing this SQL statement:
mysql> SELECT * FROM user;The result should include an row with the
Host
and User
columns matching your computer's hostname and your MySQL username.
Access denied
error message will tell you who you are trying
to log in as, the client host from which you are trying to connect, and whether
or not you were using a password. Normally, you should have one row in
the user
table that exactly matches the hostname and username
that were given in the error message. For example, if you get an error
message that contains using password: NO
, it means that you
tried to log in without an password.
user
table with a Host
value that matches the client
host:
Host ... is not allowed to connect to this MySQL serverYou can fix this by setting up an account for the combination of client hostname and username that you are using when trying to connect. If you don't know the IP number or hostname of the machine from which you are connecting, you should put an row with
'%'
as the Host
column value in the user
table and restart mysqld
with the --log
option on the server
machine. After trying to connect from the client machine, the information
in the MySQL log will indicate how you really did connect. (Then change
the '%'
in the user
table row to the actual hostname
that shows up in the log. Otherwise, you'll have a system that is insecure
because it allows connections from any host for the given username.)
On Linux, another reason that this error might occur is that you are using
a binary MySQL version that is compiled with a different version of the
glibc
library than the one you are using. In this case, you should
either upgrade your operating system or glibc
, or download a source
distribution of MySQL version and compile it yourself. A source RPM is
normally trivial to compile and install, so this isn't a big problem.
shell> mysqladmin -u root -pxxxx -h some-hostname ver Access denied for user 'root'@'' (using password: YES)This indicates a DNS problem. To fix it, execute
mysqladmin
flush-hosts
to reset the internal DNS hostname cache. See section 7.5.6 How MySQL Uses DNS.
Some permanent solutions are:
/etc/hosts
.
mysqld
with the --skip-name-resolve
option.
mysqld
with the --skip-host-cache
option.
localhost
. Unix connections to localhost
use a Unix
socket file rather than TCP/IP.
.
(period). Connections to .
use a named pipe rather than
TCP/IP.
mysql -u root test
works but mysql -h your_hostname -u root
test
results in Access denied
(where your_hostname is the
actual hostname of the local host), you may not have the correct name
for your host in the user
table. A common problem here is that the
Host
value in the user
table row specifies an unqualified hostname,
but your system's name resolution routines return a fully qualified domain
name (or vice versa). For example, if you have an entry with host
'tcx'
in the user
table, but your DNS tells MySQL that
your hostname is 'tcx.subnet.se'
, the entry will not work. Try adding
an entry to the user
table that contains the IP number of your host as
the Host
column value. (Alternatively, you could add an entry to the
user
table with a Host
value that contains a wildcard; for
example, 'tcx.%'
. However, use of hostnames ending with `%' is
insecure and is not recommended!)
mysql -u user_name test
works but mysql -u user_name
other_db_name
does not, you have not granted database access for
other_db_name to the given user.
mysql -u user_name
works when executed on the server host, but
mysql -h host_name -u user_name
doesn't work when executed on a
remote client host, you have not enabled access to the server for the given
username from the remote host.
Access denied
, remove from the
user
table all entries that have Host
values containing
wildcards (entries that contain `%' or `_'). A very common error
is to insert a new entry with Host
='%'
and
User
='some_user'
, thinking that this will allow you to specify
localhost
to connect from the same machine. The reason that this
doesn't work is that the default privileges include an entry with
Host
='localhost'
and User
=''
. Because that entry
has a Host
value 'localhost'
that is more specific than
'%'
, it is used in preference to the new entry when connecting from
localhost
! The correct procedure is to insert a second entry with
Host
='localhost'
and User
='some_user'
, or to
delete the entry with Host
='localhost'
and
User
=''
.
After deleting the entry, remember to issue a FLUSH PRIVILEGES
statement to reload the grant tables.
db
or
host
table:
Access to database deniedIf the entry selected from the
db
table has an empty value in the
Host
column, make sure that there are one or more corresponding entries in
the host
table specifying which hosts the db
table entry
applies to.
Access
denied
message whenever you issue a SELECT ... INTO OUTFILE
or
LOAD DATA INFILE
statement, your entry in the user
table
doesn't have the FILE
privilege enabled.
INSERT
,
UPDATE
, or DELETE
statements) and your changes seem to be
ignored, remember that you must execute a FLUSH PRIVILEGES
statement
or a mysqladmin flush-privileges
command to cause the server
to re-read the privilege tables. Otherwise, your changes have no effect
until the next time the server is restarted. Remember that after you change
the root
password with an UPDATE
command, you won't need
to specify the new password until after you flush the privileges, because
the server won't know you've changed the password yet!
mysql -u user_name db_name
or mysql
-u user_name -pyour_pass db_name
. If you are able to connect using the
mysql
client, the problem lies with your program, not with the
access privileges. (There is no space between -p
and the
password; you can also use the --password=your_pass
syntax to specify
the password. If you use the -p
option alone, MySQL will
prompt you for the password.)
mysqld
server with the
--skip-grant-tables
option. Then you can change the MySQL
grant tables and use the mysqlaccess
script to check whether
your modifications have the desired effect. When you are satisfied with your
changes, execute mysqladmin flush-privileges
to tell the mysqld
server to start using the new grant tables. (Reloading the
grant tables overrides the --skip-grant-tables
option. This allows
you to tell the server to begin using the grant tables again without stopping
and restarting it.)
mysqld
server with a debugging
option (for example, --debug=d,general,query
). This will print host and
user information about attempted connections, as well as information about
each command issued. See section E.1.2 Creating Trace Files.
mysqldump mysql
command. As always, post your problem using
the mysqlbug
script. See section 1.4.1.3 How to Report Bugs or Problems. In some cases, you may need
to restart mysqld
with --skip-grant-tables
to run
mysqldump
.
MySQL user accounts are listed in the user
table of the mysql
database. Each MySQL account is assigned a password, although
what is stored in the Password
column of the user
table is not the
plaintext version of the password, but a hash value computed from
it. Password hash values are computed by the PASSWORD()
function.
MySQL uses passwords in two phases of client/server communication:
user
table for
the account that the client wants to use.
user
table.
The client can do this by using the PASSWORD()
function to generate a
password hash, or by using the GRANT
or SET PASSWORD
statements.
In other words, the server uses hash values during authentication when
a client first attempts to connect. The server generates hash values
if a connected client invokes the PASSWORD()
function or uses a
GRANT
or SET PASSWORD
statement to set or change a password.
The password hashing mechanism was updated in MySQL 4.1 to provide
better security and to reduce the risk of passwords being intercepted.
However, this new mechanism is understood only by the 4.1 server and
4.1 clients, which can result in some compatibility problems.
A 4.1 client can connect to a pre-4.1 server, because the client
understands both the old and new password hashing mechanisms. However,
a pre-4.1 client that attempts to connect to a 4.1 server may run into
difficulties. For example, a 4.0 mysql
client that attempts to connect
to a 4.1 server may fail with the following error message:
shell> mysql -h localhost -u root Client does not support authentication protocol requested by server; consider upgrading MySQL client
The following discussion describes the differences between the old and
new password mechanisms, and what you should do if you upgrade your
server to 4.1 but need to maintain backward compatibility with pre-4.1
clients. Additional information can be found in section A.2.3 Client does not support authentication protocol
.
Note: This discussion contrasts 4.1 behavior with pre-4.1 behavior, but the 4.1 behavior described here actually begins with 4.1.1. MySQL 4.1.0 is an ``odd'' release because it has a slightly different mechanism than that implemented in 4.1.1 and up. Differences between 4.1.0 and more recent versions are described further in section 5.5.9.2 Password Hashing in MySQL 4.1.0.
Prior to MySQL 4.1, password hashes computed by the PASSWORD()
function
are 16 bytes long. Such hashes look like this:
mysql> SELECT PASSWORD('mypass'); +--------------------+ | PASSWORD('mypass') | +--------------------+ | 6f8c114b58f2ce9e | +--------------------+
The Password
column of the user
table (in which these hashes are stored)
also is 16 bytes long before MySQL 4.1.
As of MySQL 4.1, the PASSWORD()
function has been modified to produce
a longer 41-byte hash value:
mysql> SELECT PASSWORD('mypass'); +-----------------------------------------------+ | PASSWORD('mypass') | +-----------------------------------------------+ | *43c8aa34cdc98eddd3de1fe9a9c2c2a9f92bb2098d75 | +-----------------------------------------------+
Accordingly, the Password
column in the user
table also must be 41
bytes long to store these values:
Password
column
will be made 41 bytes long automatically.
mysql_fix_privilege_tables
script to increase the length of the
Password
column from 16 to 41 bytes. (The script does not change existing
password values, which remain 16 bytes long.)
A widened Password
column can store password hashes in both the old and
new formats. The format of any given password hash value can be
determined two ways:
The longer password hash format has better cryptographic properties, and client authentication based on long hashes is more secure than that based on the older short hashes.
The differences between short and long password hashes are relevant both for how the server uses passwords during authentication and for how it generates password hashes for connected clients that perform password-changing operations.
The way in which the server uses password hashes during authentication
is affected by the width of the Password
column:
For short-hash accounts, the authentication process is actually a bit more secure for 4.1 clients than for older clients. In terms of security, the gradient from least to most secure is:
The way in which the server generates password hashes for connected
clients is affected by the width of the Password
column and by the
--old-passwords
option. A 4.1 server generates long hashes only if certain
conditions are met:
The Password
column must be wide enough to hold long
values and the --old-passwords
option must not be given.
These conditions apply as follows:
Password
column must be wide enough to hold long hashes (41 bytes).
If the column has not been updated and still has the pre-4.1 width of
16 bytes, the server notices that long hashes cannot fit into it and
generates only short hashes when a client performs password-changing
operations using PASSWORD()
, GRANT
, or SET PASSWORD
.
This is the behavior that
occurs if you have upgraded to 4.1 but have not yet run the
mysql_fix_privilege_tables
script to widen the Password
column.
Password
column is wide, it can store either short or long
password hashes. In this case, PASSWORD()
, GRANT
, and SET PASSWORD
generate long hashes unless the server was started with the
--old-passwords
option. That option forces the server to generate
short password hashes instead.
The purpose of the --old-passwords
option is to allow you to maintain
backward compatibility with pre-4.1 clients under circumstances where
the server would otherwise generate long password hashes. The option doesn't
affect authentication (4.1 clients can still use accounts that have
long password hashes), but it does prevent creation of a long
password hash in the user
table as the result of a password-changing
operation. Were that to occur, the account no longer could be used
by pre-4.1 clients. Without the --old-passwords
option, the following
undesirable scenario is possible:
--old-passwords
,
this results in the account having a long password hash.
This scenario illustrates that, if you must support older pre-4.1 clients,
it is dangerous to run a 4.1 server without using the --old-passwords
option. By running the server with --old-passwords
, password-changing
operations will not generate long password hashes and thus do not cause
accounts to become inaccessible to older clients. (Those clients cannot
inadvertently lock themselves out by changing their password and ending
up with a long password hash.)
The downside of the --old-passwords
option is that any passwords you
create or change will use short hashes, even for 4.1 clients. Thus, you
lose the additional security provided by long password hashes. If you want
to create an account that has a long hash (for example, for use by 4.1
clients), you must do so while running the server without
--old-passwords
.
The following scenarios are possible for running a 4.1 server:
Scenario 1: Short Password
column in user table:
Password
column.
PASSWORD()
, GRANT
, or SET PASSWORD
use short hashes
exclusively. Any change to an account's password results in
that account having a short password hash.
--old-passwords
option can be used but is superfluous because
with a short Password
column, the server will generate only short
password hashes anyway.
Scenario 2: Long Password
column; server not started with
--old-passwords
option:
Password
column.
PASSWORD()
, GRANT
, or SET PASSWORD
use long hashes
exclusively. A change to an account's password results in that account
having a long password hash.
As indicated earlier, a danger in this scenario is that it is possible for
accounts that have a short password hash to become inaccessible to pre-4.1
clients. A change to such an account's password made via GRANT
,
PASSWORD()
, or SET PASSWORD
results in the account being
given a long password hash. From that point on, no pre-4.1 client can
authenticate to that account until the client upgrades to 4.1.
To deal with this problem, you can change a password in a special way.
For example, normally you use SET PASSWORD
as follows to change
an account password:
mysql> SET PASSWORD FOR 'some_user'@'some_host' = PASSWORD('mypass');
To change the password but create a short hash, use the
OLD_PASSWORD()
function instead:
mysql> SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('mypass');
OLD_PASSWORD()
is useful for situations in which you explicitly want
to generate a short hash.
Scenario 3: Long Password
column; server started with
--old-passwords
option:
Password
column.
--old-passwords
).
PASSWORD()
, GRANT
, or SET PASSWORD
use short hashes
exclusively. Any change to an account's password results in that
account having a short password hash.
In this scenario, you cannot create accounts that have long password
hashes, because the --old-passwords
option prevents generation of long hashes. Also,
if you create an account with a long hash before using the
--old-passwords
option, changing the account's password while --old-passwords
is in
effect results in the account being given a short password, causing it
to lose the security benefits of a longer hash.
The disadvantages for these scenarios may be summarized as follows:
In scenario 1, you cannot take advantage of longer hashes that provide more secure authentication.
In scenario 2, accounts with short hashes become inaccessible to pre-4.1
clients if you change their passwords without explicitly using
OLD_PASSWORD()
.
In scenario 3, --old-passwords
prevents accounts with short hashes from
becoming inaccessible, but password-changing operations cause accounts
with long hashes to revert to short hashes, and you cannot change them
back to long hashes while --old-passwords
is in effect.
An upgrade to MySQL 4.1 can cause a compatibility issue for
applications that use PASSWORD()
to generate passwords for their own
purposes. Applications really should not do this, because PASSWORD()
should be used only to manage passwords for MySQL accounts. But some
applications use PASSWORD()
for their own purposes anyway.
If you upgrade to 4.1 and run the server under conditions where it
generates long password hashes, an application that uses PASSWORD()
for its own passwords will break. The recommended course of action is
to modify the application to use another function, such as SHA1()
or MD5()
, to produce hashed values. If that is not possible, you
can use the OLD_PASSWORD()
function, which is provided to generate
short hashes in the old format. But note that OLD_PASSWORD()
may
one day no longer be supported.
If the server is running under circumstances where it generates short hashes,
OLD_PASSWORD()
is available but is equivalent to PASSWORD()
.
Password hashing in MySQL 4.1.0 differs from hashing in 4.1.1 and up. The 4.1.0 differences are:
PASSWORD()
function is non-repeatable. That is, with a given
argument X, successive calls to PASSWORD(X)
generate different
results.
These differences make authentication in 4.1.0 incompatible with that of
releases that follow it. If you have upgraded to MySQL 4.1.0, it is
recommended that you upgrade to a newer version as soon as possible. After
you do, reassign any long passwords in the user
table so that they are
compatible with the 41-byte format.
This section describes how to set up accounts for clients of your MySQL server. It discusses the following topics:
A MySQL account is defined in terms of a username and the client host or hosts from which the user can connect to the server. The account also has a password. There are several distinctions between the way usernames and passwords are used by MySQL and the way they are used by your operating system:
-u
or --user
option. Because this means
that anyone can attempt to connect to the server using any username, you
can't make a database secure in any way unless all MySQL accounts have
passwords. Anyone who specifies a username for an account that
has no password will be able to connect successfully to the server.
PASSWORD()
SQL
function. Unix password encryption is the same as that implemented by the
ENCRYPT()
SQL function. See the descriptions of the
PASSWORD()
and ENCRYPT()
functions in section 12.8.2 Encryption Functions. From version 4.1 on, MySQL employs a stronger authentication
method that has better password protection during the connection process
than in earlier versions. It is secure even if TCP/IP packets are sniffed or
the mysql
database is captured. (In earlier versions, even though
passwords are stored in encrypted form in the user
table, knowledge
of the encrypted password value could be used to connect to the MySQL
server.)
When you install MySQL, the grant tables are populated with an initial set of
accounts. These accounts have names and access privileges that are described
in section 2.9.3 Securing the Initial MySQL Accounts, which also discusses how to assign passwords
to them. Thereafter, you normally set up, modify, and remove MySQL accounts
using the GRANT
and REVOKE
statements.
See section 13.5.1.3 GRANT
and REVOKE
Syntax.
When you connect to a MySQL server with a command-line client, you should specify the username and password for the account that you want to use:
shell> mysql --user=monty --password=guess db_name
If you prefer short options, the command looks like this:
shell> mysql -u monty -pguess db_name
There must be no space between the -p
option and the
following password value.
See section 5.5.4 Connecting to the MySQL Server.
The preceding commands include the password value on the command line, which
can be a security risk.
See section 5.6.6 Keeping Your Password Secure.
To avoid this, specify the --password
or -p
option without any
following password value:
shell> mysql --user=monty --password db_name shell> mysql -u monty -p db_name
Then the client program will print a prompt and wait for you to enter the password. (In these examples, db_name is not interpreted as a password, because it is separated from the preceding password option by a space.)
On some systems, the library call that MySQL uses to prompt for a password automatically limits the password to eight characters. That is a problem with the system library, not with MySQL. Internally, MySQL doesn't have any limit for the length of the password. To work around the problem, change your MySQL password to a value that is eight or fewer characters long, or put your password in an option file.
You can create MySQL accounts in two ways:
GRANT
statements
The preferred method is to use GRANT
statements, because they are
more concise and less error-prone. GRANT
is available as of MySQL
3.22.11; its syntax is described in
section 13.5.1.3 GRANT
and REVOKE
Syntax.
Another option for creating accounts is to use one of several available
third-party programs that offer capabilities for MySQL account
administration. phpMyAdmin
is one such program.
The following examples show how to use the mysql
client program to
set up new users. These examples assume that privileges are set up
according to the defaults described in section 2.9.3 Securing the Initial MySQL Accounts. This means
that to make changes, you must connect to the MySQL server as the MySQL
root
user, and the root
account must have the INSERT
privilege for the mysql
database and the RELOAD
administrative
privilege.
First, use the mysql
program to connect to the server as the
MySQL root
user:
shell> mysql --user=root mysql
If you have assigned a password to the root
account, you'll also
need to supply a --password
or -p
option for this mysql
command and also for those later in this section.
After connecting to the server as root
, you can add new accounts. The following
statements use GRANT
to set up four new accounts:
mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'localhost' -> IDENTIFIED BY 'some_pass' WITH GRANT OPTION; mysql> GRANT ALL PRIVILEGES ON *.* TO 'monty'@'%' -> IDENTIFIED BY 'some_pass' WITH GRANT OPTION; mysql> GRANT RELOAD,PROCESS ON *.* TO 'admin'@'localhost'; mysql> GRANT USAGE ON *.* TO 'dummy'@'localhost';
The accounts created by these GRANT
statements have the
following properties:
monty
and a password of
some_pass
. Both accounts are superuser accounts with full privileges
to do anything. One account ('monty'@'localhost'
) can be used only
when connecting from the local host. The other ('monty'@'%'
) can be
used to connect from any other host. Note that it is necessary to have both
accounts for monty
to be able to connect from anywhere as
monty
. Without the localhost
account, the anonymous-user
account for localhost
that is created by mysql_install_db
would take precedence when monty
connects from the local host. As a
result, monty
would be treated as an anonymous user. The reason for
this is that the anonymous-user account has a more specific Host
column value than the 'monty'@'%'
account and thus comes earlier in
the user
table sort order. (user
table sorting is discussed
in section 5.5.5 Access Control, Stage 1: Connection Verification.)
admin
and no password. This account
can be used only by connecting from the local host. It is granted the
RELOAD
and PROCESS
administrative privileges. These
privileges allow the admin
user to execute the mysqladmin
reload
, mysqladmin refresh
, and mysqladmin flush-xxx
commands,
as well as mysqladmin processlist
. No privileges are granted for
accessing any databases. You could add such privileges later by issuing
additional GRANT
statements.
dummy
and no password. This account
can be used only by connecting from the local host. No privileges are
granted. The USAGE
privilege in the GRANT
statement allows you
to create an account without giving it any privileges. It has the effect of
setting all the global privileges to 'N'
. It is assumed that you
will grant specific privileges to the account later.
As an alternative to GRANT
, you can create the same accounts
directly by issuing INSERT
statements and then telling
the server to reload the grant tables:
shell> mysql --user=root mysql mysql> INSERT INTO user -> VALUES('localhost','monty',PASSWORD('some_pass'), -> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); mysql> INSERT INTO user -> VALUES('%','monty',PASSWORD('some_pass'), -> 'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'); mysql> INSERT INTO user SET Host='localhost',User='admin', -> Reload_priv='Y', Process_priv='Y'; mysql> INSERT INTO user (Host,User,Password) -> VALUES('localhost','dummy',''); mysql> FLUSH PRIVILEGES;
The reason for using FLUSH PRIVILEGES
when you create accounts with
INSERT
is to tell the server to re-read the grant tables.
Otherwise, the changes will go unnoticed until you restart the server. With
GRANT
, FLUSH PRIVILEGES
is unnecessary.
The reason for using the PASSWORD()
function with INSERT
is to
encrypt the password. The GRANT
statement encrypts the password for
you, so PASSWORD()
is unnecessary.
The 'Y'
values enable privileges for the accounts. Depending on your
MySQL version, you may have to use a different number of 'Y'
values
in the first two INSERT
statements. (Versions prior to 3.22.11 have
fewer privilege columns, and versions from 4.0.2 on have more.) For the
admin
account, the more readable extended INSERT
syntax using
SET
that is available starting with MySQL 3.22.11 is used.
In the INSERT
statement for the dummy
account, only the
Host
, User
, and Password
columns in the user
table record are assigned values. None of the privilege columns are set
explicitly, so MySQL assigns them all the default value of 'N'
.
This is equivalent to what GRANT USAGE
does.
Note that to set up a superuser account, it is necessary only to create a
user
table entry with the privilege columns set to 'Y'
.
user
table privileges are global, so no entries in any of the other
grant tables are needed.
The next examples create three accounts and give them access to specific
databases. Each of them has a username of custom
and password of
obscure
.
To create the accounts with GRANT
, use the following statements:
shell> mysql --user=root mysql mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP -> ON bankaccount.* -> TO 'custom'@'localhost' -> IDENTIFIED BY 'obscure'; mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP -> ON expenses.* -> TO 'custom'@'whitehouse.gov' -> IDENTIFIED BY 'obscure'; mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP -> ON customer.* -> TO 'custom'@'server.domain' -> IDENTIFIED BY 'obscure';
The three accounts can be used as follows:
bankaccount
database, but only from the local host.
expenses
database, but only from the host whitehouse.gov
.
customer
database, but only from the host server.domain
.
To set up the custom
accounts without GRANT
, use INSERT
statements as follows to modify the grant tables directly:
shell> mysql --user=root mysql mysql> INSERT INTO user (Host,User,Password) -> VALUES('localhost','custom',PASSWORD('obscure')); mysql> INSERT INTO user (Host,User,Password) -> VALUES('whitehouse.gov','custom',PASSWORD('obscure')); mysql> INSERT INTO user (Host,User,Password) -> VALUES('server.domain','custom',PASSWORD('obscure')); mysql> INSERT INTO db -> (Host,Db,User,Select_priv,Insert_priv, -> Update_priv,Delete_priv,Create_priv,Drop_priv) -> VALUES('localhost','bankaccount','custom', -> 'Y','Y','Y','Y','Y','Y'); mysql> INSERT INTO db -> (Host,Db,User,Select_priv,Insert_priv, -> Update_priv,Delete_priv,Create_priv,Drop_priv) -> VALUES('whitehouse.gov','expenses','custom', -> 'Y','Y','Y','Y','Y','Y'); mysql> INSERT INTO db -> (Host,Db,User,Select_priv,Insert_priv, -> Update_priv,Delete_priv,Create_priv,Drop_priv) -> VALUES('server.domain','customer','custom', -> 'Y','Y','Y','Y','Y','Y'); mysql> FLUSH PRIVILEGES;
The first three INSERT
statements add user
table entries that
allow the user custom
to connect from the various hosts with the given
password, but grant no global privileges (all privileges are set to the
default value of 'N'
). The next three INSERT
statements add
db
table entries that grant privileges to custom
for the
bankaccount
, expenses
, and customer
databases, but only
when accessed from the proper hosts. As usual when you modify the grant
tables directly, you tell the server to reload them with
FLUSH PRIVILEGES
so that the privilege changes take effect.
If you want to give a specific user access from all machines in a given
domain (for example, mydomain.com
), you can issue a GRANT
statement that uses the `%' wildcard character in the host part of the
account name:
mysql> GRANT ... -> ON *.* -> TO 'myname'@'%.mydomain.com' -> IDENTIFIED BY 'mypass';
To do the same thing by modifying the grant tables directly, do this:
mysql> INSERT INTO user (Host,User,Password,...) -> VALUES('%.mydomain.com','myname',PASSWORD('mypass'),...); mysql> FLUSH PRIVILEGES;
To remove an account, use the DROP USER
statement, which was added in
MySQL 4.1.1. For older versions of MySQL, use DELETE
instead.
The account removal procedure is described in section 13.5.1.2 DROP USER
Syntax.
Before MySQL 4.0.2, the only available method for limiting use of MySQL
server resources is to set the max_user_connections
system
variable to a non-zero value. But that method is strictly global. It does
not allow for management of individual accounts. Also, it limits only the
number of simultaneous connections made using a single account, not
what a client can do once connected. Both types of control are
interest to many MySQL administrators, particularly those for Internet
Service Providers.
Starting from MySQL 4.0.2, you can limit the following server resources for individual accounts:
Any statement that a client can issue counts against the query limit. Only statements that modify databases or tables count against the update limit.
From MySQL 5.0.3 on, it is also possible to limit the number of simultaneous connection to the server on a per-account basis.
An account in this context is a single record in the user
table. Each
account is uniquely identified by its User
and Host
column
values.
As a prerequisite for using this feature, the user
table in the
mysql
database must contain the resource-related columns. Resource
limits are stored in the max_questions
, max_updates
,
max_connections
, and max_user_connections
columns. If your
user
table doesn't have these columns, it must be upgraded; see
section 2.10.7 Upgrading the Grant Tables.
To set resource limits with a GRANT
statement, use a WITH
clause that names each resource to be limited and a per-hour count
indicating the limit value. For example, to create a new account that can
access the customer
database, but only in a limited fashion, issue
this statement:
mysql> GRANT ALL ON customer.* TO 'francis'@'localhost' -> IDENTIFIED BY 'frank' -> WITH MAX_QUERIES_PER_HOUR 20 -> MAX_UPDATES_PER_HOUR 10 -> MAX_CONNECTIONS_PER_HOUR 5 -> MAX_USER_CONNECTIONS 2;
The limit types need not all be named in the WITH
clause, but those
named can be present in any order. The value for each per-hour limit should
be an integer representing a count per hour. If the GRANT
statement
has no WITH
clause, the limits are each set to the default value of
zero (that is, no limit). For MAX_USER_CONNECTIONS
, the limit is an
integer indicating the maximum number of simultaneous connections the
account can make at any one time. If the limit is set to the default value
of zero, the max_user_connections
system variable determines the number
of simultaneous connections for the account.
To set or change limits for an existing account, use a GRANT USAGE
statement at the global level (ON *.*
). The following statement
changes the query limit for francis
to 100:
mysql> GRANT USAGE ON *.* TO 'francis'@'localhost' -> WITH MAX_QUERIES_PER_HOUR 100;
This statement leaves the account's existing privileges unchanged and modifies only the limit values specified.
To remove an existing limit, set its value to zero. For example, to remove the
limit on how many times per hour francis
can connect, use this
statement:
mysql> GRANT USAGE ON *.* TO 'francis'@'localhost' -> WITH MAX_CONNECTIONS_PER_HOUR 0;
Resource-use counting takes place when any account has a non-zero limit placed on its use of any of the resources.
As the server runs, it counts the number of times each account uses resources. If an account reaches its limit on number of connections within the last hour, further connections for the account are rejected until that hour is up. Similarly, if the account reaches its limit on the number of queries or updates, further queries or updates are rejected until the hour is up. In all such cases, an appropriate error message is issued.
Resource counting is done per account, not per client. For example, if your account has a query limit of 50, you cannot increase your limit to 100 by making two simultaneous client connections to the server. Queries issued on both connections are counted together.
The current per-hour resource-use counts can be reset globally for all accounts, or individually for a given account:
FLUSH
USER_RESOURCES
statement. The counts also can be reset by reloading the
grant tables (for example, with a FLUSH PRIVILEGES
statement or a
mysqladmin reload
command).
GRANT USAGE
as described earlier
and specify a limit value equal to the value that the account currently has.
Counter resets do not affect the MAX_USER_CONNECTIONS
limit.
All counts begin at zero when the server starts; counts are not carried over through a restart.
Passwords may be assigned from the command line by using the mysqladmin
command:
shell> mysqladmin -u user_name -h host_name password "newpwd"
The account for which this command resets the password is the one with a
user
table record that matches user_name in the User
column and the client host from which you connect in the
Host
column.
Another way to assign a password to an account is to issue a SET
PASSWORD
statement:
mysql> SET PASSWORD FOR 'jeffrey'@'%' = PASSWORD('biscuit');
Only users such as root
with update access to the mysql
database can change the password for other users. If you are not connected
as an anonymous user, you can change your own password by omitting the
FOR
clause:
mysql> SET PASSWORD = PASSWORD('biscuit');
You can also use a GRANT USAGE
statement at the global level
(ON *.*
) to assign a password to an account without affecting the
account's current privileges:
mysql> GRANT USAGE ON *.* TO 'jeffrey'@'%' IDENTIFIED BY 'biscuit';
Although it is generally preferable to assign passwords using one of the
preceding methods, you can also do so by modifying the user
table
directly:
Password
column:
shell> mysql -u root mysql mysql> INSERT INTO user (Host,User,Password) -> VALUES('%','jeffrey',PASSWORD('biscuit')); mysql> FLUSH PRIVILEGES;
UPDATE
to set the
Password
column value:
shell> mysql -u root mysql mysql> UPDATE user SET Password = PASSWORD('bagel') -> WHERE Host = '%' AND User = 'francis'; mysql> FLUSH PRIVILEGES;
When you assign an account a password using SET PASSWORD
,
INSERT
, or UPDATE
, you must use the PASSWORD()
function
to encrypt it. (The only exception is that you need not use
PASSWORD()
if the password is empty.) PASSWORD()
is
necessary because the user
table stores passwords in encrypted form,
not as plaintext. If you forget that fact, you are likely to set passwords
like this:
shell> mysql -u root mysql mysql> INSERT INTO user (Host,User,Password) -> VALUES('%','jeffrey','biscuit'); mysql> FLUSH PRIVILEGES;
The result is that the literal value 'biscuit'
is stored as the
password in the user
table, not the encrypted value. When
jeffrey
attempts to connect to the server using this password, the
value is encrypted and compared to the value stored in the user
table. However, the stored value is the literal string 'biscuit'
, so
the comparison fails and the server rejects the connection:
shell> mysql -u jeffrey -pbiscuit test Access denied
If you set passwords using the GRANT ... IDENTIFIED BY
statement or
the mysqladmin password
command, they both take care of encrypting
the password for you. The PASSWORD()
function is unnecessary.
Note: PASSWORD()
encryption is different from Unix password
encryption.
See section 5.6.1 MySQL Usernames and Passwords.
On an administrative level, you should never grant access to the
mysql.user
table to any non-administrative accounts. Passwords in the
user
table are stored in encrypted form, but in versions of MySQL
earlier than 4.1, knowing the encrypted password for an account makes it
possible to connect to the server using that account.
When you run a client program to connect to the MySQL server, it is inadvisable to specify your password in a way that exposes it to discovery by other users. The methods you can use to specify your password when you run client programs are listed here, along with an assessment of the risks of each method:
-pyour_pass
or --password=your_pass
option on the command
line. For example:
shell> mysql -u francis -pfrank db_nameThis is convenient but insecure, because your password becomes visible to system status programs such as
ps
that may be invoked by other users
to display command lines. MySQL clients typically overwrite the
command-line password argument with zeros during their initialization
sequence, but there is still a brief interval during which the value is
visible.
-p
or --password
option with no password value
specified. In this case, the client program solicits the password from
the terminal:
shell> mysql -u francis -p db_name Enter password: ********The `*' characters indicate where you enter your password. The password is not displayed as you enter it. It is more secure to enter your password this way than to specify it on the command line because it is not visible to other users. However, this method of entering a password is suitable only for programs that you run interactively. If you want to invoke a client from a script that runs non-interactively, there is no opportunity to enter the password from the terminal. On some systems, you may even find that the first line of your script is read and interpreted (incorrectly) as your password!
[client]
section of the `.my.cnf' file in your
home directory:
[client] password=your_passIf you store your password in `.my.cnf', the file should not be accessible to anyone but yourself. To ensure this, set the file access mode to
400
or 600
. For example:
shell> chmod 600 .my.cnfsection 4.3.2 Using Option Files discusses option files in more detail.
MYSQL_PWD
environment variable.
This method of specifying your MySQL password must be considered
extremely insecure and should not be used. Some versions of ps
include an option to display the environment of running processes. If you
set MYSQL_PWD
, your password will be exposed to any other user who
runs ps
. Even on systems without such a version of ps
, it is
unwise to assume that there are no other methods by which users can examine
process environments.
See section F Environment Variables.
All in all, the safest methods are to have the client program prompt for the password or to specify the password in a properly protected option file.
Beginning with version 4.0.0, MySQL has support for secure (encrypted) connections between MySQL clients and the server using the Secure Sockets Layer (SSL) protocol. This section discusses how to use SSL connections. It also describes a way to set up SSH on Windows.
The standard configuration of MySQL is intended to be as fast as possible, so encrypted connections are not used by default. Doing so would make the client/server protocol much slower. Encrypting data is a CPU-intensive operation that requires the computer to do additional work and can delay other MySQL tasks. For applications that require the security provided by encrypted connections, the extra computation is warranted.
MySQL allows encryption to be enabled on a per-connection basis. You can choose a normal unencrypted connection or a secure encrypted SSL connection according the requirements of individual applications.
To understand how MySQL uses SSL, it's necessary to explain some basic SSL and X509 concepts. People who are familiar with them can skip this part.
By default, MySQL uses unencrypted connections between the client and the
server. This means that someone with access to the network could watch all
your traffic and look at the data being sent or received. They could even
change the data while it is in transit between client and server. To improve
security a little, you can compress client/server traffic by using the
--compress
option when invoking client programs. However, this will
not foil a determined attacker.
When you need to move information over a network in a secure fashion, an unencrypted connection is unacceptable. Encryption is the way to make any kind of data unreadable. In fact, today's practice requires many additional security elements from encryption algorithms. They should resist many kind of known attacks such as changing the order of encrypted messages or replaying data twice.
SSL is a protocol that uses different encryption algorithms to ensure that data received over a public network can be trusted. It has mechanisms to detect any data change, loss, or replay. SSL also incorporates algorithms that provide identity verification using the X509 standard.
X509 makes it possible to identify someone on the Internet. It is most commonly used in e-commerce applications. In basic terms, there should be some company called a ``Certificate Authority'' (or CA) that assigns electronic certificates to anyone who needs them. Certificates rely on asymmetric encryption algorithms that have two encryption keys (a public key and a secret key). A certificate owner can show the certificate to another party as proof of identity. A certificate consists of its owner's public key. Any data encrypted with this public key can be decrypted only using the corresponding secret key, which is held by the owner of the certificate.
If you need more information about SSL, X509, or encryption, use your favorite Internet search engine to search for keywords in which you are interested.
To use SSL connections between the MySQL server and client programs, your system must be able to support OpenSSL and your version of MySQL must be 4.0.0 or newer.
To get secure connections to work with MySQL, you must do the following:
configure
script with the
--with-vio
and --with-openssl
options.
mysql.user
table.
This is necessary if your grant tables date from a version prior to MySQL
4.0.0. The upgrade procedure is described in section 2.10.7 Upgrading the Grant Tables.
mysqld
server supports OpenSSL,
examine the value of the have_openssl
system variable:
mysql> SHOW VARIABLES LIKE 'have_openssl'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | have_openssl | YES | +---------------+-------+If the value is
YES
, the server supports OpenSSL connections.
Here is an example for setting up SSL certificates for MySQL:
DIR=`pwd`/openssl PRIV=$DIR/private mkdir $DIR $PRIV $DIR/newcerts cp /usr/share/ssl/openssl.cnf $DIR replace ./demoCA $DIR -- $DIR/openssl.cnf # Create necessary files: $database, $serial and $new_certs_dir # directory (optional) touch $DIR/index.txt echo "01" > $DIR/serial # # Generation of Certificate Authority(CA) # openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/cacert.pem \ -config $DIR/openssl.cnf # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Generating a 1024 bit RSA private key # ................++++++ # .........++++++ # writing new private key to '/home/monty/openssl/private/cakey.pem' # Enter PEM pass phrase: # Verifying password - Enter PEM pass phrase: # ----- # You are about to be asked to enter information that will be # incorporated into your certificate request. # What you are about to enter is what is called a Distinguished Name # or a DN. # There are quite a few fields but you can leave some blank # For some fields there will be a default value, # If you enter '.', the field will be left blank. # ----- # Country Name (2 letter code) [AU]:FI # State or Province Name (full name) [Some-State]:. # Locality Name (eg, city) []: # Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB # Organizational Unit Name (eg, section) []: # Common Name (eg, YOUR name) []:MySQL admin # Email Address []: # # Create server request and key # openssl req -new -keyout $DIR/server-key.pem -out \ $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Generating a 1024 bit RSA private key # ..++++++ # ..........++++++ # writing new private key to '/home/monty/openssl/server-key.pem' # Enter PEM pass phrase: # Verifying password - Enter PEM pass phrase: # ----- # You are about to be asked to enter information that will be # incorporated into your certificate request. # What you are about to enter is what is called a Distinguished Name # or a DN. # There are quite a few fields but you can leave some blank # For some fields there will be a default value, # If you enter '.', the field will be left blank. # ----- # Country Name (2 letter code) [AU]:FI # State or Province Name (full name) [Some-State]:. # Locality Name (eg, city) []: # Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB # Organizational Unit Name (eg, section) []: # Common Name (eg, YOUR name) []:MySQL server # Email Address []: # # Please enter the following 'extra' attributes # to be sent with your certificate request # A challenge password []: # An optional company name []: # # Remove the passphrase from the key (optional) # openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem # # Sign server cert # openssl ca -policy policy_anything -out $DIR/server-cert.pem \ -config $DIR/openssl.cnf -infiles $DIR/server-req.pem # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Enter PEM pass phrase: # Check that the request matches the signature # Signature ok # The Subjects Distinguished Name is as follows # countryName :PRINTABLE:'FI' # organizationName :PRINTABLE:'MySQL AB' # commonName :PRINTABLE:'MySQL admin' # Certificate is to be certified until Sep 13 14:22:46 2003 GMT # (365 days) # Sign the certificate? [y/n]:y # # # 1 out of 1 certificate requests certified, commit? [y/n]y # Write out database with 1 new entries # Data Base Updated # # Create client request and key # openssl req -new -keyout $DIR/client-key.pem -out \ $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Generating a 1024 bit RSA private key # .....................................++++++ # .............................................++++++ # writing new private key to '/home/monty/openssl/client-key.pem' # Enter PEM pass phrase: # Verifying password - Enter PEM pass phrase: # ----- # You are about to be asked to enter information that will be # incorporated into your certificate request. # What you are about to enter is what is called a Distinguished Name # or a DN. # There are quite a few fields but you can leave some blank # For some fields there will be a default value, # If you enter '.', the field will be left blank. # ----- # Country Name (2 letter code) [AU]:FI # State or Province Name (full name) [Some-State]:. # Locality Name (eg, city) []: # Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB # Organizational Unit Name (eg, section) []: # Common Name (eg, YOUR name) []:MySQL user # Email Address []: # # Please enter the following 'extra' attributes # to be sent with your certificate request # A challenge password []: # An optional company name []: # # Remove a passphrase from the key (optional) # openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem # # Sign client cert # openssl ca -policy policy_anything -out $DIR/client-cert.pem \ -config $DIR/openssl.cnf -infiles $DIR/client-req.pem # Sample output: # Using configuration from /home/monty/openssl/openssl.cnf # Enter PEM pass phrase: # Check that the request matches the signature # Signature ok # The Subjects Distinguished Name is as follows # countryName :PRINTABLE:'FI' # organizationName :PRINTABLE:'MySQL AB' # commonName :PRINTABLE:'MySQL user' # Certificate is to be certified until Sep 13 16:45:17 2003 GMT # (365 days) # Sign the certificate? [y/n]:y # # # 1 out of 1 certificate requests certified, commit? [y/n]y # Write out database with 1 new entries # Data Base Updated # # Create a my.cnf file that you can use to test the certificates # cnf="" cnf="$cnf [client]" cnf="$cnf ssl-ca=$DIR/cacert.pem" cnf="$cnf ssl-cert=$DIR/client-cert.pem" cnf="$cnf ssl-key=$DIR/client-key.pem" cnf="$cnf [mysqld]" cnf="$cnf ssl-ca=$DIR/cacert.pem" cnf="$cnf ssl-cert=$DIR/server-cert.pem" cnf="$cnf ssl-key=$DIR/server-key.pem" echo $cnf | replace " " ' ' > $DIR/my.cnf
To test SSL connections, start the server as follows, where $DIR
is the
pathname to the directory where the sample `my.cnf' option file is
located:
shell> mysqld --defaults-file=$DIR/my.cnf &
Then invoke a client program using the same option file:
shell> mysql --defaults-file=$DIR/my.cnf
If you have a MySQL source distribution, you can also test your setup by modifying the preceding `my.cnf' file to refer to the demonstration certificate and key files in the `SSL' directory of the distribution.
GRANT
Options
MySQL can check X509 certificate attributes in addition to the usual
authentication that is based on the username and password. To specify
SSL-related options for a MySQL account, use the REQUIRE
clause of
the GRANT
statement.
See section 13.5.1.3 GRANT
and REVOKE
Syntax.
There are different possibilities for limiting connection types for an account:
REQUIRE SSL
option limits the server to allow only SSL
encrypted connections for the account. Note that this option can be omitted
if there are any ACL records that allow non-SSL connections.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;
REQUIRE X509
means that the client must have a valid certificate
but that the exact certificate, issuer, and subject do not matter.
The only requirement is that it should be possible to verify its
signature with one of the CA certificates.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' REQUIRE X509;
REQUIRE ISSUER 'issuer'
places the restriction on connection attempts
that the client must present a valid X509 certificate issued by CA
'issuer'
. If the client presents a certificate that is valid but has
a different issuer, the server rejects the connection. Use of X509
certificates always implies encryption, so the SSL
option is
unnecessary.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/ O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';Note that the
ISSUER
value should be entered as a single string.
REQUIRE SUBJECT 'subject'
places the restriction on connection
attempts that the client must present a valid X509 certificate with subject
'subject'
on it. If the client presents a certificate that is valid
but has a different subject, the server rejects the connection.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/ O=MySQL demo client certificate/ CN=Tonu Samuel/Email=tonu@example.com';Note that the
SUBJECT
value should be entered as a single string.
REQUIRE CIPHER 'cipher'
is needed to ensure that strong enough ciphers
and key lengths will be used. SSL itself can be weak if old algorithms
with short encryption keys are used. Using this option, we can ask for
some exact cipher method to allow a connection.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';
The SUBJECT
, ISSUER
, and CIPHER
options can be
combined in the REQUIRE
clause like this:
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/ O=MySQL demo client certificate/ CN=Tonu Samuel/Email=tonu@example.com' -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/ O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com' -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
Note that the SUBJECT
and ISSUER
values each should be entered
as a single string.
Starting from MySQL 4.0.4, the AND
keyword is optional between
REQUIRE
options.
The order of the options does not matter, but no option can be specified twice.
The following list describes options that are used for specifying the use of SSL, certificate files, and key files. These options are available beginning with MySQL 4.0. They may be given on the command line or in an option file.
--ssl
--ssl-ca
, --ssl-cert
, and --ssl-key
options.
This option is more often used in its opposite form to indicate that SSL
should not be used. To do this, specify the option as
--skip-ssl
or --ssl=0
.
Note that use of --ssl
doesn't require an SSL connection.
For example, if the server or client is compiled without SSL support,
a normal unencrypted connection will be used.
The secure way to ensure that an SSL connection will be used is
to create an account on the server that includes a
REQUIRE SSL
clause in the GRANT
statement.
Then use this account to connect to the server, with both a server and client
that have SSL support enabled.
--ssl-ca=file_name
--ssl-capath=directory_name
--ssl-cert=file_name
--ssl-cipher=cipher_list
openssl ciphers
command.
Example: --ssl-cipher=ALL:-AES:-EXP
--ssl-key=file_name
Here is a note about how to connect to get a secure connection to remote MySQL server with SSH (by David Carlson dcarlson@mplcomm.com):
SecureCRT
from http://www.vandyke.com/.
Another option is f-secure
from http://www.f-secure.com/. You
can also find some free ones on Google
at
http://directory.google.com/Top/Computers/Security/Products_and_Tools/Cryptography/SSH/Clients/Windows/.
Host_Name = yourmysqlserver_URL_or_IP
.
Set userid=your_userid
to log in to your server. This userid
value may not be the same as the username of your MySQL account.
local_port: 3306
, remote_host: yourmysqlservername_or_ip
, remote_port: 3306
)
or a local forward (Set port: 3306
, host: localhost
, remote port: 3306
).
localhost
for the MySQL host server, not yourmysqlservername
.
You should have an ODBC connection to MySQL, encrypted using SSH.
This section discusses how to make database backups (full and incremental)
and how to perform
table maintenance. The syntax of the SQL statements described here is
given in section 13.5 Database Administration Statements.
Much of the information here pertains primarily to MyISAM
tables.
InnoDB
backup procedures are given in section 15.9 Backing Up and Recovering an InnoDB
Database.
Because MySQL tables are stored as files, it is easy to do a
backup. To get a consistent backup, do a LOCK TABLES
on the
relevant tables, followed by FLUSH TABLES
for the tables.
See section 13.4.5 LOCK TABLES
and UNLOCK TABLES
Syntax and
section 13.5.5.2 FLUSH
Syntax.
You need only a read lock; this allows other clients to continue to
query the tables while you are making a copy of the files in the
database directory. The FLUSH TABLES
statement is needed to ensure that
the all active index pages are written to disk before you start the backup.
If you want to make an SQL-level backup of a table, you can use
SELECT INTO ... OUTFILE
or BACKUP TABLE
.
For SELECT INTO ... OUTFILE
, the output file cannot previously exist.
For BACKUP TABLE
, the same is true as of
MySQL 3.23.56 and 4.0.12, because this would be a security risk.
See section 13.1.7 SELECT
Syntax and
section 13.5.2.2 BACKUP TABLE
Syntax.
Another way to back up a database is to use the mysqldump
program or
the mysqlhotcopy script
.
See section 8.8 The mysqldump
Database Backup Program and
section 8.9 The mysqlhotcopy
Database Backup Program.
shell> mysqldump --tab=/path/to/some/dir --opt db_nameOr:
shell> mysqlhotcopy db_name /path/to/some/dirYou can also simply copy all table files (`*.frm', `*.MYD', and `*.MYI' files) as long as the server isn't updating anything. The
mysqlhotcopy
script uses this method. (But note that these
methods
will not work if your database contains InnoDB
tables. InnoDB
does not store table contents in database directories, and mysqlhotcopy
works only for MyISAM
and ISAM
tables.)
mysqld
if it's running, then start it with the
--log-bin[=file_name]
option. See section 5.9.4 The Binary Log. The binary
log files provide you with the information you need to replicate
changes to the database that are made subsequent to the point at which
you executed mysqldump
.
For InnoDB
tables, it's possible to perform an online backup that
takes no locks on tables; see section 8.8 The mysqldump
Database Backup Program
MySQL supports incremental backups: You need to start the server with the
--log-bin
option to enable binary logging; see section 5.9.4 The Binary Log.
At the moment you want to make an incremental backup (containing all
changes that happened since the last full or incremental backup), you should
rotate the binary log by using FLUSH LOGS
. This done, you need to
copy to the backup location all binary logs which range from the one of the
moment of the last full or incremental backup to the last but one. These
binary logs are the incremental backup; at restore time, you apply them
as explained further below. The next time you do a full backup, you should
also rotate the binary log using FLUSH LOGS
, mysqldump
--flush-logs
, or mysqlhotcopy --flushlogs
. See section 8.8 The mysqldump
Database Backup Program and section 8.9 The mysqlhotcopy
Database Backup Program.
If your MySQL server is a slave replication server, then regardless of the
backup method you choose, you should also back up the
`master.info' and `relay-log.info' files
when you back up your slave's data. These files
are always needed to resume replication after you restore
the slave's data. If your slave is subject to replicating LOAD
DATA INFILE
commands, you should also back up any `SQL_LOAD-*' files
that may exist in the directory specified by the --slave-load-tmpdir
option. (This location defaults to the value of the tmpdir
variable
if not specified.) The slave needs these files to resume
replication of any interrupted LOAD DATA INFILE
operations.
If you have to restore MyISAM
tables, try to recover them using
REPAIR TABLE
or myisamchk -r
first. That should work in
99.9% of all cases. If myisamchk
fails, try the following procedure.
Note that it will work only if you have enabled binary logging by starting
MySQL with the --log-bin
option; see section 5.9.4 The Binary Log.
mysqldump
backup, or binary backup.
shell> mysqlbinlog hostname-bin.[0-9]* | mysqlIn your case, you may want to re-run only certain binary logs, from certain positions (usually you want to re-run all binary logs from the date of the restored backup, excepting possibly some incorrect queries). See section 8.5 The
mysqlbinlog
Binary Log Utility for more information on
the mysqlbinlog
utility and how to use it.
If you are using the update logs instead (which is a deprecated feature removed
in MySQL 5.0), you can process their contents like this:
shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql
ls
is used to sort the update log filenames into the right order.
You can also do selective backups of individual files:
SELECT * INTO OUTFILE 'file_name' FROM tbl_name
.
LOAD DATA INFILE 'file_name' REPLACE ...
To avoid duplicate records, the table must have a PRIMARY KEY
or a
UNIQUE
index. The REPLACE
keyword causes old records
to be replaced with new ones when a new record duplicates an old record on
a unique key value.
If you have performance problems with your server while making backups, one strategy that can help is to set up replication and perform backups on the slave rather than on the master. See section 6.1 Introduction to Replication.
If you are using a Veritas filesystem, you can make a backup like this:
FLUSH TABLES WITH READ LOCK
.
mount vxfs snapshot
.
UNLOCK TABLES
.
This section discusses a procedure for performing backups that allows you to recover data after several types of crashes:
The following instructions assume a minimum version of MySQL 4.1.8,
because some mysqldump
options used here are not available in
earlier versions.
The example commands do not include options such as --user
and
--password
for the mysqldump
and mysql
programs.
You should include such options as necessary so that the MySQL server allows
you to connect to it.
We'll consider data is stored into the InnoDB
storage engine of
MySQL, which has support for transactions and automatic crash recovery.
We'll always assume the MySQL server is under load at the time of crash. If
it were not, no recovery would ever be needed.
For the cases of operating system crashes or power failures, we can assume
the MySQL disk data is available after a restart. The InnoDB
data
files will not contain consistent data due to the crash, but InnoDB
reads its logs and finds in them the list of pending committed and
non-committed transactions that have not been flushed to the data files. It
automatically rolls back those that were not committed, and flushes to the
data files those that were committed. Information about this recovery
process is conveyed to the user through the MySQL error log. The following
is an example log excerpt:
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
For the cases of filesystem crashes or hardware problems, we can assume the MySQL disk data is not available after a restart. This means that MySQL will fail to start successfully because some blocks of disk data are no longer readable. In this case, it's necessary to reformat the disk, install a new one, or otherwise correct the underlying problem. Then it's necessary to recover our MySQL data from backups--which means that we must already have made backups. To make sure that is the case, let's step back in time and design a backup policy.
We all know that backups must be scheduled periodically. Full backups (a
snapshot of the data at a point in time) can be done in MySQL with several
tools. For example, InnoDB Hot Backup
provides online non-blocking
physical backup of the InnoDB data file, and mysqldump
provides
online logical backup. This discussion uses mysqldump
.
Assume that we make a backup on Sunday at 1 PM, when load is low. The
following command makes a full backup of all our
InnoDB
tables in all databases:
shell> mysqldump --single-transaction --all-databases > backup_sunday_1_PM.sql
This is an online, non-blocking backup that does not disturb the reads
and writes on the tables. We assumed earlier that our tables are InnoDB
tables, so --single-transaction
uses a consistent read and guarantees
that data seen by mysqldump
does not change. (Changes made by other
clients to InnoDB
tables are not seen by the mysqldump
process.) If we do also have other types of tables, we must assume that they
are not changed during the backup. For example, for the MyISAM
tables
in the mysql
database, we must assume that no administrative changes are
being made to MySQL accounts during the backup.
The resulting `.sql' file produced by the mysqldump
command
contains SQL INSERT
statements that can be used to reload the dumped
tables later.
Full backups are necessary, but they are not always convenient. They produce large backup files and take time to generate. They are not optimal in the sense that each successive full backup includes all data, even that part that didn't change since the previous full backup. After we have made the initial full backup, it is more optimal to make incremental backups. They are smaller and take less time to produce. (The tradeoff is that at recovery time, you do not restore your data just by reloading the full backup. You must also process the incremental backups to recover the incremental changes.)
To make incremental backups, we need to save the incremental changes. The
MySQL server should always be started with the --log-bin
option so
that it stores these changes in a file while it updates data. This option
enables binary logging, so that the server writes each SQL statement that
updates data into a file called a MySQL binary log. Let's look at the data
directory of a MySQL server that was started with the --log-bin
option and that has been running for some days. We find these MySQL binary
log files:
-rw-rw---- 1 guilhem guilhem 1277324 Nov 10 23:59 gbichot2-bin.000001 -rw-rw---- 1 guilhem guilhem 4 Nov 10 23:59 gbichot2-bin.000002 -rw-rw---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003 -rw-rw---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004 -rw-rw---- 1 guilhem guilhem 220047446 Nov 12 16:47 gbichot2-bin.000005 -rw-rw---- 1 guilhem guilhem 998412 Nov 14 10:08 gbichot2-bin.000006 -rw-rw---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index
Each time it restarts, the MySQL server creates a new binary log file using
the next number in the sequence. While the server is running, you can also
tell it to close the current binary log file and begin a new one manually by
issuing a FLUSH LOGS
SQL statement or with a mysqladmin
flush-logs
command. mysqldump
also has an option to flush the
logs. The .index
file contains the list of all MySQL binary logs in
the directory. This file is used for replication.
The MySQL binary logs are important for recovery, because they are
incremental backups. If you make sure to flush the logs when you make your
full backup, then any binary log files created afterward contain all the
data changes made since the backup. Let's modify the previous
mysqldump
command a bit so that it flushes the MySQL binary logs
at the moment of the full backup, and so that the dump file contains
the name of the new current binary log:
shell> mysqldump --single-transaction --flush-logs --master-data=2 --all-databases > backup_sunday_1_PM.sql
After executing this command, the the data directory contains a new binary log file, `gbichot2-bin.000007'. The resulting `.sql' file contains these lines:
-- Position to start replication or point-in-time recovery from -- CHANGE MASTER TO MASTER_LOG_FILE='gbichot2-bin.000007',MASTER_LOG_POS=4;
Because the mysqldump
command made a full backup, these lines mean
two things:
On Monday at 1 PM, we can create an incremental backup by flushing the logs
to begin a new binary log file. For example, executing a mysqladmin
flush-logs
command will create `gbichot2-bin.000008'. All changes
between the Sunday 1 PM full backup and Monday 1 PM are the file
`gbichot2-bin.000007'. This incremental backup is important, so it's a
good idea to copy it to a safe place. (For example, back it up on tape or
DVD, or copy it to another machine.) On Tuesday 1 PM, execute another
mysqladmin flush-logs
command. All changes between Monday 1 PM and
Tuesday 1 PM are the file `gbichot2-bin.000008' (which also should be
copied somewhere safe).
The MySQL binary logs take up disk space. To free up space, purge them from time to time. One way to do this is by deleting the binary logs that are no longer needed, such as when we make a full backup:
shell> mysqldump --single-transaction --flush-logs --master-data=2 --all-databases --delete-master-logs > backup_sunday_1_PM.sql
Note: Deleting the MySQL binary logs with mysqldump
--delete-master-logs
can be dangerous if your server is a replication
master server, because slave servers might not yet fully have processed
the contents of the binary log.
The description for the PURGE MASTER LOGS
statement explains what
should be verified before deleting the MySQL binary logs.
See section 13.6.1.1 PURGE MASTER LOGS
Syntax.
Now suppose that we have a catastrophic crash on Wednesday at 8 AM that requires recovery from backups. To recover, first we restore the last full backup we have (the one from Sunday 1 PM). The full backup file is just a set of SQL statements, so restoring it is very easy:
shell> mysql < backup_sunday_1_PM.sql
At this point, the data is restored to its state as of Sunday 1 PM. To restore the changes made since then, we must use the incremental backups, that is, the `gbichot2-bin.000007' and `gbichot2-bin.000008' binary log files. Fetch them if necessary from where they were backed up, and then process their contents like this:
shell> mysqlbinlog gbichot2-bin.000007 gbichot2-bin.000008 | mysql
We now have recovered the data to its state as of Tuesday 1 PM, but still
are missing the changes from that date to the date of the crash. To not
miss them, we would have needed to have the MySQL server store its MySQL
binary logs into a safe location (RAID disks, SAN, ...) different from the
place where it stores its data files, so that these logs were not in the
destroyed disk. (That is, we can start the server with a --log-bin
option that specifies a location on a different physical device than the
one on which the data directory resides. That way, the logs are not lost
even if the device containing the directory is.) If we had done this,
we would have the `gbichot2-bin.000009' at hand, and we could apply
it to restore the most recent data changes with no loss how it was at the
moment of the crash.
In case of an operating system crash or power failure, InnoDB
itself does all the job of recovering data. But to make sure that you can
sleep well, observe the following guidelines:
--log-bin
option, or even
--log-bin=log_name
, where the log file name is located on
some safe media different from the drive on which the data directory is
located. If you have such safe media, this will also be good for disk load
balancing (which results in a performance improvement).
mysqldump
command given
earlier that makes an online, non-blocking backup.
FLUSH LOGS
or mysqladmin flush-logs
.
The following text discusses how to use myisamchk
to check or repair
MyISAM
tables (tables with `.MYI' and `.MYD' files).
The same concepts apply to using isamchk
to check or repair
ISAM
tables (tables with `.ISM' and `.ISD' files).
See section 14 MySQL Storage Engines and Table Types.
You can use the myisamchk
utility to get information about your
database tables or to check, repair, or optimize them. The following
sections describe how to invoke myisamchk
(including a
description of its options), how to set up a table maintenance schedule,
and how to use myisamchk
to perform its various functions.
Even though table repair with myisamchk
is quite secure, it's
always a good idea to make a backup before doing a repair (or any
maintenance operation that could make a lot of changes to a table)
myisamchk
operations that affect indexes can cause
FULLTEXT
indexes to be rebuilt with full-text parameters that
are incompatible with the values used by the MySQL server. To avoid this,
read the instructions in
section 5.7.3.2 General Options for myisamchk
.
In many cases, you may find it simpler to do MyISAM
table maintenance
using the SQL statements that perform operations that myisamchk
can
do:
MyISAM
tables, use CHECK TABLE
or
REPAIR TABLE
.
MyISAM
tables, use OPTIMIZE TABLE
.
MyISAM
tables, use ANALYZE TABLE
.
These statements were introduced in different versions, but all are available
from MySQL 3.23.14 on.
See
section 13.5.2.1 ANALYZE TABLE
Syntax,
section 13.5.2.3 CHECK TABLE
Syntax,
section 13.5.2.5 OPTIMIZE TABLE
Syntax,
and section 13.5.2.6 REPAIR TABLE
Syntax.
The statements can be used directly, or by means of the mysqlcheck
client program, which provides a command-line interface to them.
One advantage of these statements over myisamchk
is that the server
does all the work. With myisamchk
, you must make sure that the server
does not use the tables at the same time. Otherwise, there can be unwanted
interaction between myisamchk
and the server.
myisamchk
Invocation Syntax
Invoke myisamchk
like this:
shell> myisamchk [options] tbl_name
The options specify what you want myisamchk
to do. They are
described in the following sections. You can also get a list of options by
invoking myisamchk --help
.
With no options, myisamchk
simply checks your table as the default
operation. To get more information or to tell myisamchk
to take
corrective action, specify options as described in the following discussion.
tbl_name is the database table you want to check or repair. If you run
myisamchk
somewhere other than in the database directory, you must
specify the path to the database directory, because myisamchk
has no
idea where the
database is located. In fact, myisamchk
doesn't actually care whether
the files you are working on are located in a database directory. You can
copy the files that correspond to a database table into some other location and
perform recovery operations on them there.
You can name several tables on the myisamchk
command line if you
wish. You can also specify a table by naming its index file (the file with
the `.MYI' suffix). This allows you to specify all tables in a
directory by using the pattern `*.MYI'. For example, if you are in a
database directory, you can check all the MyISAM
tables in that
directory like this:
shell> myisamchk *.MYI
If you are not in the database directory, you can check all the tables there by specifying the path to the directory:
shell> myisamchk /path/to/database_dir/*.MYI
You can even check all tables in all databases by specifying a wildcard with the path to the MySQL data directory:
shell> myisamchk /path/to/datadir/*/*.MYI
The recommended way to quickly check all MyISAM
and ISAM
tables is:
shell> myisamchk --silent --fast /path/to/datadir/*/*.MYI shell> isamchk --silent /path/to/datadir/*/*.ISM
If you want to check all MyISAM
and ISAM
tables and repair any
that are corrupted, you can use the following commands:
shell> myisamchk --silent --force --fast --update-state \ -O key_buffer=64M -O sort_buffer=64M \ -O read_buffer=1M -O write_buffer=1M \ /path/to/datadir/*/*.MYI shell> isamchk --silent --force -O key_buffer=64M \ -O sort_buffer=64M -O read_buffer=1M -O write_buffer=1M \ /path/to/datadir/*/*.ISM
These commands assume that you have more than 64MB free.
For more information about memory allocation with myisamchk
, see
section 5.7.3.6 myisamchk
Memory Usage.
You must ensure that no other program is using the tables while you are
running myisamchk
. Otherwise, when you run myisamchk
, it may
display the following error message:
warning: clients are using or haven't closed the table properly
This means that you are trying to check a table that has been updated by
another program (such as the mysqld
server) that hasn't yet closed
the file or that has died without closing the file properly.
If mysqld
is running, you must force it to flush any table
modifications that are still buffered in memory by using FLUSH
TABLES
. You should then ensure that no one is using the tables while you
are running myisamchk
. The easiest way to
avoid this problem is to use CHECK TABLE
instead of myisamchk
to check tables.
myisamchk
The options described in this section can be used for any
type of table maintenance operation performed by myisamchk
.
The sections following this one describe options that pertain only to specific
operations, such as table checking or repairing.
--help, -?
--debug=debug_options, -# debug_options
'd:t:o,file_name'
.
--silent, -s
-s
twice (-ss
) to make myisamchk
very silent.
--verbose, -v
-d
and
-e
. Use -v
multiple times (-vv
, -vvv
) for even
more output.
--version, -V
--wait, -w
mysqld
with the --skip-external-locking
option, the table can
be locked only by another myisamchk
command.
You can also set the following variables by using --var_name=value
options:
Variable | Default Value |
decode_bits | 9 |
ft_max_word_len | version-dependent |
ft_min_word_len | 4 |
ft_stopword_file | built-in list |
key_buffer_size | 523264 |
myisam_block_size | 1024 |
read_buffer_size | 262136 |
sort_buffer_size | 2097144 |
sort_key_blocks | 16 |
write_buffer_size | 262136 |
It is also possible to set variables by using
--set-variable=var_name=value
or -O var_name=value
syntax. However, this syntax is deprecated as of MySQL 4.0.
The possible myisamchk
variables and their default values
can be examined with myisamchk --help
:
sort_buffer_size
is used when the keys are repaired by sorting
keys, which is the normal case when you use --recover
.
key_buffer_size
is used when you are checking the table with
--extend-check
or when the keys are repaired by inserting keys
row by row into the table (like when doing normal inserts). Repairing
through the key buffer is used in the following cases:
--safe-recover
.
CHAR
, VARCHAR
, or TEXT
columns, because the sort operation needs to store the complete key values
as it proceeds. If you have lots of temporary space and you can force
myisamchk
to repair by sorting, you can use the --sort-recover
option.
Repairing through the key buffer takes much less disk space than using sorting, but is also much slower.
If you want a faster repair, set the key_buffer_size
and
sort_buffer_size
variables to about 25% of your available memory.
You can set both variables to large values, because only one of them is used
at a time.
myisam_block_size
is the size used for index blocks. It is available
as of MySQL 4.0.0.
The ft_min_word_len
and ft_max_word_len
variables are
available as of MySQL 4.0.0. ft_stopword_file
is available as of
MySQL 4.0.19.
ft_min_word_len
and ft_max_word_len
indicate the minimum and
maximum word length for FULLTEXT
indexes. ft_stopword_file
names the stopword file. These need to be set under the following
circumstances.
If you use myisamchk
to perform an operation that modifies
table indexes (such as repair or analyze), the FULLTEXT
indexes
are rebuilt using the default full-text parameter values for minimum and
maximum word length and the stopword file unless you specify otherwise.
This can result in queries failing.
The problem occurs because these parameters are known only by the server.
They are not stored in MyISAM
index files. To avoid the problem if
you have modified the minimum or maximum word length or the stopword file in
the server, specify the same ft_min_word_len
, ft_max_word_len
,
and ft_stopword_file
values to myisamchk
that you use for
mysqld
. For example, if you have set the minimum word length to 3,
you can repair a table with myisamchk
like this:
shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI
To ensure that myisamchk
and the server use the same values for
full-text parameters, you can place each one in both the [mysqld]
and [myisamchk]
sections of an option file:
[mysqld] ft_min_word_len=3 [myisamchk] ft_min_word_len=3
An alternative to using myisamchk
is to use the REPAIR TABLE
,
ANALYZE TABLE
, OPTIMIZE TABLE
, or ALTER TABLE
.
These statements are performed by the server, which knows the proper
full-text parameter values to use.
myisamchk
myisamchk
supports the following options for table checking operations:
--check, -c
--check-only-changed, -C
--extend-check, -e
myisamchk
or myisamchk --medium-check
should
be able to determine whether there are any errors in the table.
If you are using --extend-check
and have plenty of memory, setting
the key_buffer_size
variable to a large value will help the repair
operation run faster.
--fast, -F
--force, -f
myisamchk
finds any errors in the table.
The repair type is the same as that specified with the --repair
or
-r
option.
--information, -i
--medium-check, -m
--extend-check
operation.
This finds only 99.99% of all errors, which should be good enough in most cases.
--read-only, -T
myisamchk
to check a table that is in use by some other application that doesn't
use locking, such as mysqld
when run with the
--skip-external-locking
option.
--update-state, -U
--check-only-changed
option, but you shouldn't use this
option if the mysqld
server is using the table and you are
running it with the --skip-external-locking
option.
myisamchk
myisamchk
supports the following options for table repair operations:
--backup, -B
--character-sets-dir=path
--correct-checksum
--data-file-length=#, -D #
--extend-check, -e
--force, -f
--keys-used=#, -k #
myisamchk
, the option value indicates which indexes to update.
Each binary bit of the option value corresponds to a table index, where the
first index is bit 0.
For isamchk
, the option value indicates that only the first # of
the table indexes should be updated.
In either case, an option value of 0 disables updates to all indexes, which
can be used to get faster inserts.
Deactivated indexes can be reactivated by using myisamchk -r
or (isamchk -r
).
--no-symlinks, -l
myisamchk
repairs the
table that a symlink points to. This option doesn't exist as of MySQL 4.0,
because versions from 4.0 on will not remove symlinks during repair operations.
--parallel-recover, -p
-r
and -n
, but creates
all the keys in parallel, using different threads.
This option was added in MySQL 4.0.2.
This is alpha code. Use at your own risk!
--quick, -q
myisamchk
to modify the original data file in
case of duplicate keys.
--recover, -r
ISAM
/MyISAM
tables). If you want to recover a table, this is the option to try
first. You should try -o
only if myisamchk
reports that the
table can't be recovered by -r
. (In the unlikely case
that -r
fails, the data file is still intact.)
If you have lots of memory, you should increase the value of
sort_buffer_size
.
--safe-recover, -o
-r
, but can handle a couple of very unlikely cases that
-r
cannot. This recovery method also uses much less disk
space than -r
. Normally, you should repair first with
-r
, and then with -o
only if -r
fails.
If you have lots of memory, you should increase the value of
key_buffer_size
.
--set-character-set=name
--sort-recover, -n
myisamchk
to use sorting to resolve the keys even if the
temporary files should be very big.
--tmpdir=path, -t path
myisamchk
uses the value of the TMPDIR
environment variable.
Starting from MySQL 4.1, tmpdir
can be set to a list of directory paths
that will be used successively in round-robin fashion for creating
temporary files. The separator character between directory names should be
colon (`:') on Unix and semicolon (`;') on Windows, NetWare, and
OS/2.
--unpack, -u
myisampack
.
myisamchk
myisamchk
supports the following options for actions other than
table checks and repairs:
--analyze, -a
myisamchk --description --verbose tbl_name
command or the
SHOW KEYS FROM tbl_name
statement.
--description, -d
--set-auto-increment[=value], -A[value]
AUTO_INCREMENT
numbering for new records to start at the given
value (or higher, if there are existing records with AUTO_INCREMENT
values this large). If value is not specified, AUTO_INCREMENT
number for new records begins with the largest value currently in the table,
plus one.
--sort-index, -S
--sort-records=#, -R #
SELECT
and ORDER
BY
operations that use this index. (The first time you use this option to
sort a table, it may be very slow.) To determine a table's index numbers,
use SHOW KEYS
, which displays a table's indexes in the same order
that myisamchk
sees them. Indexes are numbered beginning with 1.
myisamchk
Memory Usage
Memory allocation is important when you run myisamchk
.
myisamchk
uses no more memory than you specify with the -O
options. If you are going to use myisamchk
on very large tables,
you should first decide how much memory you want it to use. The default
is to use only about 3MB to perform repairs. By using larger values, you can
get myisamchk
to operate faster. For example, if you have more
than 32MB RAM, you could use options such as these (in addition to any
other options you might specify):
shell> myisamchk -O sort=16M -O key=16M -O read=1M -O write=1M ...
Using -O sort=16M
should probably be enough for most cases.
Be aware that myisamchk
uses temporary files in TMPDIR
. If
TMPDIR
points to a memory filesystem, you may easily get out of
memory errors. If this happens, set TMPDIR
to point at some directory
located on a filesystem
with more space and run myisamchk
again.
When repairing, myisamchk
will also need a lot of disk space:
--quick
; in this
case, only the index file is re-created. This space is needed on the same
filesystem as the original data file! (The copy is created in the
same directory as the original.)
--recover
or --sort-recover
(but not when using --safe-recover
), you will need space for a
sort buffer. The amount of space required is:
(largest_key + row_pointer_length) * number_of_rows * 2You can check the length of the keys and the
row_pointer_length
with myisamchk -dv tbl_name
. This space is allocated in the temporary
directory (specified by TMPDIR
or --tmpdir=path
).
If you have a problem with disk space during repair, you can try to use
--safe-recover
instead of --recover
.
myisamchk
for Crash Recovery
If you run mysqld
with --skip-external-locking
(which is the
default on some systems, such as Linux), you can't reliably use myisamchk
to check a table when mysqld
is using the same table. If you
can be sure that no one is accessing the tables through mysqld
while you run myisamchk
, you only have to do mysqladmin
flush-tables
before you start checking the tables. If you can't
guarantee this, then you must stop mysqld
while you
check the tables. If you run myisamchk
while mysqld
is updating
the tables, you may get a warning that a table is corrupt even when it
isn't.
If you are not using --skip-external-locking
, you can use
myisamchk
to check tables at any time. While you do this, all clients
that try to update the table will wait until myisamchk
is ready before
continuing.
If you use myisamchk
to repair or optimize tables, you
must always ensure that the mysqld
server is not using
the table (this also applies if you are using --skip-external-locking
).
If you don't take down mysqld
, you should at least do a
mysqladmin flush-tables
before you run myisamchk
.
Your tables may become corrupted if the server and myisamchk
access the tables simultaneously.
This section describes how to check for and deal with data corruption in MySQL databases. If your tables get corrupted frequently you should try to find the reason why. See section A.4.2 What to Do If MySQL Keeps Crashing.
The MyISAM
table section contains reason for why a table could be
corrupted. See section 14.1.4 MyISAM
Table Problems.
When performing crash recovery, it is important to understand that each
MyISAM
table tbl_name in a database corresponds to three files
in the database directory:
File | Purpose |
`tbl_name.frm' | Definition (format) file |
`tbl_name.MYD' | Data file |
`tbl_name.MYI' | Index file |
Each of these three file types is subject to corruption in various ways, but problems occur most often in data files and index files.
myisamchk
works by creating a copy of the `.MYD' data file
row by row. It ends the repair stage by removing the old `.MYD'
file and renaming the new file to the original file name. If you use
--quick
, myisamchk
does not create a temporary `.MYD'
file, but instead assumes that the `.MYD' file is correct and only
generates a new index file without touching the `.MYD' file. This is
safe, because myisamchk
automatically detects whether the `.MYD'
file is corrupt and aborts the repair if it is. You can also specify
the --quick
option twice to myisamchk
. In this case,
myisamchk
does not abort on some errors (such as duplicate-key
errors) but instead tries to resolve them by modifying the `.MYD'
file. Normally the use of two --quick
options is useful only if you
have too little free disk space to perform a normal repair. In this case,
you should at least make a backup before running myisamchk
.
MyISAM
Tables for Errors
To check a MyISAM
table, use the following commands:
myisamchk tbl_name
myisamchk
without options or
with either the -s
or --silent
option.
myisamchk -m tbl_name
myisamchk -e tbl_name
-e
means
``extended check''). It does a check-read of every key for each row to verify
that they indeed point to the correct row. This may take a long time for a
large table that has many indexes. Normally, myisamchk
stops after
the first error it finds. If you want to obtain more information, you can
add the --verbose
(-v
) option. This causes myisamchk
to keep going, up through a maximum of 20 errors.
myisamchk -e -i tbl_name
-i
option tells myisamchk
to
print some informational statistics, too.
In most cases, a simple myisamchk
with no arguments other than the
table name is sufficient to check a table.
The discussion in this section describes how to use myisamchk
on
MyISAM
tables (extensions `.MYI' and `.MYD'). If you
are using ISAM
tables (extensions `.ISM' and `.ISD'),
you should use isamchk
instead; the concepts are similar.
If you are using MySQL 3.23.16 and above, you can (and
should) use the CHECK TABLE
and REPAIR TABLE
statements to
check and repair MyISAM
tables.
See section 13.5.2.3 CHECK TABLE
Syntax
and section 13.5.2.6 REPAIR TABLE
Syntax.
The symptoms of a corrupted table include queries that abort unexpectedly and observable errors such as these:
To get more information about the error you can run perror
###,
where ### is the error number. The following example shows how to use
perror
to find the meanings for the most common error numbers that
indicate a problem with a table:
shell> perror 126 127 132 134 135 136 141 144 145 126 = Index file is crashed / Wrong file format 127 = Record-file is crashed 132 = Old database file 134 = Record was already deleted (or record file crashed) 135 = No more room in record file 136 = No more room in index file 141 = Duplicate unique key or constraint on write or update 144 = Table is crashed and last repair failed 145 = Table was marked as crashed and should be repaired
Note that error 135 (no more room in record file) and error 136 (no more
room in index file) are not errors that can be fixed by a simple repair. In
this case, you have to use ALTER TABLE
to increase the
MAX_ROWS
and AVG_ROW_LENGTH
table option values:
ALTER TABLE tbl_name MAX_ROWS=xxx AVG_ROW_LENGTH=yyy;
If you don't know the current table option values, use SHOW CREATE TABLE
tbl_name
.
For the other errors, you must repair your tables. myisamchk
can
usually detect and fix most problems that occur.
The repair process involves up to four stages, described here. Before you
begin, you should change location to the database directory and check the
permissions of the table files. On Unix, make sure that they are readable by
the user that mysqld
runs as (and to you, because you need to access
the files you are checking). If it turns out you need to modify files, they
must also be writable by you.
The options that you can use for table maintenance with myisamchk
and isamchk
are described in several of the earlier subsections of
section 5.7.3 Table Maintenance and Crash Recovery.
The following section is for the cases where the above command fails or
if you want to use the extended features that myisamchk
and
isamchk
provide.
If you are going to repair a table from the command line, you must first
stop the mysqld
server. Note that when you do
mysqladmin shutdown
on a remote server, the mysqld
server
will still be alive for a while after mysqladmin
returns, until
all queries are stopped and all keys have been flushed to disk.
Stage 1: Checking your tables
Run myisamchk *.MYI
or myisamchk -e *.MYI
if you have
more time. Use the -s
(silent) option to suppress unnecessary
information.
If the mysqld
server is down, you should use the --update-state
option to tell myisamchk
to mark the table as 'checked'.
You have to repair only those tables for which myisamchk
announces an
error. For such tables, proceed to Stage 2.
If you get weird errors when checking (such as out of
memory
errors), or if myisamchk
crashes, go to Stage 3.
Stage 2: Easy safe repair
Note: If you want a repair operation to go much faster, you should set the
values of the sort_buffer_size
and key_buffer_size
variables
each to about 25% of your available memory when running myisamchk
or isamchk
.
First, try myisamchk -r -q tbl_name
(-r -q
means ``quick
recovery mode''). This will attempt to repair the index file without
touching the data file. If the data file contains everything that it
should and the delete links point at the correct locations within the
data file, this should work, and the table is fixed. Start repairing the
next table. Otherwise, use the following procedure:
myisamchk -r tbl_name
(-r
means ``recovery mode''). This will
remove incorrect records and deleted records from the data file and
reconstruct the index file.
myisamchk --safe-recover tbl_name
.
Safe recovery mode uses an old recovery method that handles a few cases that
regular recovery mode doesn't (but is slower).
If you get weird errors when repairing (such as out of
memory
errors), or if myisamchk
crashes, go to Stage 3.
Stage 3: Difficult repair
You should reach this stage only if the first 16KB block in the index file is destroyed or contains incorrect information, or if the index file is missing. In this case, it's necessary to create a new index file. Do so as follows:
shell> mysql db_name mysql> SET AUTOCOMMIT=1; mysql> TRUNCATE TABLE tbl_name; mysql> quitIf your version of MySQL doesn't have
TRUNCATE TABLE
, use
DELETE FROM tbl_name
instead.
Go back to Stage 2. myisamchk -r -q
should work. (This shouldn't
be an endless loop.)
As of MySQL 4.0.2, you can also use REPAIR TABLE tbl_name USE_FRM
,
which performs the whole procedure automatically.
Stage 4: Very difficult repair
You should reach this stage only if the `.frm' description file has also crashed. That should never happen, because the description file isn't changed after the table is created:
myisamchk -r
.
To coalesce fragmented records and eliminate wasted space resulting from
deleting or updating records, run myisamchk
in recovery mode:
shell> myisamchk -r tbl_name
You can optimize a table in the same way by using the SQL OPTIMIZE TABLE
statement. OPTIMIZE TABLE
does a repair of the table and a key
analysis, and also sorts the index tree to give faster key lookups.
There is also no possibility of unwanted interaction between a utility
and the server, because the server does all the work when you use
OPTIMIZE TABLE
. See section 13.5.2.5 OPTIMIZE TABLE
Syntax.
myisamchk
also has a number of other options you can use to improve
the performance of a table:
-S
, --sort-index
-R index_num
, --sort-records=index_num
-a
, --analyze
For a full description of the options, see section 5.7.3.1 myisamchk
Invocation Syntax.
It is a good idea to perform table checks on a regular basis rather than
waiting for problems to occur.
One way to check and repair MyISAM
tables is
with the CHECK TABLE
and REPAIR TABLE
statements.
These are available starting with MySQL 3.23.16.
See section 13.5.2.3 CHECK TABLE
Syntax and
section 13.5.2.6 REPAIR TABLE
Syntax.
Another way to check tables is to use myisamchk
. For maintenance
purposes, you can use myisamchk -s
. The -s
option (short for
--silent
) causes myisamchk
to run in silent mode, printing
messages only when errors occur.
It's also a good idea to check tables when the server starts.
For example, whenever the machine has done a restart in the middle of an
update, you usually need to check all the tables that could have been
affected. (These are ``expected crashed tables.'')
To check MyISAM
tables automatically, start the server with the --myisam-recover
option, available as of MySQL 3.23.25.
If your server is too old to support this option, you could
add a test to
mysqld_safe
that runs myisamchk
to check all tables that have
been modified during the last 24 hours if there is an old `.pid'
(process ID) file left after a restart. (The `.pid' file is created by
mysqld
when it starts and removed when it terminates normally. The
presence of a `.pid' file at system startup time indicates that
mysqld
terminated abnormally.)
An even better test would be to check any table whose last-modified time is more recent than that of the `.pid' file.
You should also check your tables regularly during normal system
operation. At MySQL AB, we run a cron
job to check all
our important tables once a week, using a line like this in a `crontab'
file:
35 0 * * 0 /path/to/myisamchk --fast --silent /path/to/datadir/*/*.MYI
This prints out information about crashed tables so that we can examine and repair them when needed.
Because we haven't had any unexpectedly crashed tables (tables that become corrupted for reasons other than hardware trouble) for a couple of years (this is really true), once a week is more than enough for us.
We recommend that to start with, you execute myisamchk -s
each
night on all tables that have been updated during the last 24 hours,
until you come to trust MySQL as much as we do.
Normally, MySQL tables need little maintenance. If you are changing
MyISAM
tables with dynamic-sized rows (tables with VARCHAR
,
BLOB
, or TEXT
columns) or have tables with many deleted rows
you may want to defragment/reclaim space from the tables
from time to time (once a month?).
You can do this by using OPTIMIZE TABLE
on the tables in question.
Or, if you can stop the mysqld
server for a while, change location
into the data directory and use this command while the server is stopped:
shell> myisamchk -r -s --sort-index -O sort_buffer_size=16M */*.MYI
For ISAM
tables, the command is similar:
shell> isamchk -r -s --sort-index -O sort_buffer_size=16M */*.ISM
To obtain a description of a table or statistics about it, use the commands shown here. We explain some of the information in more detail later:
myisamchk -d tbl_name
Runs myisamchk
in ``describe mode'' to produce a description of
your table. If you start the MySQL server using the
--skip-external-locking
option, myisamchk
may report an error
for a table that is updated while it runs. However, because myisamchk
doesn't change the table in describe mode, there is no risk of
destroying data.
myisamchk -d -v tbl_name
Adding -v
runs myisamchk
in verbose mode so that it produces
more information about what it is doing.
myisamchk -eis tbl_name
Shows only the most important information from a table. This operation is slow
because it must read the entire table.
myisamchk -eiv tbl_name
This is like -eis
, but tells you what is being done.
Sample output for some of these commands follows. They are based on a table with these data and index file sizes:
-rw-rw-r-- 1 monty tcx 317235748 Jan 12 17:30 company.MYD -rw-rw-r-- 1 davida tcx 96482304 Jan 12 18:35 company.MYM
Example of myisamchk -d
output:
MyISAM file: company.MYI Record format: Fixed length Data records: 1403698 Deleted blocks: 0 Recordlength: 226 table description: Key Start Len Index Type 1 2 8 unique double 2 15 10 multip. text packed stripped 3 219 8 multip. double 4 63 10 multip. text packed stripped 5 167 2 multip. unsigned short 6 177 4 multip. unsigned long 7 155 4 multip. text 8 138 4 multip. unsigned long 9 177 4 multip. unsigned long 193 1 text
Example of myisamchk -d -v
output:
MyISAM file: company Record format: Fixed length File-version: 1 Creation time: 1999-10-30 12:12:51 Recover time: 1999-10-31 19:13:01 Status: checked Data records: 1403698 Deleted blocks: 0 Datafile parts: 1403698 Deleted data: 0 Datafile pointer (bytes): 3 Keyfile pointer (bytes): 3 Max datafile length: 3791650815 Max keyfile length: 4294967294 Recordlength: 226 table description: Key Start Len Index Type Rec/key Root Blocksize 1 2 8 unique double 1 15845376 1024 2 15 10 multip. text packed stripped 2 25062400 1024 3 219 8 multip. double 73 40907776 1024 4 63 10 multip. text packed stripped 5 48097280 1024 5 167 2 multip. unsigned short 4840 55200768 1024 6 177 4 multip. unsigned long 1346 65145856 1024 7 155 4 multip. text 4995 75090944 1024 8 138 4 multip. unsigned long 87 85036032 1024 9 177 4 multip. unsigned long 178 96481280 1024 193 1 text
Example of myisamchk -eis
output:
Checking MyISAM file: company Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4 Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4 Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4 Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3 Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3 Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4 Total: Keyblocks used: 98% Packed: 17% Records: 1403698 M.recordlength: 226 Packed: 0% Recordspace used: 100% Empty space: 0% Blocks/Record: 1.00 Record blocks: 1403698 Delete blocks: 0 Recorddata: 317235748 Deleted data: 0 Lost space: 0 Linkdata: 0 User time 1626.51, System time 232.36 Maximum resident set size 0, Integral resident set size 0 Non physical pagefaults 0, Physical pagefaults 627, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 639, Involuntary context switches 28966
Example of myisamchk -eiv
output:
Checking MyISAM file: company Data records: 1403698 Deleted blocks: 0 - check file-size - check delete-chain block_size 1024: index 1: index 2: index 3: index 4: index 5: index 6: index 7: index 8: index 9: No recordlinks - check index reference - check data record references index: 1 Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4 - check data record references index: 2 Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4 - check data record references index: 3 Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4 - check data record references index: 4 Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3 - check data record references index: 5 Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 6 Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 7 Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 8 Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3 - check data record references index: 9 Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4 Total: Keyblocks used: 9% Packed: 17% - check records and index references [LOTS OF ROW NUMBERS DELETED] Records: 1403698 M.recordlength: 226 Packed: 0% Recordspace used: 100% Empty space: 0% Blocks/Record: 1.00 Record blocks: 1403698 Delete blocks: 0 Recorddata: 317235748 Deleted data: 0 Lost space: 0 Linkdata: 0 User time 1639.63, System time 251.61 Maximum resident set size 0, Integral resident set size 0 Non physical pagefaults 0, Physical pagefaults 10580, Swaps 0 Blocks in 4 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 10604, Involuntary context switches 122798
Explanations for the types of information myisamchk
produces are
given here. ``Keyfile'' refers to the index file. ``Record'' and ``row''
are synonymous.
MyISAM file
Name of the MyISAM
(index) file.
File-version
Version of MyISAM
format. Currently always 2.
Creation time
When the data file was created.
Recover time
When the index/data file was last reconstructed.
Data records
How many records are in the table.
Deleted blocks
How many deleted blocks still have reserved space.
You can optimize your table to minimize this space.
See section 5.7.3.10 Table Optimization.
Datafile parts
For dynamic record format, this indicates how many data blocks there are. For
an optimized table without fragmented records, this is the same as Data
records
.
Deleted data
How many bytes of unreclaimed deleted data there are.
You can optimize your table to minimize this space.
See section 5.7.3.10 Table Optimization.
Datafile pointer
The size of the data file pointer, in bytes. It is usually 2, 3, 4, or 5
bytes. Most tables manage with 2 bytes, but this cannot be controlled
from MySQL yet. For fixed tables, this is a record address. For
dynamic tables, this is a byte address.
Keyfile pointer
The size of the index file pointer, in bytes. It is usually 1, 2, or 3
bytes. Most tables manage with 2 bytes, but this is calculated
automatically by MySQL. It is always a block address.
Max datafile length
How long the table data file can become, in bytes.
Max keyfile length
How long the table index file can become, in bytes.
Recordlength
How much space each record takes, in bytes.
Record format
The format used to store table rows.
The preceding examples use Fixed length
.
Other possible values are Compressed
and Packed
.
table description
A list of all keys in the table. For each key, myisamchk
displays
some low-level information:
Key
This key's number.
Start
Where in the record this index part starts.
Len
How long this index part is. For packed numbers, this should always be
the full length of the column. For strings, it may be shorter than the full
length of the indexed column, because you can index a prefix of a string
column.
Index
Whether a key value can exist multiple times in the index. Values are
unique
or multip.
(multiple).
Type
What data type this index part has. This is a MyISAM
data type
with the options packed
, stripped
, or empty
.
Root
Address of the root index block.
Blocksize
The size of each index block. By default this is 1024, but the value may be
changed at compile time when MySQL is built from source.
Rec/key
This is a statistical value used by the optimizer. It tells how many
records there are per value for this key. A unique key always has a
value of 1. This may be updated after a table is loaded (or greatly
changed) with myisamchk -a
. If this is not updated at all, a default
value of 30 is given.
table description
lines for the ninth index. This indicates that it is a multiple-part index
with two parts.
Keyblocks used
What percentage of the keyblocks are used. When a table has just been
reorganized with myisamchk
, as for the table in the examples, the
values are very high (very near the theoretical maximum).
Packed
MySQL tries to pack keys with a common suffix. This can only be used
for indexes on CHAR
, VARCHAR
, or DECIMAL
columns. For
long indexed strings that have similar leftmost parts,
this can significantly reduce the space used. In the third example
above, the fourth key is 10 characters long and a 60% reduction in space is
achieved.
Max levels
How deep the B-tree for this key is. Large tables with long key values get high
values.
Records
How many rows are in the table.
M.recordlength
The average record length. This is the exact record length for tables
with fixed-length records, because all records have the same length.
Packed
MySQL strips spaces from the end of strings. The Packed
value indicates the percentage of savings achieved by doing this.
Recordspace used
What percentage of the data file is used.
Empty space
What percentage of the data file is unused.
Blocks/Record
Average number of blocks per record (that is, how many links a fragmented
record is composed of). This is always 1.0 for fixed-format tables. This
value should stay as close to 1.0 as possible. If it gets too big, you can
reorganize the table.
See section 5.7.3.10 Table Optimization.
Recordblocks
How many blocks (links) are used. For fixed format, this is the same as the number
of records.
Deleteblocks
How many blocks (links) are deleted.
Recorddata
How many bytes in the data file are used.
Deleted data
How many bytes in the data file are deleted (unused).
Lost space
If a record is updated to a shorter length, some space is lost. This is
the sum of all such losses, in bytes.
Linkdata
When the dynamic table format is used, record fragments are linked with
pointers (4 to 7 bytes each). Linkdata
is the sum of the amount of
storage used by all such pointers.
If a table has been compressed with myisampack
, myisamchk
-d
prints additional information about each table column. See
section 8.2 myisampack
, the MySQL Compressed Read-only Table Generator, for an example of this
information and a description of what it means.
This section describes how to configure the server to use different character sets. It also discusses how to set the server's time zone and enable per-connection time zone support.
By default, MySQL uses the ISO-8859-1 (Latin1) character set with sorting according to Swedish/Finnish rules. These defaults are suitable for the United States and most of western Europe.
All MySQL binary distributions are compiled with
--with-extra-charsets=complex
. This adds code to all
standard programs that enables them to handle latin1
and all multi-byte
character sets within the binary. Other character sets will be
loaded from a character-set definition file when needed.
The character set determines what characters are allowed in names. It also
determines how strings are sorted by the ORDER BY
and GROUP
BY
clauses of the SELECT
statement.
You can change the character set with the --default-character-set
option when you start the server. The character sets available depend
on the --with-charset=charset
and --with-extra-charsets=
list-of-charsets | complex | all | none
options to configure
, and the
character set configuration files listed in
`SHAREDIR/charsets/Index'.
See section 2.8.2 Typical configure
Options.
As of MySQL 4.1.1, you can also change the character set collation with the
--default-collation
option when you start the server. The collation
must be a legal collation for the default character set. (Use the
SHOW COLLATION
statement to determine which collations are available
for each character set.)
See section 2.8.2 Typical configure
Options.
If you change the character set when running MySQL, that may also
change the sort order. Consequently, you must run myisamchk -r -q
--set-character-set=charset
on all tables, or your indexes may not be
ordered correctly.
When a client connects to a MySQL server, the server indicates to the client what the server's default character set is. The client will switch to use this character set for this connection.
You should use mysql_real_escape_string()
when escaping strings
for an SQL query. mysql_real_escape_string()
is identical to the
old mysql_escape_string()
function, except that it takes the MYSQL
connection handle as the first parameter so that the appropriate character set
can be taken into account when escaping characters.
If the client is compiled with different paths than where the server is installed and the user who configured MySQL didn't include all character sets in the MySQL binary, you must tell the client where it can find the additional character sets it will need if the server runs with a different character set than the client.
You can do this by specifying a --character-sets-dir
option to
indicate the path to the directory in which the dynamic MySQL character
sets are stored. For example, you can put the following in an option file:
[client] character-sets-dir=/usr/local/mysql/share/mysql/charsets
You can force the client to use specific character set as follows:
[client] default-character-set=charset
This is normally unnecessary, however.
In MySQL 4.0, to get German sorting order, you should start mysqld
with a --default-character-set=latin1_de
option. This affects server
behavior in several ways:
ä -> ae ö -> oe ü -> ue ß -> ss
LIKE
, the one-character to two-character mapping
is not done. All letters are converted to uppercase. Accents are removed
from all letters except Ü
, ü
, Ö
, ö
,
Ä
, and ä
.
In MySQL 4.1 and up, character set and collation are specified separately.
You should select the latin1
character set and either the
latin1_german1_ci
or latin1_german2_ci
collation. For
example, to start the server with the latin1_german1_ci
collation,
use the --character-set-server=latin1
and
--collation-server=latin1_german1_ci
options.
For information on the differences between these two collations, see section 10.11.2 West European Character Sets.
By default, mysqld
produces error messages in English, but they can
also be displayed in any of these other languages:
Czech, Danish, Dutch, Estonian, French, German, Greek,
Hungarian, Italian, Japanese, Korean, Norwegian, Norwegian-ny, Polish,
Portuguese, Romanian, Russian, Slovak, Spanish, or Swedish.
To start mysqld
with a particular language for error messages, use the
--language
or -L
option. The option value can be a language name
or the full path to the error message file.
For example:
shell> mysqld --language=swedish
Or:
shell> mysqld --language=/usr/local/share/swedish
The language name should be specified in lowercase.
The language files are located (by default) in the `share/LANGUAGE' directory under the MySQL base directory.
To change the error message file, you should edit the `errmsg.txt' file, and then execute the following command to generate the `errmsg.sys' file:
shell> comp_err errmsg.txt errmsg.sys
If you upgrade to a newer version of MySQL, remember to repeat your changes with the new `errmsg.txt' file.
This section discusses the procedure for adding add another character set to MySQL. You must have a MySQL source distribution to use these instructions.
To choose the proper procedure, decide whether the character set is simple or complex:
For example, latin1
and danish
are simple character sets,
whereas big5
and czech
are complex character sets.
In the following procedures, the name of your character set is represented by MYSET.
For a simple character set, do the following:
ctype
array takes up the first 257 words. The
to_lower[]
, to_upper[]
and sort_order[]
arrays take up
256 words each after that.
CHARSETS_AVAILABLE
and
COMPILED_CHARSETS
lists in configure.in
.
For a complex character set, do the following:
ctype_MYSET
,
to_lower_MYSET
, and so on. These correspond to the arrays
for a simple character set. See section 5.8.4 The Character Definition Arrays.
/* * This comment is parsed by configure to create ctype.c, * so don't change it unless you know what you are doing. * * .configure. number_MYSET=MYNUMBER * .configure. strxfrm_multiply_MYSET=N * .configure. mbmaxlen_MYSET=N */The
configure
program uses this comment to include
the character set into the MySQL library automatically.
The strxfrm_multiply
and mbmaxlen
lines are explained in
the following sections. You need include them only if you need the string
collating functions or the multi-byte character set functions,
respectively.
my_strncoll_MYSET()
my_strcoll_MYSET()
my_strxfrm_MYSET()
my_like_range_MYSET()
CHARSETS_AVAILABLE
and
COMPILED_CHARSETS
lists in configure.in
.
The `sql/share/charsets/README' file includes additional instructions.
If you want to have the character set included in the MySQL
distribution, mail a patch to the MySQL internals
mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
to_lower[]
and to_upper[]
are simple arrays that hold the
lowercase and uppercase characters corresponding to each member of the
character set. For example:
to_lower['A'] should contain 'a' to_upper['a'] should contain 'A'
sort_order[]
is a map indicating how characters should be ordered for
comparison and sorting purposes. Quite often (but not for all character sets)
this is the same as to_upper[]
, which means that sorting will be
case-insensitive. MySQL will sort characters based on the values of
sort_order[]
elements. For more complicated sorting rules, see
the discussion of string collating in section 5.8.5 String Collating Support.
ctype[]
is an array of bit values, with one element for one character.
(Note that to_lower[]
, to_upper[]
, and sort_order[]
are indexed by character value, but ctype[]
is indexed by character
value + 1. This is an old legacy convention to be able to handle EOF
.)
You can find the following bitmask definitions in `m_ctype.h':
#define _U 01 /* Uppercase */ #define _L 02 /* Lowercase */ #define _N 04 /* Numeral (digit) */ #define _S 010 /* Spacing character */ #define _P 020 /* Punctuation */ #define _C 040 /* Control character */ #define _B 0100 /* Blank */ #define _X 0200 /* heXadecimal digit */
The ctype[]
entry for each character should be the union of the
applicable bitmask values that describe the character. For example,
'A'
is an uppercase character (_U
) as well as a
hexadecimal digit (_X
), so ctype['A'+1]
should contain the
value:
_U + _X = 01 + 0200 = 0201
If the sorting rules for your language are too complex to be handled
with the simple sort_order[]
table, you need to use the string
collating functions.
The best documentation for this is the existing character sets.
Look at the big5
, czech
, gbk
,
sjis
, and tis160
character sets for examples.
You must specify the strxfrm_multiply_MYSET=N
value in the
special comment at the top of the file. N should be set to
the maximum ratio the strings may grow during my_strxfrm_MYSET
(it
must be a positive integer).
If you want to add support for a new character set that includes multi-byte characters, you need to use the multi-byte character functions.
The best documentation for this is the existing character sets.
Look at the euc_kr
, gb2312
,
gbk
, sjis
, and ujis
character sets for
examples. These are implemented in the `ctype-charset.c' files
in the `strings' directory.
You must specify the mbmaxlen_MYSET=N
value in the special
comment at the top of the source file. N should be set to the
size in bytes of the largest character in the set.
If you try to use a character set that is not compiled into your binary, you might run into the following problems:
--character-sets-dir
option when you run the program in question.
ERROR 1105: File '/usr/local/share/mysql/charsets/?.conf' not found (Errcode: 2)In this case, you should either get a new
Index
file or manually add
the name of any missing character sets to the current file.
For MyISAM
tables, you can check the character set name and number for a
table with myisamchk -dvv tbl_name
.
Before MySQL 4.1.3, you can set the time zone for the server with the
--timezone=timezone_name
option to mysqld_safe
. You can
also set it by setting the TZ
environment variable before you
start mysqld
.
The allowable values for --timezone
or TZ
are
system-dependent. Consult your operating system documentation to see
what values are acceptable.
Beginning with MySQL 4.1.3, the server maintains several time zone settings:
system_time_zone
system variable.
time_zone
system variable
indicates the time zone the server currently is operating in. The initial
value is 'SYSTEM'
, which indicates that the server time zone is the
same as the system time zone. The initial value can be specified explicitly
with the --default-time-zone=timezone
option. If you have the
SUPER
privilege, you can set the global value at runtime with this
statement:
mysql> SET GLOBAL time_zone = timezone;
time_zone
variable. Initially
this is the same as the global time_zone
variable, but can be
reset with this statement:
mysql> SET time_zone = timezone;
The current values of the global and per-connection time zones can be retrieved like this:
mysql> SELECT @@global.time_zone, @@session.time_zone;
timezone values can be given as strings indicating an offset
from UTC, such as '+10:00'
or '-6:00'
. If the time zone-related
tables in the mysql
database have been created and populated, you
can also used named time zones, such as 'Europe/Helsinki'
,
'US/Eastern'
, or 'MET'
. The value 'SYSTEM'
indicates
that the time zone should be the same as the system time zone. Time zone
names are not case sensitive.
The MySQL installation procedure creates the time zone tables in the
mysql
database, but does not load them. You must do so manually.
(If you are upgrading to MySQL 4.1.3 or later from an earlier version, you
should create the tables by upgrading your mysql
database. Use the
instructions in section 2.10.7 Upgrading the Grant Tables.)
If your system has its own zoneinfo database (the set of files describing
time zones), you should use the mysql_tzinfo_to_sql
program for
filling the time zone tables. Examples of such systems are Linux, FreeBSD,
Sun Solaris, and Mac OS X. One likely location for these files is the
`/usr/share/zoneinfo' directory. If your system does not have a
zoneinfo database, you can use the downloadable package described later in
this section.
The mysql_tzinfo_to_sql
program is used to load the time zone
tables. On the command line, pass the zoneinfo directory pathname to
mysql_tzinfo_to_sql
and send the output into the mysql
program. For example:
shell> mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
mysql_tzinfo_to_sql
reads your system's time zone files and
generates SQL statements from them. mysql
processes those
statements to load the time zone tables.
mysql_tzinfo_to_sql
also can be used to load a single time zone
file, and to generate leap second information.
To load a single time zone file tz_file that corresponds to a
time zone name tz_name, invoke mysql_tzinfo_to_sql
like this:
shell> mysql_tzinfo_to_sql tz_file tz_name | mysql -u root mysql
If your time zone needs to account for leap seconds, initialize the leap second information like this, where tz_file is the name of your time zone file:
shell> mysql_tzinfo_to_sql --leap tz_file | mysql -u root mysql
If your system doesn't have a zoneinfo database (for example, Windows or
HP-UX), you can use the package of pre-built time zone tables that is
available for download at
http://dev.mysql.com/downloads/timezones.html. This package contains
`.frm', `.MYD', and `.MYI' files for the MyISAM
time
zone tables. These tables should belong to the mysql
database, so
you should place the files in the `mysql' subdirectory of your MySQL
server's data directory. The server should be shut down while you do this.
Warning! Please don't use the downloadable package if your system
has a zoneinfo database. Use the mysql_tzinfo_to_sql
utility
instead! Otherwise, you may cause a difference in datetime handling between
MySQL and other applications on your system.
For information about time zone settings in replication setup please look into section 6.7 Replication Features and Known Problems.
MySQL has several different log files that can help you find
out what's going on inside mysqld
:
Log File | Types of Information Logged to File |
The error log | Logs problems encountered starting, running, or
stopping mysqld .
|
The isam log | Logs all changes to the ISAM tables. Used only for debugging the isam code.
|
The query log | Logs established client connections and executed statements. |
The update log | Logs statements that change data. This log is deprecated. |
The binary log | Logs all statements that change data. Also used for replication. |
The slow log | Logs all queries that took more than long_query_time seconds to execute or didn't use indexes.
|
By default, all logs are created in the mysqld
data directory. You can
force mysqld
to close and reopen the log files (or in some cases
switch to a new log) by flushing the logs. Log flushing occurs when you
issue a FLUSH LOGS
statement or execute mysqladmin flush-logs
or
mysqladmin refresh
.
See section 13.5.5.2 FLUSH
Syntax.
If you are using MySQL replication capabilities, slave replication servers maintain additional log files called relay logs. These are discussed in section 6 Replication in MySQL.
The error log file contains information indicating when mysqld
was started and stopped and also any critical errors that occur while the
server is running.
If mysqld
dies unexpectedly and mysqld_safe
needs to
restart it, mysqld_safe
will write a restarted
mysqld
message to the error log. If
mysqld
notices a table that needs to be automatically checked or
repaired, it writes a message to the error log.
On some operating systems, the error log will contain a stack trace if
mysqld
dies. The trace can be used to determine where
mysqld
died. See section E.1.4 Using a Stack Trace.
Beginning with MySQL 4.0.10, you can specify where mysqld
stores the
error log file with the --log-error[=file_name]
option. If no
file_name value is given, mysqld
uses the name
`host_name.err' and writes the file in the data directory.
(Prior to MySQL 4.0.10, the Windows error log name is `mysql.err'.)
If you execute FLUSH LOGS
, the error log is renamed with a suffix
of -old
and mysqld
creates a new empty log file.
In older MySQL versions on Unix, error log handling was done by
mysqld_safe
which redirected the error file to
host_name.err
. You could change this filename by specifying a
--err-log=file_name
option to mysqld_safe
.
If you don't specify --log-error
, or (on Windows) if you use the
--console
option, errors are written to stderr, the standard error
output. Usually this is your terminal.
On Windows, error output is always written to the .err
file if
--console
is not given.
If you want to know what happens within mysqld
, you should start
it with the --log[=file_name]
or -l [file_name]
option.
If no file_name value is given, the default name is
`host_name.log'
This will log all connections and statements to the log file.
This log can be very useful when you suspect an error in a client and want
to know exactly what the client sent to mysqld
.
Older versions of the mysql.server
script (from MySQL 3.23.4 to 3.23.8)
pass a --log
option to safe_mysqld
to enable the general query log.
If you need better performance when you start using MySQL in a production
environment, you can remove the --log
option from mysql.server
or change it to --log-bin
. See section 5.9.4 The Binary Log.
mysqld
writes statements to the query log in the order that it
receives them. This may be different from the order in which they are
executed. This is in contrast to the update log and the binary log, which
are written after the query is executed, but before any locks are released.
(The query log also contains all statements, whereas the update and binary
logs do not contain statements that only select data.)
Server restarts and log flushing do not cause a new general query log file to be generated (although flushing closes and reopens it). On Unix, you can rename the file and create a new one by using the following commands:
shell> mv hostname.log hostname-old.log shell> mysqladmin flush-logs shell> cp hostname-old.log to-backup-directory shell> rm hostname-old.log
On Windows, you cannot rename the log file while the server has it open. You must stop the server and rename the log. Then restart the server to create a new log.
Note: The update log has been deprecated and replaced by the binary log. See section 5.9.4 The Binary Log. The binary log can do anything the old update log could do, and more. The update log is unavailable as of MySQL 5.0.0.
When started with the --log-update[=file_name]
option,
mysqld
writes a log file containing all SQL statements that update
data. If no file_name value is given, the default name is name of the host
machine. If a filename is given, but it doesn't contain a leading path, the file
is written in the data directory. If `file_name' doesn't have an
extension, mysqld
creates log files with names of the form
file_name.###, where ### is a number that is incremented each
time you start the server or flush the logs.
Note: For this naming scheme to work, you must not create your own files with the same names as those that might be used for the log file sequence.
Update logging is smart because it logs only statements that really update
data. So, an UPDATE
or a DELETE
with a WHERE
that finds no
rows is not written to the log. It even skips UPDATE
statements that
set a column to its existing value.
The update logging is done immediately after a query completes but before any locks are released or any commit is done. This ensures that statements are logged in execution order.
If you want to update a database from update log files, you could do the following (assuming that your update logs have names of the form `file_name.###'):
shell> ls -1 -t -r file_name.[0-9]* | xargs cat | mysql
ls
is used to sort the update log filenames into the right order.
This can be useful if you have to revert to backup files after a crash and you want to redo the updates that occurred between the time of the backup and the crash.
The binary log has replaced the old update log, which is unavailable starting from MySQL 5.0. The binary log contains all information that is available in the update log in a more efficient format and in a manner that is transactionally safe.
The binary log contains all statements which updated data or (starting from
MySQL 4.1.3) could potentially have updated it (for example, a DELETE
which matched no rows).
The binary log also contains information about how long each statement took that updated the database. It doesn't contain statements that don't modify any data. If you want to log all statements (for example, to identify a problem query) you should use the general query log. See section 5.9.2 The General Query Log.
The primary purpose of the binary log is to be able to update the database during a restore operation as fully as possible, because the binary log will contain all updates done after a backup was made.
The binary log is also used on master replication servers as a record of the statements to be sent to slave servers. See section 6 Replication in MySQL.
Running the server with the binary log enabled makes performance about 1% slower. However, the benefits of the binary log for restore operations and in allowing you to set up replication generally outweigh this minor performance decrement.
When started with the --log-bin[=file_name]
option, mysqld
writes a log file containing all SQL commands that update data. If no
file_name value is given, the default name is the name of the host machine followed
by -bin
. If file name is given, but it doesn't contain a path, the
file is written in the data directory.
It is recommended to specify a filename, see section 1.5.7.3 Open Bugs and Design Deficiencies in MySQL for the reason.
If you supply an extension in the log name (for example,
--log-bin=file_name.extension
), the
extension is silently removed and ignored.
mysqld
appends a numeric extension to the binary log name. The number
is incremented each time you start the server or flush the logs.
A new binary log also is created
automatically when the current log's size reaches
max_binlog_size
. A binary log may become larger than
max_binlog_size
if you are using large transactions: A transaction is
written to the binary log in one piece, never split between binary logs.
To be able to know which different binary log files have been used,
mysqld
also creates a binary log index file that
contains the name of all used binary log files. By default this has the
same name as the binary log file, with the extension '.index'
.
You can change the name of the binary log index file with the
--log-bin-index[=file_name]
option.
You should not manually edit this file while mysqld
is running;
doing so would confuse mysqld
.
You can delete all binary log files with the RESET MASTER
statement,
or only some of them with PURGE MASTER LOGS
.
See section 13.5.5.5 RESET
Syntax and section 13.6.1 SQL Statements for Controlling Master Servers.
The binary log format has some known limitations which can affect recovery from
backups, especially in old versions. These caveats which also affect
replication are listed at section 6.7 Replication Features and Known Problems. One caveat which does not
affect replication but only recovery with mysqlbinlog
: before MySQL 4.1,
mysqlbinlog
could not prepare output suitable for mysql
if
the binary log contained interlaced statements originating from different
clients that used temporary tables of the same name. This is fixed in MySQL
4.1. However, the problem still existed for LOAD DATA INFILE
statements
until it was fixed in MySQL 4.1.8.
You can use the following options to mysqld
to affect what is logged
to the binary log. See also the discussion that follows this option list.
--binlog-do-db=db_name
USE
) is db_name. All
other databases that are not explicitly mentioned are ignored. If you use
this, you should ensure that you only do updates in the current database.
Observe that there is an exception to the CREATE/ALTER/DROP
DATABASE
statements, which use the database manipulated to decide if
it should log the statement rather than the current database.
An example of what does not work as you might expect: If the server is
started with binlog-do-db=sales
, and you do
USE prices; UPDATE sales.january SET amount=amount+1000;
,
this statement will not be written into the binary log.
--binlog-ignore-db=db_name
USE
) is
db_name should not be stored in the binary log. If
you use this, you should ensure that you only do updates in the current
database.
An example of what does not work as you might expect: If the server is
started with binlog-ignore-db=sales
, and you do
USE prices; UPDATE sales.january SET amount=amount+1000;
,
this statement will be written into the binary log.
Similar to the case for --binlog-do-db
, there is an exception
to the CREATE/ALTER/DROP DATABASE
statements, which use the
database manipulated to decide if it should log the statement rather
than the current database.
To log or ignore multiple databases, specify the appropriate option multiple times, once for each database.
The rules for logging or ignoring updates to the binary log are
evaluated according to the following rules. Observe that there is an
exception for CREATE/ALTER/DROP DATABASE
statements. In those
cases, the database being created/altered/dropped replace the
current database in the rules below.
binlog-do-db
or binlog-ignore-db
rules?
binlog-do-db
or
binlog-ignore-db
or both). Is there a current database (has any
database been selected by USE
?)?
binlog-do-db
rules?
binlog-do-db
rules?
binlog-ignore-db
rules.
Does the current database match any of the binlog-ignore-db
rules?
For example, a slave running with only binlog-do-db=sales
will not write to the binary log any statement whose current database is
different from sales
(in other words, binlog-do-db
can
sometimes mean ``ignore other databases'').
If you are using replication, you should not delete old binary log
files until you are sure that no slave still needs to use them.
One way to do this is to do mysqladmin flush-logs
once a day and then
remove any logs that are more than three days old. You can remove them
manually, or preferably using PURGE MASTER LOGS
(see section 13.6.1 SQL Statements for Controlling Master Servers), which will also safely update the binary
log index file for you (and which can take a date argument since
MySQL 4.1)
A client with the SUPER
privilege can disable binary
logging of its own statements by using a SET
SQL_LOG_BIN=0
statement. See section 13.5.3 SET
Syntax.
You can examine the binary log file with the mysqlbinlog
utility.
This can be useful when you want to reprocess statements in the log.
For example, you can update a MySQL server from the binary log
as follows:
shell> mysqlbinlog log-file | mysql -h server_name
See section 8.5 The mysqlbinlog
Binary Log Utility for more information on the
mysqlbinlog
utility and how to use it.
If you are using transactions, you must use the MySQL binary log for backups instead of the old update log.
The binary logging is done immediately after a query completes but before any locks are released or any commit is done. This ensures that the log will be logged in the execution order.
Updates to non-transactional tables are stored in the binary log
immediately after execution. For transactional tables such as BDB
or InnoDB
tables, all updates (UPDATE
, DELETE
,
or INSERT
) that change tables are cached until a COMMIT
statement is received by the server. At that point, mysqld
writes the
whole transaction to the binary log before the COMMIT
is executed.
When the thread that handles the transaction starts, it allocates a buffer
of binlog_cache_size
to buffer queries. If a statement is bigger
than this, the thread opens a temporary file to store the transaction. The
temporary file is deleted when the thread ends.
The Binlog_cache_use
status variable shows the number of transactions
that used this buffer (and possibly a temporary file) for storing statements.
The Binlog_cache_disk_use
status variable shows how many of those
transactions actually did have to use a temporary file. These two variables
can be used for tuning binlog_cache_size
to a large enough value that
avoids the use of temporary files.
The max_binlog_cache_size
(default 4GB) can be used to restrict the
total size used to cache a multiple-statement transaction. If a transaction
is larger than this, it will fail and roll back.
If you are using the update log or binary log, concurrent inserts will
be converted to normal inserts when using CREATE ... SELECT
or
INSERT ... SELECT
.
This is to ensure that you can re-create an exact copy of your tables by
applying the log on a backup.
The binary log format is different in versions 3.23, 4.0, and 5.0.0. Those format changes were required to implement enhancements to replication. MySQL 4.1 has the same binary log format as 4.0. See section 6.5 Replication Compatibility Between MySQL Versions.
By default, the binary log is not synchronized to disk at each write. So
if the operating system or machine (not only the MySQL server) crashes
there is a chance that the last statements of the binary log are lost. To
prevent this, you can make the binary log be synchronized to disk after
every Nth binary log write, with the sync_binlog
global variable
(1 being the safest value, but also the slowest). See section 5.2.3 Server System Variables. Even with this set to 1, there is still the chance of an
inconsistency between the tables content and the binary log content in
case of crash. For example, if using InnoDB
tables, and the MySQL
server processes a COMMIT
statement, it writes the whole transaction
to the binary log and then commits this transaction into InnoDB
. If
it crashes between those two operations, at restart the transaction will be
rolled back by InnoDB but still exist in the binary log. This problem can be
solved with the --innodb-safe-binlog
option (available starting from
MySQL 4.1.3), which adds consistency between the content of InnoDB
tables and the binary log. For this option to really bring safety to you,
the MySQL server should also be configured to synchronize to disk, at every
transaction, the binary log (sync_binlog=1
) and (which is true by
default) the InnoDB
logs. The effect of this option is that at restart
after a crash,
after doing a rollback of transactions, the MySQL server will cut rolled
back InnoDB
transactions from the binary log. This ensures that the
binary log reflects the exact data of InnoDB
tables, and so, that
the slave remains in sync with the master (not receiving a statement which
has been rolled back). Note that --innodb-safe-binlog
can be used
even if the MySQL server updates other storage engines than InnoDB. Only
statements/transactions affecting InnoDB
tables are subject to
being removed from the binary log at InnoDB
's crash recovery. If at
crash recovery the MySQL server discovers that the binary log is shorter
than it should have been (that is, it lacks at least one successfully committed
InnoDB
transaction), which should not happen if sync_binlog=1
and the disk/filesystem do an actual sync when they are requested to (some
don't), it will print an error message ("The binary log <name> is shorter
than its expected size"). In this case, this binary log is not correct,
replication should be restarted from a fresh master's data snapshot.
Before MySQL 4.1.9, a write to a binary log file or binary log index file
that failed due to a full disk or an exceeded quota resulted in corruption
of the file. Starting from MySQL 4.1.9, writes to the binary log file and
binary log index file are handled the same way as writes to MyISAM
tables.
See section A.4.3 How MySQL Handles a Full Disk.
When started with the --log-slow-queries[=file_name]
option,
mysqld
writes a log file containing all SQL statements that took
more than long_query_time
seconds to execute. The time to acquire
the initial table locks are not counted as execution time.
If no file_name value is given, the default is the name of the
host machine with a suffix of -slow.log
. If a filename is given,
but doesn't contain a path, the file is written in the data directory.
A statement is logged to the slow query log after it has been executed and after all locks have been released. Log order may be different from execution order.
The slow query log can be used to find queries that take a long time to
execute and are therefore candidates for optimization. However, examining a long
slow query log can become a difficult task. To make this easier, you
can pipe the slow query log through the mysqldumpslow
command to
get a summary of the queries that appear in the log.
Before MySQL 4.1, if you also use --log-long-format
when logging
slow queries, then queries that are not using indexes are logged as well.
queries that are not using indexes also are logged to the slow query log.
--log-long-format
is deprecated as of MySQL version 4.1, when
--log-short-format
was introduced. (Long log format is the default
setting since version 4.1.) Also note that starting with MySQL 4.1,
the --log-queries-not-using-indexes
option is available for the
purpose of logging queries that do not use indexes to the slow query log.
See section 5.2.1 mysqld
Command-Line Options.
The MySQL Server can create a number of different log files that make it easy to see what is going on. See section 5.9 The MySQL Log Files. However, you must clean up these files regularly to ensure that the logs don't take up too much disk space.
When using MySQL with logging enabled, you will want to back up and remove old log files from time to time and tell MySQL to start logging to new files. See section 5.7.1 Database Backups.
On a Linux (Red Hat) installation, you can use the
mysql-log-rotate
script for this. If you installed MySQL
from an RPM distribution, the script should have been installed
automatically. You should be careful with this script if you are
using the binary log for replication! (You should not remove binary logs until
you are certain that their contents have been processed by all slaves.)
On other systems, you must install a short script yourself that you
start from cron
to handle log files.
You can force MySQL to start using new log files by using
mysqladmin flush-logs
or by using the SQL statement FLUSH LOGS
.
If you are using MySQL 3.21, you must use mysqladmin refresh
.
A log flushing operation does the following:
--log
) or slow query logging
(--log-slow-queries
) is used, closes and reopens the log file
(`mysql.log' and ``hostname`-slow.log' as default).
--log-update
) or binary logging (--log-bin
)
is used, closes the log and opens a new log file with a higher sequence number.
If you are using only an update log, you only have to rename the log file and then flush the logs before making a backup. For example, you can do something like this:
shell> cd mysql-data-directory shell> mv mysql.log mysql.old shell> mysqladmin flush-logs
Then make a backup and remove `mysql.old'.
In some cases, you might want to run multiple mysqld
servers
on the same machine. You might want to test a new
MySQL release while leaving your existing production setup undisturbed.
Or you may want to give different users access to different mysqld
servers that they manage themselves. (For example, you might be an
Internet Service Provider that wants to provide independent MySQL
installations for different customers.)
To run multiple servers on a single machine, each server must have unique values for several operating parameters. These can be set on the command line or in option files. See section 4.3 Specifying Program Options.
At least the following options must be different for each server:
--port=port_num
--port
controls the port number for TCP/IP connections.
--socket=path
--socket
controls the Unix socket file path on Unix and the name of the
named pipe on Windows. On Windows, it's necessary to specify distinct pipe names
only for those servers that support named pipe connections.
--shared-memory-base-name=name
--pid-file=path
If you use the following log file options, they must be different for each server:
--log=path
--log-bin=path
--log-update=path
--log-error=path
--log-isam=path
--bdb-logdir=path
Log file options are described in section 5.9.6 Log File Maintenance.
If you want more performance, you can also specify the following options differently for each server, to spread the load between several physical disks:
--tmpdir=path
--bdb-tmpdir=path
Having different temporary directories is also recommended, to make it easier to determine which MySQL server created any given temporary file.
Generally, each server should also use a different data directory, which is
specified using the --datadir=path
option.
Warning: Normally you should never have two servers that
update data in the same databases! This may lead to unpleasant
surprises if your operating system doesn't support fault-free system
locking!
If (despite this warning) you run multiple servers using
the same data directory and they have logging enabled, you must
use the appropriate options to specify log filenames that are
unique to each server. Otherwise, the servers will try to log to
the same files.
Please note that this kind of setup will only work with ISAM
,
MyISAM
and MERGE
tables, and not with any of the other
storage engines.
The warning against sharing a data directory among servers also applies in an NFS environment. Allowing multiple MySQL servers to access a common data directory over NFS is a bad idea!
lockd
daemon, but at the moment there is no platform that will perform
locking 100% reliably in every situation.
Make it easy for yourself: Forget about sharing a data directory among servers over NFS. A better solution is to have one computer that contains several CPUs and use an operating system that handles threads efficiently.
If you have multiple MySQL installations in different locations, normally
you can specify the base installation directory for each server with the
--basedir=path
option to cause each server to use a different data
directory, log files, and PID file. (The defaults for all these values are
determined relative to the base directory). In that case, the only other
options you need to specify are the --socket
and --port
options. For example, suppose that you install different versions of MySQL using
`tar' file binary distributions. These will install in different
locations, so you can start the server for each installation using the
command bin/mysqld_safe
under its corresponding base directory.
mysqld_safe
will determine the proper
--basedir
option to pass to mysqld
, and you need specify
only the --socket
and --port
options to mysqld_safe
.
(For versions of MySQL older than 4.0, use safe_mysqld
rather than mysqld_safe
.)
As discussed in the following sections, it is possible to start additional servers by setting environment variables or by specifying appropriate command-line options. However, if you need to run multiple servers on a more permanent basis, it will be more convenient to use option files to specify for each server those option values that must be unique to it.
You can run multiple servers on Windows by starting them manually from the command line, each with appropriate operating parameters. On Windows NT-based systems, you also have the option of installing several servers as Windows services and running them that way. General instructions for running MySQL servers from the command line or as services are given in section 2.3 Installing MySQL on Windows. This section describes how to make sure that you start each server with different values for those startup options that must be unique per server, such as the data directory. These options are described in section 5.10 Running Multiple MySQL Servers on the Same Machine.
To start multiple servers manually from the command line, you can specify the appropriate options on
the command line or in an option file. It's more convenient to place the
options in an option file, but it's necessary to make sure that each server
gets its own set of options. To do this, create an option file for each
server and tell the server the filename with a --defaults-file
option
when you run it.
Suppose that you want to run mysqld
on port 3307 with a
data directory of `C:\mydata1', and mysqld-max
on port 3308 with a
data directory of `C:\mydata2'. (To do this, make sure that before you
start the servers, each data directory exists and has its own copy of the
mysql
database that contains the grant tables.)
Then create two option files. For example, create one file named `C:\my-opts1.cnf' that looks like this:
[mysqld] datadir = C:/mydata1 port = 3307
Create a second file named `C:\my-opts2.cnf' that looks like this:
[mysqld] datadir = C:/mydata2 port = 3308
Then start each server with its own option file:
C:\> C:\mysql\bin\mysqld --defaults-file=C:\my-opts1.cnf C:\> C:\mysql\bin\mysqld-max --defaults-file=C:\my-opts2.cnf
On NT, each server will start in the foreground (no new prompt appears until the server exits later); you'll need to issue those two commands in separate console windows.
To shut down the servers, you must connect to the appropriate port number:
C:\> C:\mysql\bin\mysqladmin --port=3307 shutdown C:\> C:\mysql\bin\mysqladmin --port=3308 shutdown
Servers configured as just described will allow clients to connect over
TCP/IP. If your version of Windows supports named pipes and you also want
to allow named pipe connections, use the mysqld-nt
or
mysqld-max-nt
servers and specify options that enable the named pipe
and specify its name. Each server that supports named pipe connections must
use a unique pipe name. For example, the `C:\my-opts1.cnf' file might
be written like this:
[mysqld] datadir = C:/mydata1 port = 3307 enable-named-pipe socket = mypipe1
Then start the server this way:
C:\> C:\mysql\bin\mysqld-nt --defaults-file=C:\my-opts1.cnf
Modify `C:\my-opts2.cnf' similarly for use by the second server.
On NT-based systems, a MySQL server can be run as a Windows service. The procedures for installing, controlling, and removing a single MySQL service are described in section 2.3.12 Starting MySQL as a Windows Service.
As of MySQL 4.0.2, you can install multiple servers as services. In this case, you must make sure that each server uses a different service name in addition to all the other parameters that must be unique per server.
For the following instructions, assume that you want to run the mysqld-nt
server from two different versions of MySQL that are installed at
`C:\mysql-4.0.8' and `C:\mysql-4.0.17', respectively. (This might be
the case if you're running 4.0.8 as your production server, but want to test
4.0.17 before upgrading to it.)
The following principles apply when installing a MySQL service with the
--install
or --install-manual
option:
MySQL
and the server reads options from the [mysqld]
group in
the standard option files.
--install
option, the server ignores the [mysqld]
option
group and instead reads options from the group that has the same name as the
service. The server reads options from the standard option files.
--defaults-file
option after the service name,
the server ignores the standard option files and reads options only from the
[mysqld]
group of the named file.
Note: Before MySQL 4.0.17, only a server installed using the default service
name (MySQL
) or one installed explicitly with a service name of
mysqld
will read the [mysqld]
group in the standard option
files. As of 4.0.17, all servers read the [mysqld]
group if they read
the standard option files, even if they are installed using another service
name. This allows you to use the [mysqld]
group for options that should
be used by all MySQL services, and an option group named after each service
for use by the server installed with that service name.
Based on the preceding information, you have several ways to set up multiple services. The following instructions describe some examples. Before trying any of them, be sure that you shut down and remove any existing MySQL services first.
mysqld-nt
using the service
name of mysqld1
and the 4.0.17 mysqld-nt
using the service name mysqld2
.
In this case, you can use the [mysqld1]
group for 4.0.8 and the
[mysqld2]
group for 4.0.17.
For example, you can set up `C:\my.cnf' like this:
# options for mysqld1 service [mysqld1] basedir = C:/mysql-4.0.8 port = 3307 enable-named-pipe socket = mypipe1 # options for mysqld2 service [mysqld2] basedir = C:/mysql-4.0.17 port = 3308 enable-named-pipe socket = mypipe2Install the services as follows, using the full server pathnames to ensure that Windows registers the correct executable program for each service:
C:\> C:\mysql-4.0.8\bin\mysqld-nt --install mysqld1 C:\> C:\mysql-4.0.17\bin\mysqld-nt --install mysqld2To start the services, use the services manager, or use
NET START
with the appropriate service names:
C:\> NET START mysqld1 C:\> NET START mysqld2To stop the services, use the services manager, or use
NET STOP
with the appropriate service names:
C:\> NET STOP mysqld1 C:\> NET STOP mysqld2
--defaults-file
when you install the services to tell each server
what file to use. In this case, each file should list options using a
[mysqld]
group.
With this approach, to specify options for the 4.0.8 mysqld-nt
,
create a file `C:\my-opts1.cnf' that looks like this:
[mysqld] basedir = C:/mysql-4.0.8 port = 3307 enable-named-pipe socket = mypipe1For the 4.0.17
mysqld-nt
, create a file
`C:\my-opts2.cnf' that looks like this:
[mysqld] basedir = C:/mysql-4.0.17 port = 3308 enable-named-pipe socket = mypipe2Install the services as follows (enter each command on a single line):
C:\> C:\mysql-4.0.8\bin\mysqld-nt --install mysqld1 --defaults-file=C:\my-opts1.cnf C:\> C:\mysql-4.0.17\bin\mysqld-nt --install mysqld2 --defaults-file=C:\my-opts2.cnfTo use a
--defaults-file
option when you install a MySQL server as a
service, you must precede the option with the service name.
After installing the services, start and stop them the same way as in the
preceding example.
To remove multiple services, use mysqld --remove
for each one,
specifying a service name following the --remove
option. If the
service name is the default (MySQL
), you can omit it.
The easiest way is to run multiple servers on Unix is to compile them with different TCP/IP ports and Unix socket files so that each one is listening on different network interfaces. Also, by compiling in different base directories for each installation, that automatically results in different compiled-in data directory, log file, and PID file locations for each of your servers.
Assume that an existing server is configured for the default TCP/IP port
number (3306) and Unix socket file (`/tmp/mysql.sock'). To configure a
new server to have different operating parameters, use a configure
command something like this:
shell> ./configure --with-tcp-port=port_number \ --with-unix-socket-path=file_name \ --prefix=/usr/local/mysql-4.0.17
Here, port_number and file_name must be different from the
default TCP/IP port number and Unix socket file pathname, and the
--prefix
value should specify an installation directory different
than the one under which the existing MySQL installation is located.
If you have a MySQL server listening on a given port number, you can use the following command to find out what operating parameters it is using for several important configurable variables, including the base directory and Unix socket filename:
shell> mysqladmin --host=host_name --port=port_number variables
With the information displayed by that command, you can tell what option values not to use when configuring an additional server.
Note that if you specify localhost
as a hostname, mysqladmin
will default to using a Unix socket file connection rather than TCP/IP.
In MySQL 4.1, you can explicitly specify the connection protocol to use by
using the --protocol={TCP | SOCKET | PIPE | MEMORY}
option.
You don't have to compile a new MySQL server just to start with a different Unix socket file and TCP/IP port number. It is also possible to specify those values at runtime. One way to do so is by using command-line options:
shell> mysqld_safe --socket=file_name --port=port_number
To start a second server, provide different --socket
and
--port
option values, and pass a --datadir=path
option to
mysqld_safe
so that the server uses a different data directory.
Another way to achieve a similar effect is to use environment variables to set the Unix socket filename and TCP/IP port number:
shell> MYSQL_UNIX_PORT=/tmp/mysqld-new.sock shell> MYSQL_TCP_PORT=3307 shell> export MYSQL_UNIX_PORT MYSQL_TCP_PORT shell> mysql_install_db --user=mysql shell> mysqld_safe --datadir=/path/to/datadir &
This is a quick way of starting a second server to use for testing. The nice thing about this method is that the environment variable settings will apply to any client programs that you invoke from the same shell. Thus, connections for those clients automatically will be directed to the second server!
section F Environment Variables includes a list of other environment
variables you can use to affect mysqld
.
For automatic server execution, your startup script that is executed at boot time should execute the following command once for each server with an appropriate option file path for each command:
mysqld_safe --defaults-file=path
Each option file should contain option values specific to a given server.
On Unix,
the mysqld_multi
script is another way to start multiple servers.
See section 5.1.5 The mysqld_multi
Program for Managing Multiple MySQL Servers.
When you want to connect with a client program to a MySQL server that is listening to different network interfaces than those compiled into your client, you can use one of the following methods:
--host=host_name --port=port_number
to connect
via TCP/IP to a remote server, with --host=127.0.0.1
--port=port_number
to connect via TCP/IP to a local server, or with
--host=localhost --socket=file_name
to connect to a local server via
a Unix socket file or a Windows named pipe.
--protocol=tcp
to connect
via TCP/IP, --protocol=socket
to connect via a Unix socket file,
--protocol=pipe
to connect via a named pipe, or
--protocol=memory
to connect via shared memory. For TCP/IP
connections, you may also need to specify --host
and --port
options. For the other types of connections, you may need to specify
a --socket
option to specify a Unix socket file or named pipe name, or a
--shared-memory-base-name
option to specify the shared memory name.
Shared memory connections are supported only on Windows.
MYSQL_UNIX_PORT
and MYSQL_TCP_PORT
environment variables to point to the Unix socket file and TCP/IP port
number before you start your clients. If you normally use a specific socket
file or port number, you can place commands to set these environment
variables in your `.login' file so that they apply each time you log
in.
See section F Environment Variables.
[client]
group of an option file. For example, you can use
`C:\my.cnf' on Windows, or the `.my.cnf' file in your home
directory on Unix.
See section 4.3.2 Using Option Files.
mysql_real_connect()
call. You can also have the program read
option files by calling mysql_options()
.
See section 22.2.3 C API Function Descriptions.
DBD::mysql
module, you can read options
from MySQL option files. For example:
$dsn = "DBI:mysql:test;mysql_read_default_group=client;" . "mysql_read_default_file=/usr/local/mysql/data/my.cnf"; $dbh = DBI->connect($dsn, $user, $password);See section 22.4 MySQL Perl API. Other programming interfaces may provide similar capabilities for reading option files.
From version 4.0.1 on, MySQL Server features a query cache.
When in use, the query cache stores the text of a SELECT
query
together with the corresponding result that was sent to the client.
If the identical query is received later, the server retrieves
the results from the query cache rather than parsing and executing the
query again.
The query cache is extremely useful in an environment where (some) tables don't change very often and you have a lot of identical queries. This is a typical situation for many Web servers that generate a lot of dynamic pages based on database content.
Note: The query cache does not return stale data. When tables are modified, any relevant entries in the query cache are flushed.
Note: The query cache does not work in an environment where you
have many mysqld
servers updating the same MyISAM
tables.
Some performance data for the query cache follow. These results were generated by running the MySQL benchmark suite on a Linux Alpha 2 x 500MHz system with 2GB RAM and a 64MB query cache.
To disable the query cache at server startup, set the
query_cache_size
system variable to 0. By disabling the query cache
code, there is no noticeable overhead. Query cache capabilities can be
excluded from the server entirely by using the --without-query-cache
option to configure
when compiling MySQL.
This section describes how the query cache works when it is operational. section 5.11.3 Query Cache Configuration describes how to control whether or not it is operational.
Queries are compared before parsing, so the following two queries are regarded as different by the query cache:
SELECT * FROM tbl_name Select * from tbl_name
Queries must be exactly the same (byte for byte) to be seen as identical. In addition, query strings that are identical may be treated as different for other reasons. Queries that use different databases, different protocol versions, or different default character sets are considered different queries and are cached separately.
If a query result is returned from query cache, the server increments the
Qcache_hits
status variable, not Com_select
.
See section 5.11.4 Query Cache Status and Maintenance.
If a table changes, then all cached queries that use the table become
invalid and are removed from the cache. This includes queries that use
MERGE
tables that map to the changed table. A table can be changed
by many types of statements, such as INSERT
, UPDATE
,
DELETE
, TRUNCATE
, ALTER TABLE
, DROP TABLE
, or
DROP DATABASE
.
Transactional InnoDB
tables that have been changed are invalidated
when a COMMIT
is performed.
In MySQL 4.0, the query cache is disabled within transactions (it does
not return results). Beginning with MySQL 4.1.1, the query cache also
works within transactions when using InnoDB
tables (it uses the
table version number to detect whether or not its contents are still current).
Before MySQL 5.0, a query that begins with a leading comment might be cached, but could not be fetched from the cache. This problem is fixed in MySQL 5.0.
The query cache works for SELECT SQL_CALC_FOUND_ROWS ...
and
SELECT FOUND_ROWS()
type queries. FOUND_ROWS()
returns
the correct value even if the preceding query was fetched from the cache
because the number of found rows is also stored in the cache.
A query cannot be cached if it contains any of the following functions:
BENCHMARK()
| CONNECTION_ID()
| CURDATE()
|
CURRENT_DATE()
| CURRENT_TIME()
| CURRENT_TIMESTAMP()
|
CURTIME()
| DATABASE()
| ENCRYPT() with one parameter
|
FOUND_ROWS()
| GET_LOCK()
| LAST_INSERT_ID()
|
LOAD_FILE()
| MASTER_POS_WAIT()
| NOW()
|
RAND()
| RELEASE_LOCK()
| SYSDATE()
|
UNIX_TIMESTAMP() with no parameters
| USER()
|
A query also will not be cached under these conditions:
mysql
system database.
SELECT ... IN SHARE MODE SELECT ... INTO OUTFILE ... SELECT ... INTO DUMPFILE ... SELECT * FROM ... WHERE autoincrement_col IS NULLThe last form is not cached because it is used as the ODBC workaround for obtaining the last insert ID value. See section 23.1.14.1 How to Get the Value of an
AUTO_INCREMENT
Column in ODBC.
TEMPORARY
tables.
SELECT
privilege for all the involved databases and
tables. If this is not the case, the cached result is not used.
SELECT
Options
There are two query cache-related options that may be
specified in a SELECT
statement:
SQL_CACHE
query_cache_type
system variable is ON
or DEMAND
.
SQL_NO_CACHE
Examples:
SELECT SQL_CACHE id, name FROM customer; SELECT SQL_NO_CACHE id, name FROM customer;
The have_query_cache
server system variable indicates whether the query
cache is available:
mysql> SHOW VARIABLES LIKE 'have_query_cache'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | have_query_cache | YES | +------------------+-------+
Several other system variables control query cache operation.
These can be set in an option file or on the command line
when starting mysqld
.
The query cache-related system variables all have names that begin with
query_cache_
. They are described briefly in section 5.2.3 Server System Variables, with additional configuration information given here.
To set the size of the query cache, set the query_cache_size
system
variable. Setting it to 0 disables the query cache. The default cache size
is 0; that is, the query cache is disabled.
If the query cache is enabled, the query_cache_type
variable
influences how it works. This variable can be set to the following values:
0
or OFF
prevents caching or retrieval of cached
results.
1
or ON
allows caching except of those statements
that begin with SELECT SQL_NO_CACHE
.
2
or DEMAND
causes caching of only those statements
that begin with SELECT SQL_CACHE
.
Setting the GLOBAL
value of query_cache_type
determines query
cache behavior for all clients that connect after the change is made.
Individual clients can control cache behavior for their own connection by
setting the SESSION
value of query_cache_type
. For example, a
client can disable use of the query cache for its own queries like this:
mysql> SET SESSION query_cache_type = OFF;
To control the maximum size of individual query results that can be cached,
set the query_cache_limit
variable. The default value is 1MB.
The result of a query (the data sent to the client) is stored in the query
cache during result retrieval. Therefore the data usually is not handled in
one big chunk. The query cache allocates blocks for storing this data on
demand, so when one block is filled, a new block is allocated. Because
memory allocation operation is costly (timewise), the query cache allocates
blocks with a minimum size given by the query_cache_min_res_unit
system variable. When a query is executed, the last result block is trimmed
to the actual data size so that unused memory is freed.
Depending on the types of queries your server executes, you might find it
helpful to tune the value of query_cache_min_res_unit
:
query_cache_min_res_unit
is 4KB. This should
be adequate for most cases.
query_cache_min_res_unit
. The number of free blocks and queries
removed due to pruning are given by the values of the
Qcache_free_blocks
and Qcache_lowmem_prunes
status variables.
Qcache_total_blocks
and Qcache_queries_in_cache
status
variables), you can increase performance by increasing
query_cache_min_res_unit
. However, be careful to not make it too
large (see the previous item).
query_cache_min_res_unit
is present from MySQL 4.1.
You can check whether the query cache is present in your MySQL server using the following statement:
mysql> SHOW VARIABLES LIKE 'have_query_cache'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | have_query_cache | YES | +------------------+-------+
You can defragment the query cache to better utilize its memory
with the FLUSH QUERY CACHE
statement.
The statement does not remove any queries from the cache.
The RESET QUERY CACHE
statement removes all query results from the
query cache. The FLUSH TABLES
statement also does this.
To monitor query cache performance, use SHOW STATUS
to view
the cache status variables:
mysql> SHOW STATUS LIKE 'Qcache%'; +-------------------------+--------+ | Variable_name | Value | +-------------------------+--------+ | Qcache_free_blocks | 36 | | Qcache_free_memory | 138488 | | Qcache_hits | 79570 | | Qcache_inserts | 27087 | | Qcache_lowmem_prunes | 3114 | | Qcache_not_cached | 22989 | | Qcache_queries_in_cache | 415 | | Qcache_total_blocks | 912 | +-------------------------+--------+
Descriptions of each of these variables are given in section 5.2.4 Server Status Variables. Some uses for them are described here.
The total number of SELECT
queries is equal to:
Com_select + Qcache_hits + queries with errors found by parser
The Com_select
value is equal to:
Qcache_inserts + Qcache_not_cached + queries with errors found during columns/rights check
The query cache uses variable-length blocks, so Qcache_total_blocks
and Qcache_free_blocks
may indicate query cache memory fragmentation.
After FLUSH QUERY CACHE
, only a single free block remains.
Every cached query requires a minimum of two blocks (one for the query text and one or more for the query results). Also, every table that is used by a query requires one block. However, if two or more queries use the same table, only one block needs to be allocated.
The information provided by the Qcache_lowmem_prunes
status variable
can help you tune the query cache size. It counts the number of queries that
have been removed from the cache to free up memory for caching new queries.
The query cache uses a least recently used (LRU) strategy to decide which
queries to remove from the cache. Tuning information is given in section 5.11.3 Query Cache Configuration.
Replication capabilities allowing the databases on one MySQL server to be duplicated on another were introduced in MySQL 3.23.15. This chapter describes the various replication features provided by MySQL. It introduces replication concepts, shows how to set up replication servers, and serves as a reference to the available replication options. It also provides a list of frequently asked questions (with answers), and troubleshooting advice for solving problems.
For a description of the syntax of replication-related SQL statements, see section 13.6 Replication Statements.
We suggest that you visit our Web site at http://www.mysql.com often and read updates to this chapter. Replication is constantly being improved, and we update the manual frequently with the most current information.
MySQL 3.23.15 and up features support for one-way replication. One server acts as the master, while one or more other servers act as slaves. The master server writes updates to its binary log files, and maintains an index of the files to keep track of log rotation. These logs serve as a record of updates to be sent to slave servers. When a slave server connects to the master server, it informs the master of its last position within the logs since the last successfully propagated update. The slave catches up any updates that have occurred since then, and then blocks and waits for the master to notify it of new updates.
A slave server can also serve as a master if you want to set up chained replication servers.
Note that when you are using replication, all updates to the tables that are replicated should be performed on the master server. Otherwise, you must always be careful to avoid conflicts between updates that users make to tables on the master and updates that they make to tables on the slave.
One-way replication has benefits for robustness, speed, and system administration:
SELECT
queries may be sent to the slave to reduce the query
processing load of the master. Statements that modify data should still
be sent to the master so that the master and slave do not get out of sync.
This load-balancing strategy is effective if non-updating queries dominate,
but that is the normal case.
MySQL replication is based on the master server keeping track of all changes to your databases (updates, deletes, and so on) in the binary logs. Therefore, to use replication, you must enable binary logging on the master server. See section 5.9.4 The Binary Log.
Each slave server receives from the master the saved updates that the master has recorded in its binary log, so that the slave can execute the same updates on its copy of the data.
It is very important to realize that the binary log is simply a record starting from the fixed point in time at which you enable binary logging. Any slaves that you set up will need copies of the databases on your master as they existed at the moment you enabled binary logging on the master. If you start your slaves with databases that are not the same as what was on the master when the binary log was started, your slaves may fail.
One way to copy the master's data to the slave is to use the LOAD
DATA FROM MASTER
statement. Be aware that LOAD DATA FROM MASTER
is available only as of MySQL 4.0.0 and currently works only if all the
tables on the master are MyISAM
type. Also, this statement acquires a
global read lock, so no updates on the master are possible while the tables
are being transferred to the slave. When we implement lock-free hot table
backup (in MySQL 5.0), this global read lock will no longer be necessary.
Due to these limitations, we recommend that at this point you use
LOAD DATA FROM MASTER
only if the dataset on the master is relatively
small, or if a prolonged read lock on the master is acceptable. While the
actual speed of LOAD DATA FROM MASTER
may vary from system to system,
a good rule of thumb for how long it will take is 1 second per 1MB of data.
That is only a rough estimate, but you should get close to it if both
master and slave are equivalent to 700MHz Pentium performance and are
connected through a 100MBit/s network.
After the slave has been set up with a copy of the master's data, it
will simply connect to the master and wait for updates to process. If
the master goes away or the slave loses connectivity with your master,
it will keep trying to connect periodically until it is able to reconnect
and resume listening for updates. The retry interval is controlled by the
--master-connect-retry
option. The default is 60 seconds.
Each slave keeps track of where it left off. The master server has no knowledge of how many slaves there are or which ones are up to date at any given time.
MySQL replication capabilities are implemented using three threads (one
on the master server and two on the slave). When START SLAVE
is
issued, the slave creates an I/O thread. The I/O thread connects to the
master and asks it to send the statements recorded in its binary logs. The
master creates a thread to send the binary log contents to the slave.
This thread can be identified as the Binlog Dump
thread in the
output of SHOW PROCESSLIST
on the master. The slave I/O thread
reads what the master Binlog Dump
thread sends and simply copies
it to some local files in the slave's data directory called relay logs.
The third thread is the SQL thread, which the slave creates to read the
relay logs and execute the updates they contain.
In the preceding description, there are three threads per slave. For a master that has multiple slaves, it creates one thread for each currently connected slave, and each slave has its own I/O and SQL threads.
For versions of MySQL before 4.0.2, replication involves only two threads (one on the master and one on the slave). The slave I/O and SQL threads are combined as a single thread, and no relay log files are used.
The advantage of using two slave threads is that statement reading and execution are separated into two independent tasks. The task of reading statements is not slowed down if statement execution is slow. For example, if the slave server has not been running for a while, its I/O thread can quickly fetch all the binary log contents from the master when the slave starts, even if the SQL thread lags far behind and may take hours to catch up. If the slave stops before the SQL thread has executed all the fetched statements, the I/O thread has at least fetched everything so that a safe copy of the statements is locally stored in the slave's relay logs for execution when next the slave starts. This allows the binary logs to be purged on the master, because it no longer need wait for the slave to fetch their contents.
The SHOW PROCESSLIST
statement provides information that tells you
what is happening on the master and on the slave regarding replication.
The following example illustrates how the three threads show up in
SHOW PROCESSLIST
. The output format is that used by SHOW
PROCESSLIST
as of MySQL version 4.0.15, when the content of the
State
column was changed to be more meaningful compared to
earlier versions.
On the master server, the output from SHOW PROCESSLIST
looks like this:
mysql> SHOW PROCESSLIST\G *************************** 1. row *************************** Id: 2 User: root Host: localhost:32931 db: NULL Command: Binlog Dump Time: 94 State: Has sent all binlog to slave; waiting for binlog to be updated Info: NULL
Here, thread 2 is a replication thread for a connected slave. The information indicates that all outstanding updates have been sent to the slave and that the master is waiting for more updates to occur.
On the slave server, the output from SHOW PROCESSLIST
looks like this:
mysql> SHOW PROCESSLIST\G *************************** 1. row *************************** Id: 10 User: system user Host: db: NULL Command: Connect Time: 11 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 11 User: system user Host: db: NULL Command: Connect Time: 11 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL
This information indicates that thread 10 is the I/O thread that is communicating with the master server, and thread 11 is the SQL thread that is processing the updates stored in the relay logs. Currently, both threads are idle, waiting for further updates.
Note that the value in the Time
column can tell how late the slave
is compared to the master.
See section 6.9 Replication FAQ.
The following list shows the most common states you will see in the
State
column for the master's Binlog Dump
thread. If you
don't see any Binlog Dump
threads on a master server, replication
is not running. That is, no slaves currently are connected.
Sending binlog event to slave
Finished reading one binlog; switching to next binlog
Has sent all binlog to slave; waiting for binlog to be updated
Waiting to finalize termination
The following list shows the most common states you will see in the
State
column for a slave server I/O thread. Beginning with MySQL
4.1.1, this state also appears in the Slave_IO_State
column displayed
by the SHOW SLAVE STATUS
statement. This means that you can get a
good view of what is happening by using only SHOW SLAVE STATUS
.
Connecting to master
Checking master version
Registering slave on master
Requesting binlog dump
Waiting to reconnect after a failed binlog dump request
--master-connect-retry
option.
Reconnecting after a failed binlog dump request
Waiting for master to send event
slave_read_timeout
seconds, a timeout will occur.
At that point, the thread will consider the connection to be broken and
make an attempt to reconnect.
Queueing master event to the relay log
Waiting to reconnect after a failed master event read
master-connect-retry
seconds before attempting to reconnect.
Reconnecting after a failed master event read
Waiting for master to send event
.
Waiting for the slave SQL thread to free enough relay log space
relay_log_space_limit
value, and the relay
logs have grown so much that their combined size exceeds this value.
The I/O thread is waiting until the SQL
thread frees enough space by processing relay log contents so that it can
delete some relay log files.
Waiting for slave mutex on exit
The following list shows the most common states you will see in the
State
column for a slave server SQL thread:
Reading event from the relay log
Has read all relay log; waiting for the slave I/O thread to update it
Waiting for slave mutex on exit
The State
column for the I/O thread may also show the text of
a statement. This indicates that the thread has read an event from the
relay log, extracted the statement from it, and is executing it.
By default, relay logs are named using filenames of the form
`host_name-relay-bin.nnnnnn', where host_name is the name of the
slave server host and nnnnnn is a sequence number.
Successive relay log files are created using successive sequence numbers,
beginning with 000001
(001
in MySQL 4.0 or older).
The slave keeps track of relay logs currently in use in an index file.
The default relay log index filename is
`host_name-relay-bin.index'.
By default, these files are created in the slave's data directory.
The default filenames may be overridden with the --relay-log
and
--relay-log-index
server options.
See section 6.8 Replication Startup Options.
Relay logs have the same format as binary logs, so you can use
mysqlbinlog
to read them. A relay log is automatically deleted by
the SQL thread as soon as it has executed all its events and no longer needs
it). There is no explicit mechanism for deleting relay logs, because the SQL
thread takes care of doing so. However, from MySQL 4.0.14, FLUSH LOGS
rotates relay logs, which will influence when the SQL thread deletes them.
A new relay log is created under the following conditions:
FLUSH LOGS
or
mysqladmin flush-logs
. (This creates a new relay log only as of MySQL
4.0.14.)
max_relay_log_size
, if max_relay_log_size
> 0
max_binlog_size
, if max_relay_log_size
= 0
or MySQL is older than 4.0.14
A slave replication server creates two additional small files in the
data directory. These are status files and are named `master.info'
and `relay-log.info' by default. They contain information like
that shown in the output of the SHOW SLAVE STATUS
statement
(see section 13.6.2 SQL Statements for Controlling Slave Servers for a description of this statement).
As disk files, they survive a slave server's shutdown. The next time the
slave starts up, it reads these files to determine how far it has proceeded
in reading binary logs from the master and in processing its own relay logs.
The `master.info' file is updated by the I/O thread.
Before MySQL 4.1,
the correspondence between the lines in the file and the
columns displayed by SHOW SLAVE STATUS
is as follows:
Line | Description |
1 | Master_Log_File
|
2 | Read_Master_Log_Pos
|
3 | Master_Host
|
4 | Master_User
|
5 | Password (not shown by SHOW SLAVE STATUS )
|
6 | Master_Port
|
7 | Connect_Retry
|
As of MySQL 4.1, the file includes a line count and information about SSL options:
Line | Description |
1 | Number of lines in the file |
2 | Master_Log_File
|
3 | Read_Master_Log_Pos
|
4 | Master_Host
|
5 | Master_User
|
6 | Password (not shown by SHOW SLAVE STATUS )
|
7 | Master_Port
|
8 | Connect_Retry
|
9 | Master_SSL_Allowed
|
10 | Master_SSL_CA_File
|
11 | Master_SSL_CA_Path
|
12 | Master_SSL_Cert
|
13 | Master_SSL_Cipher
|
14 | Master_SSL_Key
|
The `relay-log.info' file is updated by the SQL thread.
The correspondence between the lines in the file and the
columns displayed by SHOW SLAVE STATUS
is as follows:
Line | Description |
1 | Relay_Log_File
|
2 | Relay_Log_Pos
|
3 | Relay_Master_Log_File
|
4 | Exec_Master_Log_Pos
|
When you back up your slave's data, you should back up these two small files
as well, along with the relay log files. They are needed to resume
replication after you restore the slave's data. If you lose the relay logs
but still have the `relay-log.info' file, you can check it to determine
how far the SQL thread has executed in the master binary logs. Then you
can use CHANGE MASTER TO
with the MASTER_LOG_FILE
and
MASTER_LOG_POS
options to tell the slave to re-read the binary
logs from that point. This requires that the binary logs still exist on
the master server.
If your slave is subject to replicating LOAD DATA INFILE
statements,
you should also back up any `SQL_LOAD-*' files that exist in the
directory that the slave uses for this purpose. The slave needs these files
to resume replication of any interrupted LOAD DATA INFILE
operations.
The directory location is specified using the --slave-load-tmpdir
option. Its default value, if not specified, is the value of the tmpdir
variable.
Here is a quick description of how to set up complete replication of your current MySQL server. It assumes that you want to replicate all your databases and have not configured replication before. You will need to shut down your master server briefly to complete the steps outlined here.
The procedure is written in terms of setting up a single slave, but you can use it to set up multiple slaves.
While this method is the most straightforward way to set up a slave, it is not the only one. For example, if you have a snapshot of the master's data, and the master has its server ID set and binary logging enabled, you can set up a slave without shutting down the master or even blocking updates to it. For more details, please see section 6.9 Replication FAQ.
If you want to administer a MySQL replication setup, we suggest that you read this entire chapter through and try all statements mentioned in section 13.6.1 SQL Statements for Controlling Master Servers and section 13.6.2 SQL Statements for Controlling Slave Servers. You should also familiarize yourself with replication startup options described in section 6.8 Replication Startup Options.
Note that this procedure and some of the replication SQL statements
in later sections refer to the SUPER
privilege. Prior to MySQL
4.0.2, use the PROCESS
privilege instead.
REPLICATION SLAVE
privilege.
If the account is used only for replication
(which is recommended), you don't need to grant any additional privileges.
Suppose that your domain is mydomain.com
and you want to create an
account with a username of repl
such that slave servers can use the
account to access the master server from any host in your domain using a
password of slavepass
.
To create the account, this use GRANT
statement:
mysql> GRANT REPLICATION SLAVE ON *.* -> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';For MySQL versions older than 4.0.2, the
REPLICATION SLAVE
privilege
does not exist. Grant the FILE
privilege instead:
mysql> GRANT FILE ON *.* -> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';If you plan to use the
LOAD TABLE FROM MASTER
or LOAD DATA
FROM MASTER
statements from the slave host, you will need to grant this
account additional privileges:
SUPER
and RELOAD
global privileges.
SELECT
privilege for all tables that
you want to load. Any master tables from which the account cannot
SELECT
will be ignored by LOAD DATA FROM MASTER
.
MyISAM
tables, flush all the tables and block
write statements by executing a FLUSH TABLES WITH READ LOCK
statement.
mysql> FLUSH TABLES WITH READ LOCK;Leave the client running from which you issue the
FLUSH TABLES
statement so that the read lock remains in effect. (If you exit the client,
the lock is released.) Then take a snapshot of the data on your master server.
The easiest way to create a snapshot is to use an archiving program to make a
binary backup of the databases in your master's data directory.
For example, use tar
on Unix, or PowerArchiver
, WinRAR
,
WinZip
, or any similar software on Windows.
To use tar
to create an archive that includes all
databases, change location into the master server's data directory, then
execute this command:
shell> tar -cvf /tmp/mysql-snapshot.tar .If you want the archive to include only a database called
this_db
, use
this command instead:
shell> tar -cvf /tmp/mysql-snapshot.tar ./this_dbThen copy the archive file to the `/tmp' directory on the slave server host. On that machine, change location into the slave's data directory, and unpack the archive file using this command:
shell> tar -xvf /tmp/mysql-snapshot.tarYou may not want to replicate the
mysql
database if the slave
server has a different set of user accounts from those that exist on the
master. In this case, you should exclude it from the archive. You also
need not include any log files in the archive, or the `master.info'
or `relay-log.info' files.
While the read lock placed by FLUSH TABLES WITH READ LOCK
is in effect,
read the value of the current binary log name and offset on the master:
mysql > SHOW MASTER STATUS; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | mysql-bin.003 | 73 | test | manual,mysql | +---------------+----------+--------------+------------------+The
File
column shows the name of the log, while Position
shows
the offset. In this example, the binary log value is
mysql-bin.003
and the offset is 73. Record the values. You will need
to use them later when you are setting up the slave. They represent the
replication coordinates at which the slave should begin processing new updates
from the master.
After you have taken the snapshot and recorded the log name and offset,
you can re-enable write activity on the master:
mysql> UNLOCK TABLES;If you are using
InnoDB
tables, ideally you should use the InnoDB Hot
Backup
tool. It takes a consistent snapshot without acquiring any locks on
the master server, and records the log name and offset corresponding to the
snapshot to be later used on the slave. InnoDB Hot Backup
is a non-free
(commercial) additional tool that is not included in the standard MySQL distribution.
See the InnoDB Hot Backup
home page at http://www.innodb.com/manual.php
for detailed information and screenshots.
Without the Hot Backup
tool, the quickest way to take a binary snapshot
of InnoDB
tables is to shut down the master server and copy the
InnoDB
data files, log files, and table definition files (`.frm'
files). To record the current log file name and offset, you should issue
the following statements before you shut down the server:
mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS;Then record the log name and the offset from the output of
SHOW MASTER
STATUS
as was shown earlier. After recording the log name and the offset,
shut down the server without unlocking the tables to make sure that the
server goes down with the snapshot corresponding to the current log file
and offset:
shell> mysqladmin -u root shutdownAn alternative that works for both
MyISAM
and InnoDB
tables is to take an SQL dump of the master instead of a binary copy as
described in the preceding discussion. For this, you can use mysqldump
--master-data
on your master and later load the SQL dump file into your
slave. However, this is slower than doing a binary copy.
If the master has been previously running without --log-bin
enabled,
the log name and position values displayed by SHOW MASTER STATUS
or mysqldump --master-data
will be empty. In that case, the values
that you will need to use later when specifying the slave's log file and
position are the empty string (''
) and 4
.
[mysqld]
section of the `my.cnf' file on
the master host includes a log-bin
option. The section should also
have a server-id=master_id
option, where master_id
must be
a positive integer value from 1 to 2^32 - 1. For example:
[mysqld] log-bin=mysql-bin server-id=1If those options are not present, add them and restart the server.
[mysqld] server-id=slave_idThe
slave_id
value, like the master_id
value, must
be a positive integer value from 1 to 2^32 - 1. In addition, it is very
important that the ID of the slave be different from the ID of the
master. For example:
[mysqld] server-id=2If you are setting up multiple slaves, each one must have a unique
server-id
value that differs from that of the master and from each
of the other slaves. Think of server-id
values as something similar
to IP addresses: These IDs uniquely identify each server instance in the
community of replication partners.
If you don't specify a server-id
value, it will be set to 1 if
you have not defined master-host
, else it will be set to 2. Note
that in the case of server-id
omission, a master will refuse
connections from all slaves, and a slave will refuse to connect to a
master. Thus, omitting server-id
is good only for backup with a
binary log.
mysqldump
, start the slave first (see next
step).
--skip-slave-start
option so that it
doesn't immediately try to connect to its master.
You also may want to start the slave server with the
--log-warnings
option (enabled by default as of MySQL 4.0.19 and 4.1.2),
to get more messages in the error log about
problems (for example, network or connection problems).
As of MySQL 4.0.21 and 4.1.3, aborted connections are not logged to the error
log unless the value is greater than 1.
mysqldump
, load
the dump file into the slave server:
shell> mysql -u root -p < dump_file.sql
mysql> CHANGE MASTER TO -> MASTER_HOST='master_host_name', -> MASTER_USER='replication_user_name', -> MASTER_PASSWORD='replication_password', -> MASTER_LOG_FILE='recorded_log_file_name', -> MASTER_LOG_POS=recorded_log_position;The following table shows the maximum length for the string options:
MASTER_HOST | 60 |
MASTER_USER | 16 |
MASTER_PASSWORD | 32 |
MASTER_LOG_FILE | 255 |
mysql> START SLAVE;
After you have performed this procedure, the slave should connect to the master and catch up on any updates that have occurred since the snapshot was taken.
If you have forgotten to set the server-id
value for the master, slaves will
not be able to connect to it.
If you have forgotten to set the server-id
value for the slave, you will get
the following error in its error log:
Warning: You should set server-id to a non-0 value if master_host is set; we force server id to 2, but this MySQL server will not act as a slave.
You will also find error messages in the slave's error log if it is not able to replicate for any other reason.
Once a slave is replicating, you will find in its data directory one
file named
`master.info' and another named `relay-log.info'.
The slave uses these two files to keep track of how much
of the master's binary log it has processed. Do not remove or
edit these files, unless you really know what you are doing and understand
the implications. Even in that case,
it is preferred that you use the CHANGE MASTER TO
statement.
Note: The content of `master.info' overrides some options specified on the command line or in `my.cnf'. See section 6.8 Replication Startup Options for more details.
Once you have a snapshot, you can use it to set up other slaves by following the slave portion of the procedure just described. You do not need to take another snapshot of the master; you can use the same one for each slave.
The original binary log format was developed in MySQL 3.23. It changed in MySQL 4.0, and again in MySQL 5.0. This has consequences when you upgrade servers in a replication setup, as described in section 6.6 Upgrading a Replication Setup.
As far as replication is concerned, any MySQL 4.1.x version and any 4.0.x version are identical, because they all use the same binary log format. Thus, any servers from these versions are compatible, and replication between them should work seamlessly. The exceptions to this compatibility is that versions from MySQL 4.0.0 to 4.0.2 were very early development versions that should not be used anymore. (These were the alpha versions in the 4.0 release series. Compatibility for them is still documented in the manual included with their distributions.)
The following table indicates master/slave replication compatibility between different versions of MySQL.
Master | Master | Master | ||
3.23.33 and up | 4.0.3 and up or any 4.1.x | 5.0.0 | ||
Slave | 3.23.33 and up | yes | no | no |
Slave | 4.0.3 and up | yes | yes | no |
Slave | 5.0.0 | yes | yes | yes |
As a general rule, we recommended using recent MySQL versions, because replication capabilities are continually being improved. We also recommend using the same version for both the master and the slave.
The preceding information pertains the replication compatibility at the protocol level. There can also be SQL-level compatibility constraints, as discussed in section 6.7 Replication Features and Known Problems.
When you upgrade servers that participate in a replication setup, the procedure for upgrading depends on the current server versions and the version to which you are upgrading.
This section applies to upgrading replication from MySQL 3.23 to 4.0 or 4.1. A 4.0 server should be 4.0.3 or newer, as mentioned in section 6.5 Replication Compatibility Between MySQL Versions.
When you upgrade a master from MySQL 3.23 to MySQL 4.0 or 4.1, you should first ensure that all the slaves of this master are at 4.0 or 4.1. If that is not the case, you should first upgrade your slaves: Shut down each one, upgrade it, restart it, and restart replication.
The upgrade can safely be done using the following procedure, assuming that you have a 3.23 master to upgrade and the slaves are 4.0 or 4.1. Note that after the master has been upgraded, you should not restart replication using any old 3.23 binary logs, because this will unfortunately confuse the 4.0 or 4.1 slave.
FLUSH TABLES WITH READ LOCK
statement.
SHOW MASTER STATUS
on the master to obtain its current binary log
file and position. Then, for each slave, use those values with a SELECT
MASTER_POS_WAIT()
statement. The statement will block on the slave and return
when the slave has caught up. Then run STOP SLAVE
on the slave.
SHOW MASTER STATUS
statement on the master. Then issue these
statements on each slave:
mysql> CHANGE MASTER TO MASTER_LOG_FILE='binary_log_name', -> MASTER_LOG_POS=4; mysql> START SLAVE;
This section applies to upgrading replication from MySQL 3.23, 4.0, or 4.1 to 5.0.0. A 4.0 server should be 4.0.3 or newer, as mentioned in section 6.5 Replication Compatibility Between MySQL Versions.
First, note that MySQL 5.0.0 is an alpha release. It is intended to work
better than older versions (easier upgrade, replication of some important
session variables such as sql_mode
; see section D.1.4 Changes in release 5.0.0 (22 Dec 2003: Alpha)). However
it has not yet been extensively tested. As with any alpha release, we
recommend that you not use it in critical production environments yet.
When you upgrade a master from MySQL 3.23, 4.0, or 4.1 to 5.0.0, you should first ensure that all the slaves of this master are 5.0.0. If that's not the case, you should first upgrade your slaves. To upgrade each slave, just shut it down, upgrade it to 5.0.0, restart it, and restart replication. The 5.0.0 slave will be able to read its old relay logs that were written before the upgrade and execute the statements they contain. Relay logs created by the slave after the upgrade will be in 5.0.0 format.
After the slaves have been upgraded, shut down your master, upgrade it to 5.0.0, and restart it. The 5.0.0 master will be able to read its old binary logs that were written before the upgrade and send them to the 5.0.0 slaves. The slaves will recognize the old format and handle it properly. Binary logs created by master after the upgrade will be in 5.0.0 format. These too will be recognized by the 5.0.0 slaves.
In other words, there are no measures to take when upgrading to 5.0.0, except that slaves must be 5.0.0 before you can upgrade the master to 5.0.0. Note that downgrading from 5.0.0 to older versions does not work so automatically: You must ensure that any 5.0.0 binary logs or relay logs have been fully processed, so that you can remove them before proceeding with the downgrade.
In general, replication compatibility at the SQL level requires that any
features used be supported by both the master and the slave servers. For
example, the GROUP_CONCAT()
function is available in MySQL 4.1 and
up. If you use this function on the master server, you cannot replicate to
a slave server that is older than MySQL 4.1.
The following list provides details about
what is supported and what is not.
Additional InnoDB
-specific information about replication is given in
section 15.7.5 InnoDB
and MySQL Replication.
AUTO_INCREMENT
,
LAST_INSERT_ID()
, and TIMESTAMP
values.
USER()
, UUID()
, and LOAD_FILE()
functions
are replicated without changes and will thus not work reliably on the
slave. This is also true for CONNECTION_ID()
in slave versions
older than 4.1.1.
The new PASSWORD()
function in MySQL 4.1 is well
replicated in masters from 4.1.1 and up; your slaves also must be 4.1.1 or above
to replicate it. If you have older slaves and need to replicate
PASSWORD()
from your 4.1.x master, you must start your master
with the --old-password
option, so that it uses the old implementation
of PASSWORD()
. (Note that the PASSWORD()
implementation in
MySQL 4.1.0 differs from every other version of MySQL. It is best to avoid
4.1.0 in a replication situation.)
FOREIGN_KEY_CHECKS
variable is replicated as of MySQL 4.0.14.
The SQL_MODE
, UNIQUE_CHECKS
, and SQL_AUTO_IS_NULL
variables are replicated as of 5.0.0. The table_type
variables is not
yet replicated, which is a good thing for replication between different storage
engines.
--default-character-set
, --default-collation
) on the
master and the slave. Otherwise, you may get duplicate-key errors on
the slave, because a key that is regarded as unique in the master's character
set may not be unique in the slave's character set.
Second, if the master is strictly older than MySQL 4.1.3, the character set of
the session should never be made different from its global value (in other words, don't
use SET NAMES
, SET CHARACTER SET
etc) because this character set
change will not be known to the slave. If the master is 4.1.3 or newer, and the
slave too, the session can freely set its local value of character set
variables (NAMES
, CHARACTER SET
, COLLATION_CLIENT
,
COLLATION_SERVER
etc) as these settings will be written to the binary
log and then known to the slave. The session will however be prevented from
changing the global value of these; as said previously the master and
slave must always have identical global character set values. There also is one
last limitation: if on the master you have databases with different character
sets from the global collation_server
value, you should design your
CREATE TABLE
statements so that they don't implicitly rely on the
default database's character set, because there currently is a bug (Bug #2326);
a good workaround is to explicitly state the character set and collation in a
clause of the CREATE TABLE
.
NOW()
or FROM_UNIXTIME()
functions, won't be replicated properly). One could set time zone in which
MySQL server runs by using --timezone=timezone_name
option of
mysqld_safe
script or by setting TZ
environment variable.
Also starting from version 4.1.3 both master and slave should have same
default connection time zone set, i.e. --default-time-zone
parameter
should have the same value for both master and slave.
InnoDB
master table as a MyISAM
slave table. However, if you do
this, you will have problems if
the slave is stopped in the middle of a BEGIN/COMMIT
block, because
the slave will restart at the beginning of the BEGIN
block.
This issue is on our TODO and will be fixed in the near future.
@var_name
) are badly replicated in 3.23 and 4.0. This is fixed
in 4.1. Note that user variable names are case insensitive starting from
MySQL 5.0. You should take this into account when setting up replication
between 5.0 and an older version.
DATA DIRECTORY
or INDEX DIRECTORY
clause is used in a
CREATE TABLE
statement on the master server, the clause is also used
on the slave. This can cause problems if no corresponding directory exists
in the slave host filesystem or exists but is not accessible to the slave
server. Starting from MySQL 4.0.15, there is a sql_mode
option
called NO_DIR_IN_CREATE
. If the slave server is run with its SQL mode
set to include this option, it will simply ignore the clauses before
replicating the CREATE TABLE
statement. The result is that the
MyISAM
data and index files are created in the table's database
directory.
LOAD DATA INFILE
is interrupted in the middle (integrity
constraint violation, killed connection...), the slave will skip this
LOAD DATA INFILE
entirely. It means that if this command permanently
inserted/updated some table records before being interrupted, these
modifications won't be replicated to the slave. This will be fixed when MySQL
features a record-level binary log format, in development.
FLUSH
, ANALYZE TABLE
, OPTIMIZE
TABLE
, and REPAIR TABLE
statements are not written to the binary
log and thus are not replicated to the slaves. This is not normally
a problem because these statements do not modify table data. However,
it can cause difficulties under certain circumstances. If you replicate
the privilege tables in the mysql
database and update those tables
directly without using the GRANT
statement, you
must issue a FLUSH PRIVILEGES
statement on your slaves to put
the new privileges into effect. Also if you use
FLUSH TABLES
when renaming a MyISAM
table that is part of a
MERGE
table, you will have to issue FLUSH TABLES
manually on the slaves.
As of MySQL 4.1.1, these statements are written to the binary log
(unless you specify NO_WRITE_TO_BINLOG
, or its alias LOCAL
).
Exceptions are that FLUSH LOGS
, FLUSH MASTER
,
FLUSH SLAVE
, and FLUSH TABLES WITH READ LOCK
are not logged in
any case. (Any of them may cause problems if replicated to a slave.)
For a syntax example, see section 13.5.5.2 FLUSH
Syntax.
SELECT
queries to different
slaves.
MEMORY
(HEAP
) tables become empty.
As of MySQL 4.0.18, the master replicates this effect as follows:
The first time that the master uses each MEMORY
table after startup,
it notifies slaves that the table needs to be emptied by writing a
DELETE FROM
statement for the table to its binary log.
See section 14.3 The MEMORY
(HEAP
) Storage Engine
for more details.
STOP SLAVE
statement.
SHOW STATUS
to check the value of the Slave_open_temp_tables
variable.
mysqladmin shutdown
command to
shut down the slave.
START SLAVE
.
--log-slave-updates
option specified.
Note, however, that many statements will not work correctly in this kind of
setup unless your client code is written to take care of the potential
problems that can occur from updates that occur in different sequence
on different servers.
This means that you can create a setup such as this:
A -> B -> C -> AServer IDs are encoded in the binary log events, so server A will know when an event that it reads was originally created by itself and will not execute the event (unless server A was started with the
--replicate-same-server-id
option, which is meaningful only in rare
setups). Thus, there will be no infinite loop. But this circular
setup will work only if you perform no conflicting
updates between the tables. In other words, if you insert data in both
A and C, you should never insert a row in A that may have a key that
conflicts with a row inserted in C. You should also not update
the same rows on two servers if the order in which the updates are
applied is significant.
START SLAVE
.
--master-connect-retry
option.)
The slave will also be able to deal with
network connectivity outages. However, the slave will notice the
network outage only after receiving no data from the master for
slave_net_timeout
seconds. If your outages are short, you may want
to decrease slave_net_timeout
.
See section 5.2.3 Server System Variables.
InnoDB
tables and the --innodb-safe-binlog
option on the
master. See section 5.9.4 The Binary Log.
MyISAM
tables, it is possible
to have a statement that only partially updates a table and returns an
error code. This can happen, for example, on a multiple-row insert that has
one row violating a key constraint, or if a long update statement is killed
after updating some of the rows. If that happens on the master, the slave
thread will exit and wait for the database administrator
to decide what to do about it unless
the error code is legitimate and the statement execution results in the same
error code. If this error code validation behavior is not desirable, some or
all errors can be masked out (ignored) with the --slave-skip-errors
option. This option is available starting with MySQL 3.23.47.
BEGIN/COMMIT
segment, updates to the binary log may be out of sync
if some thread changes the non-transactional table before the
transaction commits. This is because the transaction is written to the
binary log only when it is committed.
COMMIT
or not written at all if you use
ROLLBACK
. You must take this into account when updating both
transactional tables and non-transactional tables within the same
transaction. (This is true not only for replication, but also if you are
using binary logging for backups.) In version 4.0.15, we changed the logging
behavior for transactions that mix updates to transactional and
non-transactional tables, which solves the problems (order of statements is
good in the binary log, and all needed statements are written to the binary log
even in case of ROLLBACK
). The problem that remains is when a second
connection updates the non-transactional table while the first connection's
transaction is not finished yet; wrong order can still occur, because the
second connection's update will be written immediately after it is done.
LOAD DATA INFILE
from a 3.23 master, the
values of the Exec_Master_Log_Pos
and Relay_Log_Space
columns of
SHOW SLAVE STATUS
become incorrect.
The incorrectness of Exec_Master_Log_Pos
will cause a problem when you
stop and restart replication; so it is a good idea to correct the value before
this, by doing FLUSH LOGS
on the master.
These bugs are fixed in MySQL 5.0.0 slaves.
The following table lists replication problems in MySQL 3.23 that are fixed in MySQL 4.0:
LOAD DATA INFILE
is handled properly, as long as the data file
still resides on the master server at the time of update
propagation.
LOAD DATA LOCAL INFILE
is no longer skipped on the slave as it
was in 3.23.
RAND()
in updates does not replicate properly.
Use RAND(some_non_rand_expr)
if you are replicating updates with
RAND()
. You can, for example, use UNIX_TIMESTAMP()
as the
argument to RAND()
.
On both the master and the slave, you must use the server-id
option
to establish a unique replication ID for each server. You should pick a unique
positive integer in the range from 1 to 2^32 - 1 for each master and slave.
Example: server-id=3
The options that you can use on the master server for controlling binary logging are described in section 5.9.4 The Binary Log.
The following table describes the options you can use on slave replication servers. You can specify them on the command line or in an option file.
Some slave server replication options are handled in a special way, in the sense that they are ignored if a `master.info' file exists when the slave starts and contains values for the options. The following options are handled this way:
--master-host
--master-user
--master-password
--master-port
--master-connect-retry
As of MySQL 4.1.1, the following options also are handled specially:
--master-ssl
--master-ssl-ca
--master-ssl-capath
--master-ssl-cert
--master-ssl-cipher
--master-ssl-key
The `master.info' file format in 4.1.1 changed to include values corresponding to the SSL options. In addition, the 4.1.1 file format includes as its first line the number of lines in the file. If you upgrade an older server to 4.1.1, the new server upgrades the `master.info' file to the new format automatically when it starts. However, if you downgrade a 4.1.1 or newer server to a version older than 4.1.1, you should manually remove the first line before starting the older server for the first time. Note that, in this case, the downgraded server no longer can use an SSL connection to communicate with the master.
If no `master.info' file exists when the slave server starts,
it uses values for those options that are specified in option files
or on the command line. This will occur when you start the server
as a replication slave for the very first time, or when you have run
RESET SLAVE
and shut down and restarted the slave server.
If the `master.info' file exists when the slave server starts, the server ignores those options. Instead, it uses the values found in the `master.info' file.
If you restart the slave server with different values of the startup options
that correspond to values in the `master.info' file, the different
values have no effect, because the server continues to use the
`master.info' file. To use different values, you must either restart
after removing the `master.info' file or (preferably) use the
CHANGE MASTER TO
statement to reset the values while the slave is
running.
Suppose that you specify this option in your `my.cnf' file:
[mysqld] master-host=some_host
The first time you start the server as a replication slave, it reads and
uses that option from the `my.cnf' file. The server then records the
value in the `master.info' file. The next time you start the server,
it reads the master host value from the `master.info' file only and
ignores the value in the option file. If you modify the `my.cnf' file
to specify a different master host of some_other_host
, the change
still will have no effect. You should use CHANGE MASTER TO
instead.
Because the server gives an existing `master.info' file precedence
over the startup options just described, you might prefer not to use startup
options for these values at all, and instead specify them by using the
CHANGE MASTER TO
statement.
See section 13.6.2.1 CHANGE MASTER TO
Syntax.
This example shows a more extensive use of startup options to configure a slave server:
[mysqld] server-id=2 master-host=db-master.mycompany.com master-port=3306 master-user=pertinax master-password=freitag master-connect-retry=60 report-host=db-slave.mycompany.com
The following list describes startup options for controlling replication:
Many of these options can be reset while the server is running by using the
CHANGE MASTER TO
statement. Others, such as the --replicate-*
options, can be set only when the slave server starts. We plan to fix this.
--log-slave-updates
--log-bin
option to
enable binary logging. --log-slave-updates
is used when you want to
chain replication servers. For example, you might want a setup like this:
A -> B -> CThat is, A serves as the master for the slave B, and B serves as the master for the slave C. For this to work, B must be both a master and a slave. You must start both A and B with
--log-bin
to enable binary logging,
and B with the --log-slave-updates
option.
--log-warnings
--skip-log-warnings
.
As of MySQL 4.0.21 and 4.1.3, aborted connections are not logged to the error
log unless the value is greater than 1.
This option is not limited to replication use only. It produces warnings
across a spectrum of server activities.
--master-connect-retry=seconds
--master-host=host
--master-info-file=file_name
--master-password=password
--master-port=port_number
configure
options, this should be 3306.
--master-ssl
--master-ssl-ca=file_name
--master-ssl-capath=directory_name
--master-ssl-cert=file_name
--master-ssl-cipher=cipher_list
--master-ssl-key=file_name
--ssl
,
--ssl-ca
,
--ssl-capath
,
--ssl-cert
,
--ssl-cipher
,
--ssl-key
options described in
section 5.6.7.5 SSL Command-Line Options.
The values in the `master.info' file take precedence if they can be read.
These options are operational as of MySQL 4.1.1.
--master-user=username
REPLICATION SLAVE
privilege. (Prior to MySQL 4.0.2, it must have the
FILE
privilege instead.)
The value in the `master.info' file takes precedence if it can be read.
If the master user is not set, user test
is assumed.
--max-relay-log-size=#
--read-only
SUPER
privilege. This can be useful to ensure
that a slave server accepts no updates from clients.
This option is available as of MySQL 4.0.14.
--relay-log=file_name
host_name-relay-bin.nnnnnn
, where host_name is the name of
the slave server host and nnnnnn indicates that relay logs are
created in numbered sequence.
You can specify the option to create hostname-independent relay log names, or
if your relay logs tend to be big (and you don't want to decrease
max_relay_log_size
) and you need to put them in some area
different from the data directory, or if you want to increase speed by
balancing load between disks.
--relay-log-index=file_name
host_name-relay-bin.index
, where host_name is the name of
the slave server.
--relay-log-info-file=file_name
--relay-log-purge={0|1}
SET GLOBAL
relay_log_purge
.
This option is available as of MySQL 4.1.1.
--relay-log-space-limit=#
--relay-log-space-limit
to less than twice the value
of --max-relay-log-size
(or --max-binlog-size
if
--max-relay-log-size
is 0). In that case, there is a chance that the
I/O thread will wait for free space because --relay-log-space-limit
is exceeded, but the SQL thread will have no relay log to purge and be
unable to satisfy the I/O thread. This forces the I/O thread to temporarily
ignore --relay-log-space-limit
.
--replicate-do-db=db_name
USE
)
is db_name.
To specify more than one database, use this option multiple
times, once for each database. Note that this will not replicate
cross-database statements such as UPDATE some_db.some_table
SET foo='bar'
while having selected a different database or no database. If you
need cross-database updates to work, make sure that you have MySQL 3.23.28 or
later, and use --replicate-wild-do-table=db_name.%
.
Please read the notes that follow this option list.
An example of what does not work as you might expect: If the slave is
started with --replicate-do-db=sales
and you issue the following
statements on the master, the UPDATE
statement will not be
replicated:
USE prices; UPDATE sales.january SET amount=amount+1000;If you need cross-database updates to work, use
--replicate-wild-do-table=db_name.%
instead.
The main reason for this ``just-check-the-default-database''
behavior is that it's difficult from the statement
alone to know whether or not it should be replicated (for example, if you
are using multiple-table DELETE
or multiple-table UPDATE
statements
that go across multiple databases). It's also very fast to just check
the default database.
--replicate-do-table=db_name.tbl_name
--replicate-do-db
.
Please read the notes that follow this option list.
--replicate-ignore-db=db_name
USE
)
is db_name. To specify more than one database to
ignore, use this option multiple times, once for each database.
You should not use this option if you are using cross-database updates
and you don't want these updates to be replicated.
Please read the notes that follow this option list.
An example of what does not work as you might expect: If the slave is
started with --replicate-ignore-db=sales
and you issue the following
statements on the master, the UPDATE
statement will be replicated:
USE prices; UPDATE sales.january SET amount=amount+1000;If you need cross-database updates to work, use
--replicate-wild-ignore-table=db_name.%
instead.
--replicate-ignore-table=db_name.tbl_name
--replicate-ignore-db
.
Please read the notes that follow this option list.
--replicate-wild-do-table=db_name.tbl_name
LIKE
pattern-matching operator. To specify
more than one table, use this option multiple times, once for each
table. This will work for cross-database updates.
Please read the notes that follow this option list.
Example: --replicate-wild-do-table=foo%.bar%
will replicate only
updates that use a table where the database name starts with foo
and the table name starts with bar
.
If the table name pattern is %
, it matches any table name and the
option also applies to database-level statements (CREATE DATABASE
, DROP DATABASE
, and
ALTER DATABASE
).
For example, if you use --replicate-wild-do-table=foo%.%
,
database-level statements are replicated
if the database name matches the pattern foo%
.
To include literal wildcard characters in the database or table name
patterns, escape them with a backslash. For example, to replicate all tables
of a database that is named my_own%db
, but not replicate tables
from the my1ownAABCdb
database, you should escape the `_' and
`%' characters like this: --replicate-wild-do-table=my\_own\%db
.
If you're using the option on the command line, you might need to double
the backslashes or quote the option value, depending on your command
interpreter. For example, with the bash
shell, you would need to
type --replicate-wild-do-table=my\\_own\\%db
.
--replicate-wild-ignore-table=db_name.tbl_name
--replicate-wild-ignore-table=foo%.bar%
will not replicate
updates that use a table where the database name starts with foo
and the table name starts with bar
.
For information about how matching works, see the description of
the --replicate-wild-do-table
option.
The rules for including literal wildcard characters in the option value
are the same as for
--replicate-wild-ignore-table
as well.
--replicate-rewrite-db=from_name->to_name
USE
)
to to_name if it was from_name on the master.
Only statements involving tables are affected
(not statements such as CREATE DATABASE
, DROP DATABASE
,
and ALTER DATABASE
),
and only if from_name was the default database on the master.
This will not work for cross-database updates.
Note that the database name translation is done before --replicate-*
rules are tested.
If you use this option on the command line and the `>' character is
special to your command interpreter, quote the option value. For example:
shell> mysqld --replicate-rewrite-db="olddb->newdb"
--replicate-same-server-id
--log-slave-updates
is used.
Be careful that starting from MySQL 4.1, by default the slave I/O thread does
not even write binary log events to the relay log if they have the slave's server
id (this optimization helps save disk usage compared to 4.0). So if you want to
use --replicate-same-server-id
in 4.1 versions, be sure to start the
slave with this option before you make the slave read its own events which you
want the slave SQL thread to execute.
--report-host=host
SHOW SLAVE
HOSTS
on the master server. Leave the value unset if you do not want the
slave to register itself with the master. Note that it is not sufficient for
the master to simply read the IP number of the slave from the TCP/IP socket
after the slave connects. Due to NAT
and other routing issues, that IP
may not be valid for connecting to the slave from the master or other hosts.
This option is available as of MySQL 4.0.0.
--report-port=port_number
--skip-slave-start
START SLAVE
statement.
--slave_compressed_protocol={0|1}
--slave-load-tmpdir=file_name
tmpdir
system variable.
When the slave SQL thread replicates a LOAD DATA INFILE
statement, it
extracts the to-be-loaded file from the relay log into temporary files,
then loads these into the table. If the file loaded on the master was
huge, the temporary files on the slave will be huge, too. Therefore, it might
be advisable to use this option to tell the slave to put temporary files in
a directory located in some filesystem that has a lot of available space.
In that case, you may also use the --relay-log
option to place
the relay logs in that filesystem, because the relay logs
will be huge as well.
--slave-load-tmpdir
should point to a disk-based filesystem, not a
memory-based one: The slave needs the
temporary files used to replicate LOAD DATA INFILE
to survive a
machine's restart.
The directory also should not be one that is cleared by the operating system
during the system startup process.
--slave-net-timeout=seconds
--master-connect-retry
option.
--slave-skip-errors= [err_code1,err_code2,... | all]
SHOW SLAVE STATUS
.
The server error codes are listed in section 24 Error Handling in MySQL.
You can (but should not) also use the very non-recommended value of all
which will ignore all error messages and keep barging along regardless of what
happens. Needless to say, if you use it, we make no promises regarding your
data integrity. Please do not complain if your data on the slave is not
anywhere close to what it is on the master in this case. You have been
warned.
Examples:
--slave-skip-errors=1062,1053 --slave-skip-errors=all
The --replicate-*
rules are evaluated as follows to determine whether a
statement will be executed by the slave or ignored:
--replicate-do-db
or --replicate-ignore-db
rules?
--binlog-do-db
and --binlog-ignore-db
(see section 5.9.4 The Binary Log). What is the result of the test?
--replicate-*-table
rules?
INSERT INTO sales SELECT * FROM prices
: only
sales
will be compared to the rules). If several tables are to be
updated (multiple-table statement),
the first matching table (matching ``do'' or ``ignore'') wins.
That is, the first table is compared to the rules. Then, if no decision could
be mad, the second table is compared to the rules, and so forth.
--replicate-do-table
rules?
--replicate-ignore-table
rules?
--replicate-wild-do-table
rules?
--replicate-wild-ignore-table
rules?
--replicate-*-table
rule was matched.
Is there another table to test against these rules?
--replicate-do-table
or --replicate-wild-do-table
rules?
Q: How do I configure a slave if the master is running and I do not want to stop it?
A: There are several options. If you have taken a backup of the
master at some point and recorded the binary log name and offset (from the
output of SHOW MASTER STATUS
) corresponding to the snapshot, use
the following procedure:
mysql> CHANGE MASTER TO -> MASTER_HOST='master_host_name', -> MASTER_USER='master_user_name', -> MASTER_PASSWORD='master_pass', -> MASTER_LOG_FILE='recorded_log_file_name', -> MASTER_LOG_POS=recorded_log_position;
START SLAVE
on the slave.
If you do not have a backup of the master server, here is a quick procedure for creating one. All steps should be performed on the master host.
mysql> FLUSH TABLES WITH READ LOCK;
shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql
mysql> SHOW MASTER STATUS;
mysql> UNLOCK TABLES;
An alternative is to make an SQL dump of the master instead of a binary copy
as in the preceding procedure. To do this, you can use mysqldump
--master-data
on your master and later load the SQL dump into your slave.
However, this is slower than making a binary copy.
No matter which of the two methods you use, afterward follow the instructions for the case when you have a snapshot and have recorded the log name and offset. You can use the same snapshot to set up several slaves. Once you have the snapshot of the master, you can wait to set up a slave as long as the binary logs of the master are left intact. The two practical limitations on the length of time you can wait are the amount of disk space available to retain binary logs on the master and the length of time it will take the slave to catch up.
You can also use LOAD DATA FROM MASTER
. This is a convenient
statement that transfers a snapshot to the slave and adjusts the log name
and offset all at once. In the future, LOAD DATA FROM MASTER
will be
the recommended way to set up a slave. Be warned, however, that it works
only for MyISAM
tables and it may hold a read lock for a long time.
It is not yet implemented as efficiently as we would like. If you have large
tables, the preferred method at this time is still to make a binary snapshot
on the master server after executing FLUSH TABLES WITH READ LOCK
.
Q: Does the slave need to be connected to the master all the time?
A: No, it does not. The slave can go down or stay disconnected for hours or even days, then reconnect and catch up on the updates. For example, you can set up a master/slave relationship over a dial-up link where the link is up only sporadically and for short periods of time. The implication of this is that, at any given time, the slave is not guaranteed to be in sync with the master unless you take some special measures. In the future, we will have the option to block the master until at least one slave is in sync.
Q: How do I know how late a slave is compared to the master? In other words, how do I know the date of the last query replicated by the slave?
A:
If the slave is 4.1.1 or newer, read the Seconds_Behind_Master
column
in SHOW SLAVE STATUS
. For older versions, the following applies.
This is possible only if SHOW SLAVE STATUS
on the slave shows that the
SQL thread is running (or for MySQL 3.23, that the slave thread is running),
and that the thread has executed at least one event from the master.
See section 6.3 Replication Implementation Details.
When the slave SQL thread executes an event read from the master, it
modifies its own time to the event timestamp (this is why TIMESTAMP
is well replicated). In the Time
column in the output of
SHOW PROCESSLIST
, the number of seconds displayed for the slave SQL
thread is the number of seconds between the timestamp of the last replicated
event and the real time of the slave machine. You can use this to determine
the date of the last replicated event. Note that if your slave has been
disconnected from the master for one hour, and then reconnects, you may
immediately see Time
values like 3600 for the slave SQL thread in
SHOW PROCESSLIST
. This would be because the slave is executing
statements that are one hour old.
Q: How do I force the master to block updates until the slave catches up?
A: Use the following procedure:
mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS;Record the log name and the offset from the output of the
SHOW
statement. These are the replication coordinates.
MASTER_POS_WAIT()
function are the replication coordinate values
obtained in the previous step:
mysql> SELECT MASTER_POS_WAIT('log_name', log_offset);The
SELECT
statement will block until the slave reaches the specified
log file and offset. At that point, the slave will be in sync with the master
and the statement will return.
mysql> UNLOCK TABLES;
Q: What issues should I be aware of when setting up two-way replication?
A: MySQL replication currently does not support any locking protocol between master and slave to guarantee the atomicity of a distributed (cross-server) update. In other words, it is possible for client A to make an update to co-master 1, and in the meantime, before it propagates to co-master 2, client B could make an update to co-master 2 that will make the update of client A work differently than it did on co-master 1. Thus, when the update of client A makes it to co-master 2, it will produce tables that are different than what you have on co-master 1, even after all the updates from co-master 2 have also propagated. This means that you should not co-chain two servers in a two-way replication relationship unless you are sure that your updates can safely happen in any order, or unless you take care of mis-ordered updates somehow in the client code.
You must also realize that two-way replication actually does not improve performance very much (if at all), as far as updates are concerned. Both servers need to do the same number of updates each, as you would have one server do. The only difference is that there will be a little less lock contention, because the updates originating on another server will be serialized in one slave thread. Even this benefit might be offset by network delays.
Q: How can I use replication to improve performance of my system?
A: You should set up one server as the master and direct all
writes to it. Then configure as many slaves as you have the budget and
rackspace for, and distribute the reads among the master and the slaves.
You can also start the slaves with the --skip-innodb
, --skip-bdb
,
--low-priority-updates
, and --delay-key-write=ALL
options
to get speed improvements on the slave end. In this case, the slave will
use non-transactional MyISAM
tables instead of InnoDB
and
BDB
tables to get more speed.
Q: What should I do to prepare client code in my own applications to use performance-enhancing replication?
A: If the part of your code that is responsible for database access has been properly abstracted/modularized, converting it to run with a replicated setup should be very smooth and easy. Just change the implementation of your database access to send all writes to the master, and to send reads to either the master or a slave. If your code does not have this level of abstraction, setting up a replicated system will give you the opportunity and motivation to it clean up. You should start by creating a wrapper library or module with the following functions:
safe_writer_connect()
safe_reader_connect()
safe_reader_statement()
safe_writer_statement()
safe_
in each function name means that the function will take care
of handling all the error conditions.
You can use different names for the
functions. The important thing is to have a unified interface for connecting
for reads, connecting for writes, doing a read, and doing a write.
You should then convert your client code to use the wrapper library. This may be a painful and scary process at first, but it will pay off in the long run. All applications that use the approach just described will be able to take advantage of a master/slave configuration, even one involving multiple slaves. The code will be a lot easier to maintain, and adding troubleshooting options will be trivial. You will just need to modify one or two functions; for example, to log how long each statement took, or which statement among your many thousands gave you an error.
If you have
written a lot of code, you may want to automate the conversion
task by using the replace
utility that comes with standard MySQL
distributions, or just write your own conversion script. Ideally, your
code uses consistent programming style conventions. If not, then you
are probably better off rewriting it anyway, or at least going through
and manually regularizing it to use a consistent style.
Q: When and how much can MySQL replication improve the performance of my system?
A: MySQL replication is most beneficial for a system with frequent reads and infrequent writes. In theory, by using a single-master/multiple-slave setup, you can scale the system by adding more slaves until you either run out of network bandwidth, or your update load grows to the point that the master cannot handle it.
In order to determine how many slaves you can get before the added benefits
begin to level out, and how much you can improve performance of your site,
you need to know your query patterns, and to determine empirically by
benchmarking the relationship between the throughput for reads (reads per
second, or max_reads
) and for writes (max_writes
) on a typical
master and a typical slave. The example here shows a rather simplified
calculation of what you can get with replication for a hypothetical system.
Let's say that system load consists of 10% writes and 90% reads, and we
have determined by benchmarking that max_reads
is 1200 -
2 * max_writes
. In other words, the system can do 1,200 reads per
second with no writes, the average write is twice as slow as the average
read, and the relationship is linear. Let us suppose that the master
and each slave have the same capacity, and that we have one master and N
slaves. Then we have for each server (master or slave):
reads = 1200 - 2 * writes
reads = 9 * writes / (N + 1)
(reads are split, but writes go
to all servers)
9 * writes / (N + 1) + 2 * writes = 1200
writes = 1200 / (2 + 9/(N+1))
The last equation indicates that the maximum number of writes for N slaves, given a maximum possible read rate of 1,200 per minute and a ratio of nine reads per write.
This analysis yields the following conclusions:
Note that these computations assume infinite network bandwidth and neglect several other factors that could turn out to be significant on your system. In many cases, you may not be able to perform a computation similar to the just shown that will accurately predict what will happen on your system if you add N replication slaves. However, answering the following questions should help you decide whether and how much replication will improve the performance of your system:
Q: How can I use replication to provide redundancy/high availability?
A: With the currently available features, you would have to set up a master and a slave (or several slaves), and write a script that will monitor the master to see whether it is up. Then instruct your applications and the slaves to change master in case of failure. Some suggestions:
CHANGE MASTER TO
statement.
bind
you can use `nsupdate' to dynamically update your DNS.
--log-bin
option and without
--log-slave-updates
. This way the slave will be ready to become a
master as soon as you issue STOP SLAVE
; RESET MASTER
, and
CHANGE MASTER TO
on the other slaves.
For example, assume that you have the following setup:
WC \ v WC----> M / | \ / | \ v v v S1 S2 S3M means the master, S the slaves, WC the clients that issue database writes and reads; clients that issue only database reads are not represented, because they need not switch. S1, S2, and S3 are slaves running with
--log-bin
and without --log-slave-updates
.
Because updates received by a slave from the master are not logged in the
binary log unless --log-slave-updates
is specified, the binary log on
each slave is empty. If for some reason M becomes unavailable, you can
pick one slave to become the new master. For example, if you pick S1,
all WC should be redirected to S1, and S2 and S3 should replicate from S1.
Make sure that all slaves have processed any statements in their relay log.
On each slave, issue STOP SLAVE IO_THREAD
, then check the output
of SHOW PROCESSLIST
until you see Has read all relay log
.
When this is true for all slaves, they can be reconfigured to the new setup.
On the slave S1 being promoted to become the master, issue
STOP SLAVE
and RESET MASTER
.
On the other slaves S2 and S3, use STOP SLAVE
and CHANGE MASTER
TO MASTER_HOST='S1'
(where 'S1'
represents the real hostname of
S1). To CHANGE MASTER
, add all information about how to connect to
S1 from S2 or S3 (user, password, port). In CHANGE MASTER
, there is
no need to specify the name of S1's binary log or binary log position to
read from: We know it is the first binary log and position 4, which are
the defaults for CHANGE MASTER
. Finally, use START SLAVE
on S2 and S3.
Then instruct all WC to direct their statements to S1. From that point on,
all updates statements sent by WC to S1 are written to the binary log of S1,
which will contain exactly every update statement sent to S1 since M died.
The result is this configuration:
WC / | WC | M(unavailable) \ | \ | v v S1<--S2 S3 ^ | +-------+When M is up again, you just have to issue on it the same
CHANGE
MASTER
as the one issued on S2 and S3, so that M becomes a slave of S1 and
picks all the WC writes it has missed while it was down. To make M a
master again (because it is the most powerful machine, for example), use
the preceding procedure as if S1 was unavailable and M was to be the new
master. During the procedure, don't forget to run RESET MASTER
on M
before making S1, S2, and S3 slaves of M. Otherwise, they may pick up old
WC writes from before the point at which M became unavailable.
We are currently working on integrating an automatic master election system into MySQL, but until it is ready, you will have to create your own monitoring tools.
If you have followed the instructions, and your replication setup is not working, first check the following:
SHOW MASTER STATUS
.
If it is, Position
will be non-zero. If not, verify that you are
running the master with the log-bin
and server-id
options.
SHOW SLAVE STATUS
to check whether the
Slave_IO_Running
and Slave_SQL_Running
values are both
Yes
.
If not, verify the options that were used when starting the slave server.
SHOW PROCESSLIST
, find the I/O and SQL threads and check their
State
column to see how they display.
See section 6.3 Replication Implementation Details.
If the I/O thread state says Connecting to master
, verify the
privileges for the replication user on the master, master hostname, your
DNS setup, whether the master is actually running, and whether it is reachable
from the slave.
START SLAVE
.
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n; mysql> START SLAVE;The value of
n
should be 1 if the next statement from the master
does not use AUTO_INCREMENT
or LAST_INSERT_ID()
. Otherwise,
the value should be 2. The reason for using a value of 2 for statements
that use AUTO_INCREMENT
or LAST_INSERT_ID()
is that they
take two events in the binary log of the master.
When you have determined that there is no user error involved, and replication still either does not work at all or is unstable, it is time to send us a bug report. We need to get as much information as possible from you to be able to track down the bug. Please do spend some time and effort preparing a good bug report.
If you have a repeatable test case that demonstrates the bug, please enter it into our bugs database at http://bugs.mysql.com/. If you have a phantom problem (one that you cannot duplicate ``at will''), use the following procedure:
--log-slave-updates
and --log-bin
options.
They will cause the slave to log the updates that it receives from the master
into its own binary logs.
SHOW MASTER STATUS
from the master at the time
you have discovered the problem
SHOW SLAVE STATUS
from the master at the time
you have discovered the problem
mysqlbinlog
to examine the binary logs. The following should
be helpful
to find the trouble query, for example:
shell> mysqlbinlog -j pos_from_slave_status \ /path/to/log_from_slave_status | head
Once you have collected the evidence for the phantom problem, try hard to isolate it into a separate test case first. Then enter the problem into our bugs database at http://bugs.mysql.com/ with as much information as possible.
Optimization is a complex task because ultimately it requires understanding of the entire system to be optimized. Although it may be possible to perform some local optimizations with little knowledge of your system or application, the more optimal you want your system to become, the more you will have to know about it.
This chapter tries to explain and give some examples of different ways to optimize MySQL. Remember, however, that there are always additional ways to make the system even faster, although they may require increasing effort to achieve.
The most important factor in making a system fast is its basic design. You also need to know what kinds of things your system will be doing, and what your bottlenecks are.
The most common system bottlenecks are:
When using the MyISAM
storage engine, MySQL uses extremely fast table
locking that allows multiple readers or a single writer. The biggest problem
with this storage engine occurs when you have a steady stream of mixed
updates and slow selects on a single table. If this is a problem for
certain tables, you can use another storage engine for them. See section 14 MySQL Storage Engines and Table Types.
MySQL can work with both transactional and non-transactional tables.
To be able to work smoothly with non-transactional tables (which can't
roll back if something goes wrong), MySQL has the following rules
(when not running in strict mode or if you use the IGNORE
specifier to INSERT
or UPDATE
).
NULL
.
(This behavior can be changed by using the
ERROR_FOR_DIVISION_BY_ZERO
SQL mode).
If you are using non-transactional tables, you should not use MySQL to check column content. In general, the safest (and often fastest) way is to let the application ensure that it passes only legal values to the database.
For more information about this, see section 1.5.6 How MySQL Deals with Constraints and section 13.1.4 INSERT
Syntax or
section 5.2.2 The Server SQL Mode.
Because all SQL servers implement different parts of standard SQL, it takes work to write portable SQL applications. It is very easy to achieve portability for very simple selects and inserts, but becomes more difficult the more capabilities you require. If you want an application that is fast with many database systems, it becomes even harder!
To make a complex application portable, you need to determine which SQL servers it must work with, then determine what features those servers support.
All database systems have some weak points. That is, they have different design compromises that lead to different behavior.
You can use the MySQL crash-me
program to find functions, types, and
limits that you can use with a selection of database servers.
crash-me
does not check for every possible feature, but it is still
reasonably comprehensive, performing about 450 tests.
An example of the type of information crash-me
can provide is that
you shouldn't have column names longer than 18 characters
if you want to be able to use Informix or DB2.
The crash-me
program and the MySQL benchmarks are all very database
independent. By taking a look at how they are written, you can get
a feeling for what you have to do to make your own applications database
independent. The programs can be found in the `sql-bench' directory
of MySQL source distributions. They are written in Perl and use the DBI
database interface. Use of DBI in itself solves part of the portability
problem because it provides database-independent access methods.
For crash-me
results, visit
http://dev.mysql.com/tech-resources/crash-me.php.
See http://dev.mysql.com/tech-resources/benchmarks/ for the results
from the benchmarks.
If you strive for database independence, you need to get a good feeling
for each SQL server's bottlenecks. For example, MySQL is very fast in
retrieving and updating records for MyISAM
tables, but will have
a problem in mixing slow readers and writers on the same table. Oracle,
on the other hand, has a big problem when you try to access rows that
you have recently updated (until they are flushed to disk). Transactional
databases in general are not very good at generating summary tables from
log tables, because in this case row locking is almost useless.
To make your application really database independent, you need to define an easily extendable interface through which you manipulate your data. As C++ is available on most systems, it makes sense to use a C++ class-based interface to the databases.
If you use some feature that is specific to a given database system (such
as the REPLACE
statement, which is specific to MySQL), you should
implement the same feature for other SQL servers by coding an alternative
method. Although the alternative may be slower, it will allow the other
servers to perform the same tasks.
With MySQL, you can use the /*! */
syntax to add MySQL-specific
keywords to a query. The code inside /**/
will be treated as a
comment (and ignored) by most other SQL servers.
If high performance is more important than exactness, as in some Web applications, it is possible to create an application layer that caches all results to give you even higher performance. By letting old results ``expire'' after a while, you can keep the cache reasonably fresh. This provides a method to handle high load spikes, in which case you can dynamically increase the cache and set the expiration timeout higher until things get back to normal.
In this case, the table creation information should contain information of the initial size of the cache and how often the table should normally be refreshed.
An alternative to implementing an application cache is to use the MySQL query cache. By enabling the query cache, the server handles the details of determining whether a query result can be reused. This simplifies your application. See section 5.11 The MySQL Query Cache.
This section describes an early application for MySQL.
During MySQL initial development, the features of MySQL were made to fit our largest customer, which handled data warehousing for a couple of the largest retailers in Sweden.
From all stores, we got weekly summaries of all bonus card transactions, and were expected to provide useful information for the store owners to help them find how their advertising campaigns were affecting their own customers.
The volume of data was quite huge (about seven million summary transactions per month), and we had data for 4-10 years that we needed to present to the users. We got weekly requests from our customers, who wanted to get ``instant'' access to new reports from this data.
We solved this problem by storing all information per month in compressed ``transaction'' tables. We had a set of simple macros that generated summary tables grouped by different criteria (product group, customer id, store, and so on) from the tables in which the transactions were stored. The reports were Web pages that were dynamically generated by a small Perl script. This script parsed a Web page, executed the SQL statements in it, and inserted the results. We would have used PHP or mod_perl instead, but they were not available at the time.
For graphical data, we wrote a simple tool in C that could process SQL query results and produce GIF images based on those results. This tool also was dynamically executed from the Perl script that parses the Web pages.
In most cases, a new report could be created simply by copying an existing script and modifying the SQL query in it. In some cases, we needed to add more columns to an existing summary table or generate a new one. This also was quite simple because we kept all transaction-storage tables on disk. (This amounted to about 50GB of transaction tables and 200GB of other customer data.)
We also let our customers access the summary tables directly with ODBC so that the advanced users could experiment with the data themselves.
This system worked well and we had no problems handling the data with quite modest Sun Ultra SPARCstation hardware (2x200MHz). Eventually the system was migrated to Linux.
This section should contain a technical description of the MySQL
benchmark suite (and crash-me
), but that description has not yet
been written. Currently, you can get a good idea of the benchmarks by
looking at the code and results in the `sql-bench' directory in any
MySQL source distribution.
This benchmark suite is meant to tell any user what operations a given SQL implementation performs well or poorly.
Note that this benchmark is single-threaded, so it measures the minimum time for the operations performed. We plan to add multi-threaded tests to the benchmark suite in the future.
To use the benchmark suite, the following requirements must be satisfied:
DBD::mysql
, DBD::Pg
, and DBD::DB2
modules installed.
See section 2.13 Perl Installation Notes.
After you obtain a MySQL source distribution, you will find the benchmark
suite located in its `sql-bench' directory. To run the benchmark tests,
build MySQL, then
change location into the `sql-bench' directory and execute the run-all-tests
script:
shell> cd sql-bench shell> perl run-all-tests --server=server_name
server_name is one of the supported servers. To get a list of all options and supported servers, invoke this command:
shell> perl run-all-tests --help
The crash-me
script also is located in the `sql-bench' directory.
crash-me
tries to determine what features a database supports and
what its capabilities and limitations are by actually running
queries. For example, it determines:
VARCHAR
column can be
You can find the results from crash-me
for many different database
servers at http://dev.mysql.com/tech-resources/crash-me.php.
For more information about benchmark results, visit
http://dev.mysql.com/tech-resources/benchmarks/.
You should definitely benchmark your application and database to find out where the bottlenecks are. By fixing a bottleneck (or by replacing it with a ``dummy module''), you can then easily identify the next bottleneck. Even if the overall performance for your application currently is acceptable, you should at least make a plan for each bottleneck, and decide how to solve it if someday you really need the extra performance.
For an example of portable benchmark programs, look at the MySQL benchmark suite. See section 7.1.4 The MySQL Benchmark Suite. You can take any program from this suite and modify it for your needs. By doing this, you can try different solutions to your problem and test which really is fastest for you.
Another free benchmark suite is the Open Source Database Benchmark, available at http://osdb.sourceforge.net/.
It is very common for a problem to occur only when the system is very heavily loaded. We have had many customers who contact us when they have a (tested) system in production and have encountered load problems. In most cases, performance problems turn out to be due to issues of basic database design (for example, table scans are not good at high load) or problems with the operating system or libraries. Most of the time, these problems would be a lot easier to fix if the systems were not in production.
To avoid problems like this, you should put some effort into benchmarking your whole application under the worst possible load! You can use Super Smack for this. It is available at http://jeremy.zawodny.com/mysql/super-smack/. As the name suggests, it can bring a system to its knees if you ask it, so make sure to use it only on your development systems.
SELECT
Statements and Other QueriesFirst, one factor affects all statements: The more complex your permission setup is, the more overhead you will have.
Using simpler permissions when you issue GRANT
statements enables
MySQL to reduce permission-checking overhead when clients execute
statements. For example, if you don't grant any table-level or column-level
privileges, the server need not ever check the contents of the
tables_priv
and columns_priv
tables. Similarly, if you place
no resource limits on any accounts, the server does not have to perform
resource counting. If you have a very high query volume, it may be worth
the time to use a simplified grant structure to reduce permission-checking
overhead.
If your problem is with some specific MySQL expression or function, you can
use the BENCHMARK()
function from the mysql
client program
to perform a timing test. Its syntax is
BENCHMARK(loop_count,expression)
. For example:
mysql> SELECT BENCHMARK(1000000,1+1); +------------------------+ | BENCHMARK(1000000,1+1) | +------------------------+ | 0 | +------------------------+ 1 row in set (0.32 sec)
This result was obtained on a Pentium II 400MHz system. It shows that MySQL can execute 1,000,000 simple addition expressions in 0.32 seconds on that system.
All MySQL functions should be very optimized, but there may be some
exceptions. BENCHMARK()
is a great tool to find out if this is a
problem with your query.
EXPLAIN
Syntax (Get Information About a SELECT
)EXPLAIN tbl_name
Or:
EXPLAIN SELECT select_options
The EXPLAIN
statement can be used either as a synonym for
DESCRIBE
or as a way to obtain information about how MySQL will execute
a SELECT
statement:
EXPLAIN tbl_name
syntax is synonymous with DESCRIBE tbl_name
or
SHOW COLUMNS FROM tbl_name
.
SELECT
statement with the keyword EXPLAIN
,
MySQL explains how it would process the SELECT
, providing
information about how tables are joined and in which order.
This section provides information about the second use of EXPLAIN
.
With the help of EXPLAIN
, you can see when you must add indexes
to tables to get a faster SELECT
that uses indexes to find
records.
If you have a problem with incorrect index usage, you should run
ANALYZE TABLE
to update table statistics such as cardinality of
keys, which can affect the choices the optimizer makes. See section 13.5.2.1 ANALYZE TABLE
Syntax.
You can also see whether the optimizer joins the tables in an optimal order.
To force the optimizer to use a join order corresponding to the order
in which the tables are named in the SELECT
statement, begin the
statement with SELECT STRAIGHT_JOIN
rather than just SELECT
.
EXPLAIN
returns a row of information for each table used in the
SELECT
statement. The tables are listed in the output in the order
that MySQL would read them while processing the query. MySQL resolves
all joins using a single-sweep
multi-join method. This means that MySQL reads a row from the first
table, then finds a matching row in the second table, then in the third table,
and so on. When all tables are processed, it outputs the selected columns and
backtracks through the table list until a table is found for which there are
more matching rows. The next row is read from this table and the process
continues with the next table.
In MySQL version 4.1, the EXPLAIN
output format was changed to work
better with constructs such as UNION
statements, subqueries, and
derived tables. Most notable is the addition of two new columns: id
and select_type
. You will not see these columns when using servers
older than MySQL 4.1.
Each output row from EXPLAIN
provides information about one table, and
each row consists of the following columns:
id
SELECT
identifier. This is the sequential number of the
SELECT
within the query.
select_type
SELECT
, which can be any of the following:
SIMPLE
SELECT
(not using UNION
or subqueries)
PRIMARY
SELECT
UNION
SELECT
statement in a UNION
DEPENDENT UNION
SELECT
statement in a UNION
, dependent on outer
query
UNION RESULT
UNION
.
SUBQUERY
SELECT
in subquery
DEPENDENT SUBQUERY
SELECT
in subquery, dependent on outer query
DERIVED
SELECT
(subquery in FROM
clause)
table
type
system
const
join type.
const
const
tables are very fast because they are read only once!
const
is used when you compare all parts of a
PRIMARY KEY
or UNIQUE
index with constant values. In the
following queries, tbl_name can be used as a const
table:
SELECT * FROM tbl_name WHERE primary_key=1; SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;
eq_ref
const
types, this is the best
possible join type. It is used when all parts of an index are used by
the join and the index is a PRIMARY KEY
or UNIQUE
index.
eq_ref
can be used for indexed columns that are compared using the
=
operator. The comparison value can be a constant or an expression
that uses columns from tables that are read before this table.
In the following examples, MySQL can use an eq_ref
join to process
ref_table:
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
ref
ref
is used
if the join uses only a leftmost prefix of the key or if the key is not
a PRIMARY KEY
or UNIQUE
index (in other words, if the join
cannot select a single row based on the key value). If the key that is
used matches only a few rows, this is a good join type.
ref
can be used for indexed columns that are compared using the =
operator.
In the following examples, MySQL can use a ref
join to process
ref_table:
SELECT * FROM ref_table WHERE key_column=expr; SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
ref_or_null
ref
, but with the addition that MySQL will
do an extra search for rows that contain NULL
values. This join
type optimization is new for MySQL 4.1.1 and is mostly used when resolving
subqueries.
In the following examples, MySQL can use a ref_or_null
join to process
ref_table:
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;See section 7.2.7 How MySQL Optimizes
IS NULL
.
index_merge
key
column contains a list of indexes used, and
key_len
contains a list of the longest key parts for the indexes
used. For more information, see
section 7.2.6 Index Merge Optimization.
unique_subquery
ref
for some IN
subqueries of the following
form:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery
is just an index lookup function that replaces the
subquery completely for better efficiency.
index_subquery
unique_subquery
. It replaces IN
subqueries, but
it works for non-unique indexes in subqueries of the following form:
value IN (SELECT key_column FROM single_table WHERE some_expr)
range
key
column indicates which index is used.
The key_len
contains the longest key part that was used.
The ref
column will be NULL
for this type.
range
can be used for when a key column is compared to a
constant using any of the =
, <>
, >
, >=
, <
,
<=
, IS NULL
, <=>
, BETWEEN
, or IN
operators:
SELECT * FROM tbl_name WHERE key_column = 10; SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20; SELECT * FROM tbl_name WHERE key_column IN (10,20,30); SELECT * FROM tbl_name WHERE key_part1= 10 AND key_part2 IN (10,20,30);
index
ALL
, except that only the index tree
is scanned. This usually is faster than ALL
, because the index
file usually is smaller than the data file.
MySQL can use this join type when the query uses only columns that are
part of a single index.
ALL
const
, and usually very bad in all other
cases. Normally, you can avoid ALL
by adding indexes that allow row
retrieval from the table based on constant values or column values from
earlier tables.
possible_keys
possible_keys
column indicates which indexes MySQL could use to
find the rows in this table. Note that this column is totally independent of
the order of the tables as displayed in the output from EXPLAIN
. That
means that some of the keys in possible_keys
might not be usable in
practice with the generated table order.
If this column is NULL
, there are no relevant indexes. In this case,
you may be able to improve the performance of your query by examining
the WHERE
clause to see whether it refers to some column or columns
that would be suitable for indexing. If so, create an appropriate index
and check the query with EXPLAIN
again.
See section 13.2.2 ALTER TABLE
Syntax.
To see what indexes a table has, use SHOW INDEX FROM tbl_name
.
key
key
column indicates the key (index) that MySQL actually decided
to use. The key is NULL
if no index was chosen. To force MySQL
to use or ignore an index listed in the possible_keys
column, use
FORCE INDEX
, USE INDEX
, or IGNORE INDEX
in your query.
See section 13.1.7 SELECT
Syntax.
For MyISAM
and BDB
tables, running ANALYZE TABLE
will help the optimizer choose better indexes. For MyISAM
tables,
myisamchk --analyze
will do the same. See section 13.5.2.1 ANALYZE TABLE
Syntax and section 5.7.3 Table Maintenance and Crash Recovery.
key_len
key_len
column indicates the length of the key that MySQL
decided to use. The length is NULL
if the key
column says
NULL
. Note that the value of key_len
allows you to determine
how many parts of a multiple-part key MySQL will actually use.
ref
ref
column shows which columns or constants are used with the
key
to select rows from the table.
rows
rows
column indicates the number of rows MySQL
believes it must examine to execute the query.
Extra
Distinct
Not exists
LEFT JOIN
optimization on the
query and will not examine more rows in this table for the previous row
combination after it finds one row that matches the LEFT JOIN
criteria.
Here is an example of the type of query that can be optimized this way:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;Assume that
t2.id
is defined as NOT NULL
. In this case,
MySQL will scan t1
and look up the rows in t2
using the values
of t1.id
. If MySQL finds a matching row in t2
, it knows that
t2.id
can never be NULL
, and will not scan through the rest
of the rows in t2
that have the same id
value. In other
words, for each row in t1
, MySQL needs to do only a single lookup
in t2
, regardless of how many rows actually match in t2
.
range checked for each record (index map: #)
range
or index_merge
access method to
retrieve rows. The applicability criteria are as described in section 7.2.5 Range Optimization
and section 7.2.6 Index Merge Optimization, with the exception that all column values for the
preceding table are known and considered to be constants.
This is not very fast, but is faster than performing a join with no index
at all.
Using filesort
WHERE
clause. The keys then are
sorted and the rows are retrieved in sorted order.
See section 7.2.10 How MySQL Optimizes ORDER BY
.
Using index
Using temporary
GROUP BY
and ORDER BY
clauses that list columns differently.
Using where
WHERE
clause will be used to restrict which rows to match
against the next table or send to the client. Unless you specifically intend
to fetch or examine all rows from the table, you may have something wrong
in your query if the Extra
value is not Using where
and the table join type is ALL
or index
.
If you want to make your queries as fast as possible, you should look out for
Extra
values of Using filesort
and Using temporary
.
Using sort_union(...)
Using union(...)
Using intersect(...)
index_merge
join type. See section 7.2.6 Index Merge Optimization for more information.
Using index for group-by
Using index
way of accessing a table, Using
index for group-by
indicates that MySQL found an index that can be used
to retrieve all columns of a GROUP BY
or DISTINCT
query
without any extra disk access to the actual table. Additionally, the index
will be used in the most efficient way so that for each group, only a few
index entries will be read. For details, see
section 7.2.11 How MySQL Optimizes GROUP BY
.
You can get a good indication of how good a join is by taking the
product of the values in the rows
column of the EXPLAIN
output. This should tell you roughly how many rows MySQL must examine to
execute the query. If you restrict queries with the max_join_size
system variable, this product also is used to determine which multiple-table
SELECT
statements to execute.
See section 7.5.2 Tuning Server Parameters.
The following example shows how a multiple-table join can be optimized
progressively based on the information provided by EXPLAIN
.
Suppose that you have the SELECT
statement shown here and you plan to
examine it using EXPLAIN
:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC = et_1.EMPLOYID AND tt.ClientID = do.CUSTNMBR;
For this example, make the following assumptions:
Table | Column | Column Type |
tt | ActualPC | CHAR(10)
|
tt | AssignedPC | CHAR(10)
|
tt | ClientID | CHAR(10)
|
et | EMPLOYID | CHAR(15)
|
do | CUSTNMBR | CHAR(15)
|
Table | Index |
tt | ActualPC
|
tt | AssignedPC
|
tt | ClientID
|
et | EMPLOYID (primary key)
|
do | CUSTNMBR (primary key)
|
tt.ActualPC
values are not evenly distributed.
Initially, before any optimizations have been performed, the EXPLAIN
statement produces the following information:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL 74 tt ALL AssignedPC, NULL NULL NULL 3872 ClientID, ActualPC range checked for each record (key map: 35)
Because type
is ALL
for each table, this output indicates
that MySQL is generating a Cartesian product of all the tables; that is,
every combination of rows. This will take quite a long time, because the
product of the number of rows in each table must be examined. For the case
at hand, this product is 74 * 2135 * 74 * 3872 = 45,268,558,720
rows.
If the tables were bigger, you can only imagine how long it would take.
One problem here is that MySQL can use indexes on columns more efficiently
if they are declared the same. (For ISAM
tables, indexes may not be
used at all unless the columns are declared the same.) In this context,
VARCHAR
and CHAR
are the same unless they are declared as
different lengths. Because tt.ActualPC
is declared as CHAR(10)
and et.EMPLOYID
is declared as CHAR(15)
, there is a length
mismatch.
To fix this disparity between column lengths, use ALTER TABLE
to
lengthen ActualPC
from 10 characters to 15 characters:
mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
tt.ActualPC
and et.EMPLOYID
are both VARCHAR(15)
.
Executing the EXPLAIN
statement again produces this result:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC, NULL NULL NULL 3872 Using ClientID, where ActualPC do ALL PRIMARY NULL NULL NULL 2135 range checked for each record (key map: 1) et_1 ALL PRIMARY NULL NULL NULL 74 range checked for each record (key map: 1) et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
This is not perfect, but is much better: The product of the rows
values is less by a factor of 74. This version is executed in a couple
of seconds.
A second alteration can be made to eliminate the column length mismatches
for the tt.AssignedPC = et_1.EMPLOYID
and tt.ClientID =
do.CUSTNMBR
comparisons:
mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15), -> MODIFY ClientID VARCHAR(15);
EXPLAIN
produces the output shown here:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using ClientID, where ActualPC et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
This is almost as good as it can get.
The remaining problem is that, by default, MySQL assumes that values
in the tt.ActualPC
column are evenly distributed, and that is not the
case for the tt
table. Fortunately, it is easy to tell MySQL
to analyze the key distribution:
mysql> ANALYZE TABLE tt;
The join is perfect, and EXPLAIN
produces this result:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC NULL NULL NULL 3872 Using ClientID, where ActualPC et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Note that the rows
column in the output from EXPLAIN
is an
educated guess from the MySQL join optimizer. You should check whether the
numbers are even close to the truth. If not, you may get better performance
by using STRAIGHT_JOIN
in your SELECT
statement and trying
to list the tables in a different order in the FROM
clause.
In most cases, you can estimate the performance by counting disk seeks.
For small tables, you can usually find a row in one disk seek (because the
index is probably cached). For bigger tables, you can estimate that,
using B-tree indexes, you will need this many seeks to find a row:
log(row_count) / log(index_block_length / 3 * 2 /
(index_length + data_pointer_length)) +
1
.
In MySQL, an index block is usually 1024 bytes and the data
pointer is usually 4 bytes. For a 500,000-row table with an
index length of 3 bytes (medium integer), the formula indicates
log(500,000)/log(1024/3*2/(3+4)) + 1
= 4
seeks.
This index would require storage of about 500,000 * 7 * 3/2 = 5.2MB (assuming a typical index buffer fill ratio of 2/3), so you will probably have much of the index in memory and you will probably need only one or two calls to read data to find the row.
For writes, however, you will need four seek requests (as above) to find where to place the new index and normally two seeks to update the index and write the row.
Note that the preceding discussion doesn't mean that your application
performance will slowly degenerate by log N! As long as everything
is cached by the OS or SQL server, things will become only marginally
slower as the table gets bigger. After the data gets too big to be cached,
things will start to go much slower until your applications is only bound
by disk-seeks (which increase by log N). To avoid this, increase the key
cache size as the data grows. For MyISAM
tables, the key cache
size is controlled by the key_buffer_size
system variable.
See section 7.5.2 Tuning Server Parameters.
SELECT
Queries
In general, when you want to make a slow SELECT ... WHERE
query
faster, the first thing to check is whether you can add an index.
All references between different tables should usually be done with
indexes. You can use the EXPLAIN
statement to determine which
indexes are used for a SELECT
.
See section 7.4.5 How MySQL Uses Indexes and
section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
).
Some general tips for speeding up queries on MyISAM
tables:
ANALYZE TABLE
or
run myisamchk --analyze
on a table after it has been loaded with
data. This updates a value for each index part that indicates the average
number of rows that have the same value. (For unique indexes, this is
always 1.) MySQL will use this to decide which index to choose when you
join two tables based on a non-constant expression. You can check the
result from the table analysis by using SHOW INDEX FROM tbl_name
and examining the Cardinality
value. myisamchk --description
--verbose
shows index distribution information.
myisamchk
--sort-index --sort-records=1
(if you want to sort on index 1). This is
a good way to make queries faster if you have a unique index from which
you want to read all records in order according to the index. Note that
the first time you sort a large table this way, it may take a long time.
WHERE
Clauses
This section discusses optimizations that can be made for processing
WHERE
clauses. The examples use SELECT
statements, but
the same optimizations apply for WHERE
clauses in DELETE
and UPDATE
statements.
Note that work on the MySQL optimizer is ongoing, so this section is incomplete. MySQL does many optimizations, not all of which are documented here.
Some of the optimizations performed by MySQL are listed here:
((a AND b) AND c OR (((a AND b) AND (c AND d)))) -> (a AND b AND c) OR (a AND b AND c AND d)
(a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6) -> B=5 OR B=6
COUNT(*)
on a single table without a WHERE
is retrieved
directly from the table information for MyISAM
and HEAP
tables.
This is also done for any NOT NULL
expression when used with only one
table.
SELECT
statements are impossible and returns no rows.
HAVING
is merged with WHERE
if you don't use GROUP BY
or group functions (COUNT()
, MIN()
, and so on).
WHERE
is constructed to get a fast
WHERE
evaluation for the table and also to skip records as
soon as possible.
WHERE
clause on a PRIMARY KEY
or a UNIQUE
index, where all index parts are compared to constant
expressions and are defined as NOT NULL
.
SELECT * FROM t WHERE primary_key=1; SELECT * FROM t1,t2 WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
ORDER BY
and GROUP
BY
clauses come from the same table, that table is preferred first when
joining.
ORDER BY
clause and a different GROUP BY
clause, or if the ORDER BY
or GROUP BY
contains columns
from tables other than the first table in the join queue, a temporary
table is created.
SQL_SMALL_RESULT
, MySQL uses an in-memory
temporary table.
HAVING
clause
are skipped.
Some examples of queries that are very fast:
SELECT COUNT(*) FROM tbl_name; SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name; SELECT MAX(key_part2) FROM tbl_name WHERE key_part1=constant; SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... LIMIT 10; SELECT ... FROM tbl_name ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;
The following queries are resolved using only the index tree, assuming that the indexed columns are numeric:
SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val; SELECT COUNT(*) FROM tbl_name WHERE key_part1=val1 AND key_part2=val2; SELECT key_part2 FROM tbl_name GROUP BY key_part1;
The following queries use indexing to retrieve the rows in sorted order without a separate sorting pass:
SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,... ; SELECT ... FROM tbl_name ORDER BY key_part1 DESC, key_part2 DESC, ... ;
The range
access method uses a single index to retrieve a subset
of table records that are contained within one or several index value
intervals. It can be used for a single-part or multiple-part index.
A detailed description of how intervals are extracted from the
WHERE
clause is given in the following sections.
For a single-part index, index value intervals can be conveniently
represented by corresponding conditions in the WHERE
clause, so
we'll talk about ``range conditions'' instead of intervals.
The definition of a range condition for a single-part index is as follows:
BTREE
and HASH
indexes, comparison of a key part with
a constant value is a range condition when using the =
, <=>
,
IN
, IS NULL
, or IS NOT NULL
operators.
BTREE
indexes, comparison of a key part with a constant
value is a range condition when using the >
, <
, >=
,
<=
, BETWEEN
, !=
, or <>
operators, or LIKE
'pattern'
(where 'pattern'
doesn't start with a
wildcard).
OR
or AND
form a range condition.
``Constant value'' in the preceding descriptions means one of the following:
const
or system
table from the same join
Here are some examples of queries with range conditions in the
WHERE
clause:
SELECT * FROM t1 WHERE key_col > 1 AND key_col < 10; SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,20); SELECT * FROM t1 WHERE key_col LIKE 'ab%' OR key_col BETWEEN 'bar' AND 'foo';
Note that some non-constant values may be converted to constants during the constant propagation phase.
MySQL tries to extract range conditions from the WHERE
clause for
each of the possible indexes. During the extraction process, conditions
that can't be used for constructing the range condition are dropped,
conditions that produce overlapping ranges are combined, and conditions that
produce empty ranges are removed.
For example, consider the following statement, where key1
is an
indexed column and nonkey
is not indexed:
SELECT * FROM t1 WHERE (key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z');
The extraction process for key key1
is as follows:
WHERE
clause:
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR key1 LIKE '%b')) OR (key1 < 'bar' AND nonkey = 4) OR (key1 < 'uux' AND key1 > 'z')
nonkey = 4
and key1 LIKE '%b'
because they cannot be
used for a range scan. The right way to remove them is to replace them
with TRUE
, so that we don't miss any matching records when doing
the range scan. Having replaced them with TRUE
, we get:
(key1 < 'abc' AND (key1 LIKE 'abcde%' OR TRUE)) OR (key1 < 'bar' AND TRUE) OR (key1 < 'uux' AND key1 > 'z')
(key1 LIKE 'abcde%' OR TRUE)
is always true
(key1 < 'uux' AND key1 > 'z')
is always false
(key1 < 'abc' AND TRUE) OR (key1 < 'bar' AND TRUE) OR (FALSE)Removing unnecessary
TRUE
and FALSE
constants, we obtain
(key1 < 'abc') OR (key1 < 'bar')
(key1 < 'bar')
In general (and as demonstrated in the example), the condition used for
a range scan is less restrictive than the WHERE
clause. MySQL will
perform an additional check to filter out rows that satisfy the range
condition but not the full WHERE
clause.
The range condition extraction algorithm can handle nested
AND
/OR
constructs of arbitrary depth, and its output doesn't
depend on the order in which conditions appear in WHERE
clause.
Range conditions on a multiple-part index are an extension of range conditions for a single-part index. A range condition on a multiple-part index restricts index records to lie within one or several key tuple intervals. Key tuple intervals are defined over a set of key tuples, using ordering from the index.
For example, consider a multiple-part index defined as
key1(key_part1, key_part2, key_part3)
, and the
following set of key tuples listed in key order:
key_part1 key_part2 key_part3 NULL 1 'abc' NULL 1 'xyz' NULL 2 'foo' 1 1 'abc' 1 1 'xyz' 1 2 'abc' 2 1 'aaa'
The condition key_part1 = 1
defines this interval:
(1, -inf, -inf) <= (key_part1, key_part2, key_part3) < (1, +inf, +inf)
The interval covers the 4th, 5th, and 6th tuples in the preceding data set and can be used by the range access method.
By contrast, the condition key_part3 = 'abc'
does not define a single
interval and cannot be used by the range access method.
The following descriptions indicate how range conditions work for multiple-part indexes in greater detail.
HASH
indexes, each interval containing identical values
can be used. This means that the interval can be produced only for
conditions in the following form:
key_part1 cmp const1 AND key_part2 cmp const2 AND ... AND key_partN cmp constN;Here, const1, const2, ... are constants, cmp is one of the
=
, <=>
, or IS NULL
comparison operators, and the
conditions cover all index parts. (That is, there are N conditions,
one for each part of an N-part index.)
See section 7.2.5.1 Range Access Method for Single-Part Indexes for the definition of
what is considered to be a constant.
For example, the following is a range condition for a three-part
HASH
index:
key_part1 = 1 AND key_part2 IS NULL AND key_part3 = 'foo'
BTREE
index, an interval might be usable for conditions
combined with AND
, where each condition compares a key part with
a constant value using =
, <=>
, IS NULL
, >
,
<
, >=
, <=
, !=
, <>
, BETWEEN
, or
LIKE 'pattern'
(where 'pattern'
doesn't start
with a wildcard). An interval can be used as long as it is possible to
determine a single key tuple containing all records that match the condition
(or two intervals if <>
or !=
is used). For example, for
this condition:
key_part1 = 'foo' AND key_part2 >= 10 AND key_part3 > 10The single interval will be:
('foo', 10, 10) < (key_part1, key_part2, key_part3) < ('foo', +inf, +inf)It is possible that the created interval will contain more records than the initial condition. For example, the preceding interval includes the value
('foo', 11, 0)
,
which does not satisfy the original condition.
OR
, they form a condition that covers a set of records
contained within the union of their intervals. If the conditions are combined
with AND
, they form a condition that covers a set of records
contained within the intersection of their intervals. For example, for
this condition on a two-part index:
(key_part1 = 1 AND key_part2 < 2) OR (key_part1 > 5)The intervals will be:
(1, -inf) < (key_part1, key_part2) < (1, 2) (5, -inf) < (key_part1, key_part2)In this example, the interval on the first line uses one key part for the left bound and two key parts for the right bound. The interval on the second line uses only one key part. The
key_len
column in the EXPLAIN
output indicates the maximum length of the key prefix used.
In some cases, key_len
may indicate that a key part was used, but
that might be not what you would expect. Suppose that key_part1
and key_part2 can be NULL
. Then the key_len
column
will display two key part lengths for the following condition:
key_part1 >= 1 AND key_part2 < 2But in fact, the condition will be converted to this:
key_part1 >= 1 AND key_part2 IS NOT NULL
section 7.2.5.1 Range Access Method for Single-Part Indexes describes how optimizations are performed to combine or eliminate intervals for range conditions on single-part index. Analogous steps are performed for range conditions on multiple-part keys.
The Index Merge (index_merge
) method is used to retrieve rows with
several ref
, ref_or_null
, or range
scans and merge
the results into one. This method is employed when the table condition
is a disjunction of conditions for which ref
, ref_or_null
,
or range
could be used with different keys.
This ``join'' type optimization is new in MySQL 5.0.0, and represents a significant change in behavior with regard to indexes, because the old rule was that the server is only ever able to use at most one index for each referenced table.
In EXPLAIN
output, this method appears as index_merge
in the
type
column. In this case, the key
column contains a list of
indexes used, and key_len
contains a list of the longest key parts
for those indexes.
Examples:
SELECT * FROM tbl_name WHERE key_part1 = 10 OR key_part2 = 20; SELECT * FROM tbl_name WHERE (key_part1 = 10 OR key_part2 = 20) AND non_key_part=30; SELECT * FROM t1, t2 WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%') AND t2.key1=t1.some_col; SELECT * FROM t1, t2 WHERE t1.key1=1 AND (t2.key1=t1.some_col OR t2.key2=t1.some_col2);
The Index Merge method has several access algorithms (seen in the
Extra
field of EXPLAIN
output):
The following sections describe these methods in greater detail.
Note: The Index Merge optimization algorithm has the following known deficiencies:
SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;For this query, two plans are possible:
(goodkey1 < 10 OR goodkey2 < 20)
condition.
badkey < 30
condition.
index_merge
by using
IGNORE INDEX
or FORCE INDEX
. The following queries will be
executed using Index Merge:
SELECT * FROM t1 FORCE INDEX(goodkey1,goodkey2) WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30; SELECT * FROM t1 IGNORE INDEX(badkey) WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
WHERE
clause with deep
AND
/OR
nesting and MySQL doesn't choose the optimal plan,
try distributing terms using the following identity laws:
(x AND y) OR z = (x OR z) AND (y OR z) (x OR y) AND z = (x AND z) OR (y AND z)
The choice between different possible variants of the index_merge
access method and other access methods is based on cost estimates of
various available options.
This access algorithm can be employed when a WHERE
clause was
converted to several range conditions on different keys combined with
AND
, and each condition is one of the following:
key_part1=const1 AND key_part2=const2 ... AND key_partN=constN
InnoDB
or BDB
table.
Here are some examples:
SELECT * FROM innodb_table WHERE primary_key < 10 AND key_col1=20; SELECT * FROM tbl_name WHERE (key1_part1=1 AND key1_part2=2) AND key2=2;
The Index Merge intersection algorithm performs simultaneous scans on all used indexes and produces the intersection of row sequences that it receives from the merged index scans.
If all columns used in the query are covered by the used indexes, full
table records will not be retrieved (EXPLAIN
output will contain
Using index
in Extra
field in this case). Here is an example
of such query:
SELECT COUNT(*) FROM t1 WHERE key1=1 AND key2=1;
If the used indexes don't cover all columns used in the query, full records will be retrieved only when the range conditions for all used keys are satisfied.
If one of the merged conditions is a condition over a primary key of an
InnoDB
or BDB
table, it is not used for record retrieval,
but is used to filter out records retrieved using other conditions.
The applicability criteria for this algorithm are similar to those of the
Index Merge method intersection algorithm. The algorithm can be
employed when the table WHERE
clause was converted to several range
conditions on different keys combined with OR
, and each condition
is one of the following:
key_part1=const1 AND key_part2=const2 ... AND key_partN=constN
InnoDB
or BDB
table.
Here are some examples:
SELECT * FROM t1 WHERE key1=1 OR key2=2 OR key3=3; SELECT * FROM innodb_table WHERE (key1=1 AND key2=2) OR (key3='foo' AND key4='bar') AND key5=5;
This access algorithm is employed when the WHERE
clause was converted
to several range conditions combined by OR
, but for which the
Index Merge method union algorithm is not applicable.
Here are some examples:
SELECT * FROM tbl_name WHERE key_col1 < 10 OR key_col2 < 20; SELECT * FROM tbl_name WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col=30;
The difference between the sort-union algorithm and the union algorithm is that the sort-union algorithm must first fetch row IDs for all records and sort them before returning any records.
IS NULL
MySQL can do the same optimization on col_name IS NULL
that it can do
with col_name =
constant_value. For example, MySQL can use
indexes and ranges to search for NULL
with IS NULL
.
SELECT * FROM tbl_name WHERE key_col IS NULL; SELECT * FROM tbl_name WHERE key_col <=> NULL; SELECT * FROM tbl_name WHERE key_col=const1 OR key_col=const2 OR key_col IS NULL;
If a WHERE
clause includes a col_name IS NULL
condition for a
column that is declared as NOT NULL
, that expression will be
optimized away. This optimization does not occur in cases when the column
might produce NULL
anyway; for example, if it comes from a table on
the right side of a LEFT JOIN
.
MySQL 4.1.1 and up can additionally optimize the combination
col_name = expr AND col_name IS NULL
,
a form that is common in resolved subqueries.
EXPLAIN
will show ref_or_null
when this
optimization is used.
This optimization can handle one IS NULL
for any key part.
Some examples of queries that are optimized, assuming that there is an index
on columns a
and b
of table t2
:
SELECT * FROM t1 WHERE t1.a=expr OR t1.a IS NULL; SELECT * FROM t1, t2 WHERE t1.a=t2.a OR t2.a IS NULL; SELECT * FROM t1, t2 WHERE (t1.a=t2.a OR t2.a IS NULL) AND t2.b=t1.b; SELECT * FROM t1, t2 WHERE t1.a=t2.a AND (t2.b=t1.b OR t2.b IS NULL); SELECT * FROM t1, t2 WHERE (t1.a=t2.a AND t2.a IS NULL AND ...) OR (t1.a=t2.a AND t2.a IS NULL AND ...);
ref_or_null
works by first doing a read on the reference key,
and then a separate search for rows with a NULL
key value.
Note that the optimization can handle only one IS NULL
level.
In the following query, MySQL will use key lookups only on the expression
(t1.a=t2.a AND t2.a IS NULL)
and not be able to use the key part on
b
:
SELECT * FROM t1, t2 WHERE (t1.a=t2.a AND t2.a IS NULL) OR (t1.b=t2.b AND t2.b IS NULL);
DISTINCT
DISTINCT
combined with ORDER BY
will
need a temporary table in many cases.
Note that because DISTINCT
may use GROUP BY
, you should be
aware of how MySQL works with columns in ORDER BY
or HAVING
clauses that are not part of the selected columns.
See section 12.9.3 GROUP BY
with Hidden Fields.
In most cases, a DISTINCT
clause can be considered as a special case
of GROUP BY
. For example, the following two queries are equivalent:
SELECT DISTINCT c1, c2, c3 FROM t1 WHERE c1 > const; SELECT c1, c2, c3 FROM t1 WHERE c1 > const GROUP BY c1, c2, c3;
Due to this equivalence, the optimizations applicable to GROUP BY
queries can be also applied to queries with a DISTINCT
clause. Thus,
for more details on the optimization possibilities for DISTINCT
queries, see section 7.2.11 How MySQL Optimizes GROUP BY
.
When combining LIMIT row_count
with DISTINCT
, MySQL stops
as soon as it finds row_count unique rows.
If you don't use columns from all tables named in a query, MySQL stops
scanning the not-used tables as soon as it finds the first match.
In the following case, assuming that t1
is used before t2
(which you can check with EXPLAIN
), MySQL stops reading from t2
(for any particular row in t1
) when the first row in t2
is found:
SELECT DISTINCT t1.a FROM t1, t2 where t1.a=t2.a;
LEFT JOIN
and RIGHT JOIN
A LEFT JOIN B join_condition
is implemented in MySQL as follows:
B
is set to depend on table A
and all tables
on which A
depends.
A
is set to depend on all tables (except B
)
that are used in the LEFT JOIN
condition.
LEFT JOIN
condition is used to decide how to retrieve rows
from table B. (In other words, any condition in the WHERE
clause
is not used.)
WHERE
optimizations are done.
A
that matches the WHERE
clause, but there
is no row in B
that matches the ON
condition,
an extra B
row is generated with all columns set to NULL
.
LEFT JOIN
to find rows that don't exist in some
table and you have the following test: col_name IS NULL
in the
WHERE
part, where col_name is a column that is declared as
NOT NULL
, MySQL stops searching for more rows
(for a particular key combination) after it has found one row that
matches the LEFT JOIN
condition.
RIGHT JOIN
is implemented analogously to LEFT JOIN
, with the
roles of the tables reversed.
The join optimizer calculates the order in which tables should be joined.
The table read order forced by LEFT JOIN
and STRAIGHT_JOIN
helps the join optimizer do its work much more quickly, because there are
fewer table permutations to check.
Note that this means that if you do a query of the following type,
MySQL will do a full scan on b
because the LEFT JOIN
forces
it to be read before d
:
SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
The fix in this case is to rewrite the query as follows:
SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key) WHERE b.key=d.key;
Starting from 4.0.14, MySQL does the following LEFT JOIN
optimization:
If the WHERE
condition is always false for the generated
NULL
row, the LEFT JOIN
is changed to a normal join.
For example, the WHERE
clause would be
false in the following query
if t2.column1
would be NULL
:
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;
Therefore, it's safe to convert the query to a normal join:
SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;
This can be made faster because MySQL can use table t2
before
table t1
if this would result in a better query plan. To force a
specific table order, use STRAIGHT_JOIN
.
ORDER BY
In some cases, MySQL can use an index to satisfy an ORDER BY
clause without doing any extra sorting.
The index can also 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
are ORDER BY
columns are constants in the WHERE
clause. The following queries will use the index to resolve the
ORDER BY
part:
SELECT * FROM t1 ORDER BY key_part1,key_part2,... ; SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2; SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC;
In some cases, MySQL cannot use indexes to resolve the ORDER
BY
, although it still will use indexes to find the rows that
match the WHERE
clause. These cases include the following:
ORDER BY
on different keys:
SELECT * FROM t1 ORDER BY key1, key2;
ORDER BY
on non-consecutive key parts:
SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;
ASC
and DESC
:
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
ORDER BY
:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
ORDER
BY
are not all from the first non-constant table that is used to
retrieve rows. (This is the first table in the EXPLAIN
output that
doesn't have a const
join type.)
ORDER BY
and GROUP BY
expressions.
HASH
index in a HEAP
table.
With EXPLAIN SELECT ... ORDER BY
, you can check whether MySQL can use
indexes to resolve the query. It cannot if you see Using filesort
in
the Extra
column.
See section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
).
In those cases where MySQL must sort the result, it uses the following
filesort
algorithm before MySQL 4.1:
WHERE
clause are skipped.
sort_buffer_size
system variable.
MERGEBUFF
(7) regions to one block in
another temporary file. Repeat until all blocks from the first file
are in the second file.
MERGEBUFF2
(15)
blocks left.
read_rnd_buffer_size
system variable.
The code for this step is in the `sql/records.cc' source file.
One problem with this approach is that it reads rows twice: One time when
evaluating the WHERE
clause, and again after sorting the pair values.
And even if the rows were accessed successively the first time (for example,
if a table scan is done), the second time they are accessed randomly. (The
sort keys are ordered, but the row positions are not.)
In MySQL 4.1 and up, a filesort
optimization is used that records not
only the sort key value and row position, but also the columns required for
the query. This avoids reading the rows twice. The modified filesort
algorithm works like this:
WHERE
clause, as before.
Using the modified filesort
algorithm, the tuples are longer than the
pairs used in the original method, and fewer of them fit in the sort buffer
(the size of which is given by sort_buffer_size
). As a result, it is
possible for the extra I/O to make the modified approach slower, not faster.
To avoid a slowdown, the optimization is used only if the total size of the
extra columns in the sort tuple does not exceed the value of the
max_length_for_sort_data
system variable. (A symptom of setting the
value of this variable too high is that you will see high disk activity and
low CPU activity.)
If you want to increase ORDER BY
speed, first see whether you can get
MySQL to use indexes rather than an extra sorting phase. If this is not
possible, you can try the following strategies:
sort_buffer_size
variable.
read_rnd_buffer_size
variable.
tmpdir
to point to a dedicated filesystem with lots of empty
space. If you use MySQL 4.1 or later, this option accepts several paths
that are used in round-robin fashion. Paths should be separated by colon
characters (`:') on Unix and semicolon characters (`;') on
Windows, NetWare, and OS/2. You can use this feature to spread the load
across several directories. Note: The paths should be for
directories in filesystems that are located on different physical
disks, not different partitions of the same disk.
By default, MySQL sorts all GROUP BY col1, col2, ...
queries as if
you specified ORDER BY col1, col2, ...
in the query as well. If you
include an ORDER BY
clause explicitly that contains the same column
list, MySQL optimizes it away without any speed penalty, although the sorting
still occurs. If a query includes GROUP BY
but you want to avoid the
overhead of sorting the result, you can suppress sorting by specifying
ORDER BY NULL
. For example:
INSERT INTO foo SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;
GROUP BY
The most general way to satisfy a GROUP BY
clause is to scan the whole
table and create a new temporary table where all rows from each group are
consecutive, and then use this temporary table to discover groups and apply
aggregate functions (if any). In some cases, MySQL is able to do much better
than that and to avoid creation of temporary tables by using index access.
The most important preconditions for using indexes for GROUP BY
are
that all GROUP BY
columns reference attributes from the same index,
and the index stores its keys in order (for example, this is a B-Tree index,
and not a HASH index). Whether usage of temporary tables can be replaced by
index access also depends on which parts of an index are used in a query, the
conditions specified for these parts, and the selected aggregate functions.
There are two ways to execute a GROUP BY
query via index access,
as detailed in the following sections. In the first method, the grouping
operation is applied together with all range predicates (if any). The second
method first performs a range scan, and then groups the resulting tuples.
The most efficient way is when the index is used to directly retrieve
the group fields. With this access method, MySQL uses the property of
some index types (for example, B-Trees) that the keys are ordered. This
property allows use of lookup groups in an index without having to consider
all keys in the index that satisfy all WHERE
conditions. Since
this access method considers only a fraction of the keys in an index,
it is called ``loose index scan.'' When there is no WHERE
clause,
a loose index scan will read as many keys as the number of groups, which
may be a much smaller number than all keys. If the WHERE
clause
contains range predicates (described in section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
),
under the range
join type), a loose index scan looks up the first key of
each group that satisfies the range conditions, and again reads the least
possible number of keys. This is possible under the following conditions:
GROUP BY
includes the first consecutive parts of the index
(if instead of GROUP BY
, the query has a DISTINCT
clause,
then all distinct attributes refer to the beginning of the index).
MIN()
and MAX()
,
and all of them refer to the same column.
GROUP BY
referenced in the
query must be constants (that is, they must be referenced in equalities
with constants), except for the argument of MIN()
or MAX()
functions.
The EXPLAIN
output for such queries shows Using index for
group-by
in the Extra
column.
The following queries provide several examples that fall into this
category, assuming there is an index idx(c1, c2, c3)
on table
t1(c1,c2,c3,c4)
:
SELECT c1, c2 FROM t1 GROUP BY c1, c2; SELECT DISTINCT c1, c2 FROM t1; SELECT c1, MIN(c2) FROM t1 GROUP BY c1; SELECT c1, c2 FROM t1 WHERE c1 < const GROUP BY c1, c2; SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 > const GROUP BY c1, c2; SELECT c2 FROM t1 WHERE c1 < const GROUP BY c1, c2; SELECT c1, c2 FROM t1 WHERE c3 = const GROUP BY c1, c2;
The following queries cannot be executed with this quick select method, for the reasons given:
MIN()
or MAX()
:
SELECT c1, SUM(c2) FROM t1 GROUP BY c1;
GROUP BY
do not refer to the beginning of the index:
SELECT c1,c2 FROM t1 GROUP BY c2, c3;
GROUP BY
parts,
and for which there is no equality with a constant:
SELECT c1,c3 FROM t1 GROUP BY c1, c2;
A tight index scan may be either a full index scan or a range index scan, depending on the query conditions.
When the conditions for a loose index scan are not met, it is still
possible to avoid creation of temporary tables for GROUP BY
queries. If there are range conditions in the WHERE
clause, this
method will read only the keys that satisfy these conditions. Otherwise,
it performs an index scan. Since this method reads all keys in each range
defined by the WHERE
clause, or scans the whole index if there are
no range conditions, we term it a ``tight index scan.'' Notice that with a
tight index scan, the grouping operation is performed after all keys that
satisfy the range conditions have been found.
For this method to work, it is sufficient that for all columns in a query
referring to key parts before or in between the GROUP BY
key parts,
there is a constant equality condition. The constants from the equality
conditions fill in the ``gaps'' in the search keys so that it is possible
to form complete prefixes of the index. Then these index prefixes can
be used for index lookups. If we require sorting of the GROUP BY
result, and it is possible to form search keys that are prefixes of the
index, MySQL also will avoid sorting because searching with prefixes in
an ordered index retrieves all keys in order.
The following queries will not work with the first method above, but will
still work with the second index access method (assuming we have the
aforementioned index idx
on table t1
):
GROUP BY
, but it is covered by the condition (c2 = 'a').
SELECT c1, c2, c3 FROM t1 WHERE c2 = 'a' GROUP BY c1, c3;
GROUP BY
does not begin from the first key part, but there is a
condition that provides a constant for that key part:
SELECT c1, c2, c3 FROM t1 WHERE c1 = 'a' GROUP BY c2, c3;
LIMIT
In some cases, MySQL will handle a query differently when you are
using LIMIT row_count
and not using HAVING
:
LIMIT
, MySQL
uses indexes in some cases when normally it would prefer to do a
full table scan.
LIMIT row_count
with ORDER BY
, MySQL ends the
sorting as soon as it has found the first row_count lines rather
than sorting the whole table.
LIMIT row_count
with DISTINCT
, MySQL stops
as soon as it finds row_count unique rows.
GROUP BY
can be resolved by reading the key in order
(or doing a sort on the key) and then calculating summaries until the
key value changes. In this case, LIMIT row_count
will not calculate any
unnecessary GROUP BY
values.
SQL_CALC_FOUND_ROWS
.
LIMIT 0
always quickly returns an empty set. This is useful
to check the query or to get the column types of the result columns.
LIMIT row_count
is used to calculate how much space is required.
The output from EXPLAIN
will show ALL
in the type
column when MySQL uses a table scan to resolve a query. This usually happens
under the following conditions:
ON
or WHERE
clause
for indexed columns.
WHERE
Clauses.
For small tables, a table scan often is appropriate. For large tables, try the following techniques to avoid having the optimizer incorrectly choose a table scan:
ANALYZE TABLE tbl_name
to update the key distributions for the
scanned table. See section 13.5.2.1 ANALYZE TABLE
Syntax.
FORCE INDEX
for the scanned table to tell MySQL that table
scans are very expensive compared to using the given index.
See section 13.1.7 SELECT
Syntax.
SELECT * FROM t1, t2 FORCE INDEX (index_for_column) WHERE t1.col_name=t2.col_name;
mysqld
with the --max-seeks-for-key=1000
option or use
SET max_seeks_for_key=1000
to tell the optimizer to assume that no
key scan will cause more than 1,000 key seeks.
See section 5.2.3 Server System Variables.
INSERT
StatementsThe time to insert a record is determined by the following factors, where the numbers indicate approximate proportions:
This does not take into consideration the initial overhead to open tables, which is done once for each concurrently running query.
The size of the table slows down the insertion of indexes by log N, assuming B-tree indexes.
You can use the following methods to speed up inserts:
INSERT
statements with multiple VALUES
lists to insert several
rows at a time. This is much faster (many times faster in some cases) than
using separate single-row INSERT
statements. If you are adding data
to a non-empty table, you may tune the bulk_insert_buffer_size
variable to make it even faster.
See section 5.2.3 Server System Variables.
INSERT DELAYED
statement. See section 13.1.4 INSERT
Syntax.
MyISAM
tables you can insert rows at the same time that
SELECT
statements are running if there are no deleted rows in the
tables.
LOAD DATA INFILE
. This
is usually 20 times faster than using a lot of INSERT
statements.
See section 13.1.5 LOAD DATA INFILE
Syntax.
LOAD DATA INFILE
run even
faster when the table has many indexes. Use the following procedure:
CREATE TABLE
.
FLUSH TABLES
statement or a mysqladmin flush-tables
command.
myisamchk --keys-used=0 -rq /path/to/db/tbl_name.
This will
remove all use of all indexes for the table.
LOAD DATA INFILE
. This will not
update any indexes and will therefore be very fast.
myisampack
to make it smaller. See section 14.1.3.3 Compressed Table Characteristics.
myisamchk -r -q
/path/to/db/tbl_name
. This will create the index tree in memory before
writing it to disk, which is much faster because it avoids lots of disk
seeks. The resulting index tree is also perfectly balanced.
FLUSH TABLES
statement or a mysqladmin flush-tables
command.
LOAD DATA INFILE
also performs the preceding optimization
if you insert into an empty MyISAM
table; the main difference is that you can let
myisamchk
allocate much more temporary memory for the index creation
than you might want the server to allocate for index re-creation when it
executes the LOAD DATA INFILE
statement.
As of MySQL 4.0, you can also use
ALTER TABLE tbl_name DISABLE KEYS
instead of
myisamchk --keys-used=0 -rq /path/to/db/tbl_name
and
ALTER TABLE tbl_name ENABLE KEYS
instead of
myisamchk -r -q /path/to/db/tbl_name
. This way you can also skip the
FLUSH TABLES
steps.
INSERT
operations that are done
with multiple statements by locking your tables:
LOCK TABLES a WRITE; INSERT INTO a VALUES (1,23),(2,34),(4,33); INSERT INTO a VALUES (8,26),(6,29); UNLOCK TABLES;A performance benefit occurs because the index buffer is flushed to disk only once, after all
INSERT
statements have completed. Normally there would
be as many index buffer flushes as there are different INSERT
statements. Explicit locking statements are not needed if you can insert
all rows with a single statement.
For transactional tables, you should use BEGIN/COMMIT
instead of
LOCK TABLES
to get a speedup.
Locking also lowers the total time of multiple-connection tests, although the
maximum wait time for individual connections might go up because they wait for
locks. For example:
Connection 1 does 1000 inserts Connections 2, 3, and 4 do 1 insert Connection 5 does 1000 insertsIf you don't use locking, connections 2, 3, and 4 will finish before 1 and 5. If you use locking, connections 2, 3, and 4 probably will not finish before 1 or 5, but the total time should be about 40% faster.
INSERT
, UPDATE
, and DELETE
operations are very
fast in MySQL, but you will obtain better overall performance by
adding locks around everything that does more than about five inserts or
updates in a row. If you do very many inserts in a row, you could do a
LOCK TABLES
followed by an UNLOCK TABLES
once in a while
(about each 1,000 rows) to allow other threads access to the table. This
would still result in a nice performance gain.
INSERT
is still much slower for loading data than LOAD DATA
INFILE
, even when using the strategies just outlined.
MyISAM
tables, for both LOAD DATA
INFILE
and INSERT
, enlarge the key cache by increasing the
key_buffer_size
system variable.
See section 7.5.2 Tuning Server Parameters.
UPDATE
Statements
Update statements are optimized as a SELECT
query with the additional
overhead of a write. The speed of the write depends on the amount of
data being updated and the number of indexes that are updated. Indexes that
are not changed will not be updated.
Also, another way to get fast updates is to delay updates and then do many updates in a row later. Doing many updates in a row is much quicker than doing one at a time if you lock the table.
Note that for a MyISAM
table that uses dynamic record format,
updating a record to a longer total length may split the record. If you do
this often, it is very important to use OPTIMIZE TABLE
occasionally.
See section 13.5.2.5 OPTIMIZE TABLE
Syntax.
DELETE
StatementsThe time to delete individual records is exactly proportional to the number of indexes. To delete records more quickly, you can increase the size of the key cache. See section 7.5.2 Tuning Server Parameters.
If you want to delete all rows in the table, use TRUNCATE TABLE
tbl_name
rather than DELETE FROM tbl_name
.
See section 13.1.9 TRUNCATE
Syntax.
This section lists a number of miscellaneous tips for improving query processing speed:
thread_cache_size
variable. See section 7.5.2 Tuning Server Parameters.
EXPLAIN
statement. See section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
).
SELECT
queries on MyISAM
tables that are
updated frequently, to avoid problems with table locking that occur
due to contention between readers and writers.
MyISAM
tables that have no deleted rows, you can insert rows at
the end at the same time that another query is reading from the table. If this
is important for you, you should consider using the table in ways that avoid
deleting rows. Another possibility is to run OPTIMIZE TABLE
after you
have deleted a lot of rows.
ALTER TABLE ... ORDER BY expr1, expr2, ...
if you mostly
retrieve rows in expr1, expr2, ...
order. By using this option after
extensive changes to the table, you may be able to get higher performance.
SELECT * FROM tbl_name WHERE hash_col=MD5(CONCAT(col1,col2)) AND col1='constant' AND col2='constant';
MyISAM
tables that change a lot, you should try to avoid all
variable-length columns (VARCHAR
, BLOB
, and TEXT
). The
table will use dynamic record format if it includes even a single
variable-length column.
See section 14 MySQL Storage Engines and Table Types.
MyISAM
table with dynamic record format (see above) that you can
change to a fixed record size,
or if you very often need to scan the table but do not need
most of the columns. See section 14 MySQL Storage Engines and Table Types.
UPDATE tbl_name SET count_col=count_col+1 WHERE key_col=constant;This is really important when you use MySQL storage engines such as
MyISAM
and ISAM
that have only table-level locking (multiple
readers / single writers). This will also give better performance with most
databases, because the row locking manager in this case will have less to do.
BLOB
column. In this case, you must add some extra code in your application to
pack and unpack information in the BLOB
values, but this may save a
lot of accesses at some stage. This is practical when you have data that
doesn't conform to a rows-and-columns table structure.
INSERT DELAYED
when you do not need to know when your
data is written. This speeds things up because many records can be written
with a single disk write.
INSERT LOW_PRIORITY
when you want to give SELECT
statements higher priority than your inserts.
SELECT HIGH_PRIORITY
to get retrievals that jump the
queue. That is, the SELECT
is done even if there is another client
waiting to do a write.
INSERT
statements to store many rows with one
SQL statement (many SQL servers support this).
LOAD DATA INFILE
to load large amounts of data. This is
faster than using INSERT
statements.
AUTO_INCREMENT
columns to generate unique values.
OPTIMIZE TABLE
once in a while to avoid fragmentation
with MyISAM
tables
when
using a dynamic table format.
See section 14.1.3 MyISAM
Table Storage Formats.
HEAP
tables when possible to get more speed.
See section 14 MySQL Storage Engines and Table Types.
customer
,
use a column name of name
instead of customer_name
. To make
your names portable to other SQL servers, you should keep them shorter than
18 characters.
MyISAM
storage engine directly, you could
get a speed increase of two to five times compared to using the SQL interface.
To be able to do this, the data must be on the same server as
the application, and usually it should only be accessed by one process
(because external file locking is really slow). One could eliminate these
problems by introducing low-level MyISAM
commands in the
MySQL server (this could be one easy way to get more
performance if needed). By carefully designing the database interface,
it should be quite easy to support this types of optimization.
MyISAM
table with the DELAY_KEY_WRITE=1
table
option makes index updates faster because they are not flushed to disk
until the table is closed. The downside is that if something kills the
server while such a table is open, you should ensure that they are okay by
running the server with the --myisam-recover
option, or by
running myisamchk
before restarting the server. (However, even in
this case, you should not lose anything by using DELAY_KEY_WRITE
,
because the key information can always be generated from the data rows.)
Currently, MySQL supports table-level locking for ISAM
,
MyISAM
, and MEMORY
(HEAP
) tables, page-level locking
for BDB
tables, and row-level locking for InnoDB
tables.
In many cases, you can make an educated guess about which locking type is best for an 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 parts of an application may require different lock types.
To decide whether you want to use a storage engine with row-level locking,
you will want to look at what your application does and what mix of select
and update statements it uses. For example, most Web applications do lots
of selects, very few deletes, updates based mainly on key values, and
inserts into some specific tables. The base MySQL MyISAM
setup is
very well tuned for this.
Table locking in MySQL is deadlock-free for storage engines that use table-level locking. Deadlock avoidance is managed by always requesting all needed locks at once at the beginning of a query and always locking the tables in the same order.
The table-locking method MySQL uses for WRITE
locks works as follows:
The table-locking method MySQL uses for READ
locks works as follows:
When a lock is released, the lock is made available to the threads in the write lock queue, then to the threads in the read lock queue.
This means that if you have many updates for a table, SELECT
statements will wait until there are no more updates.
Starting in MySQL 3.23.33, you can analyze the table lock contention
on your system by checking the Table_locks_waited
and
Table_locks_immediate
status variables:
mysql> SHOW STATUS LIKE 'Table%'; +-----------------------+---------+ | Variable_name | Value | +-----------------------+---------+ | Table_locks_immediate | 1151552 | | Table_locks_waited | 15324 | +-----------------------+---------+
As of MySQL 3.23.7 (3.23.25 for Windows), you can freely mix concurrent
INSERT
and SELECT
statements for a MyISAM
table without
locks if the INSERT
statements are non-conflicting. That is, you can
insert rows into a MyISAM
table at the same time other clients are
reading from it. No conflict occurs if the data file contains no free
blocks in the middle, because in that case, records always are inserted at
the end of the data file. (Holes can result from rows having been deleted
from or updated in the middle of the table.) If there are holes, concurrent
inserts are re-enabled automatically when all holes have been filled with
new data.
If you want to do many INSERT
and SELECT
operations on a table
when concurrent inserts are not possible, you can insert rows in a temporary
table and update the real table with the records from the temporary table
once in a while. This can be done with the following code:
mysql> LOCK TABLES real_table WRITE, insert_table WRITE; mysql> INSERT INTO real_table SELECT * FROM insert_table; mysql> TRUNCATE TABLE insert_table; mysql> UNLOCK TABLES;
InnoDB
uses row locks and BDB
uses page locks. For the
InnoDB
and BDB
storage engines, deadlock is possible. This is
because InnoDB
automatically acquires row locks and BDB
acquires page locks during the processing of SQL statements, not at the
start of the transaction.
Advantages of row-level locking:
Disadvantages of row-level locking:
GROUP
BY
operations on a large part of the data or if you often must scan the
entire table.
Table locks are superior to page-level or row-level locks in the following cases:
UPDATE tbl_name SET column=value WHERE unique_key_col=key_value; DELETE FROM tbl_name WHERE unique_key_col=key_value;
SELECT
combined with concurrent INSERT
statements, and very
few UPDATE
and DELETE
statements.
GROUP BY
operations on the entire table without any writers.
Options other than row-level or page-level locking:
Versioning (such as 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 you started to access it. Other names for this are time travel, copy on write, or copy on demand.
Copy on demand is in many cases much better than page-level or row-level locking. However, the worst case does use much more memory than when using normal locks.
Instead of using row-level locks, you can use application-level locks,
such as GET_LOCK()
and RELEASE_LOCK()
in MySQL. These are
advisory locks, so they work only in well-behaved applications.
To achieve a very high lock speed, MySQL uses table locking (instead of
page, row, or column locking) for all storage engines except InnoDB
and BDB
.
For InnoDB
and BDB
tables, MySQL only uses table locking if
you explicitly lock the table with LOCK TABLES
. For these table
types, we recommend you to not use LOCK TABLES
at all, because
InnoDB
uses automatic row-level locking and BDB
uses
page-level locking to ensure transaction isolation.
For large tables, table locking is much better than row locking for most applications, but there are some pitfalls.
Table locking enables many threads to read from a table at the same time, but if a thread wants to write to a table, it must first get exclusive access. During the update, all other threads that want to access this particular table must wait until the update is done.
Table updates normally are considered to be more important than table
retrievals, so they are given higher priority. This should ensure that
updates to a table are not ``starved'' even if there is heavy SELECT
activity for the table.
Table locking causes problems in cases such as when a thread is waiting because the disk is full and free space needs to become available before the thread can proceed. In this case, all threads that want to access the problem table will also be put in a waiting state until more disk space is made available.
Table locking is also disadvantageous under the following scenario:
SELECT
that takes a long time to run.
UPDATE
on the same table. This client
will wait until the SELECT
is finished.
SELECT
statement on the same table.
Because
UPDATE
has higher priority than SELECT
, this SELECT
will wait for the UPDATE
to finish. It will also wait for the first
SELECT
to finish!
The following list describes some ways to avoid or reduce contention caused by table locking:
SELECT
statements to run faster. You might have to
create some summary tables to do this.
mysqld
with --low-priority-updates
. This gives
all statements that update (modify) a table lower priority than SELECT
statements. In this case, the second SELECT
statement in the preceding
scenario would execute before the INSERT
statement, and would not need
to wait for the first SELECT
to finish.
SET LOW_PRIORITY_UPDATES=1
statement.
See section 13.5.3 SET
Syntax.
INSERT
, UPDATE
, or DELETE
statement lower priority with the LOW_PRIORITY
attribute.
SELECT
statement higher priority with the
HIGH_PRIORITY
attribute. See section 13.1.7 SELECT
Syntax.
mysqld
with a low value for
the max_write_lock_count
system variable to force MySQL to
temporarily elevate the priority of all SELECT
statements that are
waiting for a table after a specific number of inserts to the table occur.
This allows READ
locks after a certain number of WRITE
locks.
INSERT
combined with SELECT
, switch
to using MyISAM
tables, which support concurrent SELECT
and
INSERT
statements.
INSERT DELAYED
may be of great help.
See section 13.1.4.2 INSERT DELAYED
Syntax.
SELECT
and DELETE
statements,
the LIMIT
option to DELETE
may help.
See section 13.1.1 DELETE
Syntax.
SQL_BUFFER_RESULT
with SELECT
statements can help to
make the duration of table locks shorter.
See section 13.1.7 SELECT
Syntax.
Here are some tips about table locking in MySQL:
LOCK TABLES
to speed up things (many updates within
a single lock is much faster than updates without locks). Splitting
table contents into separate tables may also help.
InnoDB
or
BDB
tables.
See section 15 The InnoDB
Storage Engine.
See section 14.4 The BDB
(BerkeleyDB
) Storage Engine.
MySQL keeps row data and index data in separate files. Many (almost all) other databases mix row and index data in the same file. We believe that the MySQL choice is better for a very wide range of modern systems.
Another way to store the row data is to keep the information for each column in a separate area (examples are SDBM and Focus). This will cause a performance hit for every query that accesses more than one column. Because this degenerates so quickly when more than one column is accessed, we believe that this model is not good for general-purpose databases.
The more common case is that the index and data are stored together (as in Oracle/Sybase, et al). In this case, you will find the row information at the leaf page of the index. The good thing with this layout is that it, in many cases, depending on how well the index is cached, saves a disk read. The bad things with this layout are:
One of the most basic optimizations is to design your tables to take as little space on the disk as possible. This can give huge improvements because disk reads are faster, and smaller tables normally require less main memory while their contents are being actively processed during query execution. Indexing also is a lesser resource burden if done on smaller columns.
MySQL supports a lot of different table types and row formats. For each table, you can decide which storage/index method to use. Choosing the right table format for your application may give you a big performance gain. See section 14 MySQL Storage Engines and Table Types.
You can get better performance on a table and minimize storage space using the techniques listed here:
MEDIUMINT
is often better than INT
.
NOT NULL
if possible. It makes everything
faster and you save one bit per column. If you really need
NULL
in your application, you should definitely use it. Just avoid
having it on all columns by default.
MyISAM
tables, if you don't have any variable-length columns
(VARCHAR
, TEXT
, or BLOB
columns), a fixed-size record
format is used. This is faster but unfortunately may waste some space.
See section 14.1.3 MyISAM
Table Storage Formats.
You can hint that you want to have fixed length rows even if you have
VARCHAR
columns with the CREATE
option
ROW_FORMAT=fixed
.
InnoDB
tables use a more
compact storage format. In earlier versions of MySQL, InnoDB records
contain some redundant information, such as the number of columns and
the lengths of each column, even for fixed-size columns. By default,
tables will be created in the compact format
(ROW_FORMAT=COMPACT
). If you wish to downgrade to older
versions of MySQL/InnoDB, you can request the old format with
ROW_FORMAT=REDUNDANT
.
All MySQL column types can be indexed. Use of indexes on the
relevant columns is the best way to improve the performance of SELECT
operations.
The maximum number of indexes per table and the maximum index length is defined per storage engine. See section 14 MySQL Storage Engines and Table Types. All storage engines support at least 16 indexes per table and a total index length of at least 256 bytes. Most storage engines have higher limits.
With col_name(length)
syntax in an index specification,
you can create an index that uses only the first length characters of
a CHAR
or VARCHAR
column. Indexing only a prefix of column
values like this can make the index file much smaller.
The MyISAM
and (as of MySQL 4.0.14) InnoDB
storage engines also
support indexing on BLOB
and TEXT
columns. When indexing
a BLOB
or TEXT
column, you must specify a prefix
length for the index. For example:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
Prefixes can be up to 255 bytes long (or 1000 bytes for MyISAM
and InnoDB
tables as of MySQL 4.1.2). Note that prefix limits
are measured in bytes, whereas the prefix length in CREATE TABLE
statements is interpreted as number of characters. Take this into account
when specifying a prefix length for a column that uses a multi-byte
character set.
As of MySQL 3.23.23, you can also create FULLTEXT
indexes.
They are used for full-text searches. Only the MyISAM
table type
supports FULLTEXT
indexes and only for CHAR
, VARCHAR
,
and TEXT
columns. Indexing always happens over the entire column and
partial (prefix) indexing is not supported. See section 12.6 Full-Text Search Functions for
details.
As of MySQL 4.1.0, you can create indexes on spatial column types.
Currently, spatial types are supported only by the MyISAM
storage
engine. Spatial indexes use R-trees.
The MEMORY
(HEAP
) storage engine uses hash indexes by default.
It also supports B-tree indexes as of MySQL 4.1.0.
MySQL can create indexes on multiple columns. An index may consist of up to 15 columns. For certain column types, you can index a prefix of the column (see section 7.4.3 Column Indexes).
A multiple-column index can be considered a sorted array containing values that are created by concatenating the values of the indexed columns.
MySQL uses multiple-column indexes in such a way that queries are
fast when you specify a known quantity for the first column of the index in a
WHERE
clause, even if you don't specify values for the other columns.
Suppose that a table has the following specification:
CREATE TABLE test ( id INT NOT NULL, last_name CHAR(30) NOT NULL, first_name CHAR(30) NOT NULL, PRIMARY KEY (id), INDEX name (last_name,first_name));
The name
index is an index over last_name
and
first_name
. The index can be used for queries that specify
values in a known range for last_name
, or for both last_name
and first_name
.
Therefore, the name
index will be used in the following queries:
SELECT * FROM test WHERE last_name='Widenius'; SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael'; SELECT * FROM test WHERE last_name='Widenius' AND (first_name='Michael' OR first_name='Monty'); SELECT * FROM test WHERE last_name='Widenius' AND first_name >='M' AND first_name < 'N';
However, the name
index will not be used in the following
queries:
SELECT * FROM test WHERE first_name='Michael'; SELECT * FROM test WHERE last_name='Widenius' OR first_name='Michael';
The manner in which MySQL uses indexes to improve query performance is discussed further in the next section.
Indexes are used to find rows with specific column values fast. Without an index, MySQL has to start with the first record and then read through the whole table to find the relevant rows. The larger the table, the more this costs. If the table has an index for the columns in question, MySQL can quickly determine the position to seek to in the middle of the data file without having to look at all the data. If a table has 1,000 rows, this is at least 100 times faster than reading sequentially. Note that if you need to access almost all 1,000 rows, it is faster to read sequentially, because that minimizes disk seeks.
Most MySQL indexes (PRIMARY KEY
, UNIQUE
, INDEX
, and
FULLTEXT
) are stored in B-trees. Exceptions are that indexes on
spatial column types use R-trees, and MEMORY
(HEAP
) tables
support hash indexes.
Strings are automatically prefix- and end-space compressed.
See section 13.2.5 CREATE INDEX
Syntax.
In general, indexes are used as described in the following discussion.
Characteristics specific to hash indexes (as used in MEMORY
tables)
are described at the end of this section.
Indexes are used for these operations:
WHERE
clause.
MIN()
or MAX()
value for a specific indexed column
key_col. This is optimized by a preprocessor that checks whether you are
using WHERE key_part_# = constant
on all key parts that occur before
key_col in the index. In this case, MySQL will do a single key
lookup for each MIN()
or MAX()
expression and replace it
with a constant. If all expressions are replaced with constants, the
query will return at once. For example:
SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1=10;
ORDER BY key_part1,
key_part2
). If all key parts are followed by DESC
, the key
is read in reverse order.
See section 7.2.10 How MySQL Optimizes ORDER BY
.
SELECT key_part3 FROM tbl_name WHERE key_part1=1
Suppose that you issue the following SELECT
statement:
mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
If a multiple-column index exists on col1
and col2
, the
appropriate rows can be fetched directly. If separate single-column
indexes exist on col1
and col2
, the optimizer tries to
find the most restrictive index by deciding which index will find fewer
rows and using that index to fetch the rows.
If the table has a multiple-column index, any leftmost prefix of the
index can be used by the optimizer to find rows. For example, if you
have a three-column index on (col1, col2, col3)
, you have indexed
search capabilities on (col1)
, (col1, col2)
, and
(col1, col2, col3)
.
MySQL can't use a partial index if the columns don't form a
leftmost prefix of the index. Suppose that you have the SELECT
statements shown here:
SELECT * FROM tbl_name WHERE col1=val1; SELECT * FROM tbl_name WHERE col2=val2; SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
If an index exists on (col1, col2, col3)
, only the first of the preceding
queries uses the index. The second and third queries do involve
indexed columns, but (col2)
and (col2, col3)
are not
leftmost prefixes of (col1, col2, col3)
.
A B-tree index can be used for column comparisons in expressions that use
the =
, >
, >=
, <
, <=
, or BETWEEN
operators. The index also can be used for LIKE
comparisons if the
argument to LIKE
is a constant string that doesn't start with a
wildcard character. For example, the following SELECT
statements
use indexes:
SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%'; SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';
In the first statement, only rows with 'Patrick' <= key_col <
'Patricl'
are considered. In the second statement, only rows with
'Pat' <= key_col < 'Pau'
are considered.
The following SELECT
statements will not use indexes:
SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%'; SELECT * FROM tbl_name WHERE key_col LIKE other_col;
In the first statement, the LIKE
value begins with a wildcard
character. In the second statement, the LIKE
value is not a
constant.
MySQL 4.0 and up performs an additional LIKE
optimization. If you use
... LIKE '%string%'
and string is longer than three characters,
MySQL will use the Turbo Boyer-Moore
algorithm to initialize the
pattern for the string and then use this pattern to perform the search
quicker.
Searching using col_name IS NULL
will use indexes if col_name
is indexed.
Any index that doesn't span all AND
levels in the WHERE
clause
is not used to optimize the query. In other words, to be able to use an
index, a prefix of the index must be used in every AND
group.
The following WHERE
clauses use indexes:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3 /* index = 1 OR index = 2 */ ... WHERE index=1 OR A=10 AND index=2 /* optimized like "index_part1='hello'" */ ... WHERE index_part1='hello' AND index_part3=5 /* Can use index on index1 but not on index2 or index3 */ ... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;
These WHERE
clauses do not use indexes:
/* index_part1 is not used */ ... WHERE index_part2=1 AND index_part3=2 /* Index is not used in both AND parts */ ... WHERE index=1 OR A=10 /* No index spans all rows */ ... WHERE index_part1=1 OR index_part2=10
Sometimes MySQL will not use an index, even if one is available. One way
this occurs is when the optimizer estimates that using the index would
require MySQL to access a large percentage of the rows in the table.
(In this case, a table scan is probably much faster, because it will
require many fewer seeks.) However, if such a query uses LIMIT
to
only retrieve part of the rows, MySQL will use an index anyway, because
it can much more quickly find the few rows to return in the result.
Hash indexes have somewhat different characteristics than those just discussed:
=
or
<=>
operators (but are very fast). They are not used for
comparison operators such as <
that find a range of values.
ORDER BY
operations. (This type of index cannot be used to search for the next entry
in order.)
MyISAM
table to a hash-indexed MEMORY
table.
MyISAM
Key Cache
To minimize disk I/O, the MyISAM
storage engine employs a strategy that
is used by many database management systems. It exploits a cache
mechanism to keep the most frequently accessed table blocks in memory:
This section first describes the basic operation of the MyISAM
key
cache. Then it discusses changes made in MySQL 4.1 that improve key cache
performance and that enable you to better control cache operation:
The key cache mechanism also is used for ISAM
tables. However, the
significance of this fact is on the wane. ISAM
table use has been
decreasing since MySQL 3.23 when MyISAM
was introduced. MySQL 4.1
carries this trend further; the ISAM
storage engine is disabled by
default.
You can control the size of the key cache by means of the
key_buffer_size
system variable. If this variable is set equal
to zero, no key cache is used. The key cache also is not used if the
key_buffer_size
value is too small to allocate the minimal number
of block buffers (8).
When the key cache is not operational, index files are accessed using only the native filesystem buffering provided by the operating system. (In other words, table index blocks are accessed using the same strategy as that employed for table data blocks.)
An index block is a contiguous unit of access to the MyISAM
index files.
Usually the size of an index block is equal to the size of nodes of the
index B-tree. (Indexes are represented on disk using a B-tree data structure.
Nodes at the bottom of the tree are leaf nodes. Nodes above the leaf nodes
are non-leaf nodes.)
All block buffers in a key cache structure are the same size. This size can be equal to, greater than, or less than the size of a table index block. Usually one these two values is a multiple of the other.
When data from any table index block must be accessed, the server first checks whether it is available in some block buffer of the key cache. If it is, the server accesses data in the key cache rather than on disk. That is, it reads from the cache or writes into it rather than reading from or writing to disk. Otherwise, the server chooses a cache block buffer containing a different table index block (or blocks) and replaces the data there by a copy of required table index block. As soon as the new index block is in the cache, the index data can be accessed.
If it happens that a block selected for replacement has been modified, the block is considered ``dirty.'' In this case, before being replaced, its contents are flushed to the table index from which it came.
Usually the server follows an LRU (Least Recently Used) strategy: When choosing a block for replacement, it selects the least recently used index block. To be able to make such a choice easy, the key cache module maintains a special queue (LRU chain) of all used blocks. When a block is accessed, it is placed at the end of the queue. When blocks need to be replaced, blocks at the beginning of the queue are the least recently used and become the first candidates for eviction.
Prior to MySQL 4.1, access to the key cache is serialized: No two threads can access key cache buffers simultaneously. The server processes a request for an index block only after it has finished processing the previous request. As a result, a request for an index block not present in any key cache buffer blocks access by other threads while a buffer is being updated to contain the requested index block.
Starting from version 4.1.0, the server supports shared access to the key cache:
Shared access to the key cache allows the server to improve throughput significantly.
Shared access to the key cache improves performance but does not eliminate contention among threads entirely. They still compete for control structures that manage access to the key cache buffers. To reduce key cache access contention further, MySQL 4.1.1 offers the feature of multiple key caches. This allows you to assign different table indexes to different key caches.
When there can be multiple key caches, the server must know which cache to
use when processing queries for a given MyISAM
table. By default, all
MyISAM
table indexes are cached in the default key cache. To assign
table indexes to a specific key cache, use the CACHE INDEX
statement.
For example, the following statement assigns indexes from the tables
t1
, t2
, and t3
to the key cache named hot_cache
:
mysql> CACHE INDEX t1, t2, t3 IN hot_cache; +---------+--------------------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------+--------------------+----------+----------+ | test.t1 | assign_to_keycache | status | OK | | test.t2 | assign_to_keycache | status | OK | | test.t3 | assign_to_keycache | status | OK | +---------+--------------------+----------+----------+
Note: If the server has been built with the ISAM
storage
engine enabled, ISAM
tables use the key cache mechanism. However,
ISAM
indexes use only the default key cache and cannot be reassigned to
a different cache.
The key cache referred to in a CACHE INDEX
statement can be created
by setting its size with a SET GLOBAL
parameter setting statement or by
using server startup options. For example:
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
To destroy a key cache, set its size to zero:
mysql> SET GLOBAL keycache1.key_buffer_size=0;
Key cache variables are structured system variables that have a name and
components. For keycache1.key_buffer_size
, keycache1
is the
cache variable name and key_buffer_size
is the cache component.
See section 9.4.1 Structured System Variables for a description of the syntax used
for referring to structured key cache system variables.
By default, table indexes are assigned to the main (default) key cache created at the server startup. When a key cache is destroyed, all indexes assigned to it are reassigned to the default key cache.
For a busy server, we recommend a strategy that uses three key caches:
One reason the use of three key caches is beneficial is that access to one key cache structure does not block access to the others. Queries that access tables assigned to one cache do not compete with queries that access tables assigned to another cache. Performance gains occur for other reasons as well:
CACHE INDEX
sets up an association between a table and a key cache,
but the association is lost each time the server restarts. If you want the
association to take effect each time the server starts, one way to accomplish
this is to use an option file: Include variable settings that configure
your key caches, and an init-file
option that names a file containing
CACHE INDEX
statements to be executed. For example:
key_buffer_size = 4G hot_cache.key_buffer_size = 2G cold_cache.key_buffer_size = 2G init_file=/path/to/data-directory/mysqld_init.sql
The statements in `mysqld_init.sql' will be executed each time the
server starts. It should contain one SQL statement per line. The following
example assigns several tables each to hot_cache
and cold_cache
:
CACHE INDEX a.t1, a.t2, b.t3 IN hot_cache CACHE INDEX a.t4, b.t5, b.t6 IN cold_cache
By default, the key cache management system of MySQL 4.1 uses the LRU strategy for choosing key cache blocks to be evicted, but it also supports a more sophisticated method called the "midpoint insertion strategy."
When using the midpoint insertion strategy, the LRU chain is divided into
two parts: a hot sub-chain and a warm sub-chain. The division point between
two parts is not fixed, but the key cache management system takes care that
the warm part is not ``too short,'' always containing at least
key_cache_division_limit
percent of the key cache blocks.
key_cache_division_limit
is a component of structured key cache
variables, so its value is a parameter that can be set per cache.
When an index block is read from a table into the key cache, it is placed at the end of the warm sub-chain. After a certain number of hits (accesses of the block), it is promoted to the hot sub-chain. At present, the number of hits required to promote a block (3) is the same for all index blocks. In the future, we will allow the hit count to depend on the B-tree level of the node corresponding to an index block: Fewer hits will be required for promotion of an index block if it contains a non-leaf node from the upper levels of the index B-tree than if it contains a leaf node.
A block promoted into the hot sub-chain is placed at the end of the chain.
The block then circulates within this sub-chain. If the block stays at the
beginning of the sub-chain for a long enough time, it is demoted to the warm
chain. This time is determined by the value of the
key_cache_age_threshold
component of the key cache.
The threshold value prescribes that, for a key cache containing N
blocks, the block at the beginning of the hot sub-chain not accessed within
the last N*key_cache_age_threshold/100
hits is to be moved to the
beginning of the warm sub-chain. It then becomes the first candidate for
eviction, because blocks for replacement always are taken from the beginning
of the warm sub-chain.
The midpoint insertion strategy allows you to keep more-valued blocks
always in the cache. If you prefer to use the plain LRU strategy, leave the
key_cache_division_limit
value set to its default of 100.
The midpoint insertion strategy helps to improve performance when execution
of a query that requires an index scan effectively pushes out of the cache
all the index blocks corresponding to valuable high-level B-tree nodes. To
avoid this, you must use a midpoint insertion strategy with the
key_cache_division_limit
set to much less than 100. Then valuable
frequently hit nodes will be preserved in the hot sub-chain during an index
scan operation as well.
If there are enough blocks in a key cache to hold blocks of an entire index, or at least the blocks corresponding to its non-leaf nodes, then it makes sense to preload the key cache with index blocks before starting to use it. Preloading allows you to put the table index blocks into a key cache buffer in the most efficient way: by reading the index blocks from disk sequentially.
Without preloading, the blocks still will be placed into the key cache as needed by queries. Although the blocks will stay in the cache, because there are enough buffers for all of them, they will be fetched from disk in a random order, not sequentially.
To preload an index into a cache, use the LOAD INDEX INTO CACHE
statement. For example,
the following statement preloads nodes (index blocks) of indexes of the
tables t1
and t2
:
mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES; +---------+--------------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------+--------------+----------+----------+ | test.t1 | preload_keys | status | OK | | test.t2 | preload_keys | status | OK | +---------+--------------+----------+----------+
The IGNORE LEAVES
modifier causes only blocks for the non-leaf
nodes of the index to be preloaded. Thus,
the statement shown preloads all index blocks from t1
, but only
blocks for the non-leaf nodes from t2
.
If an index has been assigned to a key cache using a
CACHE INDEX
statement, preloading places index blocks into that cache.
Otherwise, the index is loaded into the default key cache.
MySQL 4.1 introduces a new key_cache_block_size
variable on
a per-key cache basis. This variable specifies the size of the block
buffers for a key cache. It is intended to allow tuning of the performance
of I/O operations for index files.
The best performance for I/O operations is achieved when the size of read buffers is equal to the size of the native operating system I/O buffers. But setting the size of key nodes equal to the size of the I/O buffer does not always ensure the best overall performance. When reading the big leaf nodes, the server pulls in a lot of unnecessary data, effectively preventing reading other leaf nodes.
Currently, you cannot control the size of the index blocks in a table. This
size is set by the server when the `.MYI' index file is created,
depending on the size of the keys in the indexes present in the table
definition. In most cases, it is set equal to the I/O buffer size. In the
future, this will be changed and then key_cache_block_size
variable
will be fully employed.
A key cache can be restructured at any time by updating its parameter values. For example:
mysql> SET GLOBAL cold_cache.key_buffer_size=4*1024*1024;
If you assign to either the key_buffer_size
or
key_cache_block_size
key cache component a value that differs from
the component's current value, the server destroys the cache's old
structure and creates a new one based on the new values. If the cache
contains any dirty blocks, the server saves them to disk before destroying
and re-creating the cache. Restructuring does not occur if you set other key
cache parameters.
When restructuring a key cache, the server first flushes the contents of any dirty buffers to disk. After that, the cache contents become unavailable. However, restructuring does not block queries that need to use indexes assigned to the cache. Instead, the server directly accesses the table indexes using native filesystem caching. Filesystem caching is not as efficient as using a key cache, so although queries will execute, a slowdown can be anticipated. Once the cache has been restructured, it becomes available again for caching indexes assigned to it, and the use of filesystem caching for the indexes ceases.
When you execute a mysqladmin status
command, you'll see something
like this:
Uptime: 426 Running threads: 1 Questions: 11082 Reloads: 1 Open tables: 12
The Open tables
value of 12 can be somewhat puzzling if you have
only six tables.
MySQL is multi-threaded, so there may be many clients issuing queries for a
given table simultaneously. To minimize the problem with multiple client threads
having different states on the same table, the table is opened independently
by each concurrent thread. This takes some memory but normally increases
performance. With MyISAM
tables, one extra file descriptor is
required for the data file for each client that has the table open. (By
contrast, the index file descriptor is shared between all threads.) The
ISAM
storage engine shares this behavior.
You can read more about this topic in the next section. See section 7.4.8 How MySQL Opens and Closes Tables.
The table_cache
, max_connections
, and max_tmp_tables
system variables affect the maximum number of files the server keeps open.
If you increase one or more of these values, you may run up against a limit
imposed by your operating system on the per-process number of open file
descriptors. Many operating systems allow you to increase the open-files
limit, although the method varies widely from system to system. Consult your
operating system documentation to determine whether it is possible to
increase the limit and how to do so.
table_cache
is related to max_connections
. For example,
for 200 concurrent running connections, you should have a table cache size of
at least 200 * N
, where N is the maximum number of tables
in a join. You also need to reserve some extra file descriptors for
temporary tables and files.
Make sure that your operating system can handle the number of open file
descriptors implied by the table_cache
setting. If
table_cache
is set too high, MySQL may run out of file
descriptors and refuse connections, fail to perform queries, and be very
unreliable. You also have to take into account that the MyISAM
storage
engine needs two file descriptors for each unique open table. You can
increase the number of file descriptors available for MySQL with
the --open-files-limit
startup option to mysqld_safe
.
See section A.2.17 File Not Found.
The cache of open tables will be kept at a level of table_cache
entries. The default value is 64; this can be changed with the
--table_cache
option to mysqld
. Note that MySQL may
temporarily open even more tables to be able to execute queries.
An unused table is closed and removed from the table cache under the following circumstances:
table_cache
entries and
a thread is no longer using a table.
FLUSH TABLES
statement or executes a mysqladmin flush-tables
or mysqladmin refresh
command.
When the table cache fills up, the server uses the following procedure to locate a cache entry to use:
When the cache is in a temporarily extended state and a table goes from a used to unused state, the table is closed and released from the cache.
A table is opened for each concurrent access. This means the table needs to be opened twice if two threads access the same table or if a thread accesses the table twice in the same query (for example, by joining the table to itself). Each concurrent open requires an entry in the table cache. The first open of any table takes two file descriptors: one for the data file and one for the index file. Each additional use of the table takes only one file descriptor, for the data file. The index file descriptor is shared among all threads.
If you are opening a table with the HANDLER tbl_name OPEN
statement, a dedicated table object is allocated for the thread.
This table object is not shared by other threads and is not closed
until the thread calls HANDLER tbl_name CLOSE
or the thread
terminates. When this happens, the table is put back in the table cache
(if the cache isn't full).
See section 13.1.3 HANDLER
Syntax.
You can determine whether your table cache is too small by checking the
mysqld
status variable Opened_tables
:
mysql> SHOW STATUS LIKE 'Opened_tables'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Opened_tables | 2741 | +---------------+-------+
If the value is quite big, even when you haven't issued a lot of FLUSH
TABLES
statements, you should increase your table cache size.
See section 5.2.3 Server System Variables and section 5.2.4 Server Status Variables.
If you have many MyISAM
or ISAM
tables in a database
directory, open, close, and create operations will be slow. If you execute
SELECT
statements on many different tables, there will be a little
overhead when the table cache is full, because for every table that has to
be opened, another must be closed. You can reduce this overhead by making
the table cache larger.
We start with system-level factors, because some of these decisions must be made very early to achieve large performance gains. In other cases, a quick look at this section may suffice. However, it is always nice to have a sense of how much can be gained by changing things at this level.
The default operating system to use is very important! To get the best use of multiple-CPU machines, you should use Solaris (because its threads implementation works really well) or Linux (because the 2.4 kernel has really good SMP support). Note that older Linux kernels have a 2GB filesize limit by default. If you have such a kernel and a desperate need for files larger than 2GB, you should get the Large File Support (LFS) patch for the ext2 filesystem. Other filesystems such as ReiserFS and XFS do not have this 2GB limitation.
Before using MySQL in production, we advise you to test it on your intended platform.
--skip-external-locking
MySQL option to avoid external
locking. This option is on by default as of MySQL 4.0.
Before that, it is on by default when compiling with
MIT-pthreads, because flock()
isn't fully supported by
MIT-pthreads on all platforms. It's also on by default for Linux
because Linux file locking is not yet safe.
Note that the --skip-external-locking
option will not affect MySQL's
functionality as long as you run only one server. Just remember to take
down the server (or lock and flush the relevant tables) before you run
myisamchk
. On some systems this option is mandatory, because the
external locking does not work in any case.
The only case when you can't use --skip-external-locking
is if you run
multiple MySQL servers (not clients) on the same data,
or if you run myisamchk
to check (not repair) a table without telling
the server to flush and lock the tables first.
You can still use LOCK TABLES
and UNLOCK TABLES
even if you
are using --skip-external-locking
.
You can determine the default buffer sizes used by the mysqld
server
with this command (prior to MySQL 4.1, omit --verbose
):
shell> mysqld --verbose --help
This command produces a list of all mysqld
options and configurable
system variables. The output includes the default variable values and
looks something like this:
back_log current value: 5 bdb_cache_size current value: 1048540 binlog_cache_size current value: 32768 connect_timeout current value: 5 delayed_insert_limit current value: 100 delayed_insert_timeout current value: 300 delayed_queue_size current value: 1000 flush_time current value: 0 interactive_timeout current value: 28800 join_buffer_size current value: 131072 key_buffer_size current value: 1048540 long_query_time current value: 10 lower_case_table_names current value: 0 max_allowed_packet current value: 1048576 max_binlog_cache_size current value: 4294967295 max_connect_errors current value: 10 max_connections current value: 100 max_delayed_threads current value: 20 max_heap_table_size current value: 16777216 max_join_size current value: 4294967295 max_sort_length current value: 1024 max_tmp_tables current value: 32 max_write_lock_count current value: 4294967295 myisam_sort_buffer_size current value: 8388608 net_buffer_length current value: 16384 net_read_timeout current value: 30 net_retry_count current value: 10 net_write_timeout current value: 60 read_buffer_size current value: 131072 read_rnd_buffer_size current value: 262144 slow_launch_time current value: 2 sort_buffer current value: 2097116 table_cache current value: 64 thread_concurrency current value: 10 thread_stack current value: 131072 tmp_table_size current value: 1048576 wait_timeout current value: 28800
If there is a mysqld
server currently running, you can see what
values it actually is using for the system variables by connecting to it and
issuing this statement:
mysql> SHOW VARIABLES;
You can also see some statistical and status indicators for a running server by issuing this statement:
mysql> SHOW STATUS;
System variable and status information also can be obtained using
mysqladmin
:
shell> mysqladmin variables shell> mysqladmin extended-status
You can find a full description for all system and status variables in section 5.2.3 Server System Variables and section 5.2.4 Server Status Variables.
MySQL uses algorithms that are very scalable, so you can usually run with very little memory. However, normally you will get better performance by giving MySQL more memory.
When tuning a MySQL server, the two most important variables to configure
are key_buffer_size
and table_cache
. You should first feel
confident that you have these set appropriately before trying to change
any other variables.
The following examples indicate some typical variable values for different
runtime configurations. The examples use the mysqld_safe
script and
use --var_name=value
syntax to set the variable var_name to the value
value. This syntax is available as of MySQL 4.0. For older versions
of MySQL, take the following differences into account:
safe_mysqld
rather than mysqld_safe
.
--set-variable=var_name=value
or -O
var_name=value
syntax.
_size
, you may need to specify them
without _size
. For example, the old name for sort_buffer_size
is
sort_buffer
. The old name for read_buffer_size
is
record_buffer
. To see which variables your version of the server
recognizes, use mysqld --help
.
If you have at least 256MB of memory and many tables and want maximum performance with a moderate number of clients, you should use something like this:
shell> mysqld_safe --key_buffer_size=64M --table_cache=256 \ --sort_buffer_size=4M --read_buffer_size=1M &
If you have only 128MB of memory and only a few tables, but you still do a lot of sorting, you can use something like this:
shell> mysqld_safe --key_buffer_size=16M --sort_buffer_size=1M
If there are very many simultaneous connections, swapping problems
may occur unless mysqld
has been configured to use very
little memory for each connection. mysqld
performs better
if you have enough memory for all connections.
With little memory and lots of connections, use something like this:
shell> mysqld_safe --key_buffer_size=512K --sort_buffer_size=100K \ --read_buffer_size=100K &
Or even this:
shell> mysqld_safe --key_buffer_size=512K --sort_buffer_size=16K \ --table_cache=32 --read_buffer_size=8K \ --net_buffer_length=1K &
If you are doing GROUP BY
or ORDER BY
operations on tables
that are much larger than your available memory, you should increase the
value of read_rnd_buffer_size
to speed up the reading of rows after
sorting operations.
When you have installed MySQL, the `support-files' directory will contain some different `my.cnf' sample files: `my-huge.cnf', `my-large.cnf', `my-medium.cnf', and `my-small.cnf'. You can use these as a basis for optimizing your system.
Note that if you specify an option on the command line for mysqld
or
mysqld_safe
, it remains in effect only for that invocation of the server.
To use the option every time the server runs, put it in an option file.
To see the effects of a parameter change, do something like this (prior to
MySQL 4.1, omit --verbose
):
shell> mysqld --key_buffer_size=32M --verbose --help
The variable values are listed near the end of the output.
Make sure that the --verbose
and --help
options are
last. Otherwise, the effect of any options listed after them on the command
line will not be reflected in the output.
For information on tuning the InnoDB
storage engine, see
section 15.12 InnoDB
Performance Tuning Tips.
The task of the query optimizer is to find an optimal plan for executing an SQL query. Because the difference in performance between ``good'' and ``bad'' plans can be orders of magnitude (that is, seconds versus hours or even days), most query optimizers, including that of MySQL, perform more or less exhaustive search for an optimal plan among all possible query evaluation plans. For join queries, the number of possible plans investigated by the MySQL optimizer grows exponentially with the number of tables referenced in a query. For small numbers of tables (typically less than 7-10) this is not a problem. However, when bigger queries are submitted, the time spent in query optimization may easily become the major bottleneck in the server performance.
MySQL 5.0.1 introduces a new more flexible method for query optimization that allows the user to control how exhaustive the optimizer is in its search for an optimal query evaluation plan. The general idea is that the fewer plans that are investigated by the optimizer, the less time it will spend in compiling a query. On the other hand, because the optimizer will skip some plans, it may miss finding an optimal plan.
The behavior of the optimizer with respect to the number of plans it evaluates can be controlled via two system variables:
optimizer_prune_level
variable tells the optimizer to skip
certain plans based on estimates of the number of rows accessed for each
table. Our experience shows that this kind of ``educated guess'' rarely
misses optimal plans, while it may dramatically reduce query compilation
times. That is why this option is on (optimizer_prune_level
=1)
by default. However, if you believe that the optimizer missed better query
plans, then this option can be switched off (optimizer_prune_level
=0)
with the risk that query compilation may take much longer. Notice that
even with the use of this heuristic, the optimizer will still explore a
roughly exponential number of plans.
optimizer_search_depth
variable tells how far in the
``future'' of each incomplete plan the optimizer should look in order
to evaluate whether it should be expanded further. Smaller values of
optimizer_search_depth
may result in orders of magnitude smaller query
compilation times. For example, queries with 12-13 or more tables may easily
require hours and even days to compile if optimizer_search_depth
is close to the number of tables in the query. At the same time, if
compiled with optimizer_search_depth
equal to 3 or 4, the compiler
may compile in less than a minute for the same query. If you are unsure of
what a reasonable value is for optimizer_search_depth
, this variable
can be set to 0 to tell the optimizer to determine the value automatically.
Most of the following tests were performed on Linux with the MySQL benchmarks, but they should give some indication for other operating systems and workloads.
You get the fastest executables when you link with -static
.
On Linux, you will get the fastest code when compiling with pgcc
and -O3
. You need about 200MB memory to compile `sql_yacc.cc'
with these options, because gcc/pgcc
needs a lot of memory to
make all functions inline. You should also set CXX=gcc
when
configuring MySQL to avoid inclusion of the libstdc++
library, which is not needed. Note that with some versions of pgcc
,
the resulting code will run only on true Pentium processors, even if you
use the compiler option indicating that you want the resulting code to work on
all x586-type processors (such as AMD).
By just using a better compiler and better compiler options, you can get a 10-30% speed increase in your application. This is particularly important if you compile the MySQL server yourself.
We have tested both the Cygnus CodeFusion and Fujitsu compilers, but when we tested them, neither was sufficiently bug-free to allow MySQL to be compiled with optimizations enabled.
The standard MySQL binary distributions are compiled with support for all
character sets. When you compile MySQL yourself, you should include support
only for the character sets that you are going to use. This is controlled by
the --with-charset
option to configure
.
Here is a list of some measurements that we have made:
pgcc
and compile everything with -O6
, the
mysqld
server is 1% faster than with gcc
2.95.2.
-static
), the result is 13%
slower on Linux. Note that you still can use a dynamically linked
MySQL library for your client applications. It is the server that is most
critical for performance.
mysqld
binary with strip mysqld
,
the resulting binary can be up to 4% faster.
localhost
,
MySQL uses a socket file by default.)
--with-debug=full
, most queries will be 20% slower.
Some queries may take substantially longer; for example,
the MySQL benchmarks ran 35% slower. If you use --with-debug
(without
=full
),
the slowdown will be only 15%. For a version of mysqld
that has
been compiled with --with-debug=full
, you can disable memory
checking at runtime by starting it with the --skip-safemalloc
option. The execution speed should then be close to that obtained when
configuring with --with-debug
.
gcc
3.2.
gcc
2.95.2 for UltraSPARC with the
-mcpu=v8 -Wa,-xarch=v8plusa
options gives 4% more performance.
gcc
without frame pointers
(-fomit-frame-pointer
or -fomit-frame-pointer -ffixed-ebp
)
makes mysqld
1-4% faster.
Binary MySQL distributions for Linux that are provided by MySQL AB used
to be compiled with pgcc
. We had to go back to regular gcc
due to a bug in pgcc
that would generate code that does
not run on AMD. We will continue using gcc
until that bug is resolved.
In the meantime, if you have a non-AMD machine, you can get a faster
binary by compiling with pgcc
. The standard MySQL
Linux binary is linked statically to make it faster and more portable.
The following list indicates some of the ways that the mysqld
server
uses memory. Where applicable, the name of the system variable relevant
to the memory use is given:
key_buffer_size
) is shared by all
threads; other buffers used by the server are allocated as
needed. See section 7.5.2 Tuning Server Parameters.
thread_stack
)
net_buffer_length
)
net_buffer_length
)
max_allowed_packet
when needed. While
a query is running, a copy of the current query string is also allocated.
ISAM
and MyISAM
tables are memory mapped. This
is because the 32-bit memory space of 4GB is not large enough for most
big tables. When systems with a 64-bit address space become more
common, we may add general support for memory mapping.
read_buffer_size
).
read_rnd_buffer_size
).
HEAP
)
tables. Temporary tables with a large record length (calculated as the
sum of all column lengths) or that contain BLOB
columns are
stored on disk.
One problem before MySQL 3.23.2 is that if an internal in-memory
heap table exceeds the size of tmp_table_size
, the error The
table tbl_name is full
occurs. From 3.23.2 on, this is handled
automatically by changing the in-memory heap table to a disk-based
MyISAM
table as necessary. To work around this problem for older
servers, you can increase the temporary table size by setting the
tmp_table_size
option to mysqld
, or by setting the SQL option
SQL_BIG_TABLES
in the client program.
See section 13.5.3 SET
Syntax.
In MySQL 3.20, the maximum size of the temporary table is
record_buffer*16
; if you are using this version, you have to increase
the value of record_buffer
. You can also start mysqld
with the
--big-tables
option to always store temporary tables on disk.
However, this will affect the speed of many complicated queries.
malloc()
and
free()
.
MyISAM
and ISAM
table that is opened, the index file
is opened once and the data file is opened once for each concurrently running
thread. For each concurrent thread, a table structure, column structures for
each column, and a buffer of size 3 * N
are allocated (where N
is the maximum row length, not counting BLOB
columns). A BLOB
column requires five to eight bytes plus the length of the BLOB
data.
The MyISAM
and ISAM
storage engines maintain one extra row
buffer for internal use.
BLOB
columns, a buffer is enlarged dynamically
to read in larger BLOB
values. If you scan a table, a buffer as large
as the largest BLOB
value is allocated.
FLUSH TABLES
statement or mysqladmin flush-tables
command
closes all tables that are not in use at once and marks all in-use tables to be
closed when the currently executing thread finishes. This effectively frees
most in-use memory. FLUSH TABLES
does not return until all tables have
been closed.
ps
and other system status programs may report that mysqld
uses a lot of memory. This may be caused by thread stacks on different
memory addresses. For example, the Solaris version of ps
counts
the unused memory between stacks as used memory. You can verify this by
checking available swap with swap -s
. We have tested
mysqld
with several memory-leakage detectors (both commercial and open
source), so there should be no memory leaks.
When a new client connects to mysqld
, mysqld
spawns a
new thread to handle the request. This thread first checks whether the
hostname is in the hostname cache. If not, the thread attempts to resolve the
hostname:
gethostbyaddr_r()
and
gethostbyname_r()
calls, the thread uses them to perform hostname
resolution.
gethostbyaddr()
and
gethostbyname()
instead. In this case, no other thread
can resolve hostnames that are not in the hostname cache until the
first thread unlocks the mutex.
You can disable DNS hostname lookups by starting mysqld
with the
--skip-name-resolve
option. However, in this case, you can use only IP
numbers in the MySQL grant tables.
If you have a very slow DNS and many hosts, you can get more performance by
either disabling DNS lookups with --skip-name-resolve
or by
increasing the HOST_CACHE_SIZE
define (default value: 128) and
recompiling mysqld
.
You can disable the hostname cache by starting the server with the
--skip-host-cache
option. To clear the hostname cache, issue a
FLUSH HOSTS
statement or execute the mysqladmin flush-hosts
command.
If you want to disallow TCP/IP connections entirely, start mysqld
with
the --skip-networking
option.
MyISAM
tables, you symlink the index file and/or
data file from their usual location in the data directory to another disk
(that may also be striped). This makes both the seek and read times better,
assuming that the disk is not used for other purposes as well. See section 7.6.1 Using Symbolic Links.
hdparm
to
configure your disk's interface. (Up to 100% under load is not uncommon.)
The following hdparm
options should be quite good for MySQL, and
probably for many other applications:
hdparm -m 16 -d 1Note that performance and reliability when using this command depends on your hardware, so we strongly suggest that you test your system thoroughly after using
hdparm
. Please consult the hdparm
manual page for more information. If hdparm
is not used wisely,
filesystem corruption may result, so back up everything before
experimenting!
-o noatime
option. That skips updates
to the last access time in inodes on the filesystem, which avoids
some disk seeks.
On many operating systems, you can set a filesystem to be updated
asynchronously by mounting it with the -o async
option. If your
computer is reasonably stable, this should give you more performance without
sacrificing too much reliability. (This flag is on by default on Linux.)
You can move tables and databases from the database directory to other locations and replace them with symbolic links to the new locations. You might want to do this, for example, to move a database to a file system with more free space or increase the speed of your system by spreading your tables to different disk.
The recommended way to do this is to just symlink databases to a different disk. Symlink tables only as a last resort.
On Unix, the way to symlink a database is to first create a directory on some disk where you have free space and then create a symlink to it from the MySQL data directory.
shell> mkdir /dr1/databases/test shell> ln -s /dr1/databases/test /path/to/datadir
MySQL doesn't support linking one directory to multiple
databases. Replacing a database directory with a symbolic link will
work fine as long as you don't make a symbolic link between databases.
Suppose that you have a database db1
under the MySQL data
directory, and then make a symlink db2
that points to db1
:
shell> cd /path/to/datadir shell> ln -s db1 db2
For any table tbl_a
in db1
, there also appears to be
a table tbl_a
in db2
. If one client updates db1.tbl_a
and another client updates db2.tbl_a
, there will be problems.
If you really need to do this, you can change one of the source files. The file to modify depends on your version of MySQL. For MySQL 4.0 and up, look for the following statement in the `mysys/my_symlink.c' file:
if (!(MyFlags & MY_RESOLVE_LINK) || (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
Before MySQL 4.0, look for this statement in the `mysys/mf_format.c' file:
if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
Change the statement to this:
if (1)
On Windows, you can use internal symbolic links to directories by compiling
MySQL with -DUSE_SYMDIR
. This allows you to put different
databases on different disks. See section 7.6.1.3 Using Symbolic Links for Databases on Windows.
(It is necessary to define USE_SYMDIR
explicitly only before
MySQL 4.0. As of MySQL 4.0, symbolic link support is enabled by default for
all Windows servers.)
Before MySQL 4.0, you should not symlink tables unless you are
very careful with them. The problem is that if you run ALTER
TABLE
, REPAIR TABLE
, or OPTIMIZE TABLE
on a symlinked
table, the symlinks will be removed and replaced by the original
files. This happens because these statements work by creating a
temporary file in the database directory and replacing the original
file with the temporary file when the statement operation is complete.
You should not symlink tables on systems that don't have a fully
working realpath()
call. (At least Linux and Solaris support
realpath()
). You can check whether your system supports symbolic links
by issuing a SHOW VARIABLES LIKE 'have_symlink'
statement.
In MySQL 4.0, symlinks are fully supported only for MyISAM
tables. For other table types, you will probably get strange problems
if you try to use symbolic links on files in the operating system with
any of the preceding statements.
The handling of symbolic links for MyISAM
tables in MySQL 4.0 works
the following way:
ln -s
if mysqld
is not running. With SQL, you can instruct the server to
perform the symlinking by using the DATA DIRECTORY
and INDEX
DIRECTORY
options to CREATE TABLE
.
See section 13.2.6 CREATE TABLE
Syntax.
myisamchk
will not replace a symlink with the data file or index file.
It works directly on the file a symlink points to. Any temporary files
are created in the directory where the data file or index file is
located.
mysqld
as root
or allow
users to have write access to the MySQL database directories.
ALTER TABLE ... RENAME
and you don't move
the table to another database, the symlinks in the database directory
are renamed to the new names and the data file and index file are
renamed accordingly.
ALTER TABLE ... RENAME
to move a table to another database,
the table is moved to the other database directory. The old
symlinks and the files to which they pointed are deleted. In other words,
the new table will not be symlinked.
--skip-symbolic-links
option to mysqld
to ensure that no one can use mysqld
to drop
or rename a file outside of the data directory.
SHOW CREATE TABLE
doesn't report if a table has symbolic links
prior to MySQL 4.0.15. This is also true for mysqldump
, which uses
SHOW CREATE TABLE
to generate CREATE TABLE
statements.
Table symlink operations that are not yet supported:
ALTER TABLE
ignores the DATA DIRECTORY
and INDEX
DIRECTORY
table options.
BACKUP TABLE
and RESTORE TABLE
don't respect symbolic
links.
db1
under the MySQL data directory,
a table tbl1
in this database, and in the db1
directory you
make a symlink tbl2
that points to tbl1
:
shell> cd /path/to/datadir/db1 shell> ln -s tbl1.frm tbl2.frm shell> ln -s tbl1.MYD tbl2.MYD shell> ln -s tbl1.MYI tbl2.MYIThere will be problems if one thread reads
db1.tbl1
and another
thread updates db1.tbl2
:
tbl1
has not been
updated so will return out-of-date results).
ALTER
statements on tbl2
will also fail.
Beginning with MySQL 3.23.16, the mysqld-max
and mysql-max-nt
servers for Windows are
compiled with the -DUSE_SYMDIR
option. This allows you to put a
database directory on a different disk by setting up a symbolic link to it.
This is similar to the way that symbolic links work on Unix, although the
procedure for setting up the link is different.
As of MySQL 4.0, symbolic links are enabled by default. If you don't need them,
you can disable them with the skip-symbolic-links
option:
[mysqld] skip-symbolic-links
Before MySQL 4.0, symbolic links are disabled by default. To enable them, you should put the following entry in your `my.cnf' or `my.ini' file:
[mysqld] symbolic-links
On Windows, you make a symbolic link to a MySQL database by creating a file in the data directory that contains the path to the destination directory. The file should be named `db_name.sym', where db_name is the database name.
Suppose that the MySQL data directory is `C:\mysql\data'
and you want to have database foo
located at `D:\data\foo'.
Set up a symlink like this:
D:\data\foo\
.
After that, all tables created in the database foo
will be created in
`D:\data\foo'. Note that the symbolic link will not be used if a
directory with the database name exists in the MySQL data directory.
There are many different MySQL client programs that connect to the server to access databases or perform administrative tasks. Other utilities are available as well. These do not communicate with the server but perform MySQL-related operations.
This chapter provides a brief overview of these programs and then a more detailed description of each one. The descriptions indicate how to invoke the programs and the options they understand. See section 4 Using MySQL Programs for general information on invoking programs and specifying program options.
The following list briefly describes the MySQL client programs and utilities:
myisampack
MyISAM
tables to produce smaller read-only
tables.
See section 8.2 myisampack
, the MySQL Compressed Read-only Table Generator.
mysql
mysql
, the Command-Line Tool.
mysqlaccess
mysqladmin
mysqladmin
can also be used to retrieve version,
process, and status information from the server.
See section 8.4 mysqladmin
, Administering a MySQL Server.
mysqlbinlog
mysqlbinlog
Binary Log Utility.
mysqlcc
mysqlcc
, the MySQL Control Center.
mysqlcheck
mysqlcheck
Table Maintenance and Repair Program.
mysqldump
mysqldump
Database Backup Program.
mysqlhotcopy
MyISAM
or ISAM
tables
while the server is running.
See section 8.9 The mysqlhotcopy
Database Backup Program.
mysqlimport
LOAD DATA INFILE
.
See section 8.10 The mysqlimport
Data Import Program.
mysqlshow
mysqlshow
, Showing Databases, Tables, and Columns.
perror
perror
, Explaining Error Codes.
replace
replace
String-Replacement Utility.
Each MySQL program takes many different options. However, every MySQL program
provides a --help
option that you can use to get a full description
of the program's different options. For example, try mysql --help
.
MySQL clients that communicate with the server using the
mysqlclient
library use the following environment variables:
MYSQL_UNIX_PORT
| The default Unix socket file; used for connections to localhost
|
MYSQL_TCP_PORT
| The default port number; used for TCP/IP connections |
MYSQL_PWD
| The default password |
MYSQL_DEBUG
| Debug trace options when debugging |
TMPDIR
| The directory where temporary tables and files are created |
Use of MYSQL_PWD
is insecure.
See section 5.6.6 Keeping Your Password Secure.
You can override the default option values or values specified in environment variables for all standard programs by specifying options in an option file or on the command line. section 4.3 Specifying Program Options.
myisampack
, the MySQL Compressed Read-only Table Generator
The myisampack
utility compresses MyISAM
tables.
myisampack
works by compressing each column in the table separately.
Usually, myisampack
packs the data file 40%-70%.
When the table is used later, the information needed to decompress columns is read into memory. This results in much better performance when accessing individual records, because you only have to uncompress exactly one record, not a much larger disk block as when using Stacker on MS-DOS.
MySQL uses mmap()
when possible to perform memory mapping on
compressed tables. If mmap()
doesn't work, MySQL falls back to
normal read/write file operations.
A similar utility, pack_isam
, compresses ISAM
tables. Because
ISAM
tables are deprecated, this section discusses only
myisampack
, but the general procedures for using myisampack
are also true for pack_isam
unless otherwise specified.
Please note the following:
mysqld
server was invoked with the
--skip-external-locking
option, it is not a good idea to invoke
myisampack
if the table might be updated by the server during the
packing process.
myisampack
can pack BLOB
or TEXT
columns.
The older pack_isam
program for ISAM
tables cannot.
Invoke myisampack
like this:
shell> myisampack [options] filename ...
Each filename should be the name of an index (`.MYI') file. If you are not in the database directory, you should specify the pathname to the file. It is permissible to omit the `.MYI' extension.
myisampack
supports the following options:
--help, -?
--backup, -b
--debug[=debug_options], -# [debug_options]
'd:t:o,file_name'
.
--force, -f
myisampack
exists.
(myisampack
creates a temporary file named `tbl_name.TMD' while
it compresses the table. If you kill myisampack
, the `.TMD'
file might not be deleted.) Normally, myisampack
exits with an
error if it finds that `tbl_name.TMD' exists. With --force
,
myisampack
packs the table anyway.
--join=big_tbl_name, -j big_tbl_name
--packlength=#, -p #
myisampack
stores all rows with length pointers of 1, 2, or 3
bytes. In most normal cases, myisampack
can determine the right length
value before it begins packing the file, but it may notice during the packing
process that it could have used a shorter length. In this case,
myisampack
will print a note that the next time you pack the same file,
you could use a shorter record length.
--silent, -s
--test, -t
--tmp_dir=path, -T path
--verbose, -v
--version, -V
--wait, -w
mysqld
server was
invoked with the --skip-external-locking
option, it is not a good idea
to invoke myisampack
if the table might be updated by the server during
the packing process.
The following sequence of commands illustrates a typical table compression session:
shell> ls -l station.* -rw-rw-r-- 1 monty my 994128 Apr 17 19:00 station.MYD -rw-rw-r-- 1 monty my 53248 Apr 17 19:00 station.MYI -rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm shell> myisamchk -dvv station MyISAM file: station Isam-version: 2 Creation time: 1996-03-13 10:08:58 Recover time: 1997-02-02 3:06:43 Data records: 1192 Deleted blocks: 0 Datafile parts: 1192 Deleted data: 0 Datafile pointer (bytes): 2 Keyfile pointer (bytes): 2 Max datafile length: 54657023 Max keyfile length: 33554431 Recordlength: 834 Record format: Fixed length table description: Key Start Len Index Type Root Blocksize Rec/key 1 2 4 unique unsigned long 1024 1024 1 2 32 30 multip. text 10240 1024 1 Field Start Length Type 1 1 1 2 2 4 3 6 4 4 10 1 5 11 20 6 31 1 7 32 30 8 62 35 9 97 35 10 132 35 11 167 4 12 171 16 13 187 35 14 222 4 15 226 16 16 242 20 17 262 20 18 282 20 19 302 30 20 332 4 21 336 4 22 340 1 23 341 8 24 349 8 25 357 8 26 365 2 27 367 2 28 369 4 29 373 4 30 377 1 31 378 2 32 380 8 33 388 4 34 392 4 35 396 4 36 400 4 37 404 1 38 405 4 39 409 4 40 413 4 41 417 4 42 421 4 43 425 4 44 429 20 45 449 30 46 479 1 47 480 1 48 481 79 49 560 79 50 639 79 51 718 79 52 797 8 53 805 1 54 806 1 55 807 20 56 827 4 57 831 4 shell> myisampack station.MYI Compressing station.MYI: (1192 records) - Calculating statistics normal: 20 empty-space: 16 empty-zero: 12 empty-fill: 11 pre-space: 0 end-space: 12 table-lookups: 5 zero: 7 Original trees: 57 After join: 17 - Compressing file 87.14% Remember to run myisamchk -rq on compressed tables shell> ls -l station.* -rw-rw-r-- 1 monty my 127874 Apr 17 19:00 station.MYD -rw-rw-r-- 1 monty my 55296 Apr 17 19:04 station.MYI -rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm shell> myisamchk -dvv station MyISAM file: station Isam-version: 2 Creation time: 1996-03-13 10:08:58 Recover time: 1997-04-17 19:04:26 Data records: 1192 Deleted blocks: 0 Datafile parts: 1192 Deleted data: 0 Datafile pointer (bytes): 3 Keyfile pointer (bytes): 1 Max datafile length: 16777215 Max keyfile length: 131071 Recordlength: 834 Record format: Compressed table description: Key Start Len Index Type Root Blocksize Rec/key 1 2 4 unique unsigned long 10240 1024 1 2 32 30 multip. text 54272 1024 1 Field Start Length Type Huff tree Bits 1 1 1 constant 1 0 2 2 4 zerofill(1) 2 9 3 6 4 no zeros, zerofill(1) 2 9 4 10 1 3 9 5 11 20 table-lookup 4 0 6 31 1 3 9 7 32 30 no endspace, not_always 5 9 8 62 35 no endspace, not_always, no empty 6 9 9 97 35 no empty 7 9 10 132 35 no endspace, not_always, no empty 6 9 11 167 4 zerofill(1) 2 9 12 171 16 no endspace, not_always, no empty 5 9 13 187 35 no endspace, not_always, no empty 6 9 14 222 4 zerofill(1) 2 9 15 226 16 no endspace, not_always, no empty 5 9 16 242 20 no endspace, not_always 8 9 17 262 20 no endspace, no empty 8 9 18 282 20 no endspace, no empty 5 9 19 302 30 no endspace, no empty 6 9 20 332 4 always zero 2 9 21 336 4 always zero 2 9 22 340 1 3 9 23 341 8 table-lookup 9 0 24 349 8 table-lookup 10 0 25 357 8 always zero 2 9 26 365 2 2 9 27 367 2 no zeros, zerofill(1) 2 9 28 369 4 no zeros, zerofill(1) 2 9 29 373 4 table-lookup 11 0 30 377 1 3 9 31 378 2 no zeros, zerofill(1) 2 9 32 380 8 no zeros 2 9 33 388 4 always zero 2 9 34 392 4 table-lookup 12 0 35 396 4 no zeros, zerofill(1) 13 9 36 400 4 no zeros, zerofill(1) 2 9 37 404 1 2 9 38 405 4 no zeros 2 9 39 409 4 always zero 2 9 40 413 4 no zeros 2 9 41 417 4 always zero 2 9 42 421 4 no zeros 2 9 43 425 4 always zero 2 9 44 429 20 no empty 3 9 45 449 30 no empty 3 9 46 479 1 14 4 47 480 1 14 4 48 481 79 no endspace, no empty 15 9 49 560 79 no empty 2 9 50 639 79 no empty 2 9 51 718 79 no endspace 16 9 52 797 8 no empty 2 9 53 805 1 17 1 54 806 1 3 9 55 807 20 no empty 3 9 56 827 4 no zeros, zerofill(2) 2 9 57 831 4 no zeros, zerofill(1) 2 9
myisampack
displays the following kinds of information:
normal
empty-space
empty-zero
empty-fill
BIGINT
column (eight bytes) can be stored as a TINYINT
column (one byte) if
all its values are in the range from -128
to 127
.
pre-space
end-space
table-lookup
ENUM
before Huffman compression.
zero
Original trees
After join
After a table has been compressed, myisamchk -dvv
prints additional
information about each column:
Type
constant
no endspace
no endspace, not_always
no endspace, no empty
table-lookup
ENUM
.
zerofill(n)
no zeros
always zero
Huff tree
Bits
After you run myisampack
, you must run
myisamchk
to re-create any indexes. At this time, you
can also sort the index blocks and create statistics needed for
the MySQL optimizer to work more efficiently:
shell> myisamchk -rq --sort-index --analyze tbl_name.MYI
A similar procedure applies for ISAM
tables. After using
pack_isam
, use isamchk
to re-create the indexes:
shell> isamchk -rq --sort-index --analyze tbl_name.ISM
After you have installed the packed table into the MySQL database directory,
you should execute mysqladmin flush-tables
to force mysqld
to start using the new table.
To unpack a packed table, use the --unpack
option to myisamchk
or isamchk
.
mysql
, the Command-Line Tool
mysql
is a simple SQL shell (with GNU readline
capabilities).
It supports interactive and non-interactive use. When used interactively,
query results are presented in an ASCII-table format. When used
non-interactively (for example, as a filter), the result is presented in
tab-separated format. The output format can be changed using command-line
options.
If you have problems due to insufficient memory for large result sets, use the
--quick
option. This forces mysql
to retrieve results from
the server a row at a time rather than retrieving the entire result set
and buffering it in memory before displaying it. This is done by using
mysql_use_result()
rather than mysql_store_result()
to
retrieve the result set.
Using mysql
is very easy. Invoke it from the prompt of your command
interpreter as follows:
shell> mysql db_name
Or:
shell> mysql --user=user_name --password=your_password db_name
Then type an SQL statement, end it with `;', \g
, or \G
and press Enter.
You can run a script simply like this:
shell> mysql db_name < script.sql > output.tab
mysql
supports the following options:
--help, -?
--batch, -B
mysql
doesn't use the history file.
--character-sets-dir=path
--compress, -C
--database=db_name, -D db_name
--debug[=debug_options], -# [debug_options]
'd:t:o,file_name'
.
The default is 'd:t:o,/tmp/mysql.trace'
.
--debug-info, -T
--default-character-set=charset
--execute=statement, -e statement
--batch
.
--force, -f
--host=host_name, -h host_name
--html, -H
--ignore-space, -i
IGNORE_SPACE
in
section 5.2.2 The Server SQL Mode.
--local-infile[={0|1}]
LOCAL
capability for LOAD DATA INFILE
.
With no value, the option enables LOCAL
. It may be given as
--local-infile=0
or --local-infile=1
to explicitly disable
or enable LOCAL
. Enabling LOCAL
has no effect if the server
does not also support it.
--named-commands, -G
quit
and \q
both
are recognized.
--no-auto-rehash, -A
mysql
to start faster,
but you must issue the rehash
command if you want to use table and
column name completion.
--no-beep, -b
--no-named-commands, -g
\*
form only, or use
named commands only at the beginning of a line ending with a semicolon
(`;'). As of MySQL 3.23.22, mysql
starts with this option
enabled by default! However, even with this option, long-format
commands still work from the first line.
--no-pager
mysql
Commands.
--no-tee
mysql
Commands.
--one-database, -O
--pager[=command]
PAGER
environment
variable. Valid pagers are less
, more
, cat [>
filename]
, and so forth. This option works only on Unix. It does not
work in batch mode.
Output paging is discussed further in
section 8.3.1 mysql
Commands.
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--port=port_num, -P port_num
--prompt=format_str
mysql>
.
The special sequences that the prompt can contain are described in
section 8.3.1 mysql
Commands.
--protocol={TCP | SOCKET | PIPE | MEMORY}
--quick, -q
mysql
doesn't use the history file.
--raw, -r
--batch
option.
--reconnect
--skip-reconnect
.
New in MySQL 4.1.0.
--safe-updates, --i-am-a-dummy, -U
UPDATE
and DELETE
statements that specify rows
to affect using key values. If you have this option in an option file,
you can override it by using --safe-updates
on the command line.
See section 8.3.3 mysql
Tips for more information about
this option.
--sigint-ignore
SIGINT
signals (typically the result of typing Control-C).
This option was added in MySQL 4.1.6.
--silent, -s
--skip-column-names, -N
--skip-line-numbers, -L
--socket=path, -S path
--table, -t
--tee=file_name
mysql
Commands.
--unbuffered, -n
--user=user_name, -u user_name
--verbose, -v
-v -v -v
produces the table output format even in batch
mode.)
--version, -V
--vertical, -E
\G
.
--wait, -w
--xml, -X
You can also set the following variables by using --var_name=value
options:
connect_timeout
max_allowed_packet
max_join_size
--safe-updates
.
(Default value is 1,000,000.)
net_buffer_length
select_limit
SELECT
statements when using
--safe-updates
.
(Default value is 1,000.)
It is also possible to set variables by using
--set-variable=var_name=value
or -O var_name=value
syntax. However, this syntax is deprecated as of MySQL 4.0.
On Unix, the mysql
client writes a record of executed statements to a
history file. By default, the history file is named `.mysql_history'
and is created in your home directory. To specify a different file,
set the value of the MYSQL_HISTFILE
environment variable.
If you do not want to maintain a history file, first remove `.mysql_history' if it exists, and then use either of the following techniques:
MYSQL_HISTFILE
variable to `/dev/null'. To cause this
setting to take effect each time you log in, put the setting in one of
your shell's startup files.
shell> ln -s /dev/null $HOME/.mysql_historyYou need do this only once.
mysql
Commands
mysql
sends SQL statements that you issue to the server to be
executed. There is also a set of commands that mysql
itself
interprets. For a list of these commands, type help
or \h
at
the mysql>
prompt:
mysql> help MySQL commands: ? (\h) Synonym for `help'. clear (\c) Clear command. connect (\r) Reconnect to the server. Optional arguments are db and host. delimiter (\d) Set query delimiter. edit (\e) Edit command with $EDITOR. ego (\G) Send command to mysql server, display result vertically. exit (\q) Exit mysql. Same as quit. go (\g) Send command to mysql server. help (\h) Display this help. nopager (\n) Disable pager, print to stdout. notee (\t) Don't write into outfile. pager (\P) Set PAGER [to_pager]. Print the query results via PAGER. print (\p) Print current command. prompt (\R) Change your mysql prompt. quit (\q) Quit mysql. rehash (\#) Rebuild completion hash. source (\.) Execute an SQL script file. Takes a file name as an argument. status (\s) Get status information from the server. system (\!) Execute a system shell command. tee (\T) Set outfile [to_outfile]. Append everything into given outfile. use (\u) Use another database. Takes database name as argument.
Each command has both a long and short form. The long form is not case sensitive; the short form is. The long form can be followed by an optional semicolon terminator, but the short form should not.
The edit
, nopager
, pager
, and system
commands
work only in Unix.
The status
command provides some information about the
connection and the server you are using. If you are running in
--safe-updates
mode, status
also prints the values for
the mysql
variables that affect your queries.
To log queries and their output, use the tee
command. All the data
displayed on the screen will be appended into a given file. This can be very
useful for debugging purposes also. You can enable this feature on the
command line with the --tee
option, or interactively with the tee
command. The tee
file can be disabled interactively with the
notee
command. Executing tee
again re-enables logging.
Without a parameter, the previous file will be used. Note that tee
flushes query results to the file after each statement, just before mysql
prints its next prompt.
Browsing or searching query results in interactive mode by using Unix
programs such as less
, more
, or any other similar program is
possible with the --pager
option. If you specify no value for the
option, mysql
checks the value of the PAGER
environment
variable and sets the pager to that. Output paging can be enabled
interactively with the pager
command and disabled with
nopager
. The command takes an optional argument; if given, the
paging program is set to that. With no argument, the pager is set to the
pager that was set on the command line, or stdout
if no pager was
specified.
Output paging works only in Unix because it uses the popen()
function, which doesn't exist on Windows. For Windows, the tee
option can be used instead to save query output, although this is not as
convenient as pager
for browsing output in some situations.
A few tips about the pager
command:
mysql> pager cat > /tmp/log.txtYou can also pass any options for the program that you want to use as your pager:
mysql> pager less -n -i -S
-S
option. You may find it very
useful for browsing wide query results. Sometimes a very wide result set is
difficult to read on the screen. The -S
option to less
can
make the result set much more readable because you can scroll it
horizontally using the left-arrow and right-arrow keys. You can also use
-S
interactively within less
to switch the horizontal-browse
mode on and off. For more information, read the less
manual page:
shell> man less
mysql> pager cat | tee /dr1/tmp/res.txt \ | tee /dr2/tmp/res2.txt | less -n -i -SIn this example, the command would send query results to two files in two different directories on two different filesystems mounted on `/dr1' and `/dr2', yet still display the results onscreen via
less
.
You can also combine the tee
and pager
functions. Have a
tee
file enabled and pager
set to less
, and you will be
able to browse the results using the less
program and still have
everything appended into a file the same time. The difference between the
Unix tee
used with the pager
command and the mysql
built-in tee
command is that the built-in tee
works even if
you don't have the Unix tee
available. The built-in tee
also
logs everything that is printed on the screen, whereas the Unix tee
used with pager
doesn't log quite that much. Additionally, tee
file logging can be turned on and off interactively from within
mysql
. This is useful when you want to log some queries to a file,
but not others.
From MySQL 4.0.2 on, the default mysql>
prompt can be reconfigured.
The string for defining the prompt can contain the following special
sequences:
Option | Description |
\v | The server version |
\d | The current database |
\h | The server host |
\p | The current TCP/IP host |
\u | Your username |
\U | Your full user_name@host_name account name
|
\\ | A literal `\' backslash character |
\n | A newline character |
\t | A tab character |
\ | A space (a space follows the backslash) |
\_ | A space |
\R | The current time, in 24-hour military time (0-23) |
\r | The current time, standard 12-hour time (1-12) |
\m | Minutes of the current time |
\y | The current year, two digits |
\Y | The current year, four digits |
\D | The full current date |
\s | Seconds of the current time |
\w | The current day of the week in three-letter format (Mon, Tue, ...) |
\P | am/pm |
\o | The current month in numeric format |
\O | The current month in three-letter format (Jan, Feb, ...) |
\c | A counter that increments for each statement you issue |
\S | Semicolon |
\' | Single quote |
\" | Double quote |
`\' followed by any other letter just becomes that letter.
If you specify the prompt
command with no argument, mysql
resets
the prompt to the default of mysql>
.
You can set the prompt in several ways:
MYSQL_PS1
environment variable to a prompt string. For
example:
shell> export MYSQL_PS1="(\u@\h) [\d]> "
prompt
option in the [mysql]
group of any MySQL
option file, such as `/etc/my.cnf' or the `.my.cnf' file in
your home directory.
For example:
[mysql] prompt=(\\u@\\h) [\\d]>\\_In this example, note that the backslashes are doubled. If you set the prompt using the
prompt
option in an option
file, it is advisable to double the backslashes when using the special
prompt options. There is
some overlap in the set of allowable prompt options and the set of special
escape sequences that are recognized in option files.
(These sequences are listed in section 4.3.2 Using Option Files.)
The overlap may cause you problems if you use single backslashes.
For example, \s
will be interpreted as a space rather than as the
current seconds value. The following example shows how to define a prompt
within an option file to
include the current time in HH:MM:SS>
format:
[mysql] prompt="\\r:\\m:\\s> "
--prompt
option on the command line to mysql
.
For example:
shell> mysql --prompt="(\u@\h) [\d]> " (user@host) [database]>
prompt
(or
\R
) command. For example:
mysql> prompt (\u@\h) [\d]>\_ PROMPT set to '(\u@\h) [\d]>\_' (user@host) [database]> (user@host) [database]> prompt Returning to default PROMPT of mysql> mysql>
The mysql
client typically is used interactively, like this:
shell> mysql db_name
However, it's also possible to put your SQL statements in a file and then
tell mysql
to read its input from that file. To do so, create a text
file `text_file' that contains the statements you wish to execute.
Then invoke mysql
as shown here:
shell> mysql db_name < text_file
You can also start your text file with a USE db_name
statement. In
this case, it is unnecessary to specify the database name on the command
line:
shell> mysql < text_file
If you are running mysql
, you can execute an SQL
script file using the source
or \.
command:
mysql> source filename mysql> \. filename
Sometimes you may want your script to display progress information to the user; for this you can insert some lines like
SELECT '<info_to_display>' AS ' ';
which will output <info_to_display>.
For more information about batch mode, see section 3.5 Using mysql
in Batch Mode.
mysql
Tips
This section describes some techniques that can help you use mysql
more
effectively.
Some query results are much more readable when displayed vertically, instead of in the usual horizontal table format. Queries can be displayed vertically by terminating the query with \G instead of a semicolon. For example, longer text values that include newlines often are much easier to read with vertical output:
mysql> SELECT * FROM mails WHERE LENGTH(txt) < 300 LIMIT 300,1\G *************************** 1. row *************************** msg_nro: 3068 date: 2000-03-01 23:29:50 time_zone: +0200 mail_from: Monty reply: monty@no.spam.com mail_to: "Thimble Smith" <tim@no.spam.com> sbj: UTF-8 txt: >>>>> "Thimble" == Thimble Smith writes: Thimble> Hi. I think this is a good idea. Is anyone familiar Thimble> with UTF-8 or Unicode? Otherwise, I'll put this on my Thimble> TODO list and see what happens. Yes, please do that. Regards, Monty file: inbox-jani-1 hash: 190402944 1 row in set (0.09 sec)
--safe-updates
Option
For beginners, a useful startup option is --safe-updates
(or
--i-am-a-dummy
, which has the same effect). This option was
introduced in MySQL 3.23.11. It is helpful for cases when you might
have issued a DELETE FROM tbl_name
statement but forgotten the
WHERE
clause. Normally, such a statement will delete all rows from the
table. With --safe-updates
, you can delete rows only by specifying
the key values that identify them. This helps prevent accidents.
When you use the --safe-updates
option, mysql
issues the
following statement when it connects to the MySQL server:
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=1000, SQL_MAX_JOIN_SIZE=1000000;
See section 13.5.3 SET
Syntax.
The SET
statement has the following effects:
UPDATE
or DELETE
statement
unless you specify a key constraint in the WHERE
clause or provide a
LIMIT
clause (or both).
For example:
UPDATE tbl_name SET not_key_column=# WHERE key_column=#; UPDATE tbl_name SET not_key_column=# LIMIT 1;
SELECT
results are automatically limited to 1,000 rows
unless the statement includes a LIMIT
clause.
SELECT
statements that will probably need to examine
more than 1,000,000 row combinations are aborted.
To specify limits other than 1,000 and 1,000,000, you can override the
defaults by using --select_limit
and --max_join_size
options:
shell> mysql --safe-updates --select_limit=500 --max_join_size=10000
mysql
Auto-Reconnect
If the mysql
client loses its connection to the server while sending
a query, it will immediately and automatically try to reconnect once to the
server and send the query again. However, even if mysql
succeeds in
reconnecting, your first connection has ended and all your previous session
objects and settings are lost: temporary tables, the autocommit mode, and
user and session variables. This behavior may be dangerous for you, as in
the following example where the server was shut down and restarted without
you knowing it:
mysql> SET @a=1; Query OK, 0 rows affected (0.05 sec) mysql> INSERT INTO t VALUES(@a); ERROR 2006: MySQL server has gone away No connection. Trying to reconnect... Connection id: 1 Current database: test Query OK, 1 row affected (1.30 sec) mysql> SELECT * FROM t; +------+ | a | +------+ | NULL | +------+ 1 row in set (0.05 sec)
The @a
user variable has been lost with the connection, and after
the reconnection it is undefined. If it is important to have mysql
terminate with an error if the connection has been lost, you can start the
mysql
client with the --skip-reconnect
option.
mysqladmin
, Administering a MySQL Server
mysqladmin
is a client for performing administrative operations.
You can use it to check the server's configuration and current status, create
and drop databases, and more.
Invoke mysqladmin
like this:
shell> mysqladmin [options] command [command-option] command ...
mysqladmin
supports the following commands:
create db_name
debug
drop db_name
extended-status
flush-hosts
flush-logs
flush-privileges
reload
).
flush-status
flush-tables
flush-threads
kill id,id,...
old-password new-password
password
command but stores the password using
the old (pre-4.1) password-hashing format. This command was added in MySQL
4.1.0.
password new-password
new-password
for the account that you use with mysqladmin
for connecting to the
server.
If new-password contains spaces or other characters that are special
to your command interpreter, you will need to enclose it within quotes.
On Windows, be sure to use double quotes rather than single quotes;
single quotes will be not be stripped from the password, they will be
interpreted as part of the password. For example:
shell> mysqladmin password "my new password"
ping
mysqladmin
is 0 if the server is running,
1 if it is not. Beginning with MySQL 4.0.22, the status is 0 even in case
of an error such as Access denied
, because that means the server is
running but disallowed the connection, which is different from the server
not running.
processlist
SHOW PROCESSLIST
statement.
If the --verbose
option is given, the output is like that of
SHOW FULL PROCESSLIST
.
reload
refresh
shutdown
start-slave
status
stop-slave
variables
version
All commands can be shortened to any unique prefix. For example:
shell> mysqladmin proc stat +----+-------+-----------+----+-------------+------+-------+------+ | Id | User | Host | db | Command | Time | State | Info | +----+-------+-----------+----+-------------+------+-------+------+ | 6 | monty | localhost | | Processlist | 0 | | | +----+-------+-----------+----+-------------+------+-------+------+ Uptime: 10077 Threads: 1 Questions: 9 Slow queries: 0 Opens: 6 Flush tables: 1 Open tables: 2 Memory in use: 1092K Max memory used: 1116K
The mysqladmin status
command result displays the following values:
Uptime
Threads
Questions
Slow queries
long_query_time
seconds. See section 5.9.5 The Slow Query Log.
Opens
Flush tables
flush ...
, refresh
, and reload
commands the
server has executed.
Open tables
Memory in use
mysqld
code.
This value is displayed only when MySQL has been compiled with
--with-debug=full
.
Maximum memory used
mysqld
code.
This value is displayed only when MySQL has been compiled with
--with-debug=full
.
If you execute mysqladmin shutdown
when connecting to a local server
using a Unix socket file, mysqladmin
waits until the server's process
ID file has been removed, to ensure that the server has stopped properly.
mysqladmin
supports the following options:
--help, -?
--character-sets-dir=path
--compress, -C
--count=#, -c #
--sleep
(-i
).
--debug[=debug_options], -# [debug_options]
'd:t:o,file_name'
.
The default is 'd:t:o,/tmp/mysqladmin.trace'
.
--default-character-set=charset
--force, -f
drop database
command.
With multiple commands, continue even if an error occurs.
--host=host_name, -h host_name
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--port=port_num, -P port_num
--protocol={TCP | SOCKET | PIPE | MEMORY}
--relative, -r
-i
. Currently, this option works only with the extended-status
command.
--silent, -s
--sleep=delay, -i delay
--socket=path, -S path
--user=user_name, -u user_name
--verbose, -v
--version, -V
--vertical, -E
--relative
, but
prints output vertically.
--wait[=#], -w[#]
You can also set the following variables by using --var_name=value
options:
connect_timeout
shutdown_timeout
It is also possible to set variables by using
--set-variable=var_name=value
or -O var_name=value
syntax. However, this syntax is deprecated as of MySQL 4.0.
mysqlbinlog
Binary Log Utility
The binary log files that the server generates are written in binary format.
To examine these files in text format, use the mysqlbinlog
utility.
It is available as of MySQL 3.23.14.
Invoke mysqlbinlog
like this:
shell> mysqlbinlog [options] log-file ...
For example, to display the contents of the binary log `binlog.000003', use this command:
shell> mysqlbinlog binlog.0000003
The output includes all statements contained in `binlog.000003', together with other information such as the time each statement took, the thread ID of the client that issued it, the timestamp when it was issued, and so forth.
Normally, you use mysqlbinlog
to read binary log files directly and
apply them to the local MySQL server. It is also possible to read binary
logs from a remote server by using the --read-from-remote-server
option.
When you read remote binary logs, the connection parameter options can be
given to indicate how to connect to the server, but they are ignored unless
you also specify the --read-from-remote-server
option. These options
are --host
, --password
, --port
, --protocol
,
--socket
, and --user
.
You can also use mysqlbinlog
to read relay log files written by a
slave server in a replication setup. Relay logs have the same format as
binary log files.
The binary log is discussed further in section 5.9.4 The Binary Log.
mysqlbinlog
supports the following options:
--help, -?
--database=db_name, -d db_name
--force-read, -f
mysqlbinlog
reads a binary log event that
it does not recognize, it prints a warning, ignores the event, and continues.
Without this option, mysqlbinlog
stops if it reads such an event.
--host=host_name, -h host_name
--local-load=path, -l path
LOAD DATA INFILE
in the specified
directory.
--offset=N, -o N
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--port=port_num, -P port_num
--position=N, -j N
--start-position
instead (starting from MySQL 4.1.4).
--protocol={TCP | SOCKET | PIPE | MEMORY}
--read-from-remote-server, -R
--host
, --password
, --port
,
--protocol
,
--socket
, and --user
.
--result-file=name, -r name
--short-form, -s
--socket=path, -S path
--start-datetime=datetime
datetime
argument. Available as of MySQL 4.1.4.
--stop-datetime=datetime
datetime
argument. Available as of MySQL 4.1.4. Useful
for point-in-time recovery.
--start-position=N
N
argument. Available as of MySQL 4.1.4 (previously named
--position
).
--stop-position=N
N
argument. Available as of MySQL 4.1.4.
--to-last-log, -t
--read-from-remote-server
. Available as of MySQL 4.1.2.
--disable-log-bin, -D
--to-last-log
option and are sending the output to the same
MySQL server. This option also is useful when restoring after a crash
to avoid duplication of the statements you have logged. Note:
This option requires that you have the SUPER
privilege. Available
as of MySQL 4.1.8.
--user=user_name, -u user_name
--version, -V
You can also set the following variable by using --var_name=value
options:
open_files_limit
You can pipe the output of mysqlbinlog
into a mysql
client to
execute the statements contained in the binary log. This is used to recover
from a crash when you have an old backup (see section 5.7.1 Database Backups):
shell> mysqlbinlog hostname-bin.000001 | mysql
Or:
shell> mysqlbinlog hostname-bin.[0-9]* | mysql
You can also redirect the output of mysqlbinlog
to a text file
instead, if you need to modify the statement log first (for example, to
remove statements that you don't want to execute for some reason). After
editing the file, execute the statements that it contains by using it as
input to the mysql
program.
mysqlbinlog
has the --position
option, which prints only
those statements with an offset in the binary log greater than or equal to
a given position (the given position must match the start of one event). It
also has options to stop or start when it sees an event of a given date and
time. This enables you to perform point-in-time recovery using the
--stop-datetime
option (to be able to say, for example, "roll forward
my databases to how they were today at 10:30 AM").
If you have more than one binary log to execute on the MySQL server, the safe method is to process them all using a single connection to the server. Here is an example that demonstrates what may be unsafe:
shell> mysqlbinlog hostname-bin.000001 | mysql # DANGER!! shell> mysqlbinlog hostname-bin.000002 | mysql # DANGER!!
Processing binary logs this way using different connections to the server
will cause problems if the first log file contains a CREATE TEMPORARY
TABLE
statement and the second log contains a statement that uses the
temporary table. When the first mysql
process terminates, the server
will drop the temporary table. When the second mysql
process attempts
to use the table, the server will report ``unknown table.''
To avoid problems like this, use a single connection to execute the contents of all binary logs that you want to process. Here is one way to do that:
shell> mysqlbinlog hostname-bin.000001 hostname-bin.000002 | mysql
Another approach is to do this:
shell> mysqlbinlog hostname-bin.000001 > /tmp/statements.sql shell> mysqlbinlog hostname-bin.000002 >> /tmp/statements.sql shell> mysql -e "source /tmp/statements.sql"
In MySQL 3.23, the binary log did not contain the data to load for
LOAD DATA INFILE
statements. To execute such a statement from a
binary log file, the original data file was needed. Starting from MySQL
4.0.14, the binary log does contain the data, so mysqlbinlog
can
produce output that reproduces the LOAD DATA INFILE
operation without
the original data file. mysqlbinlog
copies the data to a temporary
file and writes a LOAD DATA LOCAL INFILE
statement that refers to the
file. The default location of the directory where these files are written
is system-specific. To specify a directory explicitly, use the
--local-load
option.
Because mysqlbinlog
converts LOAD DATA INFILE
statements to
LOAD DATA LOCAL INFILE
statements (that is, it adds LOCAL
),
both the client and the server that you use to process the statements must be
configured to allow LOCAL
capability.
See section 5.4.4 Security Issues with LOAD DATA LOCAL
.
Warning: The temporary files created for LOAD DATA LOCAL
statements are not automatically deleted
because they are needed until you actually execute those statements. You
should delete the temporary files yourself after you no longer need the
statement log. The files can be found in the temporary file directory and
have names like `original_file_name-#-#'.
In the future, we will fix this problem by allowing mysqlbinlog
to connect directly to a mysqld
server. Then it will be possible
to safely remove the log files automatically as soon as the LOAD DATA
INFILE
statements have been executed.
Before MySQL 4.1, mysqlbinlog
could not prepare output suitable for
mysql
if the binary log contained interlaced statements originating
from different clients that used temporary tables of the same name. This is
fixed in MySQL 4.1. However, the problem still existed for LOAD DATA
INFILE
statements until it was fixed in MySQL 4.1.8.
mysqlcc
, the MySQL Control Center
mysqlcc
, the MySQL Control Center, is a platform-independent client that
provides a graphical user interface (GUI) to the MySQL database server.
It supports interactive use, including syntax highlighting and tab completion.
It provides database and table management, and allows server administration.
mysqlcc
is deprecated and it is recommended that users choose the new
MySQL Administrator and MySQL Query Browser, found at http://dev.mysql.com/downloads/.
Currently, mysqlcc
runs on Windows and Linux platforms.
Invoke mysqlcc
by double-clicking its icon in a graphical environment.
From the command line, invoke it like this:
shell> mysqlcc [options]
mysqlcc
supports the following options:
--help, -?
--blocking_queries, -b
--compress, -C
--connection_name=name, -c name
--server
.
--database=db_name, -d db_name
--history_size=#, -H #
--host=host_name, -h host_name
--local-infile[={0|1}]
LOCAL
capability for LOAD DATA INFILE
.
With no value, the option enables LOCAL
. It may be given as
--local-infile=0
or --local-infile=1
to explicitly disable
or enable LOCAL
. Enabling LOCAL
has no effect if the server
does not also support it.
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--plugins_path=name, -g name
--port=port_num, -P port_num
--query, -q
--register, -r
--server=name, -s name
--socket=path, -S path
--syntax, -y
--syntax_file=name, -Y name
--translations_path=name, -T name
--user=user_name, -u user_name
--version, -V
You can also set the following variables by using --var_name=value
options:
connect_timeout
max_allowed_packet
max_join_size
net_buffer_length
select_limit
SELECT
statements.
(Default value is 1,000.)
It is also possible to set variables by using
--set-variable=var_name=value
or -O var_name=value
syntax. However, this syntax is deprecated as of MySQL 4.0.
mysqlcheck
Table Maintenance and Repair Program
The mysqlcheck
client checks and repairs MyISAM
tables. It
can also optimize and analyze tables. mysqlcheck
is available as of
MySQL 3.23.38.
mysqlcheck
is similar in function to myisamchk
, but works
differently. The main operational difference is that mysqlcheck
must
be used when the mysqld
server is running, whereas myisamchk
should be used when it is not. The benefit of using mysqlcheck
is
that you do not have to stop the server to check or repair your tables.
mysqlcheck
uses the SQL statements CHECK TABLE
, REPAIR
TABLE
, ANALYZE TABLE
, and OPTIMIZE TABLE
in a convenient way
for the user. It determines which statements to use for the operation you want
to perform, then sends the statements to the server to be executed.
There are three general ways to invoke mysqlcheck
:
shell> mysqlcheck [options] db_name [tables] shell> mysqlcheck [options] --databases DB1 [DB2 DB3...] shell> mysqlcheck [options] --all-databases
If you don't name any tables or use the --databases
or
--all-databases
option, entire databases will be checked.
mysqlcheck
has a special feature compared to the other clients. The
default behavior of checking tables (--check
) can be changed by renaming
the binary. If you want to have a tool that repairs tables by default, you
should just make a copy of mysqlcheck
named mysqlrepair
, or make
a symbolic link to mysqlcheck
named mysqlrepair
. If you invoke
mysqlrepair
, it will repair tables by command.
The following names can be used to change mysqlcheck
default behavior:
mysqlrepair | The default option will be --repair
|
mysqlanalyze | The default option will be --analyze
|
mysqloptimize | The default option will be --optimize
|
mysqlcheck
supports the following options:
--help, -?
--all-databases, -A
--databases
option and naming all the databases on the command line.
--all-in-1, -1
--analyze, -a
--auto-repair
--character-sets-dir=path
--check, -c
--check-only-changed, -C
--compress
--databases, -B
--debug[=debug_options], -# [debug_options]
'd:t:o,file_name'
.
--default-character-set=charset
--extended, -e
--fast, -F
--force, -f
--host=host_name, -h host_name
--medium-check, -m
--extended
operation.
This finds only 99.99% of all errors, which should be good enough in most cases.
--optimize, -o
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--port=port_num, -P port_num
--protocol={TCP | SOCKET | PIPE | MEMORY}
--quick, -q
--repair, -r
--silent, -s
--socket=path, -S path
--tables
--databases
or -B
option. All arguments
following the option are regarded as table names.
--user=user_name, -u user_name
--verbose, -v
--version, -V
mysqldump
Database Backup Program
The mysqldump
client can be used
to dump a database or a collection of databases for backup or for
transferring the data to another SQL server (not necessarily a MySQL
server). The dump will contain SQL statements to create the table
and/or populate the table.
If you are doing a backup on the server, and your tables all are
MyISAM
tables, you could consider using
the mysqlhotcopy
instead (faster backup, faster
restore). See section 8.9 The mysqlhotcopy
Database Backup Program.
There are three general ways to invoke mysqldump
:
shell> mysqldump [options] db_name [tables] shell> mysqldump [options] --databases DB1 [DB2 DB3...] shell> mysqldump [options] --all-databases
If you don't name any tables or use the --databases
or
--all-databases
option, entire databases will be dumped.
To get a list of the options your version of mysqldump
supports,
execute mysqldump --help
.
If you run mysqldump
without the --quick
or
--opt
option, mysqldump
loads the whole result set into
memory before dumping the result. This will probably be a problem if
you are dumping a big database. As of MySQL 4.1, --opt
is on by
default, but can be disabled with --skip-opt
.
If you are using a recent copy of the mysqldump
program
to generate a dump to be reloaded into a very old MySQL
server, you should not use the --opt
or -e
options.
Before MySQL 4.1.2,
out-of-range numeric values such as -inf
and inf
, as well
as NaN (not-a-number) values are dumped by mysqldump
as NULL
.
You can see this using the following sample table:
mysql> CREATE TABLE t (f DOUBLE); mysql> INSERT INTO t VALUES(1e+111111111111111111111); mysql> INSERT INTO t VALUES(-1e111111111111111111111); mysql> SELECT f FROM t; +------+ | f | +------+ | inf | | -inf | +------+
For this table, mysqldump
produces the following data output:
-- -- Dumping data for table `t` -- INSERT INTO t VALUES (NULL); INSERT INTO t VALUES (NULL);
The significance of this behavior is that if you dump and restore the
table, the new table has contents that differ from the original contents.
This problem is fixed as of MySQL 4.1.2; you cannot insert inf
in the
table, so this mysqldump
behavior is only relevant when you deal
with old servers.
mysqldump
supports the following options:
--help, -?
--add-drop-table
DROP TABLE
statement before each CREATE TABLE
statement.
--add-locks
LOCK TABLES
and UNLOCK TABLES
statements. This results in faster inserts when the dump file is reloaded.
See section 7.2.14 Speed of INSERT
Statements.
--all-databases, -A
--databases
option and naming all the databases on the command line.
--allow-keywords
--comments[={0|1}]
0
, suppresses additional information in the dump file such
as program version, server version, and host. --skip-comments
has the
same effect as --comments=0
. The default value is 1
to not
suppress the extra information. New in MySQL 4.0.17.
--compact
--skip-add-drop-table
, --no-set-names
,
--skip-disable-keys
, and --skip-add-locks
options. New in
MySQL 4.1.2.
--compatible=name
name
can be
ansi
,
mysql323
,
mysql40
,
postgresql
,
oracle
,
mssql
,
db2
,
maxdb
,
no_key_options
,
no_table_options
,
or
no_field_options
.
To use several values, separate them by commas.
These values have the same meaning as the corresponding options for setting
the server SQL mode.
See section 5.2.2 The Server SQL Mode.
This option requires a server version of 4.1.0 or higher.
With older servers, it does nothing.
--complete-insert, -c
INSERT
statements that include column names.
--compress, -C
--create-options
CREATE TABLE
statements.
Before MySQL 4.1.2, use --all
instead.
--databases, -B
mysqldump
treats the first name
argument on the command line as a database name and following names as table
names. With this option, it treats all name arguments as database names.
CREATE DATABASE IF NOT EXISTS db_name
and USE
db_name
statements are included in the output before each new
database.
--debug[=debug_options], -# [debug_options]
'd:t:o,file_name'
.
--default-character-set=charset
mysqldump
from MySQL 4.1.2 or later
uses utf8
, and earlier versions use latin1
.
--delayed-insert
INSERT DELAYED
statements.
--delete-master-logs
--first-slave
before MySQL 4.1.8
and enables --master-data
thereafter.
It was added in MySQL 3.23.57 (for MySQL 3.23) and MySQL 4.0.13 (for MySQL
4.0).
--disable-keys, -K
INSERT
statements with
/*!40000 ALTER TABLE tbl_name DISABLE KEYS */;
and
/*!40000 ALTER TABLE tbl_name ENABLE KEYS */;
statements.
This makes loading the dump file into a MySQL 4.0 server faster because the
indexes are created after all rows are inserted.
This option is effective only for MyISAM
tables.
--extended-insert, -e
INSERT
syntax that include several VALUES
lists.
This results in a smaller dump file and speeds up inserts when the file is
reloaded.
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
-T
option and have the same
meaning as the corresponding clauses for LOAD DATA INFILE
.
See section 13.1.5 LOAD DATA INFILE
Syntax.
--first-slave, -x
--lock-all-tables
in MySQL 4.1.8.
--flush-logs, -F
RELOAD
privilege. Note that if you
use this option in combination with the --all-databases
(or
-A
) option, the logs are flushed for each database dumped.
The exception is when using --lock-all-tables
or --master-data
:
In this case, the logs are flushed only once, corresponding to the moment
that all tables are locked. If you want your dump and the log flush to
happen at exactly the same moment, you should use --flush-logs
together with either --lock-all-tables
or --master-data
.
--force, -f
--host=host_name, -h host_name
localhost
.
--hex-blob
'abc'
becomes 0x616263
). The affected columns are BINARY
,
VARBINARY
, and BLOB
in MySQL 4.1 and up, and CHAR
BINARY
, VARCHAR BINARY
, and BLOB
in MySQL 4.0. This option
was added in MySQL 4.0.23 and 4.1.8.
--lock-all-tables, -x
--single-transaction
and --lock-tables
. Added in
MySQL 4.1.8.
--lock-tables, -l
READ LOCAL
to allow concurrent inserts in the case of MyISAM
tables. For InnoDB
tables, --single-transaction
is a much better
option, because it does not need to lock the tables at all.
Please note that when dumping multiple databases, --lock-tables
locks
tables for each database separately. So, this option does not guarantee
that the tables in the dump file will be logically consistent between
databases. Tables in different databases may be dumped in completely
different states.
--master-data[=value]
RELOAD
privilege. If the option
value is equal to 1, the position and filename are written to the dump
output in the form of a CHANGE MASTER
statement that will make a
slave server start from the correct position in the master's binary logs if
you use this SQL dump of the master to set up a slave. If the option value
is equal to 2, the CHANGE MASTER
statement is written as an SQL
comment. This is the default action if value is omitted. value
may be given as of MySQL 4.1.8; before that, do not specify an option value.
The --master-data
option turns on --lock-all-tables
, unless
--single-transaction
also is specified (in which case, a
global read lock is only acquired a short time at the beginning of the
dump. See also the description for
--single-transaction
. In all cases,
any action on logs happens at the exact moment of the dump.
This option automatically turns off --lock-tables
.
--no-create-db, -n
CREATE DATABASE /*!32312 IF NOT EXISTS*/
db_name
statements that are otherwise included in the output if the
--databases
or --all-databases
option is given.
--no-create-info, -t
CREATE TABLE
statements that re-create each dumped table.
--no-data, -d
--opt
--add-drop-table
--add-locks --create-options --disable-keys --extended-insert
--lock-tables --quick --set-charset
. It should
give you a fast dump operation and produce a dump file that can be reloaded
into a MySQL server quickly. As of MySQL 4.1, --opt
is on by default,
but can be disabled with --skip-opt
. To disable only certain of the
options enabled by --opt
, use their --skip
forms; for example,
--skip-add-drop-table
or --skip-quick
.
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--port=port_num, -P port_num
--protocol={TCP | SOCKET | PIPE | MEMORY}
--quick, -q
mysqldump
to retrieve rows for a table from
the server a row at a time rather than retrieving the entire row set
and buffering it in memory before writing it out.
--quote-names, -Q
ANSI_QUOTES
option, names are
quoted within `"' characters.
As of MySQL 4.1.1, --quote-names
is on by default,
but can be disabled with --skip-quote-names
.
--result-file=file, -r file
--set-charset
SET NAMES default_character_set
to the output. This option
is enabled by default. To suppress the SET NAMES
statement, use
--skip-set-charset
. This option was added in MySQL 4.1.2.
--single-transaction
BEGIN
SQL statement before dumping data from
the server. It is useful only with InnoDB
tables, because then it
will dump the consistent state of the database at the time then
BEGIN
was issued without blocking any applications.
When using this option, you should keep in mind that only InnoDB
tables will be dumped in a consistent state. For example, any MyISAM
or
HEAP
tables dumped while using this option may still change
state.
The --single-transaction
option was added in MySQL 4.0.2.
This option is mutually exclusive with the --lock-tables
option,
because LOCK TABLES
causes any pending transactions to be committed
implicitly.
To dump big tables, you should combine this option with --quick
.
--socket=path, -S path
localhost
(which is the
default host).
--skip-comments
--comments
option.
--tab=path, -T path
mysqldump
creates a `tbl_name.sql' file that contains the CREATE TABLE
statement that creates the table, and a `tbl_name.txt' file that
contains its data. The option value is the directory in which to write the
files.
By default, the `.txt' data files are formatted using tab characters
between column values and a newline at the end of each line. The format can
be specified explicitly using the --fields-xxx
and
--lines--xxx
options.
Note: This option should be used only when mysqldump
is
run on the same machine as the mysqld
server. You must have the
FILE
privilege, and the server must have permission to write files in
the directory that you specify.
--tables
--databases
or -B
option. All arguments
following the option are regarded as table names.
--user=user_name, -u user_name
--verbose, -v
--version, -V
--where='where-condition', -w 'where-condition'
WHERE
condition. Note that
quotes around the condition are mandatory if it contains spaces or
characters that are special to your command interpreter.
Examples:
"--where=user='jimf'" "-wuserid>1" "-wuserid<1"
--xml, -X
You can also set the following variables by using --var_name=value
options:
max_allowed_packet
net_buffer_length
--extended-insert
or --opt
), mysqldump
will create
rows up to net_buffer_length
length. If you increase this
variable, you should also ensure that the net_buffer_length
variable in the MySQL server is at least this large.
It is also possible to set variables by using
--set-variable=var_name=value
or -O var_name=value
syntax. However, this syntax is deprecated as of MySQL 4.0.
The most common use of mysqldump
is probably for making a backup of
an entire database:
shell> mysqldump --opt db_name > backup-file.sql
You can read the dump file back into the server like this:
shell> mysql db_name < backup-file.sql
Or like this:
shell> mysql -e "source /path-to-backup/backup-file.sql" db_name
mysqldump
is also very useful for populating databases by copying
data from one MySQL server to another:
shell> mysqldump --opt db_name | mysql --host=remote_host -C db_name
It is possible to dump several databases with one command:
shell> mysqldump --databases db_name1 [db_name2 ...] > my_databases.sql
If you want to dump all databases, use the --all-databases
option:
shell> mysqldump --all-databases > all_databases.sql
If tables are stored in the InnoDB
storage engine, mysqldump
provides a
way of making an online backup of these (see command below). This backup just
needs to acquire a global read lock on all tables (using FLUSH TABLES
WITH READ LOCK
) at the beginning of the dump. As soon as this lock has been
acquired, the binary log coordinates are read and lock is released. So if and
only if one long updating statement is running when the FLUSH...
is
issued, the MySQL server may get stalled until that long statement finishes,
and then the dump becomes lock-free. So if the MySQL server receives only
short (in the sense of "short execution time") updating statements, even if
there are plenty of them, the initial lock period should not be noticeable.
shell> mysqldump --all-databases --single-transaction > all_databases.sql
For point-in-time recovery (also known as "roll-forward", when you need to restore an old backup and replay the changes which happened since that backup), it is often useful to rotate the binary log (see section 5.9.4 The Binary Log) or at least know the binary log coordinates to which the dump corresponds:
shell> mysqldump --all-databases --master-data=2 > all_databases.sql or shell> mysqldump --all-databases --flush-logs --master-data=2 > all_databases.sql
The simultaneous use of --master-data
and --single-transaction
works as of MySQL 4.1.8. It provides a convenient way to make an online backup
suitable for point-in-time recovery, if tables are stored in the
InnoDB
storage engine.
For more information on making backups, see section 5.7.1 Database Backups.
mysqlhotcopy
Database Backup Program
mysqlhotcopy
is a Perl script that was originally written and
contributed by Tim Bunce. It uses LOCK TABLES
,
FLUSH TABLES
, and cp
or scp
to quickly make a backup of
a database. It's the fastest way to make a backup of the database or single
tables, but it can be run only on the same machine where the database
directories are located. mysqlhotcopy
works only for backing up
MyISAM
and ISAM
tables.
It runs on Unix, and as of MySQL 4.0.18 also on NetWare.
shell> mysqlhotcopy db_name [/path/to/new_directory]
shell> mysqlhotcopy db_name_1 ... db_name_n /path/to/new_directory
Back up tables in the given database that match a regular expression:
shell> mysqlhotcopy db_name./regex/
The regular expression for the table name can be negated by prefixing it with a tilde (`~'):
shell> mysqlhotcopy db_name./~regex/
mysqlhotcopy
supports the following options:
--help, -?
--allowold
_old
suffix).
--checkpoint=db_name.tbl_name
--debug
--dryrun, -n
--flushlog
--keepold
--method=#
cp
or scp
).
--noindices
myisamchk -rq
for MyISAM
tables or isamchk -rq
for ISAM
tables.
--password=password, -ppassword
--port=port_num, -P port_num
--quiet, -q
--regexp=expr
--socket=path, -S path
--suffix=str
--tmpdir=path
--user=user_name, -u user_name
mysqlhotcopy
reads the [client]
and [mysqlhotcopy]
option groups from option files.
To execute mysqlhotcopy
, you must have access to the files
for the tables that you are backing up, the SELECT
privilege
for those tables, and the RELOAD
privilege (to be able to
execute FLUSH TABLES
).
Use perldoc
for additional mysqlhotcopy
documentation:
shell> perldoc mysqlhotcopy
mysqlimport
Data Import Program
The mysqlimport
client provides a command-line interface to the
LOAD DATA INFILE
SQL statement. Most options to mysqlimport
correspond directly to clauses of LOAD DATA INFILE
.
See section 13.1.5 LOAD DATA INFILE
Syntax.
Invoke mysqlimport
like this:
shell> mysqlimport [options] db_name textfile1 [textfile2 ...]
For each text file named on the command line, mysqlimport
strips any
extension from the filename and uses the result to determine the name of the
table into which to import the file's contents. For example, files named
`patient.txt', `patient.text', and `patient' all would be
imported into a table named patient
.
mysqlimport
supports the following options:
--help, -?
--columns=column_list, -c column_list
--compress, -C
--debug[=debug_options], -# [debug_options]
'd:t:o,file_name'
.
--delete, -D
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
LOAD DATA INFILE
. See section 13.1.5 LOAD DATA INFILE
Syntax.
--force, -f
--force
,
mysqlimport
exits if a table doesn't exist.
--host=host_name, -h host_name
localhost
.
--ignore, -i
--replace
option.
--ignore-lines=n
--local, -L
--lock-tables, -l
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--port=port_num, -P port_num
--protocol={TCP | SOCKET | PIPE | MEMORY}
--replace, -r
--replace
and --ignore
options control handling of input
records that duplicate existing records on unique key values. If you specify
--replace
, new rows replace existing rows that have the same unique key
value. If you specify --ignore
, input rows that duplicate an existing
row on a unique key value are skipped. If you don't specify either option, an
error occurs when a duplicate key value is found, and the rest of the text
file is ignored.
--silent, -s
--socket=path, -S path
localhost
(which is the
default host).
--user=user_name, -u user_name
--verbose, -v
--version, -V
Here is a sample session that demonstrates use of mysqlimport
:
shell> mysql -e 'CREATE TABLE imptest(id INT, n VARCHAR(30))' test shell> ed a 100 Max Sydow 101 Count Dracula . w imptest.txt 32 q shell> od -c imptest.txt 0000000 1 0 0 \t M a x S y d o w \n 1 0 0000020 1 \t C o u n t D r a c u l a \n 0000040 shell> mysqlimport --local test imptest.txt test.imptest: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0 shell> mysql -e 'SELECT * FROM imptest' test +------+---------------+ | id | n | +------+---------------+ | 100 | Max Sydow | | 101 | Count Dracula | +------+---------------+
mysqlshow
, Showing Databases, Tables, and Columns
The mysqlshow
client can be used to quickly look at which databases
exist, their tables, and a table's columns or indexes.
mysqlshow
provides a command-line interface to several SQL
SHOW
statements. The same information can be obtained by using those
statements directly. For example, you can issue them from the mysql
client program.
See section 13.5.4 SHOW
Syntax.
Invoke mysqlshow
like this:
shell> mysqlshow [options] [db_name [tbl_name [col_name]]]
Note that in newer MySQL versions, you see only those database, tables, or columns for which you have some privileges.
If the last argument contains shell or SQL wildcard characters (`*',
`?', `%', or `_'), only those names that are matched by the
wildcard are shown. If a database name contains any underscores, those
should be escaped with a backslash (some Unix shells will require two) in
order to get a list of the proper tables or columns. `*' and `?'
characters are converted into SQL `%' and `_' wildcard characters.
This might cause some confusion when you try to display the columns for a
table with a `_' in the name, because in this case mysqlshow
shows you only the table names that match the pattern. This is easily fixed
by adding an extra `%' last on the command line as a separate
argument.
mysqlshow
supports the following options:
--help, -?
--character-sets-dir=path
--compress, -C
--debug[=debug_options], -# [debug_options]
'd:t:o,file_name'
.
--default-character-set=charset
--host=host_name, -h host_name
--keys, -k
--password[=password], -p[password]
-p
), you cannot have a space between the
option and the password. If you omit the password value following the
--password
or -p
option on the command line, you will be
prompted for one.
--port=port_num, -P port_num
--protocol={TCP | SOCKET | PIPE | MEMORY}
--socket=path, -S path
localhost
(which is the
default host).
--status, -i
--user=user_name, -u user_name
--verbose, -v
--version, -V
perror
, Explaining Error CodesFor most system errors, MySQL displays, in addition to an internal text message, the system error code in one of the following styles:
message ... (errno: #) message ... (Errcode: #)
You can find out what the error code means by either examining the
documentation for your system or by using the perror
utility.
perror
prints a description for a system error code or for a storage
engine (table handler) error code.
Invoke perror
like this:
shell> perror [options] errorcode ...
Example:
shell> perror 13 64 Error code 13: Permission denied Error code 64: Machine is not on the network
Note that the meaning of system error messages may be dependent on your operating system. A given error code may mean different things on different operating systems.
replace
String-Replacement Utility
The replace
utility program changes strings in place in files or on
the standard input. It uses a finite state machine to match longer strings
first. It can be used to swap strings. For example, the following command
swaps a
and b
in the given files, `file1' and `file2':
shell> replace a b b a -- file1 file2 ...
Use the --
option to indicate where the string-replacement list
ends and the filenames begin.
Any file named on the command line is modified in place, so you may want to make a copy of the original before converting it.
If no files are named on the command line, replace
reads the standard
input and writes to the standard output. In this case, no --
option is
needed.
The replace
program is used by msql2mysql
.
See section 22.1.1 msql2mysql
, Convert mSQL Programs for Use with MySQL.
replace
supports the following options:
-?, -I
-# debug_options
debug_options
string often is
'd:t:o,file_name'
.
-s
-v
-V
This chapter discusses the rules for writing the following elements of SQL statements when using MySQL:
This section describes how to write literal values in MySQL. These include
strings, numbers, hexadecimal values, boolean values, and NULL
. The section also
covers the various nuances and ``gotchas'' that
you may run into when dealing with these basic types in MySQL.
A string is a sequence of characters, surrounded by either single quote (`'') or double quote (`"') characters. Examples:
'a string' "another string"
If the server SQL mode has ANSI_QUOTES
enabled, string literals can be
quoted only with single quotes. A string quoted with double quotes will be
interpreted as an identifier.
As of MySQL 4.1.1, string literals may have an optional character set
introducer and COLLATE
clause:
[_charset_name]'string' [COLLATE collation_name]
Examples:
SELECT _latin1'string'; SELECT _latin1'string' COLLATE latin1_danish_ci;
For more information about these forms of string syntax, see section 10.3.7 Character String Literal Character Set and Collation.
Within a string, certain sequences have special meaning. Each of these sequences begins with a backslash (`\'), known as the escape character. MySQL recognizes the following escape sequences:
These sequences are case sensitive. For example, `\b' is interpreted as a backspace, but `\B' is interpreted as `B'.
The `\%' and `\_' sequences are used to search for literal instances of `%' and `_' in pattern-matching contexts where they would otherwise be interpreted as wildcard characters. See section 12.3.1 String Comparison Functions. Note that if you use `\%' or `\_' in other contexts, they return the strings `\%' and `\_' and not `%' and `_'.
In all other escape sequences, backslash is ignored. That is, the escaped character is interpreted as if it was not escaped.
There are several ways to include quotes within a string:
The following SELECT
statements demonstrate how quoting and
escaping work:
mysql> SELECT 'hello', '"hello"', '""hello""', 'hel''lo', '\'hello'; +-------+---------+-----------+--------+--------+ | hello | "hello" | ""hello"" | hel'lo | 'hello | +-------+---------+-----------+--------+--------+ mysql> SELECT "hello", "'hello'", "''hello''", "hel""lo", "\"hello"; +-------+---------+-----------+--------+--------+ | hello | 'hello' | ''hello'' | hel"lo | "hello | +-------+---------+-----------+--------+--------+ mysql> SELECT 'This\nIs\nFour\nLines'; +--------------------+ | This Is Four Lines | +--------------------+ mysql> SELECT 'disappearing\ backslash'; +------------------------+ | disappearing backslash | +------------------------+
If you want to insert binary data into a string column (such as a
BLOB
), the following characters must be represented by escape
sequences:
NUL
| NUL byte (ASCII 0).
Represent this character by `\0' (a backslash followed by an ASCII `0' character).
|
\
| Backslash (ASCII 92). Represent this character by `\\'. |
'
| Single quote (ASCII 39). Represent this character by `\''. |
"
| Double quote (ASCII 34). Represent this character by `\"'. |
When writing application programs, any string that might contain any of these special characters must be properly escaped before the string is used as a data value in an SQL statement that is sent to the MySQL server. You can do this in two ways:
mysql_real_escape_string()
C API function to escape characters.
See section 22.2.3.47 mysql_real_escape_string()
.
The Perl DBI interface provides a
quote
method to convert special characters to the proper escape
sequences. See section 22.4 MySQL Perl API.
Integers are represented as a sequence of digits. Floats use `.' as a decimal separator. Either type of number may be preceded by `-' to indicate a negative value.
Examples of valid integers:
1221 0 -32
Examples of valid floating-point numbers:
294.42 -32032.6809e+10 148.00
An integer may be used in a floating-point context; it is interpreted as the equivalent floating-point number.
MySQL supports hexadecimal values. In numeric contexts, these act like integers (64-bit precision). In string contexts, these act like binary strings, where each pair of hex digits is converted to a character:
mysql> SELECT x'4D7953514C'; -> 'MySQL' mysql> SELECT 0xa+0; -> 10 mysql> SELECT 0x5061756c; -> 'Paul'
In MySQL 4.1 (and in MySQL 4.0 when using the --new
option), the default
type of a hexadecimal value is a string. If you want to ensure that
the value is treated as a number, you can use CAST(... AS UNSIGNED)
:
mysql> SELECT 0x41, CAST(0x41 AS UNSIGNED); -> 'A', 65
The 0x
syntax is based on ODBC. Hexadecimal strings are often used by
ODBC to supply values for BLOB
columns.
The x'hexstring'
syntax is new in 4.0 and is based on standard SQL.
Beginning with MySQL 4.0.1, you can convert a string or a number to a string
in hexadecimal format with the HEX()
function:
mysql> SELECT HEX('cat'); -> '636174' mysql> SELECT 0x636174; -> 'cat'
Beginning with MySQL 4.1, the constant TRUE
evaluates to 1
and
the constant FALSE
evaluates to 0
. The constant names can be
written in any lettercase.
mysql> SELECT TRUE, true, FALSE, false; -> 1, 1, 0, 0
NULL
Values
The NULL
value means ``no data.''
NULL
can be written in any lettercase.
Be aware that the NULL
value is different from values such
as 0
for numeric types or the empty string for string types.
See section A.5.3 Problems with NULL
Values.
For text file import or export operations performed with LOAD DATA
INFILE
or SELECT ... INTO OUTFILE
, NULL
is represented by
the \N
sequence.
See section 13.1.5 LOAD DATA INFILE
Syntax.
Database, table, index, column, and alias names are identifiers. This section describes the allowable syntax for identifiers in MySQL.
The following table describes the maximum length and allowable characters for each type of identifier.
Identifier | Maximum Length (bytes) | Allowed Characters |
Database | 64 | Any character that is allowed in a directory name, except `/', `\', or `.' |
Table | 64 | Any character that is allowed in a filename, except `/', `\', or `.' |
Column | 64 | All characters |
Index | 64 | All characters |
Alias | 255 | All characters |
In addition to the restrictions noted in the table, no identifier can contain ASCII 0 or a byte with a value of 255. Database, table, and column names should not end with space characters. Before MySQL 4.1, identifier quote characters should not be used in identifiers.
Beginning with MySQL 4.1, identifiers are stored using Unicode (UTF8).
This applies to identifiers in table definitions that stored in `.frm'
files and to identifiers stored in the grant tables in the mysql
database. Although Unicode identifiers can include multi-byte characters, note
that the maximum lengths shown in the table are byte counts. If an identifier
does contain multi-byte characters, the number of characters allowed in
the identifier is less than the value shown in the table.
An identifier may be quoted or unquoted. If an identifier is a reserved word or contains special characters, you must quote it whenever you refer to it. For a list of reserved words, see section 9.6 Treatment of Reserved Words in MySQL. Special characters are those outside the set of alphanumeric characters from the current character set, `_', and `$'.
The identifier quote character is the backtick (``'):
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
If the server SQL mode includes the ANSI_QUOTES
mode option,
it is also allowable to quote identifiers with double quotes:
mysql> CREATE TABLE "test" (col INT); ERROR 1064: You have an error in your SQL syntax. (...) mysql> SET sql_mode='ANSI_QUOTES'; mysql> CREATE TABLE "test" (col INT); Query OK, 0 rows affected (0.00 sec)
See section 5.2.2 The Server SQL Mode.
As of MySQL 4.1, identifier quote characters can be included within an
identifier if you quote the identifier. If the character to be included within
the identifier is the same as that used to quote the identifier itself,
double the character. The following statement creates a table named a`b
that contains a column named c"d
:
mysql> CREATE TABLE `a``b` (`c"d` INT);
Identifier quoting was introduced in MySQL 3.23.6 to allow use of identifiers that are reserved words or that contain special characters. Before 3.23.6, you cannot use identifiers that require quotes, so the rules for legal identifiers are more restrictive:
--default-character-set
option
to mysqld
.
See section 5.8.1 The Character Set Used for Data and Sorting.
It is recommended that you do not use names like 1e
, because
an expression like 1e+1
is ambiguous. It might be interpreted as the
expression 1e + 1
or as the number 1e+1
, depending on context.
MySQL allows names that consist of a single identifier or multiple identifiers. The components of a multiple-part name should be separated by period (`.') characters. The initial parts of a multiple-part name act as qualifiers that affect the context within which the final identifier is interpreted.
In MySQL you can refer to a column using any of the following forms:
Column Reference | Meaning |
col_name | The column col_name from whichever table used in the query contains a column of that name. |
tbl_name.col_name | The column col_name from table tbl_name of the default database. |
db_name.tbl_name.col_name | The column col_name from table tbl_name of the database db_name. This syntax is unavailable before MySQL 3.22. |
If any components of a multiple-part name require quoting, quote them
individually rather than quoting the name as a whole. For example,
`my-table`.`my-column`
is legal, whereas `my-table.my-column`
is
not.
You need not specify a tbl_name or db_name.tbl_name prefix for
a column reference in a statement unless the reference would be ambiguous.
Suppose that tables t1
and t2
each contain a column
c
, and you retrieve c
in a SELECT
statement that uses
both t1
and t2
. In this case, c
is ambiguous because it
is not unique among the tables used in the statement. You must qualify it
with a table name as t1.c
or t2.c
to indicate which table you
mean. Similarly, to retrieve from a table t
in database db1
and from a table t
in database db2
in the same statement,
you must refer to columns in those tables as db1.t.col_name
and db2.t.col_name
.
The syntax .tbl_name means the table tbl_name in the current database. This syntax is accepted for ODBC compatibility because some ODBC programs prefix table names with a `.' character.
In MySQL, databases correspond to directories within the data directory. Tables within a database correspond to at least one file within the database directory (and possibly more, depending on the storage engine). Consequently, the case sensitivity of the underlying operating system determines the case sensitivity of database and table names. This means database and table names are not case sensitive in Windows, and case sensitive in most varieties of Unix. One notable exception is Mac OS X, which is Unix-based but uses a default filesystem type (HFS+) that is not case sensitive. However, Mac OS X also supports UFS volumes, which are case sensitive just as on any Unix. See section 1.5.4 MySQL Extensions to Standard SQL.
Note: Although database and table names are not case sensitive on
some platforms, you should not refer to a given database or table using
different
cases within the same query. The following query would not work because it
refers to a table both as my_table
and as MY_TABLE
:
mysql> SELECT * FROM my_table WHERE MY_TABLE.col=1;
Column names, index names, and column aliases are not case sensitive on any platform.
Table aliases are case sensitive before MySQL 4.1.1. The following
query would not work because it refers to the alias both as a
and
as A
:
mysql> SELECT col_name FROM tbl_name AS a -> WHERE a.col_name = 1 OR A.col_name = 2;
If you have trouble remembering the allowable lettercase for database and table names, adopt a consistent convention, such as always creating databases and tables using lowercase names.
How table and database names are stored on disk and used in MySQL is defined by the
lower_case_table_names
system variable, which you can set when
starting mysqld
. lower_case_table_names
can take one of
the following values:
Value | Meaning |
0 | Table and database names are stored on disk using the lettercase specified in the CREATE TABLE or CREATE DATABASE statement. Name comparisons are case sensitive. This is the default on Unix systems. Note that if you force this to 0 with --lower-case-table-names=0 on a case-insensitive filesystem and access MyISAM tablenames using different lettercases, this may lead to index corruption.
|
1 | Table names are stored in lowercase on disk and name comparisons are not case sensitive. MySQL converts all table names to lowercase on storage and lookup. This behavior also applies to database names as of MySQL 4.0.2, and to table aliases as of 4.1.1. This value is the default on Windows and Mac OS X systems. |
2 | Table and database names are stored on disk using the lettercase specified in the CREATE TABLE or CREATE DATABASE statement, but MySQL converts them to lowercase on lookup. Name comparisons are not case sensitive. Note: This works only on filesystems that are not case sensitive! InnoDB table names are stored in lowercase, as for lower_case_table_names=1 . Setting lower_case_table_names to 2 can be done as of MySQL 4.0.18.
|
If you are using MySQL on only one platform, you don't normally have to
change the lower_case_table_names
variable. However, you may
encounter difficulties if you want to transfer tables between platforms
that differ in filesystem case sensitivity. For example, on Unix, you
can have two different tables named my_table
and MY_TABLE
,
but on Windows those names are considered the same. To avoid data
transfer problems stemming from database or table name lettercase, you
have two options:
lower_case_table_names=1
on all systems. The main disadvantage
with this is that when you use SHOW TABLES
or SHOW DATABASES
,
you don't see the names in their original lettercase.
lower_case_table_names=0
on Unix and lower_case_table_names=2
on Windows. This preserves the lettercase of database and table names.
The disadvantage of this is that you must ensure that your queries always refer
to your database and table names with the correct lettercase on Windows. If
you transfer your queries to Unix, where lettercase is significant, they will
not work if the lettercase is incorrect.
Note that before setting lower_case_table_names
to 1 on Unix, you must
first convert your old database and table names to lowercase before restarting
mysqld
.
MySQL supports user variables as of version 3.23.6. You can store a value in a user variable and refer to it later, which allows you to pass values from one statement to another. User variables are connection-specific. That is, a variable defined by one client cannot be seen or used by other clients. All variables for a client connection are automatically freed when the client exits.
User variables are written as @var_name
, where the variable name
var_name may consist of alphanumeric characters from the current
character set, `.', `_', and `$'. The default character set
is ISO-8859-1 (Latin1). This may be changed with the
--default-character-set
option to mysqld
. See section 5.8.1 The Character Set Used for Data and Sorting. User variable names are not case sensitive beginning with MySQL 5.0.
Before that, they are case sensitive.
One way to set a user variable is by issuing a SET
statement:
SET @var_name = expr [, @var_name = expr] ...
For SET
, either =
or :=
can be used as the assignment
operator. The expr assigned to each variable can evaluate
to an integer, real, string, or NULL
value.
You can also assign a value to a user variable in statements other than
SET
. In this case, the assignment operator must be :=
and not
=
because =
is treated as a comparison operator
in non-SET
statements:
mysql> SET @t1=0, @t2=0, @t3=0; mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3; +----------------------+------+------+------+ | @t1:=(@t2:=1)+@t3:=4 | @t1 | @t2 | @t3 | +----------------------+------+------+------+ | 5 | 5 | 1 | 4 | +----------------------+------+------+------+
User variables may be used where expressions are allowed. This
does not currently include contexts that explicitly require a number, such
as in the LIMIT
clause of a SELECT
statement, or the
IGNORE number LINES
clause of a LOAD DATA
statement.
If you refer to a variable that has not been initialized, its value
is NULL
.
Note: In a SELECT
statement, each expression is evaluated
only when sent to the client. This means that in a HAVING
,
GROUP BY
, or ORDER BY
clause, you cannot refer to an expression
that involves variables that are set in the SELECT
list. For example,
the following statement will not work as expected:
mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM tbl_name HAVING b=5;
The reference to b
in the HAVING
clause refers to an alias
for an expression in the SELECT
list that uses @aa
. This
does not work as expected: @aa
will not contain the value of the
current row, but the value of id
from the previous selected row.
The general rule is to never assign and use the same variable in the same statement.
Another issue with setting a variable and using it in the same statement is that the default result type of a variable is based on the type of the variable at the start of the statement. The following example illustrates this:
mysql> SET @a='test'; mysql> SELECT @a,(@a:=20) FROM tbl_name;
For this SELECT
statement, MySQL will report to the client that
column one is a string and convert all accesses of @a
to strings,
even though @a is set to a number for the second row. After the
SELECT
statement executes, @a
will be regarded as a
number for the next statement.
To avoid problems with this behavior, either do not set and use the same
variable within a single statement, or else set the variable to 0
,
0.0
, or ''
to define its type before you use it.
An unassigned variable has a value of NULL
with a type of string.
Starting from MySQL 4.0.3, we provide better access to a lot of system and connection variables. Many variables can be changed dynamically while the server is running. This allows you to modify server operation without having to stop and restart it.
The mysqld
server maintains two kinds of variables.
Global variables affect the overall operation of the server.
Session variables affect its operation for individual client connections.
When the server starts, it initializes all global variables to their default
values. These defaults may be changed by options specified in option files
or on the command line. After the server starts, those global variables
that are dynamic can be changed by connecting to the server and issuing
a SET GLOBAL var_name
statement. To change a global variable,
you must have the SUPER
privilege.
The server also maintains a set of session variables for each client
that connects. The client's session variables are initialized at connect
time using the current values of the corresponding global variables. For
those session variables that are dynamic, the client can change them
by issuing a SET SESSION var_name
statement. Setting a session
variable requires no special privilege, but a client can change only its
own session variables, not those of any other client.
A change to a global variable is visible to any client that accesses that
global variable. However, it affects the corresponding session variable
that is initialized from the global variable only for clients that connect
after the change. It does not affect the session variable for any client
that is currently connected (not even that of the client that issues the
SET GLOBAL
statement).
Global or session variables may be set or retrieved using several syntax
forms. The following examples use sort_buffer_size
as a sample variable
name.
To set the value of a GLOBAL
variable, use one
of the following syntaxes:
mysql> SET GLOBAL sort_buffer_size=value; mysql> SET @@global.sort_buffer_size=value;
To set the value of a SESSION
variable, use one of the
following syntaxes:
mysql> SET SESSION sort_buffer_size=value; mysql> SET @@session.sort_buffer_size=value; mysql> SET sort_buffer_size=value;
LOCAL
is a synonym for SESSION
.
If you don't specify GLOBAL
, SESSION
, or LOCAL
when
setting a variable, SESSION
is the default.
See section 13.5.3 SET
Syntax.
To retrieve the value of a GLOBAL
variable, use one of the
following statements:
mysql> SELECT @@global.sort_buffer_size; mysql> SHOW GLOBAL VARIABLES like 'sort_buffer_size';
To retrieve the value of a SESSION
variable, use one of the
following statements:
mysql> SELECT @@sort_buffer_size; mysql> SELECT @@session.sort_buffer_size; mysql> SHOW SESSION VARIABLES like 'sort_buffer_size';
Here, too, LOCAL
is a synonym for SESSION
.
When you retrieve a variable with SELECT @@var_name
(that is, you
do not specify global.
, session.
, or local.
, MySQL returns
the SESSION
value if it exists and the GLOBAL
value otherwise.
For SHOW VARIABLES
, if you do not specify GLOBAL
,
SESSION
, or LOCAL
, MySQL returns the SESSION
value.
The reason for requiring the GLOBAL
keyword when setting
GLOBAL
-only variables but not when retrieving them is to prevent
problems in the future. If we remove a SESSION
variable with the same name as a GLOBAL
variable, a client with the
SUPER
privilege might accidentally change the GLOBAL
variable
rather than just the SESSION
variable for its own connection. If we
add a SESSION
variable with the same name as a GLOBAL
variable, a client that intends to change the GLOBAL
variable might
find only its own SESSION
variable changed.
Further information about system startup options and system
variables can be found in section 5.2.1 mysqld
Command-Line Options and
section 5.2.3 Server System Variables.
A list of the variables that can be set at runtime is given in
section 5.2.3.1 Dynamic System Variables.
Structured system variables are supported beginning with MySQL 4.1.1. A structured variable differs from a regular system variable in two respects:
Currently, MySQL supports one structured variable type. It specifies parameters that govern the operation of key caches. A key cache structured variable has these components:
key_buffer_size
key_cache_block_size
key_cache_division_limit
key_cache_age_threshold
The purpose of this section is to describe the syntax for referring to
structured variables. Key cache variables are used for syntax examples,
but specific details about how key caches operate are found elsewhere, in
section 7.4.6 The MyISAM
Key Cache.
To refer to a component of a structured variable instance, you can use a
compound name in instance_name.component_name
format. Examples:
hot_cache.key_buffer_size hot_cache.key_cache_block_size cold_cache.key_cache_block_size
For each structured system variable, an instance with the name of
default
is always predefined. If you refer to a component of a
structured variable without any instance name, the default
instance
is used. Thus, default.key_buffer_size
and key_buffer_size
both refer to the same system variable.
The naming rules for structured variable instances and components are as follows:
default
,
so default
is not unique across variable types.
hot-cache
is not legal, but `hot-cache`
is.
global
, session
, and local
are not legal instance
names. This avoids a conflict with notation such as @@global.var_name
for referring to non-structured system variables.
At the moment, the first two rules have no possibility of being violated because the only structured variable type is the one for key caches. These rules will assume greater significance if some other type of structured variable is created in the future.
With one exception, it is allowable to refer to structured variable components using compound names in any context where simple variable names can occur. For example, you can assign a value to a structured variable using a command-line option:
shell> mysqld --hot_cache.key_buffer_size=64K
In an option file, do this:
[mysqld] hot_cache.key_buffer_size=64K
If you start the server with such an option, it creates a key cache
named hot_cache
with a size of 64KB in addition to the default
key cache that has a default size of 8MB.
Suppose that you start the server as follows:
shell> mysqld --key_buffer_size=256K \ --extra_cache.key_buffer_size=128K \ --extra_cache.key_cache_block_size=2048
In this case, the server sets the size of the default key cache to 256KB.
(You could also have written --default.key_buffer_size=256K
.)
In addition, the server creates a second key cache named extra_cache
that has a size of 128KB, with the size of block buffers for caching
table index blocks set to 2048 bytes.
The following example starts the server with three different key caches having sizes in a 3:1:1 ratio:
shell> mysqld --key_buffer_size=6M \ --hot_cache.key_buffer_size=2M \ --cold_cache.key_buffer_size=2M
Structured variable values may be set and retrieved at runtime as well.
For example, to set a key cache named hot_cache
to a size of 10MB,
use either of these statements:
mysql> SET GLOBAL hot_cache.key_buffer_size = 10*1024*1024; mysql> SET @@global.hot_cache.key_buffer_size = 10*1024*1024;
To retrieve the cache size, do this:
mysql> SELECT @@global.hot_cache.key_buffer_size;
However, the following statement does not work. The variable is not
interpreted as a compound name, but as a simple string for a LIKE
pattern-matching operation:
mysql> SHOW GLOBAL VARIABLES LIKE 'hot_cache.key_buffer_size';
This is the exception to being able to use structured variable names anywhere a simple variable name may occur.
The MySQL server supports three comment styles:
The following example demonstrates all three comment styles:
mysql> SELECT 1+1; # This comment continues to the end of line mysql> SELECT 1+1; -- This comment continues to the end of line mysql> SELECT 1 /* this is an in-line comment */ + 1; mysql> SELECT 1+ /* this is a multiple-line comment */ 1;
The comment syntax just described applies to how the mysqld
server
parses SQL statements. The mysql
client program also performs some
parsing of statements before sending them to the server. (For example, it
does this to determine statement boundaries within a multiple-statement input
line.) However, there are some limitations on the way that mysql
parses /* ... */
comments:
mysql
interactively, you can tell that it
has gotten confused like this because the prompt changes from mysql>
to '>
, ">
, or `>
.
This problem was fixed in MySQL 4.1.1.
/*! ... */
) marks portions of SQL statements for conditional
execution. For more information and examples, see section 1.5.4 MySQL Extensions to Standard SQL.
For affected versions of MySQL,
these limitations apply both when you run mysql
interactively
and when you put commands in a file and use mysql
in batch mode to
process the file with mysql < file_name
.
A common problem stems from trying to use an identifier such as a table or
column name that is the name of a built-in MySQL data type or function,
such as TIMESTAMP
or GROUP
. You're allowed
to do this (for example, ABS
is allowed as a column name). However,
by default, no whitespace is allowed in function invocations between the
function name and the following `(' character. This requirement allows
a function call to be distinguished from a reference to a column name.
A side effect of this behavior is that omitting a space in some contexts causes an identifier to be interpreted as a function name. For example, this statement is legal:
mysql> CREATE TABLE abs (val INT);
But omitting the space after abs
causes a syntax error because the
statement then appears to invoke the ABS()
function:
mysql> CREATE TABLE abs(val INT);
If the server SQL mode includes the IGNORE_SPACE
mode value, the
server allows function invocations to have whitespace between a function
name and the following `(' character. This causes function names to be
treated as reserved words. As a result, identifiers that are the same as
function names must be quoted as described in section 9.2 Database, Table, Index, Column, and Alias Names. The server
SQL mode is controlled as described in section 5.2.2 The Server SQL Mode.
The words in the following table are explicitly reserved in MySQL. Most of
them are forbidden by standard SQL as column and/or table names (for example,
GROUP
). A few are reserved because MySQL needs them and (currently)
uses a yacc
parser. A reserved word can be used as an identifier if
you quote it.
Word | Word | Word |
ADD
| ALL
| ALTER
|
ANALYZE
| AND
| AS
|
ASC
| ASENSITIVE
| BEFORE
|
BETWEEN
| BIGINT
| BINARY
|
BLOB
| BOTH
| BY
|
CALL
| CASCADE
| CASE
|
CHANGE
| CHAR
| CHARACTER
|
CHECK
| COLLATE
| COLUMN
|
CONDITION
| CONNECTION
| CONSTRAINT
|
CONTINUE
| CONVERT
| CREATE
|
CROSS
| CURRENT_DATE
| CURRENT_TIME
|
CURRENT_TIMESTAMP
| CURRENT_USER
| CURSOR
|
DATABASE
| DATABASES
| DAY_HOUR
|
DAY_MICROSECOND
| DAY_MINUTE
| DAY_SECOND
|
DEC
| DECIMAL
| DECLARE
|
DEFAULT
| DELAYED
| DELETE
|
DESC
| DESCRIBE
| DETERMINISTIC
|
DISTINCT
| DISTINCTROW
| DIV
|
DOUBLE
| DROP
| DUAL
|
EACH
| ELSE
| ELSEIF
|
ENCLOSED
| ESCAPED
| EXISTS
|
EXIT
| EXPLAIN
| FALSE
|
FETCH
| FLOAT
| FOR
|
FORCE
| FOREIGN
| FROM
|
FULLTEXT
| GOTO
| GRANT
|
GROUP
| HAVING
| HIGH_PRIORITY
|
HOUR_MICROSECOND
| HOUR_MINUTE
| HOUR_SECOND
|
IF
| IGNORE
| IN
|
INDEX
| INFILE
| INNER
|
INOUT
| INSENSITIVE
| INSERT
|
INT
| INTEGER
| INTERVAL
|
INTO
| IS
| ITERATE
|
JOIN
| KEY
| KEYS
|
KILL
| LEADING
| LEAVE
|
LEFT
| LIKE
| LIMIT
|
LINES
| LOAD
| LOCALTIME
|
LOCALTIMESTAMP
| LOCK
| LONG
|
LONGBLOB
| LONGTEXT
| LOOP
|
LOW_PRIORITY
| MATCH
| MEDIUMBLOB
|
MEDIUMINT
| MEDIUMTEXT
| MIDDLEINT
|
MINUTE_MICROSECOND
| MINUTE_SECOND
| MOD
|
MODIFIES
| NATURAL
| NOT
|
NO_WRITE_TO_BINLOG
| NULL
| NUMERIC
|
ON
| OPTIMIZE
| OPTION
|
OPTIONALLY
| OR
| ORDER
|
OUT
| OUTER
| OUTFILE
|
PRECISION
| PRIMARY
| PROCEDURE
|
PURGE
| READ
| READS
|
REAL
| REFERENCES
| REGEXP
|
RENAME
| REPEAT
| REPLACE
|
REQUIRE
| RESTRICT
| RETURN
|
REVOKE
| RIGHT
| RLIKE
|
SCHEMA
| SCHEMAS
| SECOND_MICROSECOND
|
SELECT
| SENSITIVE
| SEPARATOR
|
SET
| SHOW
| SMALLINT
|
SONAME
| SPATIAL
| SPECIFIC
|
SQL
| SQLEXCEPTION
| SQLSTATE
|
SQLWARNING
| SQL_BIG_RESULT
| SQL_CALC_FOUND_ROWS
|
SQL_SMALL_RESULT
| SSL
| STARTING
|
STRAIGHT_JOIN
| TABLE
| TERMINATED
|
THEN
| TINYBLOB
| TINYINT
|
TINYTEXT
| TO
| TRAILING
|
TRIGGER
| TRUE
| UNDO
|
UNION
| UNIQUE
| UNLOCK
|
UNSIGNED
| UPDATE
| USAGE
|
USE
| USING
| UTC_DATE
|
UTC_TIME
| UTC_TIMESTAMP
| VALUES
|
VARBINARY
| VARCHAR
| VARCHARACTER
|
VARYING
| WHEN
| WHERE
|
WHILE
| WITH
| WRITE
|
XOR
| YEAR_MONTH
| ZEROFILL
|
MySQL allows some keywords to be used as unquoted identifiers because many people previously used them. Examples are those in the following list:
ACTION
BIT
DATE
ENUM
NO
TEXT
TIME
TIMESTAMP
Improved support for character set handling was added to MySQL in Version 4.1. The features described here are as implemented in MySQL 4.1.1. (MySQL 4.1.0 has some but not all of these features, and some of them are implemented differently.)
This chapter discusses the following topics:
Character set support currently is included in the MyISAM
,
MEMORY
(HEAP
), and (as of MySQL 4.1.2) InnoDB
storage
engines. The ISAM
storage engine does not include character set
support; there are no plans to change this, because ISAM
is
deprecated.
A character set is a set of symbols and encodings. A collation is a set of rules for comparing characters in a character set. Let's make the distinction clear with an example of an imaginary character set.
Suppose that we have an alphabet with four letters: `A', `B', `a', `b'. We give each letter a number: `A' = 0, `B' = 1, `a' = 2, `b' = 3. The letter `A' is a symbol, the number 0 is the encoding for `A', and the combination of all four letters and their encodings is a character set.
Suppose that we want to compare two string values, `A' and `B'. The simplest way to do this is to look at the encodings: 0 for `A' and 1 for `B'. Because 0 is less than 1, we say `A' is less than `B'. What we've just done is apply a collation to our character set. The collation is a set of rules (only one rule in this case): ``compare the encodings.'' We call this simplest of all possible collations a binary collation.
But what if we want to say that the lowercase and uppercase letters are equivalent? Then we would have at least two rules: (1) treat the lowercase letters `a' and `b' as equivalent to `A' and `B'; (2) then compare the encodings. We call this a case-insensitive collation. It's a little more complex than a binary collation.
In real life, most character sets have many characters: not just `A' and `B' but whole alphabets, sometimes multiple alphabets or eastern writing systems with thousands of characters, along with many special symbols and punctuation marks. Also in real life, most collations have many rules: not just case insensitivity but also accent insensitivity (an ``accent'' is a mark attached to a character as in German `Ö') and multiple-character mappings (such as the rule that `Ö' = `OE' in one of the two German collations).
MySQL 4.1 can do these things for you:
In these respects, not only is MySQL 4.1 far more flexible than MySQL 4.0, it also is far ahead of other DBMSs. However, to use the new features effectively, you will need to learn what character sets and collations are available, how to change their defaults, and what the various string operators do with them.
The MySQL server can support multiple character sets. To list the available
character sets, use the SHOW CHARACTER SET
statement:
mysql> SHOW CHARACTER SET; +----------+-----------------------------+---------------------+ | Charset | Description | Default collation | +----------+-----------------------------+---------------------+ | big5 | Big5 Traditional Chinese | big5_chinese_ci | | dec8 | DEC West European | dec8_swedish_ci | | cp850 | DOS West European | cp850_general_ci | | hp8 | HP West European | hp8_english_ci | | koi8r | KOI8-R Relcom Russian | koi8r_general_ci | | latin1 | ISO 8859-1 West European | latin1_swedish_ci | | latin2 | ISO 8859-2 Central European | latin2_general_ci | ...
The output actually includes another column that is not shown so that the example fits better on the page.
Any given character set always has at least one collation. It may have several collations.
To list the collations for a character set, use the SHOW COLLATION
statement. For example, to see the collations for the latin1
(``ISO-8859-1 West European'') character set, use this statement to find
those collation names that begin with latin1
:
mysql> SHOW COLLATION LIKE 'latin1%'; +-------------------+---------+----+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen | +-------------------+---------+----+---------+----------+---------+ | latin1_german1_ci | latin1 | 5 | | | 0 | | latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 | | latin1_danish_ci | latin1 | 15 | | | 0 | | latin1_german2_ci | latin1 | 31 | | Yes | 2 | | latin1_bin | latin1 | 47 | | Yes | 1 | | latin1_general_ci | latin1 | 48 | | | 0 | | latin1_general_cs | latin1 | 49 | | | 0 | | latin1_spanish_ci | latin1 | 94 | | | 0 | +-------------------+---------+----+---------+----------+---------+
The latin1
collations have the following meanings:
Collation | Meaning |
latin1_bin | Binary according to latin1 encoding
|
latin1_danish_ci | Danish/Norwegian |
latin1_general_ci | Multilingual |
latin1_general_cs | Multilingual, case sensitive |
latin1_german1_ci | German DIN-1 |
latin1_german2_ci | German DIN-2 |
latin1_spanish_ci | Modern Spanish |
latin1_swedish_ci | Swedish/Finnish |
Collations have these general characteristics:
latin1
is
latin1_swedish_ci
.
_ci
(case
insensitive), _cs
(case sensitive), or _bin
(binary).
There are default settings for character sets and collations at four levels: server, database, table, and connection. The following description may appear complex, but it has been found in practice that multiple-level defaulting leads to natural and obvious results.
The MySQL Server has a server character set and a server collation, which may not be null.
MySQL determines the server character set and server collation thus:
At the server level, the decision is simple. The server
character set and collation depend initially on the
options that you use when you start mysqld
. You can use
--default-character-set
for the character set, and
along with it you can add --default-collation
for the
collation. If you don't specify a character set, that is the same as saying
--default-character-set=latin1
. If you specify only a character set
(for example, latin1
) but not a collation, that is the same as saying
--default-charset=latin1
--default-collation=latin1_swedish_ci
because latin1_swedish_ci
is the default collation for latin1
.
Therefore, the following three commands all have the same effect:
shell> mysqld shell> mysqld --default-character-set=latin1 shell> mysqld --default-character-set=latin1 \ --default-collation=latin1_swedish_ci
One way to change the settings is by recompiling. If you want to
change the default server character set and collation when building
from sources, use: --with-charset
and --with-collation
as arguments for configure
. For example:
shell> ./configure --with-charset=latin1
Or:
shell> ./configure --with-charset=latin1 \ --with-collation=latin1_german1_ci
Both mysqld
and configure
verify that the character
set/collation combination is valid. If not, each program displays an error
message and terminates.
The current server character set and collation are available as the values of
the character_set_server
and collation_server
system variables.
These variables can be changed at runtime.
Every database has a database character set and a database
collation, which may not be null. The CREATE DATABASE
and ALTER
DATABASE
statements have optional clauses for specifying the
database character set and collation:
CREATE DATABASE db_name [[DEFAULT] CHARACTER SET charset_name] [[DEFAULT] COLLATE collation_name] ALTER DATABASE db_name [[DEFAULT] CHARACTER SET charset_name] [[DEFAULT] COLLATE collation_name]
Example:
CREATE DATABASE db_name DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
MySQL chooses the database character set and database collation thus:
CHARACTER SET X
and COLLATE Y
were specified, then
character set X and collation Y.
CHARACTER SET X
was specified without COLLATE
, then
character set X and its default collation.
MySQL's CREATE DATABASE ... DEFAULT CHARACTER SET ...
syntax is
analogous to the standard SQL CREATE SCHEMA ... CHARACTER SET ...
syntax. Because of this, it is possible to create databases with
different character sets and collations on the same MySQL
server.
The database character set and collation are used as default
values if the table character set and collation are not specified
in CREATE TABLE
statements. They have no other purpose.
The character set and collation for the default database are available as
the values of the character_set_database
and
collation_database
system variables. The server sets these variables
whenever the default database changes. If there is no default database, the
variables have the same value as the corresponding server-level variables,
character_set_server
and collation_server
.
Every table has a table character set and a table collation, which
may not be null. The CREATE TABLE
and ALTER TABLE
statements
have optional clauses for specifying the table character set and
collation:
CREATE TABLE tbl_name (column_list) [DEFAULT CHARACTER SET charset_name [COLLATE collation_name]] ALTER TABLE tbl_name [DEFAULT CHARACTER SET charset_name] [COLLATE collation_name]
Example:
CREATE TABLE t1 ( ... ) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;
MySQL chooses the table character set and collation thus:
CHARACTER SET X
and COLLATE Y
were specified, then
character set X and collation Y.
CHARACTER SET X
was specified without COLLATE
, then
character set X and its default collation.
The table character set and collation are used as default values if the column character set and collation are not specified in individual column definitions. The table character set and collation are MySQL extensions; there are no such things in standard SQL.
Every ``character'' column (that is, a column of type CHAR
,
VARCHAR
, or TEXT
) has a column character set and a column
collation, which may not be null. Column definition syntax has optional
clauses for specifying the column character set and collation:
col_name {CHAR | VARCHAR | TEXT} (col_length) [CHARACTER SET charset_name [COLLATE collation_name]]
Example:
CREATE TABLE Table1 ( column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci );
MySQL chooses the column character set and collation thus:
CHARACTER SET X
and COLLATE Y
were specified, then
character set X and collation Y.
CHARACTER SET X
was specified without COLLATE
, then
character set X
and its default collation.
The CHARACTER SET
and COLLATE
clauses are standard SQL.
The following examples show how MySQL determines default character set and collation values.
CREATE TABLE t1 ( c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci ) DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;
Here we have a column with a latin1
character set
and a latin1_german1_ci
collation. The definition is explicit, so
that's straightforward. Notice that there's no problem storing a
latin1
column in a latin2
table.
CREATE TABLE t1 ( c1 CHAR(10) CHARACTER SET latin1 ) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;
This time we have a column with a latin1
character
set and a default collation. Although it might seem natural,
the default collation is not taken from the table level. Instead,
because the default collation for latin1
is always
latin1_swedish_ci
,
column c1
will have a collation of latin1_swedish_ci
(not
latin1_danish_ci
).
CREATE TABLE t1 ( c1 CHAR(10) ) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;
We have a column with a default character set and
a default collation. In this circumstance, MySQL looks up to the
table level for inspiration in determining the column character set and
collation. So, the character set for column c1
is
latin1
and its collation is latin1_danish_ci
.
CREATE DATABASE d1 DEFAULT CHARACTER SET latin2 COLLATE latin2_czech_ci; USE d1; CREATE TABLE t1 ( c1 CHAR(10) );
We create a column without specifying its
character set and collation. We're also not specifying a character
set and a collation at the table level. In this circumstance, MySQL
looks up to the database level for inspiration. (The database's
settings become the table's settings, and thereafter become the
column's setting.) So, the character set for column c1
is latin2
and its collation is latin2_czech_ci
.
Several character set and collation system variables relate to a client's interaction with the server. Some of these have been mentioned in earlier sections:
character_set_server
and collation_server
variables.
character_set_database
and collation_database
variables.
Additional character set and collation variables are involved in handling traffic for the connection between a client and the server. Every client has connection-related character set and collation variables.
Consider what a ``connection'' is: It's what you make when you connect to the server. The client sends SQL statements, such as queries, over the connection to the server. The server sends responses, such as result sets, over the connection back to the client. This leads to several questions about character set and collation handling for client connections, each of which can be answered in terms of system variables:
character_set_client
variable to be the
character set in which queries are sent by the client.
character_set_connection
and collation_connection
are used by the server. It converts queries sent by the client from
character_set_client
to character_set_connection
(except for string literals that have an introducer such as _latin1
or
_utf8
).
collation_connection
is important for comparisons of literal strings.
For comparisons of strings with column values, it does not matter because
columns have a higher collation precedence.
character_set_results
variable indicates the character set in
which the server returns query results to the client. This includes result
data such as column values, and result metadata such as column names.
You can fine-tune the settings for these variables, or you can depend on the defaults (in which case, you can skip this section).
There are two statements that affect the connection character sets:
SET NAMES 'charset_name' SET CHARACTER SET charset_name
SET NAMES
indicates what is in the SQL statements that the client
sends. Thus, SET NAMES 'cp1251'
tells the server ``future incoming
messages from this client will be in character set cp1251
.'' It
also specifies the character set for results that the server sends back to
the client. (For example, it indicates what character set column values
will have if you use a SELECT
statement.)
A SET NAMES 'x'
statement
is equivalent to these three statements:
mysql> SET character_set_client = x; mysql> SET character_set_results = x; mysql> SET character_set_connection = x;
Setting character_set_connection
to x
also sets
collation_connection
to the default collation for x
.
SET CHARACTER SET
is similar but sets the connection character set
and collation to be those of the default database. A SET CHARACTER SET
x
statement is equivalent to these three statements:
mysql> SET character_set_client = x; mysql> SET character_set_results = x; mysql> SET collation_connection = @@collation_database;
When a client connects, it sends to the server the name of the character set
that it wants to use. The server sets the character_set_client
,
character_set_results
, and character_set_connection
variables
to that character set. (In effect, the server performs a SET NAMES
operation using the character set.)
With the mysql
client, it is not necessary to execute SET NAMES
every time you start up if you want to use a character set different from
the default. You can add the --default-character-set
option setting
to your mysql
statement line, or in your option file. For example,
the following option file setting changes the three character set variables
set to koi8r
each time you run mysql
:
[mysql] default-character-set=koi8r
Example: Suppose that column1
is defined as CHAR(5) CHARACTER
SET latin2
. If you do not say SET NAMES
or SET CHARACTER SET
,
then for SELECT column1 FROM t
, the server will send back all the
values for column1
using the character set that the client specified
when it connected. On the other hand, if you say SET NAMES 'latin1'
or SET CHARACTER SET latin1
, then just before sending results back,
the server will convert the latin2
values to latin1
.
Conversion may be lossy if there are characters that are not in both
character sets.
If you do not want the server to perform any conversion, set
character_set_results
to NULL
:
mysql> SET character_set_results = NULL;
Every character string literal has a character set and a collation, which may not be null.
A character string literal may have an optional character set
introducer and COLLATE
clause:
[_charset_name]'string' [COLLATE collation_name]
Examples:
SELECT 'string'; SELECT _latin1'string'; SELECT _latin1'string' COLLATE latin1_danish_ci;
For the simple statement SELECT 'string'
, the string has the character
set and collation defined by the character_set_connection
and
collation_connection
system variables.
The _charset_name
expression is formally called
an introducer. It tells the parser,
``the string that is about to follow is in character set X
.''
Because this has confused people in the past, we emphasize
that an introducer does not cause any conversion, it is strictly a
signal that does not change the string's value. An introducer is
also legal before standard hex literal and numeric hex literal notation
(x'literal'
and 0xnnnn
), and before ?
(parameter
substitution when using prepared statements within a programming language
interface).
Examples:
SELECT _latin1 x'AABBCC'; SELECT _latin1 0xAABBCC; SELECT _latin1 ?;
MySQL determines a literal's character set and collation thus:
COLLATE Y
were specified, then
character set X and collation Y
COLLATE
is not specified, then
character set X and its default collation
character_set_connection
and collation_connection
system
variables
Examples:
latin1
character set and latin1_german1_ci
collation:
SELECT _latin1'Müller' COLLATE latin1_german1_ci;
latin1
character set and its default collation (that is,
latin1_swedish_ci
):
SELECT _latin1'Müller';
SELECT 'Müller';
Character set introducers and the COLLATE
clause are implemented
according to standard SQL specifications.
COLLATE
in SQL Statements
With the COLLATE
clause, you can override whatever the default
collation is for a comparison. COLLATE
may be used in
various parts of SQL statements. Here are some examples:
ORDER BY
:
SELECT k FROM t1 ORDER BY k COLLATE latin1_german2_ci;
AS
:
SELECT k COLLATE latin1_german2_ci AS k1 FROM t1 ORDER BY k1;
GROUP BY
:
SELECT k FROM t1 GROUP BY k COLLATE latin1_german2_ci;
SELECT MAX(k COLLATE latin1_german2_ci) FROM t1;
DISTINCT
:
SELECT DISTINCT k COLLATE latin1_german2_ci FROM t1;
WHERE
:
SELECT * FROM t1 WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k;
HAVING
:
SELECT k FROM t1 GROUP BY k HAVING k = _latin1 'Müller' COLLATE latin1_german2_ci;
COLLATE
Clause Precedence
The COLLATE
clause has high precedence (higher than ||
),
so the following two expressions are equivalent:
x || y COLLATE z x || (y COLLATE z)
BINARY
Operator
The BINARY
operator is a shorthand for a COLLATE
clause.
BINARY 'x'
is equivalent to 'x' COLLATE y
, where y
is
the name of the binary collation for the character set of 'x'
. Every
character set has a binary collation. For example, the binary collation for
the latin1
character set is latin1_bin
, so if the column
a
is of character set latin1
, the following two statements have
the same effect:
SELECT * FROM t1 ORDER BY BINARY a; SELECT * FROM t1 ORDER BY a COLLATE latin1_bin;
In the great majority of queries, it is obvious what collation
MySQL uses to resolve a comparison operation. For example, in the
following cases, it should be clear that the collation will be ``the
column collation of column x
'':
SELECT x FROM T ORDER BY x; SELECT x FROM T WHERE x = x; SELECT DISTINCT x FROM T;
However, when multiple operands are involved, there can be ambiguity. For example:
SELECT x FROM T WHERE x = 'Y';
Should this query use the collation of the column x
, or of the
string literal 'Y'
?
Standard SQL resolves such questions using what used to be
called ``coercibility'' rules. The essence is: Because x
and 'Y'
both have collations, whose collation takes precedence? It's complex,
but the following rules take care of most situations:
COLLATE
clause has a coercibility of 0.
(Not coercible at all.)
Those rules resolve ambiguities thus:
Examples:
column1 = 'A' | Use collation of column1
|
column1 = 'A' COLLATE x | Use collation of 'A'
|
column1 COLLATE x = 'A' COLLATE y | Error |
The COERCIBILITY()
function can be used to determine the coercibility
of a string expression:
mysql> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci); -> 0 mysql> SELECT COERCIBILITY('A'); -> 3
See section 12.8.3 Information Functions.
Recall that each character set has one or more
collations, and each collation is associated with one and only one
character set. Therefore, the following statement
causes an error message because the latin2_bin
collation is not
legal with the latin1
character set:
mysql> SELECT _latin1 'x' COLLATE latin2_bin; ERROR 1251: COLLATION 'latin2_bin' is not valid for CHARACTER SET 'latin1'
In some cases, expressions that worked before MySQL 4.1 fail as of MySQL 4.1 if you do not take character set and collation into account. For example, before 4.1, this statement works as is:
mysql> SELECT SUBSTRING_INDEX(USER(),'@',1); +-------------------------------+ | SUBSTRING_INDEX(USER(),'@',1) | +-------------------------------+ | root | +-------------------------------+
After an upgrade to MySQL 4.1, the statement fails:
mysql> SELECT SUBSTRING_INDEX(USER(),'@',1); ERROR 1267 (HY000): Illegal mix of collations (utf8_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation 'substr_index'
The reason this occurs is that usernames are stored using UTF8
(see section 10.6 UTF8 for Metadata). As a result, the USER()
function and
the literal string '@'
have different character sets (and thus
different collations):
mysql> SELECT COLLATION(USER()), COLLATION('@'); +-------------------+-------------------+ | COLLATION(USER()) | COLLATION('@') | +-------------------+-------------------+ | utf8_general_ci | latin1_swedish_ci | +-------------------+-------------------+
One way to deal with this is to tell MySQL to interpret the literal
string as utf8
:
mysql> SELECT SUBSTRING_INDEX(USER(),_utf8'@',1); +------------------------------------+ | SUBSTRING_INDEX(USER(),_utf8'@',1) | +------------------------------------+ | root | +------------------------------------+
Another way is to change the connection character set and collation to
utf8
. You can do that with SET NAMES 'utf8'
or by setting
the character_set_connection
and collation_connection
system
variables directly.
Suppose that column X
in table T
has these latin1
column values:
Muffler Müller MX Systems MySQL
And suppose that the column values are retrieved using the following statement:
SELECT X FROM T ORDER BY X COLLATE collation_name;
The resulting order of the values for different collations is shown in this table:
latin1_swedish_ci | latin1_german1_ci | latin1_german2_ci
|
Muffler | Muffler | Müller |
MX Systems | Müller | Muffler |
Müller | MX Systems | MX Systems |
MySQL | MySQL | MySQL |
The table is an example that shows what the effect would
be if we used different collations in an ORDER BY
clause. The
character that causes the different sort orders in this example is the U with
two dots over it, which the Germans call U-umlaut, but we'll call
it U-diaeresis.
SELECT
using the
Swedish/Finnish collating rule, which says that U-diaeresis sorts
with Y.
SELECT
using the
German DIN-1 rule, which says that U-diaeresis sorts with U.
SELECT
using the German
DIN-2 rule, which says that U-diaeresis sorts with UE.
Three different collations, three different results. That's what MySQL is here to handle. By using the appropriate collation, you can choose the sort order you want.
This section describes operations that take character set information into account as of MySQL 4.1.
MySQL has many operators and functions that return a string. This section answers the question: What is the character set and collation of such a string?
For simple functions that take string input and return a string result as
output, the output's character set and collation are the same as those of
the principal input value. For example, UPPER(X)
returns a string
whose character string and collation are the same as that of X.
The same applies for
INSTR()
,
LCASE()
,
LOWER()
,
LTRIM()
,
MID()
,
REPEAT()
,
REPLACE()
,
REVERSE()
,
RIGHT()
,
RPAD()
,
RTRIM()
,
SOUNDEX()
,
SUBSTRING()
,
TRIM()
,
UCASE()
, and
UPPER()
.
(Also note: The REPLACE()
function, unlike all other functions,
ignores the collation of the string input and performs a
case-insensitive comparison every time.)
For operations that combine multiple string inputs and return a single string output, the ``aggregation rules'' of standard SQL apply:
COLLATE X
occurs, then use X
COLLATE X
and COLLATE Y
occur, then error
X
, then use X
For example, with CASE ... WHEN a THEN b WHEN b THEN c COLLATE X
END
, the resultant collation is X
. The same applies for
CASE
,
UNION
,
||
,
CONCAT()
,
ELT()
,
GREATEST()
,
IF()
, and
LEAST()
.
For operations that convert to character data, the character set and
collation of the strings that result from the operations are defined by the
character_set_connection
and collation_connection
system
variables. This applies for
CAST()
,
CHAR()
,
CONV()
,
FORMAT()
,
HEX()
, and
SPACE()
.
CONVERT()
CONVERT()
provides a way to convert data between different
character sets. The syntax is:
CONVERT(expr USING transcoding_name)
In MySQL, transcoding names are the same as the corresponding character set names.
Examples:
SELECT CONVERT(_latin1'Müller' USING utf8); INSERT INTO utf8table (utf8column) SELECT CONVERT(latin1field USING utf8) FROM latin1table;
CONVERT(... USING ...)
is implemented according to the standard SQL
specification.
CAST()
You may also use CAST()
to convert a string to a different character
set. The syntax is:
CAST(character_string AS character_data_type CHARACTER SET charset_name)
Example:
SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8);
If you use CAST()
without specifying CHARACTER SET
,
the resulting character set and collation are defined by the
character_set_connection
and collation_connection
system
variables. If you use CAST()
with CHARACTER SET X
, then
the resulting character set and collation are X
and the default
collation of X
.
You may not use a COLLATE
clause inside a CAST()
, but you may use
it outside. That is, CAST(... COLLATE ...)
is illegal, but
CAST(...) COLLATE ...
is legal.
Example:
SELECT CAST(_latin1'test' AS CHAR CHARACTER SET utf8) COLLATE utf8_bin;
SHOW
Statements
Several SHOW
statements are new or modified in MySQL 4.1 to provide
additional character set information.
SHOW CHARACTER SET
,
SHOW COLLATION
, and
SHOW CREATE DATABASE
are new.
SHOW CREATE TABLE
and
SHOW COLUMNS
are modified.
The SHOW CHARACTER SET
command shows all available character sets.
It takes an optional LIKE
clause that indicates which character set
names to match. For example:
mysql> SHOW CHARACTER SET LIKE 'latin%'; +---------+-----------------------------+-------------------+--------+ | Charset | Description | Default collation | Maxlen | +---------+-----------------------------+-------------------+--------+ | latin1 | ISO 8859-1 West European | latin1_swedish_ci | 1 | | latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 | | latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 | | latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 | +---------+-----------------------------+-------------------+--------+
See section 13.5.4.1 SHOW CHARACTER SET
Syntax.
The output from SHOW COLLATION
includes all available character
sets.
It takes an optional LIKE
clause that indicates which collation
names to match. For example:
mysql> SHOW COLLATION LIKE 'latin1%'; +-------------------+---------+----+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen | +-------------------+---------+----+---------+----------+---------+ | latin1_german1_ci | latin1 | 5 | | | 0 | | latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 | | latin1_danish_ci | latin1 | 15 | | | 0 | | latin1_german2_ci | latin1 | 31 | | Yes | 2 | | latin1_bin | latin1 | 47 | | Yes | 0 | | latin1_general_ci | latin1 | 48 | | | 0 | | latin1_general_cs | latin1 | 49 | | | 0 | | latin1_spanish_ci | latin1 | 94 | | | 0 | +-------------------+---------+----+---------+----------+---------+
See section 13.5.4.2 SHOW COLLATION
Syntax.
SHOW CREATE DATABASE
displays the CREATE DATABASE
statement
that will create a given database. The result includes all database
options. DEFAULT CHARACTER SET
and COLLATE
are supported. All
database options are stored in a text file named `db.opt' that can
be found in the database directory.
mysql> SHOW CREATE DATABASE a\G *************************** 1. row *************************** Database: a Create Database: CREATE DATABASE `a` /*!40100 DEFAULT CHARACTER SET macce */
See section 13.5.4.4 SHOW CREATE DATABASE
Syntax.
SHOW CREATE TABLE
is similar, but displays the CREATE TABLE
statement to create a given table. The column definitions indicate any
character set specifications, and the table options include character set
information.
See section 13.5.4.5 SHOW CREATE TABLE
Syntax.
The SHOW COLUMNS
statement displays the collations of a table's
columns when invoked as SHOW FULL COLUMNS
.
Columns with CHAR
, VARCHAR
, or TEXT
data types have
non-NULL
collations. Numeric and other non-character types have
NULL
collations. For example:
mysql> SHOW FULL COLUMNS FROM t; +-------+---------+------------+------+-----+---------+-------+ | Field | Type | Collation | Null | Key | Default | Extra | +-------+---------+------------+------+-----+---------+-------+ | a | char(1) | latin1_bin | YES | | NULL | | | b | int(11) | NULL | YES | | NULL | | +-------+---------+------------+------+-----+---------+-------+
The character set is not part of the display. (The character set name is implied by the collation name.)
See section 13.5.4.3 SHOW COLUMNS
Syntax.
As of MySQL version 4.1, there are two new character sets for storing Unicode data:
ucs2
, the UCS-2 Unicode character set.
utf8
, the UTF8 encoding of the Unicode character set.
In UCS-2 (binary Unicode representation), every character is represented by a two-byte Unicode code with the most significant byte first. For example: "LATIN CAPITAL LETTER A" has the code 0x0041 and it's stored as a two-byte sequence: 0x00 0x41. "CYRILLIC SMALL LETTER YERU" (Unicode 0x044B) is stored as a two-byte sequence: 0x04 0x4B. For Unicode characters and their codes, please refer to the Unicode Home Page.
A temporary restriction is that UCS-2 cannot yet be used as a client
character set. That means that SET NAMES 'ucs2'
will not work.
The UTF8 character set (transform Unicode representation) is an alternative way to store Unicode data. It is implemented according to RFC2279. The idea of the UTF8 character set is that various Unicode characters fit into byte sequences of different lengths:
Currently, MySQL UTF8 support does not include four-byte sequences.
Tip: To save space with UTF8, use VARCHAR
instead of CHAR
.
Otherwise, MySQL has to reserve 30 bytes for a CHAR(10) CHARACTER
SET utf8
column, because that's the maximum possible length.
The metadata is the data about the data. Anything that
describes the database, as opposed to being the contents of the
database, is metadata. Thus column names, database names,
usernames, version names, and most of the string results from SHOW
are
metadata.
Representation of metadata must satisfy these requirements:
SHOW
wouldn't work properly because different rows in the same column would be
in different character sets.
In order to satisfy both requirements, MySQL stores metadata in a Unicode character set, namely UTF8. This will not cause any disruption if you never use accented characters. But if you do, you should be aware that metadata is in UTF8.
This means that the USER()
, CURRENT_USER()
, and VERSION()
functions will have the UTF8 character set by default. So will any
synonyms, such the SESSION_USER()
and SYSTEM_USER()
synonyms
for USER()
.
The server sets the character_set_system
system variable to the
name of the metadata character set:
mysql> SHOW VARIABLES LIKE 'character_set_system'; +----------------------+-------+ | Variable_name | Value | +----------------------+-------+ | character_set_system | utf8 | +----------------------+-------+
Storage of metadata using Unicode does not mean that the headers
of columns and the results of DESCRIBE
functions will be in the
character_set_system
character set by default. When you say
SELECT column1 FROM t
, the name column1
itself will be
returned from the server to the client in the character set as determined
by the SET NAMES
statement. More specifically, the character
set used is determined by the value of the character_set_results
system variable. If this variable is set to NULL
, no conversion is
performed and the server returns metadata using its original character set
(the set indicated by character_set_system
).
If you want the server to pass metadata results back in a
non-UTF8 character set, then use SET NAMES
to force the
server to perform character set conversion (see section 10.3.6 Connection Character Sets and Collations),
or else set the client to do the conversion. It is
always more efficient to set the client to do the conversion, but
this option will not be available for many clients until late in
the MySQL 4.x product cycle.
If you are just using, for example, the USER()
function for
comparison or assignment within a single statement, don't worry.
MySQL will do some automatic conversion for you.
SELECT * FROM Table1 WHERE USER() = latin1_column;
This will work because the contents of latin1_column
are
automatically converted to UTF8 before the comparison.
INSERT INTO Table1 (latin1_column) SELECT USER();
This will work because the contents of USER()
are automatically
converted to latin1
before the assignment.
Automatic conversion is not fully implemented yet, but should work
correctly in a later version.
Although automatic conversion is not in the SQL standard, the SQL standard document does say that every character set is (in terms of supported characters) a ``subset'' of Unicode. Since it is a well-known principle that ``what applies to a superset can apply to a subset,'' we believe that a collation for Unicode can apply for comparisons with non-Unicode strings.
For MaxDB compatibility these two statements are the same:
CREATE TABLE t1 (f1 CHAR(n) UNICODE); CREATE TABLE t1 (f1 CHAR(n) CHARACTER SET ucs2);
In MySQL 4.1, character set configuration is stored in XML files, one file per character set. In previous versions, this information was stored in `.conf' files.
Before MySQL 4.1, NCHAR
and CHAR
were synonymous. ANSI
defines NCHAR
or NATIONAL CHAR
as a way to indicate that a
CHAR
column should use some predefined character set. MySQL 4.1 and up uses utf8
as
that predefined character set. For example, these column type declarations
are equivalent:
CHAR(10) CHARACTER SET utf8 NATIONAL CHARACTER(10) NCHAR(10)
As are these:
VARCHAR(10) CHARACTER SET utf8 NATIONAL VARCHAR(10) NCHAR VARCHAR(10) NATIONAL CHARACTER VARYING(10) NATIONAL CHAR VARYING(10)
You can use N'literal'
to create a string in
the national character set.
These two statements are equivalent:
SELECT N'some text'; SELECT _utf8'some text';
What about upgrading from older versions of MySQL? MySQL 4.1 is almost upward compatible with MySQL 4.0 and earlier for the simple reason that almost all the features are new, so there's nothing in earlier versions to conflict with. However, there are some differences and a few things to be aware of.
Most important: The ``MySQL 4.0 character set'' has the properties of both ``MySQL 4.1 character sets'' and ``MySQL 4.1 collations.'' You will have to unlearn this. Henceforth, we will not bundle character set/collation properties in the same conglomerate object.
There is a special treatment of national character sets in MySQL
4.1. NCHAR
is not the same as CHAR
, and N'...'
literals
are not the same as '...'
literals.
Finally, there is a different file format for storing information about character sets and collations. Make sure that you have reinstalled the `/share/mysql/charsets/' directory containing the new configuration files.
If you want to start mysqld
from a 4.1.x distribution with data
created by MySQL 4.0, you should start the server with the same
character set and collation. In this case, you won't need to reindex
your data.
There are two ways to do so:
shell> ./configure --with-charset=... --with-collation=... shell> ./mysqld --default-character-set=... --default-collation=...
If you used mysqld
with, for example, the MySQL 4.0 danish
character set, you should use the latin1
character set and
the latin1_danish_ci
collation:
shell> ./configure --with-charset=latin1 \ --with-collation=latin1_danish_ci shell> ./mysqld --default-character-set=latin1 \ --default-collation=latin1_danish_ci
Use the table shown in section 10.10.1 4.0 Character Sets and Corresponding 4.1 Character Set/Collation Pairs to find old 4.0 character set names and their 4.1 character set/collation pair equivalents.
If you have non-latin1
data stored in a 4.0 latin1
table
and want to convert the table column definitions to reflect the actual
character set of the data, use the instructions in section 10.10.2 Converting 4.0 Character Columns to 4.1 Format.
ID | 4.0 Character Set | 4.1 Character Set | 4.1 Collation |
1 | big5 | big5 | big5_chinese_ci
|
2 | czech | latin2 | latin2_czech_ci
|
3 | dec8 | dec8 | dec8_swedish_ci
|
4 | dos | cp850 | cp850_general_ci
|
5 | german1 | latin1 | latin1_german1_ci
|
6 | hp8 | hp8 | hp8_english_ci
|
7 | koi8_ru | koi8r | koi8r_general_ci
|
8 | latin1 | latin1 | latin1_swedish_ci
|
9 | latin2 | latin2 | latin2_general_ci
|
10 | swe7 | swe7 | swe7_swedish_ci
|
11 | usa7 | ascii | ascii_general_ci
|
12 | ujis | ujis | ujis_japanese_ci
|
13 | sjis | sjis | sjis_japanese_ci
|
14 | cp1251 | cp1251 | cp1251_bulgarian_ci
|
15 | danish | latin1 | latin1_danish_ci
|
16 | hebrew | hebrew | hebrew_general_ci
|
17 | win1251 | (removed) | (removed)
|
18 | tis620 | tis620 | tis620_thai_ci
|
19 | euc_kr | euckr | euckr_korean_ci
|
20 | estonia | latin7 | latin7_estonian_ci
|
21 | hungarian | latin2 | latin2_hungarian_ci
|
22 | koi8_ukr | koi8u | koi8u_ukrainian_ci
|
23 | win1251ukr | cp1251 | cp1251_ukrainian_ci
|
24 | gb2312 | gb2312 | gb2312_chinese_ci
|
25 | greek | greek | greek_general_ci
|
26 | win1250 | cp1250 | cp1250_general_ci
|
27 | croat | latin2 | latin2_croatian_ci
|
28 | gbk | gbk | gbk_chinese_ci
|
29 | cp1257 | cp1257 | cp1257_lithuanian_ci
|
30 | latin5 | latin5 | latin5_turkish_ci
|
31 | latin1_de | latin1 | latin1_german2_ci
|
Normally, the server runs using the latin1
character set by default.
If you have been storing column data that actually is in some other
character set that the 4.1 server supports directly, you can convert the
column. However, you should avoid trying to convert directly from
latin1
to the "real" character set. This may result in data loss.
Instead, convert the column to a binary column type, and then from the
binary type to a non-binary type with the desired character set. Conversion
to and from binary involves no attempt at character value conversion and
preserves your data intact. For example, suppose that you have a 4.0 table with
three columns that are used to store values represented in latin1
,
latin2
, and utf8
:
CREATE TABLE t ( latin1_col CHAR(50), latin2_col CHAR(100), utf8_col CHAR(150) );
After upgrading to MySQL 4.1, you want to convert this table to leave
latin1_col
alone but change the latin2_col
and utf8_col
columns to have character sets of latin2
and utf8
. First,
back up your table, then convert the columns as follows:
ALTER TABLE t MODIFY latin2_col BINARY(100); ALTER TABLE t MODIFY utf8_col BINARY(150); ALTER TABLE t MODIFY latin2_col CHAR(100) CHARACTER SET latin2; ALTER TABLE t MODIFY utf8_col CHAR(150) CHARACTER SET utf8;
The first two statements ``remove'' the character set information from the
latin2_col
and utf8_col
columns. The second two statements
assign the proper character sets to the two columns.
If you like, you can combine the to-binary conversions and from-binary conversions into single statements:
ALTER TABLE t MODIFY latin2_col BINARY(100), MODIFY utf8_col BINARY(150); ALTER TABLE t MODIFY latin2_col CHAR(100) CHARACTER SET latin2, MODIFY utf8_col CHAR(150) CHARACTER SET utf8;
If you specified attributes when creating a column initially, you should
also specify them when altering the table with ALTER TABLE
. For
example, if you specified NOT NULL
and an explicit DEFAULT
value, you should also provide them in the ALTER TABLE
statement.
Otherwise, the resulting column definition will not include those attributes.
Here is an annotated list of character sets and collations that MySQL supports. Because options and installation settings differ, some sites might not have all items listed, and some sites might have items not listed.
MySQL supports 70+ collations for 30+ character sets. The character sets and
their default collations are displayed by the
SHOW CHARACTER SET
statement.
(The output actually includes another column that is not shown so that the
example fits better on the page.)
mysql> SHOW CHARACTER SET; +----------+-----------------------------+---------------------+ | Charset | Description | Default collation | +----------+-----------------------------+---------------------+ | big5 | Big5 Traditional Chinese | big5_chinese_ci | | dec8 | DEC West European | dec8_swedish_ci | | cp850 | DOS West European | cp850_general_ci | | hp8 | HP West European | hp8_english_ci | | koi8r | KOI8-R Relcom Russian | koi8r_general_ci | | latin1 | ISO 8859-1 West European | latin1_swedish_ci | | latin2 | ISO 8859-2 Central European | latin2_general_ci | | swe7 | 7bit Swedish | swe7_swedish_ci | | ascii | US ASCII | ascii_general_ci | | ujis | EUC-JP Japanese | ujis_japanese_ci | | sjis | Shift-JIS Japanese | sjis_japanese_ci | | hebrew | ISO 8859-8 Hebrew | hebrew_general_ci | | tis620 | TIS620 Thai | tis620_thai_ci | | euckr | EUC-KR Korean | euckr_korean_ci | | koi8u | KOI8-U Ukrainian | koi8u_general_ci | | gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | | greek | ISO 8859-7 Greek | greek_general_ci | | cp1250 | Windows Central European | cp1250_general_ci | | gbk | GBK Simplified Chinese | gbk_chinese_ci | | latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | | armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | | utf8 | UTF-8 Unicode | utf8_general_ci | | ucs2 | UCS-2 Unicode | ucs2_general_ci | | cp866 | DOS Russian | cp866_general_ci | | keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci | | macce | Mac Central European | macce_general_ci | | macroman | Mac West European | macroman_general_ci | | cp852 | DOS Central European | cp852_general_ci | | latin7 | ISO 8859-13 Baltic | latin7_general_ci | | cp1251 | Windows Cyrillic | cp1251_general_ci | | cp1256 | Windows Arabic | cp1256_general_ci | | cp1257 | Windows Baltic | cp1257_general_ci | | binary | Binary pseudo charset | binary | | geostd8 | GEOSTD8 Georgian | geostd8_general_ci | | cp932 | SJIS for Windows Japanese | cp932_japanese_ci | | eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | +----------+-----------------------------+---------------------+
MySQL has two Unicode character sets. You can store texts in about 650 languages using these character sets. We have added several collations for these two new sets, with more to come.
ucs2
(UCS-2 Unicode) collations:
ucs2_bin
ucs2_czech_ci
ucs2_danish_ci
ucs2_estonian_ci
ucs2_general_ci
(default)
ucs2_icelandic_ci
ucs2_latvian_ci
ucs2_lithuanian_ci
ucs2_persian_ci
ucs2_polish_ci
ucs2_roman_ci
ucs2_romanian_ci
ucs2_slovak_ci
ucs2_slovenian_ci
ucs2_spanish2_ci
ucs2_spanish_ci
ucs2_swedish_ci
ucs2_turkish_ci
ucs2_unicode_ci
utf8
(UTF-8 Unicode) collations:
utf8_bin
utf8_czech_ci
utf8_danish_ci
utf8_estonian_ci
utf8_general_ci
(default)
utf8_icelandic_ci
utf8_latvian_ci
utf8_lithuanian_ci
utf8_persian_ci
utf8_polish_ci
utf8_roman_ci
utf8_romanian_ci
utf8_slovak_ci
utf8_slovenian_ci
utf8_spanish2_ci
utf8_spanish_ci
utf8_swedish_ci
utf8_turkish_ci
utf8_unicode_ci
West European Character Sets cover most West European languages, such as French, Spanish, Catalan, Basque, Portuguese, Italian, Albanian, Dutch, German, Danish, Swedish, Norwegian, Finnish, Faroese, Icelandic, Irish, Scottish, and English.
ascii
(US ASCII) collations:
ascii_bin
ascii_general_ci
(default)
cp850
(DOS West European) collations:
cp850_bin
cp850_general_ci
(default)
dec8
(DEC West European) collations:
dec8_bin
dec8_swedish_ci
(default)
hp8
(HP West European) collations:
hp8_bin
hp8_english_ci
(default)
latin1
(ISO 8859-1 West European) collations:
latin1_bin
latin1_danish_ci
latin1_general_ci
latin1_general_cs
latin1_german1_ci
latin1_german2_ci
latin1_spanish_ci
latin1_swedish_ci
(default)
latin1
is the default character set.
The latin1_swedish_ci
collation is the default that probably is
used by the majority of MySQL customers. It is constantly stated
that this is based on the Swedish/Finnish collation rules, but you
will find Swedes and Finns who disagree with that statement.
The latin1_german1_ci
and latin1_german2_ci
collations are based on the DIN-1 and DIN-2 standards,
where DIN stands for Deutsches Institut für Normung (that is,
the German answer to ANSI).
DIN-1 is called the dictionary collation and DIN-2 is called the
phone-book collation.
latin1_german1_ci
(dictionary) rules:
Ä = A Ö = O Ü = U ß = s
latin1_german2_ci
(phone-book) rules:
Ä = AE Ö = OE Ü = UE ß = ss
latin1_spanish_ci
collation, `Ñ' (N-tilde) is a
separate letter between `N' and `O'.
macroman
(Mac West European) collations:
macroman_bin
macroman_general_ci
(default)
swe7
(7bit Swedish) collations:
swe7_bin
swe7_swedish_ci
(default)
We have some support for character sets used in the Czech Republic, Slovakia, Hungary, Romania, Slovenia, Croatia, and Poland.
cp1250
(Windows Central European) collations:
cp1250_bin
cp1250_czech_cs
cp1250_general_ci
(default)
cp852
(DOS Central European) collations:
cp852_bin
cp852_general_ci
(default)
keybcs2
(DOS Kamenicky Czech-Slovak) collations:
keybcs2_bin
keybcs2_general_ci
(default)
latin2
(ISO 8859-2 Central European) collations:
latin2_bin
latin2_croatian_ci
latin2_czech_cs
latin2_general_ci
(default)
latin2_hungarian_ci
macce
(Mac Central European) collations:
macce_bin
macce_general_ci
(default)
armscii8
(ARMSCII-8 Armenian) collations:
armscii8_bin
armscii8_general_ci
(default)
cp1256
(Windows Arabic) collations:
cp1256_bin
cp1256_general_ci
(default)
geostd8
(GEOSTD8 Georgian) collations:
geostd8_bin
geostd8_general_ci
(default)
greek
(ISO 8859-7 Greek) collations:
greek_bin
greek_general_ci
(default)
hebrew
(ISO 8859-8 Hebrew) collations:
hebrew_bin
hebrew_general_ci
(default)
latin5
(ISO 8859-9 Turkish) collations:
latin5_bin
latin5_turkish_ci
(default)
The Baltic character sets cover Estonian, Latvian, and Lithuanian languages. There are two Baltic character sets currently supported:
cp1257
(Windows Baltic) collations:
cp1257_bin
cp1257_general_ci
(default)
cp1257_lithuanian_ci
latin7
(ISO 8859-13 Baltic) collations:
latin7_bin
latin7_estonian_cs
latin7_general_ci
(default)
latin7_general_cs
Here are the Cyrillic character sets and collations for use with Belarusian, Bulgarian, Russian, and Ukrainian languages.
cp1251
(Windows Cyrillic) collations:
cp1251_bin
cp1251_bulgarian_ci
cp1251_general_ci
(default)
cp1251_general_cs
cp1251_ukrainian_ci
cp866
(DOS Russian) collations:
cp866_bin
cp866_general_ci
(default)
koi8r
(KOI8-R Relcom Russian) collations:
koi8r_bin
koi8r_general_ci
(default)
koi8u
(KOI8-U Ukrainian) collations:
koi8u_bin
koi8u_general_ci
(default)
The Asian character sets that we support include Chinese, Japanese, Korean, and Thai. These can be complicated. For example, the Chinese sets must allow for thousands of different characters.
big5
(Big5 Traditional Chinese) collations:
big5_bin
big5_chinese_ci
(default)
cp932
(SJIS for Windows Japanese) collations:
cp932_bin
cp932_japanese_ci
(default)
eucjpms
(UJIS for Windows Japanese) collations:
eucjpms_bin
eucjpms_japanese_ci
(default)
euckr
(EUC-KR Korean) collations:
euckr_bin
euckr_korean_ci
(default)
gb2312
(GB2312 Simplified Chinese) collations:
gb2312_bin
gb2312_chinese_ci
(default)
gbk
(GBK Simplified Chinese) collations:
gbk_bin
gbk_chinese_ci
(default)
sjis
(Shift-JIS Japanese) collations:
sjis_bin
sjis_japanese_ci
(default)
tis620
(TIS620 Thai) collations:
tis620_bin
tis620_thai_ci
(default)
ujis
(EUC-JP Japanese) collations:
ujis_bin
ujis_japanese_ci
(default)
MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values.
MySQL versions 4.1 and up support extensions for handing spatial data. Information about spatial types is provided in section 18 Spatial Extensions in MySQL.
Several of the column type descriptions use these conventions:
M
D
A summary of the numeric column types follows. For additional information, see section 11.2 Numeric Types. Column storage requirements are given in section 11.5 Column Type Storage Requirements.
M indicates the maximum display width. The maximum legal display width is 255. Display width is unrelated to the storage size or range of values a type can contain, as described in section 11.2 Numeric Types.
If you specify ZEROFILL
for a numeric column, MySQL
automatically adds the UNSIGNED
attribute to the column.
Warning: You should be aware that when you use subtraction
between integer values where one is of type UNSIGNED
, the result
will be unsigned! See section 12.7 Cast Functions and Operators.
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
-128
to 127
. The
unsigned range is 0
to 255
.
BIT
BOOL
BOOLEAN
TINYINT(1)
.
The BOOLEAN
synonym was added in MySQL 4.1.0.
A value of zero is considered false. Non-zero values are considered true.
In the future,
full boolean type handling will be introduced in accordance with standard SQL.
SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
-32768
to 32767
. The
unsigned range is 0
to 65535
.
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
-8388608
to
8388607
. The unsigned range is 0
to 16777215
.
INT[(M)] [UNSIGNED] [ZEROFILL]
-2147483648
to
2147483647
. The unsigned range is 0
to 4294967295
.
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
INT
.
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
-9223372036854775808
to
9223372036854775807
. The unsigned range is 0
to
18446744073709551615
.
Some things you should be aware of with respect to BIGINT
columns:
BIGINT
or DOUBLE
values, so you shouldn't use unsigned big integers larger than
9223372036854775807
(63 bits) except with bit functions! If you
do that, some of the last digits in the result may be wrong because of
rounding errors when converting a BIGINT
value to a DOUBLE
.
MySQL 4.0 can handle BIGINT
in the following cases:
BIGINT
column.
MIN(col_name)
or MAX(col_name)
, where
col_name refers to a BIGINT
column.
+
, -
, *
, and so on) where
both operands are integers.
BIGINT
column by
storing it using a string. In this case, MySQL performs a string-to-number
conversion that involves no intermediate double-precision representation.
-
, +
, and *
operators will use BIGINT
arithmetic when both operands are integer values! This means that if
you multiply two big integers (or results from functions that return
integers), you may get unexpected results when the result is larger than
9223372036854775807
.
FLOAT(p) [UNSIGNED] [ZEROFILL]
FLOAT
and DOUBLE
types described immediately following. FLOAT(p)
has the same range as the corresponding FLOAT
and DOUBLE
types, but the display width and number of decimals are undefined.
As of MySQL 3.23, this is a true floating-point value. In
earlier MySQL versions, FLOAT(p)
always has two decimals.
This syntax is provided for ODBC compatibility.
Using FLOAT
might give you some unexpected problems because
all calculations in MySQL are done with double precision.
See section A.5.7 Solving Problems with No Matching Rows.
FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
-3.402823466E+38
to -1.175494351E-38
, 0
,
and 1.175494351E-38
to 3.402823466E+38
. If
UNSIGNED
is specified, negative values are disallowed. M
is the display width and D is the number of decimals. FLOAT
without arguments or FLOAT(p)
(where p is in the range from
0 to 24) stands for a single-precision floating-point number.
DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
-1.7976931348623157E+308
to
-2.2250738585072014E-308
, 0
, and
2.2250738585072014E-308
to 1.7976931348623157E+308
. If
UNSIGNED
is specified, negative values are disallowed.
M is the display width and D is the number of decimals.
DOUBLE
without arguments or FLOAT(p)
(where
p is in the
range from 25 to 53) stands for a double-precision floating-point number.
DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL]
REAL[(M,D)] [UNSIGNED] [ZEROFILL]
DOUBLE
.
Exception: If the server SQL mode includes the REAL_AS_FLOAT
option,
REAL
is a synonym for FLOAT
rather than DOUBLE
.
DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
CHAR
column;
``unpacked'' means the number is stored as a string, using one character for
each digit of the value. M is the total number of digits and
D is the number of decimals. The decimal point and (for negative
numbers) the `-' sign are not counted in M, although space for
them is reserved. If D is 0, values have no decimal point or
fractional part. The maximum range of DECIMAL
values is the same as
for DOUBLE
, but the actual range for a given DECIMAL
column
may be constrained by the choice of M and D. If
UNSIGNED
is specified, negative values are disallowed.
If D is omitted, the default is 0. If M is omitted, the
default is 10.
Prior to MySQL 3.23, the M argument must be large enough to
include the space needed for the sign and the decimal point.
DEC[(M[,D])] [UNSIGNED] [ZEROFILL]
NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]
FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]
DECIMAL
.
The FIXED
synonym was added in MySQL 4.1.0 for compatibility
with other servers.
A summary of the temporal column types follows. For additional information, see section 11.3 Date and Time Types. Column storage requirements are given in section 11.5 Column Type Storage Requirements.
DATE
'1000-01-01'
to '9999-12-31'
.
MySQL displays DATE
values in 'YYYY-MM-DD'
format, but
allows you to assign values to DATE
columns using either strings or
numbers.
DATETIME
'1000-01-01
00:00:00'
to '9999-12-31 23:59:59'
. MySQL displays
DATETIME
values in 'YYYY-MM-DD HH:MM:SS'
format, but allows you
to assign values to DATETIME
columns using either strings or numbers.
TIMESTAMP[(M)]
'1970-01-01 00:00:00'
to partway through the
year 2037
.
A TIMESTAMP
column is useful for recording the date and time of an
INSERT
or UPDATE
operation. The first TIMESTAMP
column
in a table is automatically set to the date and time of the most recent
operation if you don't assign it a value yourself. You can also set any
TIMESTAMP
column to the current date and time by assigning it a
NULL
value.
From MySQL 4.1 on, TIMESTAMP
is returned as a string with the format
'YYYY-MM-DD HH:MM:SS'
. If you want to obtain the value as a number,
you should add +0
to the timestamp column. Different timestamp
display widths are not supported.
In MySQL 4.0 and earlier, TIMESTAMP
values are displayed in
YYYYMMDDHHMMSS
, YYMMDDHHMMSS
, YYYYMMDD
, or YYMMDD
format, depending on whether M is 14 (or missing), 12,
8, or 6, but allows you to assign values to TIMESTAMP
columns using either strings or numbers.
The M argument affects only how a TIMESTAMP
column is displayed,
not storage. Its values always are stored using four bytes each.
From MySQL 4.0.12, the --new
option can be used
to make the server behave as in MySQL 4.1.
Note that TIMESTAMP(M)
columns where M is 8 or 14 are reported to
be numbers, whereas other TIMESTAMP(M)
columns are reported to be
strings. This is just to ensure that you can reliably dump and restore
the table with these types.
TIME
'-838:59:59'
to '838:59:59'
.
MySQL displays TIME
values in 'HH:MM:SS'
format, but
allows you to assign values to TIME
columns using either strings or
numbers.
YEAR[(2|4)]
1901
to 2155
, and 0000
.
In two-digit format, the allowable values are
70
to 69
, representing years from
1970 to 2069. MySQL displays YEAR
values in
YYYY
format, but allows you to assign values to YEAR
columns
using either strings or numbers. The YEAR
type is unavailable prior
to MySQL 3.22.
A summary of the string column types follows. For additional information, see section 11.4 String Types. Column storage requirements are given in section 11.5 Column Type Storage Requirements.
In some cases, MySQL may change a string column to a type different from
that given in a CREATE TABLE
or ALTER TABLE
statement.
See section 13.2.6.1 Silent Column Specification Changes.
A change that affects many string column types is that, as of MySQL 4.1,
character column definitions can include a CHARACTER SET
attribute to
specify the character set and, optionally, a collation. This
applies to CHAR
, VARCHAR
, the TEXT
types, ENUM
,
and SET
. For example:
CREATE TABLE t ( c1 CHAR(20) CHARACTER SET utf8, c2 CHAR(20) CHARACTER SET latin1 COLLATE latin1_bin );
This table definition creates a column named c1
that has a character
set of utf8
with the default collation for that character set, and a
column named c2
that has a character set of latin1
and the
binary collation for the character set. The binary collation is not case
sensitive.
For CHAR
, VARCHAR
, and the TEXT
types, the BINARY
attribute causes the column to be assigned the binary collation of the column
character set as of MySQL 4.1. Before 4.1, BINARY
is disallowed for
the TEXT
types, and causes CHAR
and VARCHAR
to be treated
as binary strings.
Character column sorting and comparison are based on the character set
assigned to the column. Before MySQL 4.1, sorting and comparison are based
on the collation of the server character set. For CHAR
and
VARCHAR
columns, you can declare the column with the BINARY
attribute to cause sorting and comparison to use the underlying character
code values rather then a lexical ordering.
For more details, see section 10 Character Set Support.
Also as of 4.1, MySQL interprets length specifications in character column definitions in characters. (Earlier versions interpret them in bytes.)
[NATIONAL] CHAR(M) [BINARY | ASCII | UNICODE]
CHAR
values are
retrieved.
From MySQL 4.1.0, a CHAR
column with a length specification greater
than 255 is converted to the smallest TEXT
type that can hold values
of the given length. For example, CHAR(500)
is converted to
TEXT
, and CHAR(200000)
is converted to MEDIUMTEXT
.
This is a compatibility feature. However, this conversion causes the
column to become a variable-length column, and also affects trailing-space
removal.
CHAR
is shorthand for CHARACTER
.
NATIONAL CHAR
(or its equivalent short form, NCHAR
) is the
standard SQL way to define that a CHAR
column should use the default
character set. This is the default in MySQL.
As of MySQL 4.1.2, the BINARY
attribute is shorthand for specifying
the binary collation of the column character set. Before 4.1.2, BINARY
attribute causes the column to be treated as a binary string. In either
case, sorting and comparisons become case sensitive.
From MySQL 4.1.0 on, the ASCII
attribute can be specified. It
assigns the latin1
character set to a CHAR
column.
From MySQL 4.1.1 on, the UNICODE
attribute can be specified. It
assigns the ucs2
character set to a CHAR
column.
MySQL allows you to create a column of type CHAR(0)
. This is mainly
useful when you have to be compliant with some old applications that depend
on the existence of a column but that do not actually use the value. This
is also quite nice when you need a column that can take only two values: A
CHAR(0)
column that is not defined as NOT NULL
occupies only
one bit and can take only the values NULL
and ''
(the empty
string).
CHAR
CHAR(1)
.
[NATIONAL] VARCHAR(M) [BINARY]
65535
bytes. (The exact number of
characters is depending on the character set).
Note: Before 5.0.3, trailing spaces where removed when
VARCHAR
values was stored, which differs from the standard SQL
specification.
From MySQL 4.1.0 - 5.0.2 on, a VARCHAR
column with a length
specification greater than 255 is converted to the smallest TEXT
type that can hold values of the given length. For example,
VARCHAR(500)
is converted to TEXT
, and
VARCHAR(200000)
is converted to MEDIUMTEXT
. This is a
compatibility feature. However, this conversion affects trailing-space
removal.
VARCHAR
is shorthand for CHARACTER VARYING
.
As of MySQL 4.1.2, the BINARY
attribute is shorthand for specifying
the binary collation of the column character set. Before 4.1.2, BINARY
attribute causes the column to be treated as a binary string. In either
case, sorting and comparisons become case sensitive.
Starting from MySQL 5.0.3, VARCHAR
is stored with a 1 byte or 2
byte length prefix + data. The length prefix is 1 byte if the storage
size for the VARCHAR
column is less than 256.
BINARY(M)
BINARY
type is similar to the CHAR
type, but stores
binary strings rather than non-binary strings.
This type was added in MySQL 4.1.2.
VARBINARY(M)
VARBINARY
type is similar to the VARCHAR
type, but stores
binary strings rather than non-binary strings.
This type was added in MySQL 4.1.2.
TINYBLOB
TINYTEXT
BLOB
or TEXT
column with a maximum length of 255 (2^8
- 1)
characters.
BLOB
TEXT
BLOB
or TEXT
column with a maximum length of 65,535 (2^16
-1)
characters.
MEDIUMBLOB
MEDIUMTEXT
BLOB
or TEXT
column with a maximum length of 16,777,215
(2^24 - 1) characters.
LONGBLOB
LONGTEXT
BLOB
or TEXT
column with a maximum length of 4,294,967,295 or
4GB (2^32 - 1) characters. Up to MySQL
3.23, the client/server protocol and MyISAM
tables had a limit
of 16MB per communication packet / table row. From MySQL 4.0, the maximum
allowed length of LONGBLOB
or LONGTEXT
columns depends on the
configured maximum packet size in the client/server protocol and available
memory.
ENUM('value1','value2',...)
'value1'
, 'value2'
, ...
,
NULL
or the special ''
error value. An ENUM
column can
have a maximum of 65,535 distinct values.
ENUM
values are represented internally as integers.
SET('value1','value2',...)
'value1'
, 'value2'
,
...
A SET
column can have a maximum of 64 members.
SET
values are represented internally as integers.
MySQL supports all of the standard SQL numeric data types. These
types include the exact numeric data types (INTEGER
,
SMALLINT
, DECIMAL
, and NUMERIC
), as well as the
approximate numeric data types (FLOAT
, REAL
, and
DOUBLE PRECISION
). The keyword INT
is a synonym for
INTEGER
, and the keyword DEC
is a synonym for
DECIMAL
.
As an extension to the SQL standard, MySQL also supports the integer
types TINYINT
, MEDIUMINT
, and BIGINT
as listed in
the following table.
Type | Bytes | Minimum Value | Maximum Value |
(Signed/Unsigned) | (Signed/Unsigned) | ||
TINYINT | 1 | -128 | 127
|
0 | 255
| ||
SMALLINT | 2 | -32768 | 32767
|
0 | 65535
| ||
MEDIUMINT | 3 | -8388608 | 8388607
|
0 | 16777215
| ||
INT | 4 | -2147483648 | 2147483647
|
0 | 4294967295
| ||
BIGINT | 8 | -9223372036854775808 | 9223372036854775807
|
0 | 18446744073709551615
|
Another extension is supported by MySQL for optionally
specifying the display width of an integer value in parentheses following
the base keyword for the type (for example, INT(4)
). This optional
display width specification is used to left-pad the display of values
having a width less than the width specified for the column.
The display width does not constrain the range of values that can be stored in the column, nor the number of digits that will be displayed for values having a width exceeding that specified for the column.
When used in conjunction with the optional extension attribute
ZEROFILL
, the default padding of spaces is replaced with zeros.
For example, for a column declared as INT(5) ZEROFILL
, a value
of 4
is retrieved as 00004
. Note that if you store larger
values than the display width in an integer column, you may experience
problems when MySQL generates temporary tables for some
complicated joins, because in these cases MySQL trusts that the
data did fit into the original column width.
All integer types can have an optional (non-standard) attribute
UNSIGNED
. Unsigned values can be used when you want to allow only
non-negative numbers in a column and you need a bigger upper numeric
range for the column.
As of MySQL 4.0.2, floating-point and fixed-point types also can be
UNSIGNED
. As with integer types, this attribute prevents negative
values from being stored in the column. However, unlike the integer types,
the upper range of column values remains the same.
If you specify ZEROFILL
for a numeric column, MySQL
automatically adds the UNSIGNED
attribute to the column.
The DECIMAL
and NUMERIC
types are implemented as the same
type by MySQL. They are
used to store values for which it is important to preserve exact precision,
for example with monetary data. When declaring a column of one of these
types, the precision and scale can be (and usually is) specified; for
example:
salary DECIMAL(5,2)
In this example, 5
is the precision and 2
is the scale. The
precision represents the number of significant decimal digits that will be
stored for values, and the scale represents the number of digits that will
be stored following the decimal point.
MySQL stores DECIMAL
and NUMERIC
values as strings, rather
than as binary floating-point numbers, in order to preserve the decimal
precision of those values. One character is used for each digit of the
value, the decimal point (if the scale is greater than 0), and the `-' sign
(for negative numbers). If the scale is 0, DECIMAL
and
NUMERIC
values contain no decimal point or fractional part.
Standard SQL requires that the salary
column
be able to store any value with five digits and two decimals. In this case,
therefore, the range of values that can be stored in the salary
column is from -999.99
to 999.99
. MySQL varies from this in
two ways:
9999.99
. For positive numbers, MySQL uses the
byte reserved for the sign to extend the upper end of the range.
DECIMAL
columns in MySQL before 3.23 are stored differently and
cannot represent all the values required by standard SQL. This is because
for a type of DECIMAL(M,D)
, the value of M includes the bytes
for the sign and the decimal point. The range of the salary
column
before MySQL 3.23 would be -9.99
to 99.99
.
In standard SQL, the syntax DECIMAL(M)
is equivalent to
DECIMAL(M,0)
. Similarly, the syntax DECIMAL
is equivalent
to DECIMAL(M,0)
, where the implementation is allowed to decide the
value of M. As of MySQL 3.23.6, both of these variant forms of the
DECIMAL
and NUMERIC
data types are supported. The default value
of M is 10. Before 3.23.6,
M and D both must be specified explicitly.
The maximum range of DECIMAL
and NUMERIC
values is the
same as for DOUBLE
, but the actual range for a given
DECIMAL
or NUMERIC
column can be constrained by the
precision or scale for a given column. When such a column
is assigned a value with more digits following the decimal point than
are allowed by the specified scale, the value is converted to that
scale. (The precise behavior is operating system-specific, but
generally the effect is truncation to the allowable number of digits.)
When a DECIMAL
or NUMERIC
column is
assigned a value that exceeds the range implied by the
specified (or default) precision and scale,
MySQL stores the value representing the corresponding end
point of that range.
For floating-point column types, MySQL uses four bytes for single-precision values and eight bytes for double-precision values.
The FLOAT
type is used to represent approximate numeric data types.
The SQL standard allows an optional specification of the precision
(but not the range of the exponent) in bits following the keyword
FLOAT
in parentheses. The MySQL implementation also supports this
optional precision specification, but the precision value is used only to
determine storage size. A precision from 0 to 23 results in four-byte
single-precision FLOAT
column. A precision from 24 to 53 results
in eight-byte double-precision DOUBLE
column.
When the keyword
FLOAT
is used for a column type without a precision specification,
MySQL uses four bytes to store the values. MySQL also supports variant
syntax with two numbers given in parentheses following the FLOAT
keyword. The first number represents the display width
and the second number specifies the number of digits to be stored and
displayed following the decimal point (as with DECIMAL
and
NUMERIC
). When MySQL is asked to store a number for
such a column with more decimal digits following the decimal point than
specified for the column, the value is rounded to eliminate the extra
digits when the value is stored.
In standard SQL, the REAL
and DOUBLE PRECISION
types do not accept
precision specifications. MySQL supports a variant syntax with two numbers
given in parentheses following the type name. The first number represents
the display width and the second number specifies the number of digits to
be stored and displayed following the decimal point.
As an extension to the SQL standard, MySQL recognizes DOUBLE
as a synonym for the DOUBLE PRECISION
type. In contrast with the
standard's requirement that the precision for REAL
be smaller than
that used for DOUBLE PRECISION
, MySQL implements both as eight-byte
double-precision floating-point values (unless the server SQL mode
includes the REAL_AS_FLOAT
option).
For maximum portability, code requiring storage of approximate numeric
data values should use FLOAT
or DOUBLE PRECISION
with no
specification of precision or number of decimal points.
When asked to store a value in a numeric column that is outside the column type's allowable range, MySQL clips the value to the appropriate endpoint of the range and stores the resulting value instead.
For example, the range of an INT
column is -2147483648
to 2147483647
. If you try to insert -9999999999
into an
INT
column, MySQL clips the value to the lower endpoint of the
range and stores -2147483648
instead. Similarly, if you try to
insert 9999999999
, MySQL clips the value to the upper endpoint of
the range and stores 2147483647
instead.
If the INT
column is UNSIGNED
, the size of the column's
range is the same but its endpoints shift up to 0
and 4294967295
.
If you try to store -9999999999
and 9999999999
,
the values stored in the column are 0
and 4294967296
.
Conversions that occur due to clipping are reported as ``warnings'' for
ALTER TABLE
, LOAD DATA INFILE
, UPDATE
, and
multiple-row INSERT
statements.
The date and time types for representing temporal values are DATETIME
, DATE
,
TIMESTAMP
, TIME
, and YEAR
. Each temporal type has a
range of legal values, as well as a ``zero'' value that is used when you
specify an illegal value that MySQL cannot represent. The TIMESTAMP
type has special automatic updating behavior, described later on.
Starting from MySQL 5.0.2, MySQL will give warnings/errors if you try to insert
an illegal date. You can get MySQL to accept certain dates, such as
'1999-11-31'
, by using the ALLOW_INVALID_DATES
SQL mode.
(Before 5.0.2, this mode was the default behavior for MySQL).
This is useful when you want to store the ``possibly wrong'' value the user has
specified (for example, in a web form) in the database for future processing.
Under this mode, MySQL verifies only that the month is in the range from 0
to 12 and that the day is in the range from 0 to 31. These ranges
are defined to include zero because MySQL allows you to store dates where the
day or month and day are zero in a DATE
or DATETIME
column.
This is extremely useful for applications that need to store a birthdate for
which you don't know the exact date. In this case, you simply store the date
as '1999-00-00'
or '1999-01-00'
. If you store dates such as
these, you should not expect to get correct results for functions such as
DATE_SUB()
or DATE_ADD
that require complete dates. (If you
don't want to allow zero in dates, you can use the NO_ZERO_IN_DATE
SQL mode).
MySQL also allows you to store '0000-00-00'
as a ``dummy date''
(if you are not using the NO_ZERO_DATE
SQL mode). This is in some
cases is more convenient (and uses less space in data and index) than
using NULL
values.
By setting the sql_mode
system variable to the appropriate mode
values, You can more exactly what kind of dates you want MySQL to support.
See section 5.2.2 The Server SQL Mode.
Here are some general considerations to keep in mind when working with date and time types:
00-69
are converted to 2000-2069
.
70-99
are converted to 1970-1999
.
'98-09-04'
), rather than
in the month-day-year or day-month-year orders commonly used elsewhere (for
example, '09-04-98'
, '04-09-98'
).
TIME
values are clipped to the
appropriate endpoint of the TIME
range.
The following table shows the format of the ``zero'' value for each
type. Note that the use of these values produces warnings if the
NO_ZERO_DATE
SQL mode is enabled.
Column Type | ``Zero'' Value |
DATETIME | '0000-00-00 00:00:00'
|
DATE | '0000-00-00'
|
TIMESTAMP | 00000000000000
|
TIME | '00:00:00'
|
YEAR | 0000
|
'0'
or 0
, which are easier to write.
NULL
in MyODBC 2.50.12 and above,
because ODBC can't handle such values.
DATETIME
, DATE
, and TIMESTAMP
Types
The DATETIME
, DATE
, and TIMESTAMP
types are related.
This section describes their characteristics, how they are similar, and how
they differ.
The DATETIME
type is used when you need values that contain both date
and time information. MySQL retrieves and displays DATETIME
values in 'YYYY-MM-DD HH:MM:SS'
format. The supported range is
'1000-01-01 00:00:00'
to '9999-12-31 23:59:59'
. (``Supported''
means that although earlier values might work, there is no guarantee that
they will.)
The DATE
type is used when you need only a date value, without a time
part. MySQL retrieves and displays DATE
values in
'YYYY-MM-DD'
format. The supported range is '1000-01-01'
to
'9999-12-31'
.
The TIMESTAMP
column type has varying properties,
depending on the MySQL version and the SQL mode the server is running in.
These properties are described later in this section.
You can specify DATETIME
, DATE
, and TIMESTAMP
values using
any of a common set of formats:
'YYYY-MM-DD HH:MM:SS'
or 'YY-MM-DD
HH:MM:SS'
format. A ``relaxed'' syntax is allowed: Any punctuation
character may be used as the delimiter between date parts or time parts.
For example, '98-12-31 11:30:45'
, '98.12.31 11+30+45'
,
'98/12/31 11*30*45'
, and '98@12@31 11^30^45'
are
equivalent.
'YYYY-MM-DD'
or 'YY-MM-DD'
format.
A ``relaxed'' syntax is allowed here, too. For example, '98-12-31'
,
'98.12.31'
, '98/12/31'
, and '98@12@31'
are
equivalent.
'YYYYMMDDHHMMSS'
or
'YYMMDDHHMMSS'
format, provided that the string makes sense as a
date. For example, '19970523091528'
and '970523091528'
are
interpreted as '1997-05-23 09:15:28'
, but '971122129015'
is
illegal (it has a nonsensical minute part) and becomes '0000-00-00
00:00:00'
.
'YYYYMMDD'
or 'YYMMDD'
format, provided that the string makes sense as a date. For example,
'19970523'
and '970523'
are interpreted as
'1997-05-23'
, but '971332'
is illegal (it has nonsensical month
and day parts) and becomes '0000-00-00'
.
YYYYMMDDHHMMSS
or YYMMDDHHMMSS
format, provided that the number makes sense as a date. For example,
19830905132800
and 830905132800
are interpreted as
'1983-09-05 13:28:00'
.
YYYYMMDD
or YYMMDD
format, provided that the number makes sense as a date. For example,
19830905
and 830905
are interpreted as '1983-09-05'
.
DATETIME
, DATE
, or TIMESTAMP
context, such as
NOW()
or CURRENT_DATE
.
Illegal DATETIME
, DATE
, or TIMESTAMP
values are converted
to the ``zero'' value of the appropriate type ('0000-00-00 00:00:00'
,
'0000-00-00'
, or 00000000000000
).
For values specified as strings that include date part delimiters, it is not
necessary to specify two digits for month or day values that are less than
10
. '1979-6-9'
is the same as '1979-06-09'
. Similarly,
for values specified as strings that include time part delimiters, it is not
necessary to specify two digits for hour, minute, or second values that are
less than 10
. '1979-10-30 1:2:3'
is the same as
'1979-10-30 01:02:03'
.
Values specified as numbers should be 6, 8, 12, or 14 digits long. If a
number is 8 or 14 digits long, it is assumed to be in YYYYMMDD
or
YYYYMMDDHHMMSS
format and that the year is given by the first 4
digits. If the number is 6 or 12 digits long, it is assumed to be in
YYMMDD
or YYMMDDHHMMSS
format and that the year is given by the
first 2 digits. Numbers that are not one of these lengths are interpreted
as though padded with leading zeros to the closest length.
Values specified as non-delimited strings are interpreted using their length
as given. If the string is 8 or 14 characters long, the year is assumed to
be given by the first 4 characters. Otherwise, the year is assumed to be
given by the first 2 characters. The string is interpreted from left to
right to find year, month, day, hour, minute, and second values, for as many
parts as are present in the string. This means you should not use strings
that have fewer than 6 characters. For example, if you specify '9903'
,
thinking that will represent March, 1999, you will find that MySQL
inserts a ``zero'' date into your table. This is because the year and month
values are 99
and 03
, but the day part is completely missing, so
the value is not a legal date. However, as of MySQL 3.23, you can explicitly
specify a value of zero to represent missing month or day parts. For example,
you can use '990300'
to insert the value '1999-03-00'
.
You can to some extent assign values of one date type to an object of a different date type. However, there may be some alteration of the value or loss of information:
DATE
value to a DATETIME
or TIMESTAMP
object, the time part of the resulting value is set to '00:00:00'
because the DATE
value contains no time information.
DATETIME
or TIMESTAMP
value to a DATE
object, the time part of the resulting value is deleted because the
DATE
type stores no time information.
DATETIME
, DATE
, and TIMESTAMP
values all can be specified using the same set of formats, the types do not
all have the same range of values. For example, TIMESTAMP
values
cannot be earlier than 1970
or later than 2037
. This means
that a date such as '1968-01-01'
, while legal as a DATETIME
or
DATE
value, is not a valid TIMESTAMP
value and will be
converted to 0
if assigned to such an object.
Be aware of certain pitfalls when specifying date values:
'10:11:12'
might look like a time value
because of the `:' delimiter, but if used in a date context will be
interpreted as the year '2010-11-12'
. The value '10:45:15'
will be converted to '0000-00-00'
because '45'
is not a legal
month.
'0000-00-00'
. Please note that this still allows you to store
invalid dates such as '2002-04-31'
. To ensure that a date is valid,
perform a check in your application.
00-69
are converted to 2000-2069
.
70-99
are converted to 1970-1999
.
TIMESTAMP
Properties Prior to MySQL 4.1
The TIMESTAMP
column type provides a type that you can use to
automatically mark INSERT
or UPDATE
operations with the current
date and time. If you have multiple TIMESTAMP
columns in a table,
only the first one is updated automatically. (From MySQL 4.1.2 on, you can
specify which TIMESTAMP
column updates;
see section 11.3.1.2 TIMESTAMP
Properties as of MySQL 4.1.)
Automatic updating of the first TIMESTAMP
column in a table occurs
under any of the following conditions:
NULL
.
INSERT
or
LOAD DATA INFILE
statement.
UPDATE
statement and some
other column changes value. An UPDATE
that sets a column
to the value it does not cause the TIMESTAMP
column to be
updated; if you set a column to its current value, MySQL
ignores the update for efficiency.
TIMESTAMP
columns other than the first can also be set to the current
date and time. Just set the column to NULL
or to any function that
produces the current date and time (NOW()
, CURRENT_TIMESTAMP
).
You can set any TIMESTAMP
column to a value different from the current
date and time by setting it explicitly to the desired value. This is true
even for the first TIMESTAMP
column. You can use this property if,
for example, you want a TIMESTAMP
to be set to the current date and
time when you create a row, but not to be changed whenever the row is updated
later:
TIMESTAMP
column explicitly to its current value:
UPDATE tbl_name SET timestamp_col = timestamp_col, other_col1 = new_value1, other_col2 = new_value2, ...
Another way to maintain a column that records row-creation time is to use
a DATETIME
column that you initialize to NOW()
when the row
is created and leave alone for subsequent updates.
TIMESTAMP
values may range from the beginning of 1970 to partway
through the year 2037, with a resolution of one second. Values are displayed
as numbers. When you store a value in a TIMESTAMP
column, it is
assumed to be represented in the current time zone, and is converted to
UTC for storage. When you retrieve the value, it is converted from UTC
back to the local time zone for display. Before MySQL 4.1.3, the server
has a single time zone. As of 4.1.3, clients can set their time zone on
a per-connection basis, as described in Time zone support
.
The format in which MySQL retrieves and displays TIMESTAMP
values depends on the display size, as illustrated by the following table. The
``full'' TIMESTAMP
format is 14 digits, but TIMESTAMP
columns may
be created with shorter display sizes:
Column Type | Display Format |
TIMESTAMP(14) | YYYYMMDDHHMMSS
|
TIMESTAMP(12) | YYMMDDHHMMSS
|
TIMESTAMP(10) | YYMMDDHHMM
|
TIMESTAMP(8) | YYYYMMDD
|
TIMESTAMP(6) | YYMMDD
|
TIMESTAMP(4) | YYMM
|
TIMESTAMP(2) | YY
|
All TIMESTAMP
columns have the same storage size, regardless of
display size. The most common display sizes are 6, 8, 12, and 14. You can
specify an arbitrary display size at table creation time, but values of 0 or
greater than 14 are coerced to 14. Odd-valued sizes in the range from 1 to
13 are coerced to the next higher even number.
TIMESTAMP
columns store legal values using the full precision with
which the value was specified, regardless of the display size. This has
several implications:
TIMESTAMP(4)
or TIMESTAMP(2)
. Otherwise, the value is not
a legal date and 0
will be stored.
ALTER TABLE
to widen a narrow TIMESTAMP
column,
information will be displayed that previously was ``hidden.''
TIMESTAMP
column does not cause information to
be lost, except in the sense that less information is shown when the values
are displayed.
TIMESTAMP
values are stored to full precision, the only
function that operates directly on the underlying stored value is
UNIX_TIMESTAMP()
. Other functions operate on the formatted retrieved
value. This means you cannot use a function such as HOUR()
or
SECOND()
unless the relevant part of the TIMESTAMP
value is
included in the formatted value. For example, the HH
part of a
TIMESTAMP
column is not displayed unless the display size is at least
10, so trying to use HOUR()
on shorter TIMESTAMP
values
produces a meaningless result.
TIMESTAMP
Properties as of MySQL 4.1
In MySQL 4.1 and up, the properties of the TIMESTAMP
column type change
in the ways described in this section.
From MySQL 4.1.0 on, TIMESTAMP
display format differs from that of
earlier MySQL releases:
TIMESTAMP
columns are displayed in the same format as DATETIME
columns.
TIMESTAMP(2)
,
TIMESTAMP(4)
, and so on, the display width is ignored.
Beginning with MySQL 4.1.1, the MySQL server can be run in MAXDB
mode. When the server runs in this mode, TIMESTAMP
is identical
with DATETIME
. That is, if the server is running in MAXDB
mode at the time that a table is created, TIMESTAMP
columns
are created as DATETIME
columns. As a result, such columns use
DATETIME
display format, have the same range of values, and there is
no automatic initialization or updating to the current date and time.
To enable MAXDB
mode,
set the server SQL mode to MAXDB
at startup using the
--sql-mode=MAXDB
server option or by setting the global
sql_mode
variable at runtime:
mysql> SET GLOBAL sql_mode=MAXDB;
A client can cause the server to run in MAXDB
mode for its own
connection as follows:
mysql> SET SESSION sql_mode=MAXDB;
As of MySQL 5.0.2, MySQL will not accept timestamp values that includes a zero in the day or month column or values that are not a valid date. (The exception is the special value '0000-00-00 00:00:00'.)
Beginning with MySQL 4.1.2, you have more flexible control over when
automatic TIMESTAMP
initialization and updating occur and which
column should have those behaviors:
TIMESTAMP
column to automatically initialize
or update to the current date and time. This no longer need be the first
TIMESTAMP
column.
The following discussion describes the revised syntax and behavior.
Note that this information applies only to TIMESTAMP
columns for
tables not created with MAXDB
mode enabled. As noted earlier in
this section, MAXDB
mode causes columns to be created as
DATETIME
columns.
The following items summarize the pre-4.1.2 properties for TIMESTAMP
initialization and updating:
The first TIMESTAMP
column in table row automatically is set to
the current timestamp when the record is created if the column is set to
NULL
or is not specified at all.
The first TIMESTAMP
column in table row automatically is updated
to the current timestamp when the value of any other column in the row
is changed, unless the TIMESTAMP
column explicitly is assigned a
value other than NULL
.
If a DEFAULT
value is specified for the first TIMESTAMP
column when the table is created, it is silently ignored.
Other TIMESTAMP
columns in the table can be set to the current
TIMESTAMP
by assigning NULL
to them, but they do not update
automatically.
As of 4.1.2, you have more flexibility in deciding which TIMESTAMP
column automatically is initialized and updated to the current timestamp.
The rules are as follows:
If a DEFAULT
value is specified for the first TIMESTAMP
column
in a table, it is not ignored. The default can be CURRENT_TIMESTAMP
or a constant date and time value.
DEFAULT NULL
is the same as DEFAULT CURRENT_TIMESTAMP
for
the first TIMESTAMP
column. For any other TIMESTAMP
column, DEFAULT NULL
is treated as DEFAULT 0
.
Any single TIMESTAMP
column in a table can be set to be the one that
is initialized to the current timestamp and/or updated automatically.
In a CREATE TABLE
statement, the first TIMESTAMP
column can
be declared in any of the following ways:
DEFAULT CURRENT_TIMESTAMP
and ON UPDATE
CURRENT_TIMESTAMP
clauses, the column has the current timestamp for its
default value, and is automatically updated.
DEFAULT
nor ON UPDATE
clauses, it is the same
as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
.
DEFAULT CURRENT_TIMESTAMP
clause and no ON UPDATE
clause, the column has the current timestamp for its default value but is
not automatically updated.
DEFAULT
clause and with an ON UPDATE CURRENT_TIMESTAMP
clause, the column has a default of 0 and is automatically updated.
DEFAULT
value and with ON UPDATE
CURRENT_TIMESTAMP
clause, the column has the given default and is
automatically updated.
In other words, you can use the current timestamp for both the initial
value and the auto-update value, or either one, or neither. (For example,
you can specify ON UPDATE
to get auto-update without also having
the column auto-initialized.)
Any of CURRENT_TIMESTAMP
, CURRENT_TIMESTAMP()
, or NOW()
can be used in the DEFAULT
and ON UPDATE
clauses. They
all have the same effect.
The order of the two attributes does not matter. If both DEFAULT
and ON UPDATE
are specified for a TIMESTAMP
column, either
can precede the other.
Example. These statements are equivalent:
CREATE TABLE t (ts TIMESTAMP); CREATE TABLE t (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); CREATE TABLE t (ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
To specify automatic default or updating for a TIMESTAMP
column other
than the first one, you must suppress the automatic initialization and update behaviors
for the first TIMESTAMP
column by explicitly assigning it a constant
DEFAULT
value (for example, DEFAULT 0
or DEFAULT
'2003-01-01 00:00:00'
). Then for the other TIMESTAMP
column, the
rules are the same as for the first TIMESTAMP
column, except that
you cannot omit both of the DEFAULT
and ON UPDATE
clauses.
If you do that, no automatic initialization or updating occurs.
Example. These statements are equivalent:
CREATE TABLE t ( ts1 TIMESTAMP DEFAULT 0, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); CREATE TABLE t ( ts1 TIMESTAMP DEFAULT 0, ts2 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Beginning with MySQL 4.1.3, you can set the current time zone on a
per-connection basis, as described in Time zone support
.
TIMESTAMP
values still are stored in UTC, but are converted
from the current time zone for storage, and converted back to the
current time zone for retrieval. As long as the time zone setting
remains the same, you will get back the same value you store. If you
store a TIMESTAMP
value, then change the time zone and
retrieve the value, it will be different than the value you stored.
This occurs because the same time zone is not used for conversion in
both directions. The current time zone is available as the value of
the time_zone
system variable.
Beginning with MySQL 4.1.6, you can include the NULL
attribute
in the definition of a TIMESTAMP
column to allow the column
to contain NULL
values. For example:
CREATE TABLE t ( ts1 TIMESTAMP NULL DEFAULT NULL, ts2 TIMESTAMP NULL DEFAULT 0, ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP );
Before MySQL 4.1.6 (and even as of 4.1.6 if the NULL
attribute is not
specified), setting the column to NULL
sets it to the current
timestamp.
TIME
Type
MySQL retrieves and displays TIME
values in 'HH:MM:SS'
format (or 'HHH:MM:SS'
format for large hours values). TIME
values may range from '-838:59:59'
to '838:59:59'
. The reason
the hours part may be so large is that the TIME
type may be used not
only to represent a time of day (which must be less than 24 hours), but also
elapsed time or a time interval between two events (which may be much greater
than 24 hours, or even negative).
You can specify TIME
values in a variety of formats:
'D HH:MM:SS.fraction'
format.
You can also use one of the following ``relaxed'' syntaxes:
'HH:MM:SS.fraction'
, 'HH:MM:SS'
, 'HH:MM'
, 'D
HH:MM:SS'
, 'D HH:MM'
, 'D HH'
, or 'SS'
. Here D
represents days and can have a value from 0 to 34.
Note that MySQL doesn't yet store the fraction part.
'HHMMSS'
format, provided that
it makes sense as a time. For example, '101112'
is understood as
'10:11:12'
, but '109712'
is illegal (it has a nonsensical
minute part) and becomes '00:00:00'
.
HHMMSS
format, provided that it makes sense as a time.
For example, 101112
is understood as '10:11:12'
. The following
alternative formats are also understood: SS
, MMSS
, HHMMSS
,
HHMMSS.fraction
. Note that MySQL doesn't yet store the
fraction part.
TIME
context, such as CURRENT_TIME
.
For TIME
values specified as strings that include a time part
delimiter, it is not necessary to specify two digits for hours, minutes, or
seconds values that are less than 10
. '8:3:2'
is the same as
'08:03:02'
.
Be careful about assigning ``short'' TIME
values to a TIME
column. Without colons, MySQL interprets values using the
assumption that the rightmost digits represent seconds. (MySQL
interprets TIME
values as elapsed time rather than as time of
day.) For example, you might think of '1112'
and 1112
as
meaning '11:12:00'
(12 minutes after 11 o'clock), but
MySQL interprets them as '00:11:12'
(11 minutes, 12 seconds).
Similarly, '12'
and 12
are interpreted as '00:00:12'
.
TIME
values with colons, by contrast, are always treated as
time of the day. That is '11:12'
will mean '11:12:00'
,
not '00:11:12'
.
Values that lie outside the TIME
range
but are otherwise legal are clipped to the closest
endpoint of the range. For example, '-850:00:00'
and
'850:00:00'
are converted to '-838:59:59'
and
'838:59:59'
.
Illegal TIME
values are converted to '00:00:00'
. Note that
because '00:00:00'
is itself a legal TIME
value, there is no way
to tell, from a value of '00:00:00'
stored in a table, whether the
original value was specified as '00:00:00'
or whether it was illegal.
YEAR
Type
The YEAR
type is a one-byte type used for representing years.
MySQL retrieves and displays YEAR
values in YYYY
format. The range is 1901
to 2155
.
You can specify YEAR
values in a variety of formats:
'1901'
to '2155'
.
1901
to 2155
.
'00'
to '99'
. Values in the
ranges '00'
to '69'
and '70'
to '99'
are
converted to YEAR
values in the ranges 2000
to 2069
and
1970
to 1999
.
1
to 99
. Values in the
ranges 1
to 69
and 70
to 99
are converted to
YEAR
values in the ranges 2001
to 2069
and 1970
to 1999
. Note that the range for two-digit numbers is slightly
different from the range for two-digit strings, because you cannot specify zero
directly as a number and have it be interpreted as 2000
. You
must specify it as a string '0'
or '00'
or it will be
interpreted as 0000
.
YEAR
context, such as NOW()
.
Illegal YEAR
values are converted to 0000
.
MySQL itself is year 2000 (Y2K) safe (see section 1.2.5 Year 2000 Compliance), but input values presented to MySQL may not be. Any input containing two-digit year values is ambiguous, because the century is unknown. Such values must be interpreted into four-digit form because MySQL stores years internally using four digits.
For DATETIME
, DATE
, TIMESTAMP
, and YEAR
types,
MySQL interprets dates with ambiguous year values using the
following rules:
00-69
are converted to 2000-2069
.
70-99
are converted to 1970-1999
.
Remember that these rules provide only reasonable guesses as to what your data values mean. If the heuristics used by MySQL do not produce the correct values, you should provide unambiguous input containing four-digit year values.
ORDER BY
properly sorts TIMESTAMP
or YEAR
values that
have two-digit years.
Some functions like MIN()
and MAX()
will convert a
TIMESTAMP
or YEAR
to a number. This means that a value with a
two-digit year will not work properly with these functions. The fix in this
case is to convert the TIMESTAMP
or YEAR
to four-digit year
format or use something like MIN(DATE_ADD(timestamp,INTERVAL 0
DAYS))
.
The string types are CHAR
, VARCHAR
, BINARY
,
VARBINARY
, BLOB
, TEXT
, ENUM
, and SET
.
This section describes how these types work and how to use them in your
queries.
CHAR
and VARCHAR
Types
The CHAR
and VARCHAR
types are similar, but differ in the
way they are stored and retrieved.
The length of a CHAR
column is fixed to the length that you declare
when you create the table. The length can be any value from 0 to 255.
(Before MySQL 3.23, the length of CHAR
may be from 1 to 255.)
When CHAR
values are stored, they are right-padded with spaces to the
specified length. When CHAR
values are retrieved, trailing spaces are
removed.
Values in VARCHAR
columns are variable-length strings. You can
declare a VARCHAR
column to be any length from 0 to 255, just as
for CHAR
columns. (Before MySQL 4.0.2, the length of VARCHAR
may be from 1 to 255.) However, in contrast to CHAR
, VARCHAR
values are stored using only as many characters as are needed, plus one byte
to record the length. Values are not padded; instead, trailing spaces are
removed when values are stored. This space removal differs from the
standard SQL specification.
No lettercase conversion takes place during storage or retrieval.
If you assign a value to a CHAR
or VARCHAR
column that
exceeds the column's maximum length, the value is truncated to fit.
If you need a column for which trailing spaces are not removed, consider using
a BLOB
or TEXT
type.
If you want to store binary values such as results from an encryption
or compression function that might contain arbitrary byte values, use a
BLOB
column rather than a CHAR
or VARCHAR
column, to
avoid potential problems with trailing space removal that would change
data values.
The following table illustrates the differences between the two types of columns
by showing the result of storing various string values into CHAR(4)
and VARCHAR(4)
columns:
Value | CHAR(4) | Storage Required | VARCHAR(4) | Storage Required |
'' | ' ' | 4 bytes | '' | 1 byte |
'ab' | 'ab ' | 4 bytes | 'ab' | 3 bytes |
'abcd' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
'abcdefgh' | 'abcd' | 4 bytes | 'abcd' | 5 bytes |
The values retrieved from the CHAR(4)
and VARCHAR(4)
columns
are the same in each case, because trailing spaces are removed from
CHAR
columns upon retrieval.
As of MySQL 4.1, values in CHAR
and VARCHAR
columns are sorted
and compared according to the collation of the character set assigned to
the column. Before MySQL 4.1, sorting and comparison are based on
the collation of the server character set; you can declare the column
with the BINARY
attribute to cause sorting and comparison to be
case sensitive using the underlying character code values rather then a
lexical ordering. BINARY
doesn't affect how the column is stored
or retrieved.
From MySQL 4.1.0 on, column type CHAR BYTE
is an alias for
CHAR BINARY
. This is a compatibility feature.
The BINARY
attribute is sticky. This means that if a column marked
BINARY
is used in an expression, the whole expression is treated as a
BINARY
value.
From MySQL 4.1.0 on, the ASCII
attribute can be specified for
CHAR
. It assigns the latin1
character set.
From MySQL 4.1.1 on, the UNICODE
attribute can be specified for
CHAR
. It assigns the ucs2
character set.
MySQL may silently change the type of a CHAR
or VARCHAR
column at table creation time.
See section 13.2.6.1 Silent Column Specification Changes.
BINARY
and VARBINARY
Types
The BINARY
and VARBINARY
types are like CHAR
and
VARCHAR
, except that they contain binary strings rather than
non-binary strings. That is, they contain byte strings rather than character
strings. This means they have no character set and compare in case sensitive
fashion.
Before MySQL 4.1.2, BINARY(M)
and VARBINARY(M)
are
treated as CHAR(M) BINARY
and VARCHAR(M) BINARY
.
As of MySQL 4.1.2, BINARY
and VARBINARY
are available as distinct
data types, and for CHAR(M) BINARY
and VARCHAR(M)
BINARY
, the BINARY
attribute does not cause the column to be treated
as a binary string column. Instead, it causes the binary collation for the
column character set to be used, but the column itself contains non-binary
character strings rather than binary byte strings. For example, in 4.1
and up, CHAR(5) BINARY
is treated as CHAR(5) CHARACTER SET
latin1 COLLATE latin1_bin
, assuming that the default character set is
latin1
.
BLOB
and TEXT
Types
A BLOB
is a binary large object that can hold a variable amount of
data. The four BLOB
types, TINYBLOB
, BLOB
,
MEDIUMBLOB
, and LONGBLOB
, differ only in the maximum length of
the values they can hold.
See section 11.5 Column Type Storage Requirements.
The four TEXT
types, TINYTEXT
, TEXT
, MEDIUMTEXT
,
and LONGTEXT
, correspond to the four BLOB
types and have
the same maximum lengths and storage requirements.
BLOB
columns are treated as binary strings (byte strings). TEXT
columns are treated as non-binary strings (character strings). BLOB
columns have no character set, and sorting and comparison is based on the
numeric values of the bytes in column values. TEXT
columns
have a character set, and values are sorted and compared based on the
collation of the character set assigned to the column as of MySQL 4.1.
Before 4.1, TEXT
sorting and comparison are based on the collation
of the server character set.
No lettercase conversion takes place during storage or retrieval.
If you assign a value to a BLOB
or TEXT
column that exceeds
the column type's maximum length, the value is truncated to fit.
In most respects, you can regard a TEXT
column as a VARCHAR
column that can be as big as you like. Similarly, you can regard a
BLOB
column as a VARCHAR BINARY
column. The ways in which
BLOB
and TEXT
differ from CHAR
and VARCHAR
are:
BLOB
and TEXT
columns when values are stored or retrieved. This differs from CHAR
columns (trailing spaces are removed when values are retrieved) and from
VARCHAR
columns (trailing spaces are removed when values are stored).
BLOB
and TEXT
columns only as of MySQL
3.23.2 for MyISAM
tables or MySQL 4.0.14 for InnoDB
tables.
Older versions of MySQL did not support indexing these column types.
BLOB
and TEXT
columns, you must specify an index
prefix length. For CHAR
and VARCHAR
, a prefix length is
optional.
BLOB
and TEXT
columns cannot have DEFAULT
values.
From MySQL 4.1.0 on, LONG
and LONG VARCHAR
map to the
MEDIUMTEXT
data type. This is a compatibility feature. If you use the
BINARY
attribute with a TEXT
column type, the column is assigned
the binary collation of the column character set.
MySQL Connector/ODBC defines BLOB
values as LONGVARBINARY
and
TEXT
values as LONGVARCHAR
.
Because BLOB
and TEXT
values may be extremely long, you
may encounter some constraints in using them:
max_sort_length
bytes of the
column are used when sorting. The default value of max_sort_length
is 1024; this value can be changed using the --max_sort_length
option when starting the mysqld
server.
See section 5.2.3 Server System Variables.
As of MySQL 4.0.3, you can make more bytes significant in sorting or grouping
by increasing the value of max_sort_length
at runtime. Any client
can change the value of its session max_sort_length
variable:
mysql> SET max_sort_length = 2000; mysql> SELECT id, comment FROM tbl_name -> ORDER BY comment;Another way to use
GROUP BY
or ORDER BY
on a BLOB
or
TEXT
column containing long values when you want more than
max_sort_length
bytes to be significant is to convert the column
value into a fixed-length object. The standard way to do this is with the
SUBSTRING
function. For example, the following statement causes
2000 bytes of the comment
column to be taken into account for sorting:
mysql> SELECT id, SUBSTRING(comment,1,2000) FROM tbl_name -> ORDER BY SUBSTRING(comment,1,2000);Before MySQL 3.23.2, you can group on an expression involving
BLOB
or
TEXT
values by using a column alias or by specifying the column
position:
mysql> SELECT id, SUBSTRING(comment,1,2000) AS b -> FROM tbl_name GROUP BY b; mysql> SELECT id, SUBSTRING(comment,1,2000) -> FROM tbl_name GROUP BY 2;
BLOB
or TEXT
object is determined by its
type, but the largest value you actually can transmit between the client and
server is determined by the amount of available memory and the size of the
communications buffers. You can change the message buffer size by changing
the value of the
max_allowed_packet
variable, but you must
do so for both the server and your client program.
For example, both mysql
and mysqldump
allow you to change the
client-side
max_allowed_packet
value.
See
section 7.5.2 Tuning Server Parameters,
section 8.3 mysql
, the Command-Line Tool,
and
section 8.8 The mysqldump
Database Backup Program.
Each BLOB
or TEXT
value is represented
internally by a separately allocated object. This is in contrast to all
other column types, for which storage is allocated once per column when
the table is opened.
ENUM
Type
An ENUM
is a string object with a value chosen from a list
of allowed values that are enumerated explicitly in the column specification
at table creation time.
The value may also be the empty string (''
) or NULL
under
certain circumstances:
ENUM
(that is, a string not
present in the list of allowed values), the empty string is inserted
instead as a special error value. This string can be distinguished from a
``normal'' empty string by the fact that this string has the numerical value
0. More about this later.
ENUM
column is declared to allow NULL
, the NULL
value is a legal value for the column, and the default value is NULL
.
If an ENUM
column is declared NOT NULL
, its default value
is the first element of the list of allowed values.
Each enumeration value has an index:
SELECT
statement to find rows into which invalid
ENUM
values were assigned:
mysql> SELECT * FROM tbl_name WHERE enum_col=0;
NULL
value is NULL
.
For example, a column specified as ENUM('one', 'two', 'three')
can
have any of the values shown here. The index of each value is also shown:
Value | Index |
NULL | NULL
|
'' | 0 |
'one' | 1 |
'two' | 2 |
'three' | 3 |
An enumeration can have a maximum of 65,535 elements.
Starting from MySQL 3.23.51, trailing spaces are automatically deleted from
ENUM
member values when the table is created.
Lettercase is irrelevant when you assign values to an ENUM
column.
However, values retrieved from the column later are displayed using the
lettercase that was used in the column definition.
If you retrieve an ENUM
value in a numeric context, the column value's
index is returned. For example, you can retrieve numeric values from
an ENUM
column like this:
mysql> SELECT enum_col+0 FROM tbl_name;
If you store a number into an ENUM
column, the number is treated as an
index, and the value stored is the enumeration member with that index.
(However, this will not work with LOAD DATA
, which treats all
input as strings.)
It's not advisable to define an ENUM
column with enumeration values
that look like numbers, because this can easily become confusing. For example,
the following column has enumeration members with string values of
'0'
, '1'
, and '2'
,
but numeric index values of
1
, 2
, and 3
:
numbers ENUM('0','1','2')
ENUM
values are sorted according to the order in which the enumeration
members were listed in the column specification. (In other words,
ENUM
values are sorted according to their index numbers.) For
example, 'a'
sorts before 'b'
for ENUM('a', 'b')
, but
'b'
sorts before 'a'
for ENUM('b', 'a')
. The empty
string sorts before non-empty strings, and NULL
values sort before
all other enumeration values.
To prevent unexpected results, specify the ENUM
list in alphabetical
order. You can also use GROUP BY CAST(col AS VARCHAR)
or
GROUP BY CONCAT(col)
to make sure that the column
is sorted lexically rather than by index number.
If you want to determine all possible values for an ENUM
column,
use SHOW COLUMNS FROM tbl_name LIKE enum_col
and parse
the ENUM
definition in the second column of the output.
SET
Type
A SET
is a string object that can have zero or more values, each of
which must be chosen from a list of allowed values specified when the table
is created. SET
column values that consist of multiple set members
are specified with members separated by commas (`,'). A consequence of
this is that SET
member values cannot themselves contain commas.
For example, a column specified as SET('one', 'two') NOT NULL
can have
any of these values:
'' 'one' 'two' 'one,two'
A SET
can have a maximum of 64 different members.
Starting from MySQL 3.23.51, trailing spaces are automatically deleted from
SET
member values when the table is created.
MySQL stores SET
values numerically, with the low-order bit
of the stored value corresponding to the first set member. If you retrieve a
SET
value in a numeric context, the value retrieved has bits set
corresponding to the set members that make up the column value. For example,
you can retrieve numeric values from a SET
column like this:
mysql> SELECT set_col+0 FROM tbl_name;
If a number is stored into a SET
column, the bits that
are set in the binary representation of the number determine the
set members in the column value. For a column specified as
SET('a','b','c','d')
, the members have the following decimal and
binary values:
SET Member | Decimal Value | Binary Value |
'a' | 1 | 0001
|
'b' | 2 | 0010
|
'c' | 4 | 0100
|
'd' | 8 | 1000
|
If you assign a value of 9
to this column, that is 1001
in
binary, so the first and fourth SET
value members 'a'
and
'd'
are selected and the resulting value is 'a,d'
.
For a value containing more than one SET
element, it does not matter
what order the elements are listed in when you insert the value. It also
does not matter how many times a given element is listed in the value.
When the value is retrieved later, each element in the value will appear
once, with elements listed according to the order in which they were
specified at table creation time. If a column is specified as
SET('a','b','c','d')
, then 'a,d'
, 'd,a'
, and
'd,a,a,d,d'
all will appear as 'a,d'
when retrieved.
If you set a SET
column to an unsupported value, the value will
be ignored.
SET
values are sorted numerically. NULL
values sort before
non-NULL
SET
values.
Normally, you search for SET
values using
the FIND_IN_SET()
function or the LIKE
operator:
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0; mysql> SELECT * FROM tbl_name WHERE set_col LIKE '%value%';
The first statement finds rows where set_col contains the value set member. The second is similar, but not the same: It finds rows where set_col contains value anywhere, even as a substring of another set member.
The following statements also are legal:
mysql> SELECT * FROM tbl_name WHERE set_col & 1; mysql> SELECT * FROM tbl_name WHERE set_col = 'val1,val2';
The first of these statements looks for values containing the first set
member. The second looks for an exact match. Be careful with comparisons
of the second type. Comparing set values to 'val1,val2'
will
return different results than comparing values to 'val2,val1'
.
You should specify the values in the same order they are listed in the
column definition.
If you want to determine all possible values for a SET
column,
use SHOW COLUMNS FROM tbl_name LIKE set_col
and parse
the SET
definition in the second column of the output.
The storage requirements for each of the column types supported by MySQL are listed by category.
The maximum size of a row in a MyISAM
table is 65,534 bytes. Each
BLOB
and TEXT
column accounts for only five to nine bytes
toward this size.
If a MyISAM
or ISAM
table includes any variable-length column
types, the record format will also be variable length. When a table
is created, MySQL may, under certain conditions, change a column from a
variable-length type to a fixed-length type or vice versa. See section 13.2.6.1 Silent Column Specification Changes.
Column Type | Storage Required |
TINYINT | 1 byte |
SMALLINT | 2 bytes |
MEDIUMINT | 3 bytes |
INT , INTEGER | 4 bytes |
BIGINT | 8 bytes |
FLOAT(p) | 4 bytes if 0 <= p <= 24, 8 bytes if 25 <= p <= 53 |
FLOAT | 4 bytes |
DOUBLE [PRECISION] , item REAL | 8 bytes |
DECIMAL(M,D) , NUMERIC(M,D) | M+2 bytes if D > 0, M+1 bytes if D = 0 (D+2, if M < D )
|
Column Type | Storage Required |
DATE | 3 bytes |
DATETIME | 8 bytes |
TIMESTAMP | 4 bytes |
TIME | 3 bytes |
YEAR | 1 byte |
Column Type | Storage Required |
CHAR(M) | M bytes, 0 <= M <= 255
|
VARCHAR(M) | L+1 bytes, where L <= M and 0 <= M <= 255
|
TINYBLOB , TINYTEXT | L+1 bytes, where L < 2^8 |
BLOB , TEXT | L+2 bytes, where L < 2^16 |
MEDIUMBLOB , MEDIUMTEXT | L+3 bytes, where L < 2^24 |
LONGBLOB , LONGTEXT | L+4 bytes, where L < 2^32 |
ENUM('value1','value2',...) | 1 or 2 bytes, depending on the number of enumeration values (65,535 values maximum) |
SET('value1','value2',...) | 1, 2, 3, 4, or 8 bytes, depending on the number of set members (64 members maximum) |
VARCHAR
and the BLOB
and TEXT
types are variable-length
types. For each, the storage requirements depend on the actual length of
column values (represented by L in the preceding table), rather than
on the type's maximum possible size. For example, a VARCHAR(10)
column can hold a string with a maximum length of 10 characters. The actual
storage required is the length of the string (L), plus 1 byte to
record the length of the string. For the string 'abcd'
, L is 4
and the storage requirement is 5 bytes.
The BLOB
and TEXT
types require 1, 2, 3, or 4 bytes to record
the length of the column value, depending on the maximum possible length of
the type. See section 11.4.3 The BLOB
and TEXT
Types.
The size of an ENUM
object is determined by the number of
different enumeration values. One byte is used for enumerations with up
to 255 possible values. Two bytes are used for enumerations with up to
65,535 values. See section 11.4.4 The ENUM
Type.
The size of a SET
object is determined by the number of different
set members. If the set size is N, the object occupies (N+7)/8
bytes, rounded up to 1, 2, 3, 4, or 8 bytes. A SET
can have a maximum
of 64 members. See section 11.4.5 The SET
Type.
For the most efficient use of storage, try to use the most precise type in
all cases. For example, if an integer column will be used for values in the
range from 1
to 99999
, MEDIUMINT UNSIGNED
is the
best type. Of the types that represent all the required values, it uses
the least amount of storage.
Accurate representation of monetary values is a common problem. In MySQL,
you should use the DECIMAL
type. This is stored as a string, so no
loss of accuracy should occur. (Calculations on DECIMAL
values may
still be done using double-precision operations, however.) If accuracy
is not too important, the DOUBLE
type may also be good enough.
For high precision, you can always convert to a fixed-point type stored
in a BIGINT
. This allows you to do all calculations with integers
and convert results back to floating-point values only when necessary.
To make it easier to use code written for SQL implementations from other vendors, MySQL maps column types as shown in the following table. These mappings make it easier to import table definitions from other database engines into MySQL:
Other Vendor Type | MySQL Type |
BINARY(M) | CHAR(M) BINARY (before MySQL 4.1.2)
|
CHAR VARYING(M) | VARCHAR(M)
|
FLOAT4 | FLOAT
|
FLOAT8 | DOUBLE
|
INT1 | TINYINT
|
INT2 | SMALLINT
|
INT3 | MEDIUMINT
|
INT4 | INT
|
INT8 | BIGINT
|
LONG VARBINARY | MEDIUMBLOB
|
LONG VARCHAR | MEDIUMTEXT
|
LONG | MEDIUMTEXT (MySQL 4.1.0 on)
|
MIDDLEINT | MEDIUMINT
|
VARBINARY(M) | VARCHAR(M) BINARY (before MySQL 4.1.2)
|
As of MySQL 4.1.2, BINARY
and VARBINARY
are distinct data types
and are not converted to CHAR BINARY
and VARCHAR BINARY
.
Column type mapping occurs at table creation time, after which the original
type specifications are discarded. If you create a table with types used
by other vendors and then issue a DESCRIBE tbl_name
statement,
MySQL reports the table structure using the equivalent MySQL types.
Expressions can be used at several points in SQL statements, such as in the
ORDER BY
or HAVING
clauses of SELECT
statements, in the
WHERE
clause of a SELECT
, DELETE
, or UPDATE
statement, or in SET
statements. Expressions can be written using
literal values, column values, NULL
, functions, and operators.
This chapter describes the functions and operators that are allowed for
writing expressions in MySQL.
An expression that contains NULL
always produces a NULL
value
unless otherwise indicated in the documentation for a particular function or
operator.
Note: By default, there must be no whitespace between a function name and the parenthesis following it. This helps the MySQL parser distinguish between function calls and references to tables or columns that happen to have the same name as a function. Spaces around function arguments are permitted, though.
You can tell the MySQL server to accept spaces after function names by
starting it with the --sql-mode=IGNORE_SPACE
option. Individual client
programs can request this behavior by using the
CLIENT_IGNORE_SPACE
option for mysql_real_connect()
.
In either case, all function names will become reserved words.
See section 5.2.2 The Server SQL Mode.
For the sake of brevity, most examples in this chapter display the output
from the mysql
program in abbreviated form. Instead of showing
examples in this format:
mysql> SELECT MOD(29,9); +-----------+ | mod(29,9) | +-----------+ | 2 | +-----------+ 1 rows in set (0.00 sec)
This format is used instead:
mysql> SELECT MOD(29,9); -> 2
Operator precedences are shown in the following list, from lowest precedence to the highest. Operators that are shown together on a line have the same precedence.
:= ||, OR, XOR &&, AND NOT BETWEEN, CASE, WHEN, THEN, ELSE =, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN | & <<, >> -, + *, /, DIV, %, MOD ^ - (unary minus), ~ (unary bit inversion) ! BINARY, COLLATE
The precedence shown for NOT
is as of MySQL 5.0.2. For earlier
versions, or from 5.0.2 on if the HIGH_NOT_PRECEDENCE
SQL mode is
enabled, the precedence of NOT
is the same as that of the !
operator.
See section 5.2.2 The Server SQL Mode.
( ... )
mysql> SELECT 1+2*3; -> 7 mysql> SELECT (1+2)*3; -> 9
Comparison operations result in a value of 1
(TRUE), 0
(FALSE),
or NULL
. These operations work for both numbers and strings. Strings
are automatically converted to numbers and numbers to strings as necessary.
Some of the functions in this section (such as LEAST()
and
GREATEST()
) return values other than 1
(TRUE), 0
(FALSE), or NULL
. However, the value they return is based on
comparison operations performed as described by the following rules.
MySQL compares values using the following rules:
NULL
, the result of the comparison is
NULL
, except for the NULL
-safe <=>
equality comparison
operator.
TIMESTAMP
or DATETIME
column and
the other argument is a constant, the constant is converted
to a timestamp before the comparison is performed. This is done to be more
ODBC-friendly. Note that this is not done for arguments in IN()
!
To be safe, always use complete datetime/date/time strings when doing
comparisons.
By default, string comparisons are not case sensitive and use the current character set (ISO-8859-1 Latin1 by default, which also works excellently for English).
To convert a value to a specific type for comparison purposes, you can
use the CAST()
function. String values can be converted to a
different character set using CONVERT()
.
See section 12.7 Cast Functions and Operators.
The following examples illustrate conversion of strings to numbers for comparison operations:
mysql> SELECT 1 > '6x'; -> 0 mysql> SELECT 7 > '6x'; -> 1 mysql> SELECT 0 > 'x6'; -> 0 mysql> SELECT 0 = 'x6'; -> 1
Note that when you are comparing a string column with a number, MySQL can't use an index on the column to quickly look up the value. If str_col is an indexed string column, the index cannot be used when performing the lookup in the following statement:
SELECT * FROM tbl_name WHERE str_col=1;
The reason for this is that there are many different strings that may
convert to the value 1
: '1'
, ' 1'
, '1a'
, ...
=
mysql> SELECT 1 = 0; -> 0 mysql> SELECT '0' = 0; -> 1 mysql> SELECT '0.0' = 0; -> 1 mysql> SELECT '0.01' = 0; -> 0 mysql> SELECT '.01' = 0.01; -> 1
<=>
NULL
-safe equal.
This operator performs an equality comparison like the =
operator, but
returns 1
rather than NULL
if both operands are NULL
,
and 0
rather than NULL
if one operand is NULL
.
mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL; -> 1, 1, 0 mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL; -> 1, NULL, NULL
<=>
was added in MySQL 3.23.0.
<>
!=
mysql> SELECT '.01' <> '0.01'; -> 1 mysql> SELECT .01 <> '0.01'; -> 0 mysql> SELECT 'zapp' <> 'zappp'; -> 1
<=
mysql> SELECT 0.1 <= 2; -> 1
<
mysql> SELECT 2 < 2; -> 0
>=
mysql> SELECT 2 >= 2; -> 1
>
mysql> SELECT 2 > 2; -> 0
IS boolean_value
IS NOT boolean_value
TRUE
, FALSE
, or UNKNOWN
.
mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN; -> 1, 1, 1 mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN; -> 1, 1, 0
IS [NOT] boolean_value
syntax was added in MySQL 5.0.2.
IS NULL
IS NOT NULL
NULL
.
mysql> SELECT 1 IS NULL, 0 IS NULL, NULL IS NULL; -> 0, 0, 1 mysql> SELECT 1 IS NOT NULL, 0 IS NOT NULL, NULL IS NOT NULL; -> 1, 1, 0To be able to work well with ODBC programs, MySQL supports the following extra features when using
IS NULL
:
AUTO_INCREMENT
value
by issuing a statement of the following form immediately after generating the
value:
SELECT * FROM tbl_name WHERE auto_col IS NULLThis behavior can be disabled by setting
SQL_AUTO_IS_NULL=0
.
See section 13.5.3 SET
Syntax.
DATE
and DATETIME
columns that are declared as NOT
NULL
, you can find the special date '0000-00-00'
by using a statement
like this:
SELECT * FROM tbl_name WHERE date_column IS NULLThis is needed to get some ODBC applications to work because ODBC doesn't support a
'0000-00-00'
date value.
expr BETWEEN min AND max
BETWEEN
returns 1
,
otherwise it returns 0
. This is equivalent to the expression
(min <= expr AND expr <= max)
if all the arguments are of the
same type. Otherwise type conversion takes place according to the rules
described at the beginning of this section, but applied to all the three
arguments. Note: Before MySQL
4.0.5, arguments were converted to the type of expr instead.
mysql> SELECT 1 BETWEEN 2 AND 3; -> 0 mysql> SELECT 'b' BETWEEN 'a' AND 'c'; -> 1 mysql> SELECT 2 BETWEEN 2 AND '3'; -> 1 mysql> SELECT 2 BETWEEN 2 AND 'x-3'; -> 0
expr NOT BETWEEN min AND max
NOT (expr BETWEEN min AND max)
.
COALESCE(value,...)
NULL
value in the list.
mysql> SELECT COALESCE(NULL,1); -> 1 mysql> SELECT COALESCE(NULL,NULL,NULL); -> NULL
COALESCE()
was added in MySQL 3.23.3.
GREATEST(value1,value2,...)
LEAST()
.
mysql> SELECT GREATEST(2,0); -> 2 mysql> SELECT GREATEST(34.0,3.0,5.0,767.0); -> 767.0 mysql> SELECT GREATEST('B','A','C'); -> 'C'Before MySQL 3.22.5, you can use
MAX()
instead of GREATEST()
.
expr IN (value,...)
1
if expr is any of the values in the IN
list,
else returns 0
. If all values are constants, they are
evaluated according to the type of expr and sorted. The search for the
item then is done using a binary search. This means IN
is very quick
if the IN
value list consists entirely of constants. If expr
is a case-sensitive string expression, the string comparison is performed in
case-sensitive fashion.
mysql> SELECT 2 IN (0,3,5,'wefwf'); -> 0 mysql> SELECT 'wefwf' IN (0,3,5,'wefwf'); -> 1The number of values in the
IN
list is only limited by the
max_allowed_packet
value.
To comply with the SQL standard,
from MySQL 4.1 on
IN
returns NULL
not only if the expression on the left hand side is NULL
, but also if
no match is found in the list and one of the expressions in the list is
NULL
.
From MySQL 4.1 on, IN()
syntax also is used to write certain types of
subqueries.
See section 13.1.8.3 Subqueries with ANY
, IN
, and SOME
.
expr NOT IN (value,...)
NOT (expr IN (value,...))
.
ISNULL(expr)
NULL
, ISNULL()
returns 1
, otherwise
it returns 0
.
mysql> SELECT ISNULL(1+1); -> 0 mysql> SELECT ISNULL(1/0); -> 1Note that a comparison of
NULL
values using =
will always be
false!
INTERVAL(N,N1,N2,N3,...)
0
if N < N1, 1
if N < N2
and so on or -1
if N is NULL
. All arguments are treated
as integers. It is required that N1 < N2 < N3 <
...
< Nn for this function to work correctly. This is because
a binary search is used (very fast).
mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200); -> 3 mysql> SELECT INTERVAL(10, 1, 10, 100, 1000); -> 2 mysql> SELECT INTERVAL(22, 23, 30, 44, 200); -> 0
LEAST(value1,value2,...)
INTEGER
context or all arguments
are integer-valued, they are compared as integers.
REAL
context or all arguments are
real-valued, they are compared as reals.
mysql> SELECT LEAST(2,0); -> 0 mysql> SELECT LEAST(34.0,3.0,5.0,767.0); -> 3.0 mysql> SELECT LEAST('B','A','C'); -> 'A'Before MySQL 3.22.5, you can use
MIN()
instead of LEAST()
.
Note that the preceding conversion rules can produce strange results in some
borderline cases:
mysql> SELECT CAST(LEAST(3600, 9223372036854775808.0) as SIGNED); -> -9223372036854775808This happens because MySQL reads
9223372036854775808.0
in an
integer context. The integer representation is not good enough to
hold the value, so it wraps to a signed integer.
In SQL, all logical operators evaluate to TRUE, FALSE, or NULL
(UNKNOWN).
In MySQL, these are implemented as 1
(TRUE), 0
(FALSE),
and NULL
. Most of this is common to different SQL database servers,
although some servers may return any non-zero value for TRUE.
NOT
!
1
if the operand is 0
,
to 0
if the operand is non-zero,
and NOT NULL
returns NULL
.
mysql> SELECT NOT 10; -> 0 mysql> SELECT NOT 0; -> 1 mysql> SELECT NOT NULL; -> NULL mysql> SELECT ! (1+1); -> 0 mysql> SELECT ! 1+1; -> 1The last example produces
1
because the expression evaluates
the same way as (!1)+1
.
AND
&&
1
if all operands are non-zero and not NULL
,
to 0
if one or more operands are 0
,
otherwise NULL
is returned.
mysql> SELECT 1 && 1; -> 1 mysql> SELECT 1 && 0; -> 0 mysql> SELECT 1 && NULL; -> NULL mysql> SELECT 0 && NULL; -> 0 mysql> SELECT NULL && 0; -> 0Please note that MySQL versions prior to 4.0.5 stop evaluation when a
NULL
is encountered, rather than continuing the process to
check for possible 0
values. This means that in these versions,
SELECT (NULL AND 0)
returns NULL
instead of 0
.
As of MySQL 4.0.5, the code has been re-engineered so that the result is
always as prescribed by the SQL standards while still using the
optimization wherever possible.
OR
||
NULL
, the result is 1
if any
operand is non-zero, and 0
otherwise. With a NULL
operand,
the result is 1
if the other operand is non-zero, and NULL
otherwise. If both operands are NULL
, the result is NULL
.
mysql> SELECT 1 || 1; -> 1 mysql> SELECT 1 || 0; -> 1 mysql> SELECT 0 || 0; -> 0 mysql> SELECT 0 || NULL; -> NULL mysql> SELECT 1 || NULL; -> 1
XOR
NULL
if either operand is NULL
.
For non-NULL
operands, evaluates to 1
if an odd number
of operands is non-zero,
otherwise 0
is returned.
mysql> SELECT 1 XOR 1; -> 0 mysql> SELECT 1 XOR 0; -> 1 mysql> SELECT 1 XOR NULL; -> NULL mysql> SELECT 1 XOR 1 XOR 1; -> 1
a XOR b
is mathematically equal to
(a AND (NOT b)) OR ((NOT a) and b)
.
XOR
was added in MySQL 4.0.2.
CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
CASE WHEN [condition] THEN result [WHEN [condition] THEN result ...] [ELSE result] END
value=compare-value
. The second version returns the result for
the first condition that is true. If there was no matching result
value, the result after ELSE
is returned, or NULL
if there is no
ELSE
part.
mysql> SELECT CASE 1 WHEN 1 THEN 'one' -> WHEN 2 THEN 'two' ELSE 'more' END; -> 'one' mysql> SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END; -> 'true' mysql> SELECT CASE BINARY 'B' -> WHEN 'a' THEN 1 WHEN 'b' THEN 2 END; -> NULLThe type of the return value (
INTEGER
, DOUBLE
, or
STRING
) is the same as the type of the first returned value (the
expression after the first THEN
).
CASE
was added in MySQL 3.23.3.
IF(expr1,expr2,expr3)
expr1 <> 0
and expr1 <> NULL
) then
IF()
returns expr2, else it returns expr3.
IF()
returns a numeric or string value, depending on the context
in which it is used.
mysql> SELECT IF(1>2,2,3); -> 3 mysql> SELECT IF(1<2,'yes','no'); -> 'yes' mysql> SELECT IF(STRCMP('test','test1'),'no','yes'); -> 'no'If only one of
expr2
or expr3
is explicitly NULL
, the
result type of the IF()
function is the type of non-NULL
expression. (This behavior is new in MySQL 4.0.3.)
expr1
is evaluated as an integer value, which means that if you are
testing floating-point or string values, you should do so using a comparison
operation.
mysql> SELECT IF(0.1,1,0); -> 0 mysql> SELECT IF(0.1<>0,1,0); -> 1In the first case shown,
IF(0.1)
returns 0
because 0.1
is converted to an integer value, resulting in a test of IF(0)
. This
may not be what you expect. In the second case, the comparison tests the
original floating-point value to see whether it is non-zero. The result
of the comparison is used as an integer.
The default return type of IF()
(which may matter when it is
stored into a temporary table) is calculated in MySQL
3.23 as follows:
Expression | Return Value |
expr2 or expr3 returns a string | string |
expr2 or expr3 returns a floating-point value | floating-point |
expr2 or expr3 returns an integer | integer |
expr2
and expr3
are strings, the result is case
sensitive if either string is case sensitive (starting from MySQL
3.23.51).
IFNULL(expr1,expr2)
NULL
, IFNULL()
returns expr1,
else it returns expr2. IFNULL()
returns a numeric or string
value, depending on the context in which it is used.
mysql> SELECT IFNULL(1,0); -> 1 mysql> SELECT IFNULL(NULL,10); -> 10 mysql> SELECT IFNULL(1/0,10); -> 10 mysql> SELECT IFNULL(1/0,'yes'); -> 'yes'In MySQL 4.0.6 and above, the default result value of
IFNULL(expr1,expr2)
is the more ``general'' of the two expressions,
in the order STRING
, REAL
, or INTEGER
. The difference
from earlier MySQL versions is mostly notable when you create a table
based on expressions or MySQL has to internally store a value from
IFNULL()
in a temporary table.
CREATE TABLE tmp SELECT IFNULL(1,'test') AS test;As of MySQL 4.0.6, the type for the
test
column is CHAR(4)
,
whereas in earlier versions the type would be BIGINT
.
NULLIF(expr1,expr2)
NULL
if expr1 = expr2
is true, else returns expr1.
This is the same as CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END
.
mysql> SELECT NULLIF(1,1); -> NULL mysql> SELECT NULLIF(1,2); -> 1Note that MySQL evaluates
expr1
twice if the arguments are not equal.
NULLIF()
was added in MySQL 3.23.15.
String-valued functions return NULL
if the length of the result would
be greater than the value of the max_allowed_packet
system variable.
See section 7.5.2 Tuning Server Parameters.
For functions that operate on string positions, the first position is numbered 1.
ASCII(str)
0
if str is the empty string. Returns
NULL
if str is NULL
.
ASCII()
works for characters with numeric values from 0
to
255
.
mysql> SELECT ASCII('2'); -> 50 mysql> SELECT ASCII(2); -> 50 mysql> SELECT ASCII('dx'); -> 100See also the
ORD()
function.
BIN(N)
BIGINT
) number. This is equivalent to
CONV(N,10,2)
. Returns NULL
if N is NULL
.
mysql> SELECT BIN(12); -> '1100'
BIT_LENGTH(str)
mysql> SELECT BIT_LENGTH('text'); -> 32
BIT_LENGTH()
was added in MySQL 4.0.2.
CHAR(N,...)
CHAR()
interprets the arguments as integers and returns a string
consisting of the characters given by the code values of those
integers. NULL
values are skipped.
mysql> SELECT CHAR(77,121,83,81,'76'); -> 'MySQL' mysql> SELECT CHAR(77,77.3,'77.3'); -> 'MMM'
CHAR_LENGTH(str)
LENGTH()
returns 10
, whereas CHAR_LENGTH()
returns
5
.
CHARACTER_LENGTH(str)
CHARACTER_LENGTH()
is a synonym for CHAR_LENGTH()
.
COMPRESS(string_to_compress)
zlib
. Otherwise, the return
value is always NULL
. The compressed string can be uncompressed with
UNCOMPRESS()
.
mysql> SELECT LENGTH(COMPRESS(REPEAT('a',1000))); -> 21 mysql> SELECT LENGTH(COMPRESS('')); -> 0 mysql> SELECT LENGTH(COMPRESS('a')); -> 13 mysql> SELECT LENGTH(COMPRESS(REPEAT('a',16))); -> 15The compressed string contents are stored the following way:
CHAR
or VARCHAR
column. (Use of CHAR
or VARCHAR
to store
compressed strings is not recommended. It is better to use a BLOB
column instead.)
COMPRESS()
was added in MySQL 4.1.1.
CONCAT(str1,str2,...)
NULL
if any argument is NULL
. May have one or more arguments.
If all arguments are non-binary strings, the result is a non-binary string.
If the arguments include any binary strings, the result is a binary string.
A numeric argument is converted to its equivalent binary string form.
mysql> SELECT CONCAT('My', 'S', 'QL'); -> 'MySQL' mysql> SELECT CONCAT('My', NULL, 'QL'); -> NULL mysql> SELECT CONCAT(14.3); -> '14.3'
CONCAT_WS(separator,str1,str2,...)
CONCAT_WS()
stands for CONCAT With Separator and is a special form of
CONCAT()
. The first argument is the separator for the rest of the
arguments.
The separator is added between the strings to be concatenated.
The separator can be a string as can the rest of the
arguments. If the separator is NULL
, the result is NULL
.
The function skips any NULL
values after the
separator argument.
mysql> SELECT CONCAT_WS(',','First name','Second name','Last Name'); -> 'First name,Second name,Last Name' mysql> SELECT CONCAT_WS(',','First name',NULL,'Last Name'); -> 'First name,Last Name'Before MySQL 4.0.14,
CONCAT_WS()
skips empty strings as well as
NULL
values.
CONV(N,from_base,to_base)
NULL
if any argument is NULL
.
The argument N is interpreted as an integer, but may be specified as
an integer or a string. The minimum base is 2
and the maximum base is
36
. If to_base is a negative number, N is regarded as a
signed number. Otherwise, N is treated as unsigned. CONV()
works
with 64-bit precision.
mysql> SELECT CONV('a',16,2); -> '1010' mysql> SELECT CONV('6E',18,8); -> '172' mysql> SELECT CONV(-17,10,-18); -> '-H' mysql> SELECT CONV(10+'10'+'10'+0xa,10,10); -> '40'
ELT(N,str1,str2,str3,...)
1
, str2 if N =
2
, and so on. Returns NULL
if N is less than 1
or greater than the number of arguments. ELT()
is the complement of
FIELD()
.
mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo'); -> 'ej' mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo'); -> 'foo'
EXPORT_SET(bits,on,off[,separator[,number_of_bits]])
mysql> SELECT EXPORT_SET(5,'Y','N',',',4); -> 'Y,N,Y,N' mysql> SELECT EXPORT_SET(6,'1','0',',',10); -> '0,1,1,0,0,0,0,0,0,0'
FIELD(str,str1,str2,str3,...)
...
list.
Returns 0
if str is not found.
If str is NULL
, the return value is 0
because
NULL
fails equality comparison with any value.
FIELD()
is the complement of ELT()
.
mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 2 mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo'); -> 0
FIND_IN_SET(str,strlist)
1
to N if the string str is in the string list
strlist consisting of N substrings. A string list is a string
composed of substrings separated by `,' characters. If the first
argument is a constant string and the second is a column of type SET
,
the FIND_IN_SET()
function is optimized to use bit arithmetic.
Returns 0
if str is not in strlist or if strlist
is the empty string. Returns NULL
if either argument is NULL
.
This function will not work properly if the first argument contains a comma
(`,') character.
mysql> SELECT FIND_IN_SET('b','a,b,c,d'); -> 2
HEX(N_or_S)
BIGINT
) number.
This is equivalent to CONV(N,10,16)
.
From MySQL 4.0.1 and up,
if N_OR_S is a string, returns a hexadecimal string of N_OR_S
where each character in N_OR_S is converted to two hexadecimal digits.
mysql> SELECT HEX(255); -> 'FF' mysql> SELECT 0x616263; -> 'abc' mysql> SELECT HEX('abc'); -> 616263
INSERT(str,pos,len,newstr)
NULL
if any argument is null.
mysql> SELECT INSERT('Quadratic', 3, 4, 'What'); -> 'QuWhattic' mysql> SELECT INSERT('Quadratic', -1, 4, 'What'); -> 'Quadratic' mysql> SELECT INSERT('Quadratic', 3, 100, 'What'); -> 'QuWhat'This function is multi-byte safe.
INSTR(str,substr)
LOCATE()
, except that the arguments are swapped.
mysql> SELECT INSTR('foobarbar', 'bar'); -> 4 mysql> SELECT INSTR('xbar', 'foobar'); -> 0This function is multi-byte safe. In MySQL 3.23, this function is case sensitive. For 4.0 on, it is case sensitive only if either argument is a binary string.
LCASE(str)
LCASE()
is a synonym for LOWER()
.
LEFT(str,len)
mysql> SELECT LEFT('foobarbar', 5); -> 'fooba'
LENGTH(str)
LENGTH()
returns 10
, whereas CHAR_LENGTH()
returns
5
.
mysql> SELECT LENGTH('text'); -> 4
LOAD_FILE(file_name)
FILE
privilege. The file must
be readable by all and be smaller than max_allowed_packet
bytes.
If the file doesn't exist or cannot be read because one of the preceding
conditions is not satisfied, the function returns NULL
.
mysql> UPDATE tbl_name SET blob_column=LOAD_FILE('/tmp/picture') WHERE id=1;Before MySQL 3.23, you must read the file inside your application and create an
INSERT
statement to update the database with the file contents.
If you are using the MySQL++ library, one way to do this can be found in the
MySQL++ manual, available at
http://dev.mysql.com/doc/.
LOCATE(substr,str)
LOCATE(substr,str,pos)
0
if substr is not in str.
mysql> SELECT LOCATE('bar', 'foobarbar'); -> 4 mysql> SELECT LOCATE('xbar', 'foobar'); -> 0 mysql> SELECT LOCATE('bar', 'foobarbar',5); -> 7This function is multi-byte safe. In MySQL 3.23, this function is case sensitive. For 4.0 on, it is case sensitive only if either argument is a binary string.
LOWER(str)
mysql> SELECT LOWER('QUADRATICALLY'); -> 'quadratically'This function is multi-byte safe.
LPAD(str,len,padstr)
mysql> SELECT LPAD('hi',4,'??'); -> '??hi' mysql> SELECT LPAD('hi',1,'??'); -> 'h'
LTRIM(str)
mysql> SELECT LTRIM(' barbar'); -> 'barbar'This function is multi-byte safe.
MAKE_SET(bits,str1,str2,...)
NULL
values in str1, str2, ...
are not appended to the result.
mysql> SELECT MAKE_SET(1,'a','b','c'); -> 'a' mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world'); -> 'hello,world' mysql> SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world'); -> 'hello' mysql> SELECT MAKE_SET(0,'a','b','c'); -> ''
MID(str,pos,len)
MID(str,pos,len)
is a synonym for
SUBSTRING(str,pos,len)
.
OCT(N)
BIGINT
)number. This is equivalent to
CONV(N,10,8)
.
Returns NULL
if N is NULL
.
mysql> SELECT OCT(12); -> '14'
OCTET_LENGTH(str)
OCTET_LENGTH()
is a synonym for LENGTH()
.
ORD(str)
(1st byte code) + (2nd byte code * 256) + (3rd byte code * 256^2) ...If the leftmost character is not a multi-byte character,
ORD()
returns the same value as the ASCII()
function.
mysql> SELECT ORD('2'); -> 50
POSITION(substr IN str)
POSITION(substr IN str)
is a synonym for LOCATE(substr,str)
.
QUOTE(str)
NULL
, the return value is the word ``NULL'' without surrounding
single quotes.
The QUOTE()
function was added in MySQL 4.0.3.
mysql> SELECT QUOTE('Don\'t!'); -> 'Don\'t!' mysql> SELECT QUOTE(NULL); -> NULL
REPEAT(str,count)
count <= 0
, returns an empty string. Returns NULL
if
str or count are NULL
.
mysql> SELECT REPEAT('MySQL', 3); -> 'MySQLMySQLMySQL'
REPLACE(str,from_str,to_str)
mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww'); -> 'WwWwWw.mysql.com'This function is multi-byte safe.
REVERSE(str)
mysql> SELECT REVERSE('abc'); -> 'cba'This function is multi-byte safe.
RIGHT(str,len)
mysql> SELECT RIGHT('foobarbar', 4); -> 'rbar'This function is multi-byte safe.
RPAD(str,len,padstr)
mysql> SELECT RPAD('hi',5,'?'); -> 'hi???' mysql> SELECT RPAD('hi',1,'?'); -> 'h'This function is multi-byte safe.
RTRIM(str)
mysql> SELECT RTRIM('barbar '); -> 'barbar'This function is multi-byte safe.
SOUNDEX(str)
SOUNDEX()
function returns an
arbitrarily long string. You can use SUBSTRING()
on the result to get
a standard soundex string. All non-alphabetic characters are ignored in the
given string. All international alphabetic characters outside the A-Z range
are treated as vowels.
mysql> SELECT SOUNDEX('Hello'); -> 'H400' mysql> SELECT SOUNDEX('Quadratically'); -> 'Q36324'Note: This function implements the original Soundex algorithm, not the more popular enhanced version (also described by D. Knuth). The difference is that original version discards vowels first and then duplicates, whereas the enhanced version discards duplicates first and then vowels.
expr1 SOUNDS LIKE expr2
SOUNDEX(expr1) = SOUNDEX(expr2)
. It is
available only in MySQL 4.1 or later.
SPACE(N)
mysql> SELECT SPACE(6); -> ' '
SUBSTRING(str,pos)
SUBSTRING(str FROM pos)
SUBSTRING(str,pos,len)
SUBSTRING(str FROM pos FOR len)
FROM
are standard SQL syntax.
mysql> SELECT SUBSTRING('Quadratically',5); -> 'ratically' mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar' mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica'This function is multi-byte safe.
SUBSTRING_INDEX(str,delim,count)
mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2); -> 'www.mysql' mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2); -> 'mysql.com'This function is multi-byte safe.
TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str)
TRIM(remstr FROM] str)
BOTH
, LEADING
, or
TRAILING
is given, BOTH
is assumed. If remstr is optional
and not specified, spaces are removed.
mysql> SELECT TRIM(' bar '); -> 'bar' mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx'); -> 'barxxx' mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx'); -> 'bar' mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz'); -> 'barx'This function is multi-byte safe.
UCASE(str)
UCASE()
is a synonym for UPPER()
.
UNCOMPRESS(string_to_uncompress)
COMPRESS()
function.
If the argument is not a compressed value, the result is NULL
.
This function requires MySQL to have been compiled with a compression library
such as zlib
. Otherwise, the return value is always NULL
.
mysql> SELECT UNCOMPRESS(COMPRESS('any string')); -> 'any string' mysql> SELECT UNCOMPRESS('any string'); -> NULL
UNCOMPRESS()
was added in MySQL 4.1.1.
UNCOMPRESSED_LENGTH(compressed_string)
mysql> SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a',30))); -> 30
UNCOMPRESSED_LENGTH()
was added in MySQL 4.1.1.
UNHEX(str)
HEX(str)
. That is, it interprets each pair of
hexadecimal digits in the argument as a number and converts it to the
character represented by the number. The resulting characters are returned as
a binary string.
mysql> SELECT UNHEX('4D7953514C'); -> 'MySQL' mysql> SELECT 0x4D7953514C; -> 'MySQL' mysql> SELECT UNHEX(HEX('string')); -> 'string' mysql> SELECT HEX(UNHEX('1267')); -> '1267'
UNHEX()
was added in MySQL 4.1.2.
UPPER(str)
mysql> SELECT UPPER('Hej'); -> 'HEJ'This function is multi-byte safe.
MySQL automatically converts numbers to strings as necessary, and vice versa.
mysql> SELECT 1+'1'; -> 2 mysql> SELECT CONCAT(2,' test'); -> '2 test'
If you want to convert a number to a string explicitly, use the CAST()
or CONCAT()
function:
mysql> SELECT 38.8, CAST(38.8 AS CHAR); -> 38.8, '38.8' mysql> SELECT 38.8, CONCAT(38.8); -> 38.8, '38.8'
CAST()
is preferable, but it is unavailable before MySQL 4.0.2.
If a string function is given a binary string as an argument, the resulting string is also a binary string. A number converted to a string is treated as a binary string. This affects only comparisons.
Normally, if any expression in a string comparison is case sensitive, the comparison is performed in case-sensitive fashion.
expr LIKE pat [ESCAPE 'escape-char']
1
(TRUE) or 0
(FALSE). If either expr or pat is NULL
, the result is
NULL
.
The pattern need not be a literal string. For example, it can be specified
as a string expression or table column.
With LIKE
you can use the following two wildcard characters
in the pattern:
Character | Description |
% | Matches any number of characters, even zero characters |
_ | Matches exactly one character |
mysql> SELECT 'David!' LIKE 'David_'; -> 1 mysql> SELECT 'David!' LIKE '%D%v%'; -> 1To test for literal instances of a wildcard character, precede the character with the escape character. If you don't specify the
ESCAPE
character,
`\' is assumed.
String | Description |
\% | Matches one `%' character |
\_ | Matches one `_' character |
mysql> SELECT 'David!' LIKE 'David\_'; -> 0 mysql> SELECT 'David_' LIKE 'David\_'; -> 1To specify a different escape character, use the
ESCAPE
clause:
mysql> SELECT 'David_' LIKE 'David|_' ESCAPE '|'; -> 1The following two statements illustrate that string comparisons are not case sensitive unless one of the operands is a binary string:
mysql> SELECT 'abc' LIKE 'ABC'; -> 1 mysql> SELECT 'abc' LIKE BINARY 'ABC'; -> 0In MySQL,
LIKE
is allowed on numeric expressions. (This is an
extension to the standard SQL LIKE
.)
mysql> SELECT 10 LIKE '1%'; -> 1Note: Because MySQL uses the C escape syntax in strings (for example, `\n' to represent newline), you must double any `\' that you use in your
LIKE
strings. For example, to search for `\n', specify it as `\\n'. To
search for `\', specify it as `\\\\' (the backslashes are stripped
once by the parser and another time when the pattern match is done, leaving
a single backslash to be matched).
expr NOT LIKE pat [ESCAPE 'escape-char']
NOT (expr LIKE pat [ESCAPE 'escape-char'])
.
expr NOT REGEXP pat
expr NOT RLIKE pat
NOT (expr REGEXP pat)
.
expr REGEXP pat
expr RLIKE pat
1
if expr matches pat, otherwise returns 0
. If either
expr or pat is NULL
, the result is NULL
.
RLIKE
is a synonym for REGEXP
, provided for mSQL
compatibility.
The pattern need not be a literal string. For example, it can be specified
as a string expression or table column.
Note: Because MySQL uses the C escape syntax in strings (for example,
`\n' to represent newline), you must double any `\' that you
use in your REGEXP
strings.
As of MySQL 3.23.4, REGEXP
is not case sensitive for normal (not
binary) strings.
mysql> SELECT 'Monty!' REGEXP 'm%y%%'; -> 0 mysql> SELECT 'Monty!' REGEXP '.*'; -> 1 mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line'; -> 1 mysql> SELECT 'a' REGEXP 'A', 'a' REGEXP BINARY 'A'; -> 1 0 mysql> SELECT 'a' REGEXP '^[a-d]'; -> 1
REGEXP
and RLIKE
use the current character set (ISO-8859-1
Latin1 by default) when deciding the type of a character.
However, these operators are not multi-byte safe.
STRCMP(expr1,expr2)
STRCMP()
returns 0
if the strings are the same, -1
if the first
argument is smaller than the second according to the current sort order,
and 1
otherwise.
mysql> SELECT STRCMP('text', 'text2'); -> -1 mysql> SELECT STRCMP('text2', 'text'); -> 1 mysql> SELECT STRCMP('text', 'text'); -> 0As of MySQL 4.0,
STRCMP()
uses the current character set when performing comparisons.
This makes the default comparison behavior case insensitive unless
one or both of the operands are binary strings.
Before MySQL 4.0, STRCMP()
is case sensitive.
The usual arithmetic operators are available. Note that in the case of
-
, +
, and *
, the result is calculated with
BIGINT
(64-bit) precision if both arguments are integers.
If one of the argument is an unsigned integer, and the other argument
is also an integer, the result will be an unsigned integer.
See section 12.7 Cast Functions and Operators.
+
mysql> SELECT 3+5; -> 8
-
mysql> SELECT 3-5; -> -2
-
mysql> SELECT - 2; -> -2Note that if this operator is used with a
BIGINT
, the return value is a
BIGINT
! This means that you should avoid using -
on integers that
may have the value of -2^63
!
*
mysql> SELECT 3*5; -> 15 mysql> SELECT 18014398509481984*18014398509481984.0; -> 324518553658426726783156020576256.0 mysql> SELECT 18014398509481984*18014398509481984; -> 0The result of the last expression is incorrect because the result of the integer multiplication exceeds the 64-bit range of
BIGINT
calculations.
/
mysql> SELECT 3/5; -> 0.60Division by zero produces a
NULL
result:
mysql> SELECT 102/(1-1); -> NULLA division will be calculated with
BIGINT
arithmetic only if performed
in a context where its result is converted to an integer!
DIV
FLOOR()
but safe with BIGINT
values.
mysql> SELECT 5 DIV 2; -> 2
DIV
is new in MySQL 4.1.0.
All mathematical functions return NULL
in case of an error.
ABS(X)
mysql> SELECT ABS(2); -> 2 mysql> SELECT ABS(-32); -> 32This function is safe to use with
BIGINT
values.
ACOS(X)
NULL
if X is not in the range -1
to
1
.
mysql> SELECT ACOS(1); -> 0.000000 mysql> SELECT ACOS(1.0001); -> NULL mysql> SELECT ACOS(0); -> 1.570796
ASIN(X)
NULL
if X is not in the range -1
to
1
.
mysql> SELECT ASIN(0.2); -> 0.201358 mysql> SELECT ASIN('foo'); -> 0.000000
ATAN(X)
mysql> SELECT ATAN(2); -> 1.107149 mysql> SELECT ATAN(-2); -> -1.107149
ATAN(Y,X)
ATAN2(Y,X)
Y / X
, except that the
signs of both arguments are used to determine the quadrant of the
result.
mysql> SELECT ATAN(-2,2); -> -0.785398 mysql> SELECT ATAN2(PI(),0); -> 1.570796
CEILING(X)
CEIL(X)
mysql> SELECT CEILING(1.23); -> 2 mysql> SELECT CEIL(-1.23); -> -1Note that the return value is converted to a
BIGINT
!
The CEIL()
alias was added in MySQL 4.0.6.
COS(X)
mysql> SELECT COS(PI()); -> -1.000000
COT(X)
mysql> SELECT COT(12); -> -1.57267341 mysql> SELECT COT(0); -> NULL
CRC32(expr)
NULL
if the argument is NULL
.
The argument is expected be a string and will be treated as one if it is not.
mysql> SELECT CRC32('MySQL'); -> 3259397556
CRC32()
is available as of MySQL 4.1.0.
DEGREES(X)
mysql> SELECT DEGREES(PI()); -> 180.000000
EXP(X)
e
(the base of natural logarithms) raised to
the power of X.
mysql> SELECT EXP(2); -> 7.389056 mysql> SELECT EXP(-2); -> 0.135335
FLOOR(X)
mysql> SELECT FLOOR(1.23); -> 1 mysql> SELECT FLOOR(-1.23); -> -2Note that the return value is converted to a
BIGINT
!
LN(X)
mysql> SELECT LN(2); -> 0.693147 mysql> SELECT LN(-2); -> NULLThis function was added in MySQL 4.0.3. It is synonymous with
LOG(X)
in MySQL.
LOG(X)
LOG(B,X)
mysql> SELECT LOG(2); -> 0.693147 mysql> SELECT LOG(-2); -> NULLIf called with two parameters, this function returns the logarithm of X for an arbitrary base B.
mysql> SELECT LOG(2,65536); -> 16.000000 mysql> SELECT LOG(1,100); -> NULLThe arbitrary base option was added in MySQL 4.0.3.
LOG(B,X)
is equivalent to LOG(X)/LOG(B)
.
LOG2(X)
X
.
mysql> SELECT LOG2(65536); -> 16.000000 mysql> SELECT LOG2(-100); -> NULL
LOG2()
is useful for finding out how many bits a number would
require for storage.
This function was added in MySQL 4.0.3.
In earlier versions, you can use LOG(X)/LOG(2)
instead.
LOG10(X)
mysql> SELECT LOG10(2); -> 0.301030 mysql> SELECT LOG10(100); -> 2.000000 mysql> SELECT LOG10(-100); -> NULL
MOD(N,M)
N % M
N MOD M
mysql> SELECT MOD(234, 10); -> 4 mysql> SELECT 253 % 7; -> 1 mysql> SELECT MOD(29,9); -> 2 mysql> SELECT 29 MOD 9; -> 2This function is safe to use with
BIGINT
values.
The N MOD M
syntax works only as of MySQL 4.1.
As of MySQL 4.1.7, MOD()
works on values with a fractional part and
returns the exact remainder after division:
mysql> SELECT MOD(34.5,3); -> 1.5Before MySQL 4.1.7,
MOD()
rounds arguments with a fractional value
to integers and returns an integer result:
mysql> SELECT MOD(34.5,3); -> 2
PI()
mysql> SELECT PI(); -> 3.141593 mysql> SELECT PI()+0.000000000000000000; -> 3.141592653589793116
POW(X,Y)
POWER(X,Y)
mysql> SELECT POW(2,2); -> 4.000000 mysql> SELECT POW(2,-2); -> 0.250000
RADIANS(X)
mysql> SELECT RADIANS(90); -> 1.570796
RAND()
RAND(N)
0
to 1.0
.
If an integer argument N is specified, it is used as the seed value
(producing a repeatable sequence).
mysql> SELECT RAND(); -> 0.9233482386203 mysql> SELECT RAND(20); -> 0.15888261251047 mysql> SELECT RAND(20); -> 0.15888261251047 mysql> SELECT RAND(); -> 0.63553050033332 mysql> SELECT RAND(); -> 0.70100469486881You can't use a column with
RAND()
values in an ORDER BY
clause, because ORDER BY
would evaluate the column multiple times.
As of MySQL 3.23, you can retrieve rows in random order like this:
mysql> SELECT * FROM tbl_name ORDER BY RAND();
ORDER BY RAND()
combined with LIMIT
is useful for selecting
a random sample of a set of rows:
mysql> SELECT * FROM table1, table2 WHERE a=b AND c<d -> ORDER BY RAND() LIMIT 1000;Note that
RAND()
in a WHERE
clause is re-evaluated
every time the WHERE
is executed.
RAND()
is not meant to be a perfect random generator, but instead a
fast way to generate ad hoc random numbers that will be portable between
platforms for the same MySQL version.
ROUND(X)
ROUND(X,D)
mysql> SELECT ROUND(-1.23); -> -1 mysql> SELECT ROUND(-1.58); -> -2 mysql> SELECT ROUND(1.58); -> 2 mysql> SELECT ROUND(1.298, 1); -> 1.3 mysql> SELECT ROUND(1.298, 0); -> 1 mysql> SELECT ROUND(23.298, -1); -> 20Note that the behavior of
ROUND()
when the argument
is halfway between two integers depends on the C library
implementation. Different implementations round to the nearest even number,
always up, always down, or always toward zero. If you need
one kind of rounding, you should use a well-defined function
such as TRUNCATE()
or FLOOR()
instead.
SIGN(X)
-1
, 0
, or 1
, depending
on whether X is negative, zero, or positive.
mysql> SELECT SIGN(-32); -> -1 mysql> SELECT SIGN(0); -> 0 mysql> SELECT SIGN(234); -> 1
SIN(X)
mysql> SELECT SIN(PI()); -> 0.000000
SQRT(X)
mysql> SELECT SQRT(4); -> 2.000000 mysql> SELECT SQRT(20); -> 4.472136
TAN(X)
mysql> SELECT TAN(PI()+1); -> 1.557408
TRUNCATE(X,D)
0
, the result will have no decimal point or fractional part.
If D is negative, the integer part of the number is zeroed out.
mysql> SELECT TRUNCATE(1.223,1); -> 1.2 mysql> SELECT TRUNCATE(1.999,1); -> 1.9 mysql> SELECT TRUNCATE(1.999,0); -> 1 mysql> SELECT TRUNCATE(-1.999,1); -> -1.9 mysql> SELECT TRUNCATE(122,-2); -> 100Starting from MySQL 3.23.51, all numbers are rounded toward zero. Note that decimal numbers are normally not stored as exact numbers in computers, but as double-precision values, so you may be surprised by the following result:
mysql> SELECT TRUNCATE(10.28*100,0); -> 1027This happens because
10.28
is actually stored as something like
10.2799999999999999
.
This section describes the functions that can be used to manipulate temporal values. See section 11.3 Date and Time Types for a description of the range of values each date and time type has and the valid formats in which values may be specified.
Here is an example that uses date functions. The following query selects
all records with a date_col
value from within the last 30 days:
mysql> SELECT something FROM tbl_name -> WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= date_col;
Note that the query also will select records with dates that lie in the future.
Functions that expect date values usually will accept datetime values and ignore the time part. Functions that expect time values usually will accept datetime values and ignore the date part.
Functions that return the current date or time each are evaluated only once
per query at the start of query execution. This means that multiple references
to a function such as NOW()
within a single query will always produce
the same result. This principle also applies to CURDATE()
,
CURTIME()
, UTC_DATE()
, UTC_TIME()
, UTC_TIMESTAMP()
,
and to any of their synonyms.
Beginning with MySQL 4.1.3, the CURRENT_TIMESTAMP()
,
CURRENT_TIME()
, CURRENT_DATE()
, and FROM_UNIXTIME()
functions return values in the connection's current time zone, which is
available as the value of the time_zone
system variable. Also,
UNIX_TIMESTAMP()
assumes that its argument is a datetime value in
the current time zone. See section 5.8.8 MySQL Server Time Zone Support.
The return value ranges in the following function descriptions apply for
complete dates. If a date is a ``zero'' value or an incomplete date such
as '2001-11-00'
, functions that extract a part of a date may return
0
. For example, DAYOFMONTH('2001-11-00')
returns 0
.
ADDDATE(date,INTERVAL expr type)
ADDDATE(expr,days)
INTERVAL
form of the second argument,
ADDDATE()
is a synonym for DATE_ADD()
. The related
function SUBDATE()
is a synonym for DATE_SUB()
.
For information on the INTERVAL
argument, see the
discussion for DATE_ADD()
.
mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY); -> '1998-02-02' mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY); -> '1998-02-02'As of MySQL 4.1.1, the second syntax is allowed, where expr is a date or datetime expression and days is the number of days to be added to expr.
mysql> SELECT ADDDATE('1998-01-02', 31); -> '1998-02-02'
ADDTIME(expr,expr2)
ADDTIME()
adds expr2 to expr and returns the result.
expr is a time or datetime expression, and expr2 is a time
expression.
mysql> SELECT ADDTIME('1997-12-31 23:59:59.999999', -> '1 1:1:1.000002'); -> '1998-01-02 01:01:01.000001' mysql> SELECT ADDTIME('01:00:00.999999', '02:00:00.999998'); -> '03:00:01.999997'
ADDTIME()
was added in MySQL 4.1.1.
CONVERT_TZ(dt,from_tz,to_tz)
CONVERT_TZ()
converts a datetime value dt from time zone given by from_tz
to the time zone given by to_tz and returns the resulting value.
Time zones may be specified as described in section 5.8.8 MySQL Server Time Zone Support.
This function returns NULL
if the arguments are invalid.
If the value falls out of the supported range of the TIMESTAMP
type when converted fom from_tz to UTC, no conversion occurs.
The TIMESTAMP
range is described at
section 11.1.2 Overview of Date and Time Types.
mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET'); -> '2004-01-01 13:00:00' mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','-07:00'); -> '2004-01-01 05:00:00'To use named time zones such as
'MET'
or 'Europe/Moscow'
,
the time zone tables must be properly set up. See
section 5.8.8 MySQL Server Time Zone Support for instructions.
CONVERT_TZ()
was added in MySQL 4.1.3.
CURDATE()
'YYYY-MM-DD'
or YYYYMMDD
format, depending on whether the function is used in a string or numeric
context.
mysql> SELECT CURDATE(); -> '1997-12-15' mysql> SELECT CURDATE() + 0; -> 19971215
CURRENT_DATE
CURRENT_DATE()
CURRENT_DATE
and CURRENT_DATE()
are synonyms for
CURDATE()
.
CURTIME()
'HH:MM:SS'
or HHMMSS
format, depending on whether the function is used in a string or numeric
context.
mysql> SELECT CURTIME(); -> '23:50:26' mysql> SELECT CURTIME() + 0; -> 235026
CURRENT_TIME
CURRENT_TIME()
CURRENT_TIME
and CURRENT_TIME()
are synonyms for
CURTIME()
.
CURRENT_TIMESTAMP
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP
and CURRENT_TIMESTAMP()
are synonyms for
NOW()
.
DATE(expr)
mysql> SELECT DATE('2003-12-31 01:02:03'); -> '2003-12-31'
DATE()
is available as of MySQL 4.1.1.
DATEDIFF(expr,expr2)
DATEDIFF()
returns the number of days between the start date
expr and the end date expr2.
expr and expr2 are date or date-and-time expressions.
Only the date parts of the values are used in the calculation.
mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30'); -> 1 mysql> SELECT DATEDIFF('1997-11-30 23:59:59','1997-12-31'); -> -31
DATEDIFF()
was added in MySQL 4.1.1.
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
DATETIME
or DATE
value specifying the starting
date. expr is an expression specifying the interval value to be added
or subtracted from the starting date. expr is a string; it may start
with a `-' for negative intervals. type is a keyword indicating
how the expression should be interpreted.
The INTERVAL
keyword and the type
specifier are not case
sensitive.
The following table shows how the type and expr arguments
are related:
type Value | Expected expr Format |
MICROSECOND | MICROSECONDS
|
SECOND | SECONDS
|
MINUTE | MINUTES
|
HOUR | HOURS
|
DAY | DAYS
|
WEEK | WEEKS
|
MONTH | MONTHS
|
QUARTER | QUARTERS
|
YEAR | YEARS
|
SECOND_MICROSECOND | 'SECONDS.MICROSECONDS'
|
MINUTE_MICROSECOND | 'MINUTES.MICROSECONDS'
|
MINUTE_SECOND | 'MINUTES:SECONDS'
|
HOUR_MICROSECOND | 'HOURS.MICROSECONDS'
|
HOUR_SECOND | 'HOURS:MINUTES:SECONDS'
|
HOUR_MINUTE | 'HOURS:MINUTES'
|
DAY_MICROSECOND | 'DAYS.MICROSECONDS'
|
DAY_SECOND | 'DAYS HOURS:MINUTES:SECONDS'
|
DAY_MINUTE | 'DAYS HOURS:MINUTES'
|
DAY_HOUR | 'DAYS HOURS'
|
YEAR_MONTH | 'YEARS-MONTHS'
|
DAY_MICROSECOND
, HOUR_MICROSECOND
,
MINUTE_MICROSECOND
, SECOND_MICROSECOND
,
and MICROSECOND
are allowed as of MySQL 4.1.1.
The values QUARTER
and WEEK
are allowed as of MySQL 5.0.0.
MySQL allows any punctuation delimiter in the expr format.
Those shown in the table are the suggested delimiters. If the date
argument is a DATE
value and your calculations involve only
YEAR
, MONTH
, and DAY
parts (that is, no time parts), the
result is a DATE
value. Otherwise, the result is a DATETIME
value.
As of MySQL 3.23, INTERVAL expr type
is allowed on either
side of the +
operator if the expression on the other side is a
date or datetime value.
For the -
operator, INTERVAL expr type
is allowed only on
the right side, because
it makes no sense to subtract a date or datetime value from an interval.
(See examples below.)
mysql> SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND; -> '1998-01-01 00:00:00' mysql> SELECT INTERVAL 1 DAY + '1997-12-31'; -> '1998-01-01' mysql> SELECT '1998-01-01' - INTERVAL 1 SECOND; -> '1997-12-31 23:59:59' mysql> SELECT DATE_ADD('1997-12-31 23:59:59', -> INTERVAL 1 SECOND); -> '1998-01-01 00:00:00' mysql> SELECT DATE_ADD('1997-12-31 23:59:59', -> INTERVAL 1 DAY); -> '1998-01-01 23:59:59' mysql> SELECT DATE_ADD('1997-12-31 23:59:59', -> INTERVAL '1:1' MINUTE_SECOND); -> '1998-01-01 00:01:00' mysql> SELECT DATE_SUB('1998-01-01 00:00:00', -> INTERVAL '1 1:1:1' DAY_SECOND); -> '1997-12-30 22:58:59' mysql> SELECT DATE_ADD('1998-01-01 00:00:00', -> INTERVAL '-1 10' DAY_HOUR); -> '1997-12-30 14:00:00' mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY); -> '1997-12-02' mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002', -> INTERVAL '1.999999' SECOND_MICROSECOND); -> '1993-01-01 00:00:01.000001'If you specify an interval value that is too short (does not include all the interval parts that would be expected from the type keyword), MySQL assumes that you have left out the leftmost parts of the interval value. For example, if you specify a
type
of DAY_SECOND
, the
value of expr is expected to have days, hours, minutes, and seconds
parts. If you specify a value like '1:10'
, MySQL assumes
that the days and hours parts are missing and the value represents minutes
and seconds. In other words, '1:10' DAY_SECOND
is interpreted in such
a way that it is equivalent to '1:10' MINUTE_SECOND
. This is
analogous to the way that MySQL interprets TIME
values
as representing elapsed time rather than as time of day.
If you add to or subtract from a date value something that
contains a time part, the result is automatically converted to a
datetime value:
mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY); -> '1999-01-02' mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR); -> '1999-01-01 01:00:00'If you use really malformed dates, the result is
NULL
. If you add
MONTH
, YEAR_MONTH
, or YEAR
and the resulting date
has a day that is larger than the maximum day for the new month, the day is
adjusted to the maximum days in the new month:
mysql> SELECT DATE_ADD('1998-01-30', INTERVAL 1 MONTH); -> '1998-02-28'
DATE_FORMAT(date,format)
Specifier | Description |
%a | Abbreviated weekday name (Sun ..Sat )
|
%b | Abbreviated month name (Jan ..Dec )
|
%c | Month, numeric (0 ..12 )
|
%D | Day of the month with English suffix (0th , 1st , 2nd , 3rd , ...)
|
%d | Day of the month, numeric (00 ..31 )
|
%e | Day of the month, numeric (0 ..31 )
|
%f | Microseconds (000000 ..999999 )
|
%H | Hour (00 ..23 )
|
%h | Hour (01 ..12 )
|
%I | Hour (01 ..12 )
|
%i | Minutes, numeric (00 ..59 )
|
%j | Day of year (001 ..366 )
|
%k | Hour (0 ..23 )
|
%l | Hour (1 ..12 )
|
%M | Month name (January ..December )
|
%m | Month, numeric (00 ..12 )
|
%p | AM or PM
|
%r | Time, 12-hour (hh:mm:ss followed by AM or PM )
|
%S | Seconds (00 ..59 )
|
%s | Seconds (00 ..59 )
|
%T | Time, 24-hour (hh:mm:ss )
|
%U | Week (00 ..53 ), where Sunday is the first day of the week
|
%u | Week (00 ..53 ), where Monday is the first day of the week
|
%V | Week (01 ..53 ), where Sunday is the first day of the week; used with %X
|
%v | Week (01 ..53 ), where Monday is the first day of the week; used with %x
|
%W | Weekday name (Sunday ..Saturday )
|
%w | Day of the week (0 =Sunday..6 =Saturday)
|
%X | Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
|
%x | Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
|
%Y | Year, numeric, four digits |
%y | Year, numeric, two digits |
%% | A literal `%'. |
%v
, %V
, %x
, and %X
format specifiers are
available as of MySQL 3.23.8. %f
is available as of MySQL 4.1.1.
As of MySQL 3.23, the `%' character is required before
format specifier characters. In earlier versions of MySQL,
`%' was optional.
The reason the ranges for the month and day specifiers begin with zero
is that MySQL allows incomplete dates such as '2004-00-00'
to be
stored as of MySQL 3.23.
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y'); -> 'Saturday October 1997' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%D %y %a %d %m %b %j'); -> '4th 97 Sat 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52'
DAY(date)
DAY()
is a synonym for DAYOFMONTH()
.
It is available as of MySQL 4.1.1.
DAYNAME(date)
mysql> SELECT DAYNAME('1998-02-05'); -> 'Thursday'
DAYOFMONTH(date)
1
to
31
.
mysql> SELECT DAYOFMONTH('1998-02-03'); -> 3
DAYOFWEEK(date)
1
= Sunday, 2
= Monday, ..., 7
=
Saturday). These index values correspond to the ODBC standard.
mysql> SELECT DAYOFWEEK('1998-02-03'); -> 3
DAYOFYEAR(date)
1
to
366
.
mysql> SELECT DAYOFYEAR('1998-02-03'); -> 34
EXTRACT(type FROM date)
EXTRACT()
function uses the same kinds of interval type
specifiers as DATE_ADD()
or DATE_SUB()
, but extracts parts
from the date rather than performing date arithmetic.
mysql> SELECT EXTRACT(YEAR FROM '1999-07-02'); -> 1999 mysql> SELECT EXTRACT(YEAR_MONTH FROM '1999-07-02 01:02:03'); -> 199907 mysql> SELECT EXTRACT(DAY_MINUTE FROM '1999-07-02 01:02:03'); -> 20102 mysql> SELECT EXTRACT(MICROSECOND -> FROM '2003-01-02 10:30:00.00123'); -> 123
EXTRACT()
was added in MySQL 3.23.0.
FROM_DAYS(N)
DATE
value.
mysql> SELECT FROM_DAYS(729669); -> '1997-10-07'
FROM_DAYS()
is not intended for use with values that precede the
advent of the Gregorian calendar (1582), because it does not take into account
the days that were lost when the calendar was changed.
FROM_UNIXTIME(unix_timestamp)
FROM_UNIXTIME(unix_timestamp,format)
'YYYY-MM-DD HH:MM:SS'
or YYYYMMDDHHMMSS
format, depending on
whether the function is used in a string or numeric context.
mysql> SELECT FROM_UNIXTIME(875996580); -> '1997-10-04 22:23:00' mysql> SELECT FROM_UNIXTIME(875996580) + 0; -> 19971004222300If format is given, the result is formatted according to the format string. format may contain the same specifiers as those listed in the entry for the
DATE_FORMAT()
function.
mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(), -> '%Y %D %M %h:%i:%s %x'); -> '2003 6th August 06:22:58 2003'
GET_FORMAT(DATE|TIME|DATETIME, 'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL')
DATE_FORMAT()
and the STR_TO_DATE()
functions.
The three possible values for the first argument
and the five possible values for the second argument result in 15 possible
format strings (for the specifiers used, see the table in the
DATE_FORMAT()
function description).
Function Call | Result |
GET_FORMAT(DATE,'USA') | '%m.%d.%Y'
|
GET_FORMAT(DATE,'JIS') | '%Y-%m-%d'
|
GET_FORMAT(DATE,'ISO') | '%Y-%m-%d'
|
GET_FORMAT(DATE,'EUR') | '%d.%m.%Y'
|
GET_FORMAT(DATE,'INTERNAL') | '%Y%m%d'
|
GET_FORMAT(DATETIME,'USA') | '%Y-%m-%d-%H.%i.%s'
|
GET_FORMAT(DATETIME,'JIS') | '%Y-%m-%d %H:%i:%s'
|
GET_FORMAT(DATETIME,'ISO') | '%Y-%m-%d %H:%i:%s'
|
GET_FORMAT(DATETIME,'EUR') | '%Y-%m-%d-%H.%i.%s'
|
GET_FORMAT(DATETIME,'INTERNAL') | '%Y%m%d%H%i%s'
|
GET_FORMAT(TIME,'USA') | '%h:%i:%s %p'
|
GET_FORMAT(TIME,'JIS') | '%H:%i:%s'
|
GET_FORMAT(TIME,'ISO') | '%H:%i:%s'
|
GET_FORMAT(TIME,'EUR') | '%H.%i.%S'
|
GET_FORMAT(TIME,'INTERNAL') | '%H%i%s'
|
TIMESTAMP
can also be used;
GET_FORMAT()
returns the same values as for DATETIME
.
mysql> SELECT DATE_FORMAT('2003-10-03',GET_FORMAT(DATE,'EUR')); -> '03.10.2003' mysql> SELECT STR_TO_DATE('10.31.2003',GET_FORMAT(DATE,'USA')); -> 2003-10-31
GET_FORMAT()
is available as of MySQL 4.1.1.
See section 13.5.3 SET
Syntax.
HOUR(time)
0
to 23
for time-of-day values.
mysql> SELECT HOUR('10:05:03'); -> 10However, the range of
TIME
values actually is much larger, so
HOUR
can return values greater than 23
.
mysql> SELECT HOUR('272:59:59'); -> 272
LAST_DAY(date)
NULL
if the argument is invalid.
mysql> SELECT LAST_DAY('2003-02-05'); -> '2003-02-28' mysql> SELECT LAST_DAY('2004-02-05'); -> '2004-02-29' mysql> SELECT LAST_DAY('2004-01-01 01:01:01'); -> '2004-01-31' mysql> SELECT LAST_DAY('2003-03-32'); -> NULL
LAST_DAY()
is available as of MySQL 4.1.1.
LOCALTIME
LOCALTIME()
LOCALTIME
and LOCALTIME()
are synonyms for
NOW()
.
They were added in MySQL 4.0.6.
LOCALTIMESTAMP
LOCALTIMESTAMP()
LOCALTIMESTAMP
and LOCALTIMESTAMP()
are synonyms for
NOW()
.
They were added in MySQL 4.0.6.
MAKEDATE(year,dayofyear)
NULL
.
mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32); -> '2001-01-31', '2001-02-01' mysql> SELECT MAKEDATE(2001,365), MAKEDATE(2004,365); -> '2001-12-31', '2004-12-30' mysql> SELECT MAKEDATE(2001,0); -> NULL
MAKEDATE()
is available as of MySQL 4.1.1.
MAKETIME(hour,minute,second)
mysql> SELECT MAKETIME(12,15,30); -> '12:15:30'
MAKETIME()
is available as of MySQL 4.1.1.
MICROSECOND(expr)
0
to 999999
.
mysql> SELECT MICROSECOND('12:00:00.123456'); -> 123456 mysql> SELECT MICROSECOND('1997-12-31 23:59:59.000010'); -> 10
MICROSECOND()
is available as of MySQL 4.1.1.
MINUTE(time)
0
to 59
.
mysql> SELECT MINUTE('98-02-03 10:05:03'); -> 5
MONTH(date)
1
to 12
.
mysql> SELECT MONTH('1998-02-03'); -> 2
MONTHNAME(date)
mysql> SELECT MONTHNAME('1998-02-05'); -> 'February'
NOW()
'YYYY-MM-DD HH:MM:SS'
or YYYYMMDDHHMMSS
format, depending on whether the function is used in
a string or numeric context.
mysql> SELECT NOW(); -> '1997-12-15 23:50:26' mysql> SELECT NOW() + 0; -> 19971215235026
PERIOD_ADD(P,N)
YYMM
or
YYYYMM
). Returns a value in the format YYYYMM
.
Note that the period argument P is not a date value.
mysql> SELECT PERIOD_ADD(9801,2); -> 199803
PERIOD_DIFF(P1,P2)
YYMM
or YYYYMM
.
Note that the period arguments P1 and P2 are not
date values.
mysql> SELECT PERIOD_DIFF(9802,199703); -> 11
QUARTER(date)
1
to 4
.
mysql> SELECT QUARTER('98-04-01'); -> 2
SECOND(time)
0
to 59
.
mysql> SELECT SECOND('10:05:03'); -> 3
SEC_TO_TIME(seconds)
'HH:MM:SS'
or HHMMSS
format, depending on whether
the function is used in a string or numeric context.
mysql> SELECT SEC_TO_TIME(2378); -> '00:39:38' mysql> SELECT SEC_TO_TIME(2378) + 0; -> 3938
STR_TO_DATE(str,format)
DATE_FORMAT()
function. It takes a
string str and a format string format.
STR_TO_DATE()
returns a DATETIME
value if the format
string contains both date and time parts, or a DATE
or TIME
value if the string contains only date or time parts.
The date, time, or datetime values contained in str should be given
in the format indicated by format. For the specifiers that can be
used in format, see the table in the DATE_FORMAT()
function
description. All other characters are just taken verbatim, thus not being
interpreted.
If str contains an illegal date, time, or datetime value,
STR_TO_DATE()
returns NULL
.
mysql> SELECT STR_TO_DATE('03.10.2003 09.20', -> '%d.%m.%Y %H.%i'); -> '2003-10-03 09:20:00' mysql> SELECT STR_TO_DATE('10arp', '%carp'); -> '0000-10-00 00:00:00' mysql> SELECT STR_TO_DATE('2003-15-10 00:00:00', -> '%Y-%m-%d %H:%i:%s'); -> NULLRange checking on the parts of date values is as described in section 11.3.1 The
DATETIME
, DATE
, and TIMESTAMP
Types. This means, for example, that a date with
a day part larger than the number of days in a month is allowable as long
as the day part is in the range from 1 to 31. Also, ``zero'' dates or dates
with part values of 0 are allowed.
mysql> SELECT STR_TO_DATE('00/00/0000', '%m/%d/%Y'); -> '0000-00-00' mysql> SELECT STR_TO_DATE('04/31/2004', '%m/%d/%Y'); -> '2004-04-31'
STR_TO_DATE()
is available as of MySQL 4.1.1.
SUBDATE(date,INTERVAL expr type)
SUBDATE(expr,days)
INTERVAL
form of the second argument,
SUBDATE()
is a synonym for DATE_SUB()
.
For information on the INTERVAL
argument, see the
discussion for DATE_ADD()
.
mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY); -> '1997-12-02' mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY); -> '1997-12-02'As of MySQL 4.1.1, the second syntax is allowed, where expr is a date or datetime expression and days is the number of days to be subtracted from expr.
mysql> SELECT SUBDATE('1998-01-02 12:00:00', 31); -> '1997-12-02 12:00:00'
SUBTIME(expr,expr2)
SUBTIME()
subtracts expr2 from expr and returns the result.
expr is a time or datetime expression, and expr2 is a time
expression.
mysql> SELECT SUBTIME('1997-12-31 23:59:59.999999', -> '1 1:1:1.000002'); -> '1997-12-30 22:58:58.999997' mysql> SELECT SUBTIME('01:00:00.999999', '02:00:00.999998'); -> '-00:59:59.999999'
SUBTIME()
was added in MySQL 4.1.1.
SYSDATE()
SYSDATE()
is a synonym for NOW()
.
TIME(expr)
mysql> SELECT TIME('2003-12-31 01:02:03'); -> '01:02:03' mysql> SELECT TIME('2003-12-31 01:02:03.000123'); -> '01:02:03.000123'
TIME()
is available as of MySQL 4.1.1.
TIMEDIFF(expr,expr2)
TIMEDIFF()
returns the time between the start time
expr and the end time expr2.
expr and expr2 are time or date-and-time expressions, but both
must be of the same type.
mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', -> '2000:01:01 00:00:00.000001'); -> '-00:00:00.000001' mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001', -> '1997-12-30 01:01:01.000002'); -> '46:58:57.999999'
TIMEDIFF()
was added in MySQL 4.1.1.
TIMESTAMP(expr)
TIMESTAMP(expr,expr2)
mysql> SELECT TIMESTAMP('2003-12-31'); -> '2003-12-31 00:00:00' mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00'); -> '2004-01-01 00:00:00'
TIMESTAMP()
is available as of MySQL 4.1.1.
TIMESTAMPADD(interval,int_expr,datetime_expr)
interval
argument, which should be one of the following values:
FRAC_SECOND
,
SECOND
,
MINUTE
,
HOUR
,
DAY
,
WEEK
,
MONTH
,
QUARTER
,
or
YEAR
.
The interval value may be specified using one of keywords as shown,
or with a prefix of SQL_TSI_
. For example, DAY
or
SQL_TSI_DAY
both are legal.
mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02'); -> '2003-01-02 00:01:00' mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02'); -> '2003-01-09'
TIMESTAMPADD()
is available as of MySQL 5.0.0.
TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)
TIMESTAMPADD()
function.
mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01'); -> 3 mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01'); -> -1
TIMESTAMPDIFF()
is available as of MySQL 5.0.0.
TIME_FORMAT(time,format)
DATE_FORMAT()
function, but the
format string may contain only those format specifiers that handle
hours, minutes, and seconds. Other specifiers produce a NULL
value or
0
.
If the time value contains an hour part that is greater than
23
, the %H
and %k
hour format specifiers produce a
value larger than the usual range of 0..23
. The other hour format
specifiers produce the hour value modulo 12.
mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l'); -> '100 100 04 04 4'
TIME_TO_SEC(time)
mysql> SELECT TIME_TO_SEC('22:23:00'); -> 80580 mysql> SELECT TIME_TO_SEC('00:39:38'); -> 2378
TO_DAYS(date)
mysql> SELECT TO_DAYS(950501); -> 728779 mysql> SELECT TO_DAYS('1997-10-07'); -> 729669
TO_DAYS()
is not intended for use with values that precede the advent
of the Gregorian calendar (1582), because it does not take into account the
days that were lost when the calendar was changed.
Remember that MySQL converts two-digit year values in dates to
four-digit form using the rules in section 11.3 Date and Time Types. For example,
'1997-10-07'
and '97-10-07'
are seen as identical dates:
mysql> SELECT TO_DAYS('1997-10-07'), TO_DAYS('97-10-07'); -> 729669, 729669For other dates before 1582, results from this function are undefined.
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
'1970-01-01 00:00:00'
GMT) as an unsigned integer. If
UNIX_TIMESTAMP()
is called with a date argument, it
returns the value of the argument as seconds since '1970-01-01
00:00:00'
GMT. date may be a DATE
string, a
DATETIME
string, a TIMESTAMP
, or a number in the format
YYMMDD
or YYYYMMDD
in local time.
mysql> SELECT UNIX_TIMESTAMP(); -> 882226357 mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00'); -> 875996580When
UNIX_TIMESTAMP
is used on a TIMESTAMP
column, the function
returns the internal timestamp value directly, with no implicit
``string-to-Unix-timestamp'' conversion.
If you pass an out-of-range date to UNIX_TIMESTAMP()
, it
returns 0
, but please note that only basic range checking is performed
(year from 1970
to 2037
, month from 01
to 12
, day
from 01
from 31
).
If you want to subtract UNIX_TIMESTAMP()
columns, you might want to
cast the result to signed integers. See section 12.7 Cast Functions and Operators.
UTC_DATE
UTC_DATE()
'YYYY-MM-DD'
or
YYYYMMDD
format, depending on whether the function is used in a
string or numeric context.
mysql> SELECT UTC_DATE(), UTC_DATE() + 0; -> '2003-08-14', 20030814
UTC_DATE()
is available as of MySQL 4.1.1.
UTC_TIME
UTC_TIME()
'HH:MM:SS'
or HHMMSS
format, depending on whether the function is used in a string or numeric
context.
mysql> SELECT UTC_TIME(), UTC_TIME() + 0; -> '18:07:53', 180753
UTC_TIME()
is available as of MySQL 4.1.1.
UTC_TIMESTAMP
UTC_TIMESTAMP()
'YYYY-MM-DD HH:MM:SS'
or YYYYMMDDHHMMSS
format, depending on whether the function is used in
a string or numeric context.
mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0; -> '2003-08-14 18:08:04', 20030814180804
UTC_TIMESTAMP()
is available as of MySQL 4.1.1.
WEEK(date[,mode])
WEEK()
allows you to specify whether the week starts on Sunday or
Monday and whether the return value should be in the range from 0
to
53
or from 1
to 53
. If the mode argument is
omitted, the value of the default_week_format
system variable is
used (or 0
before MySQL 4.0.14).
See section 5.2.3 Server System Variables.
The following table describes how the mode argument works:
First day | |||
Mode | of week | Range | Week 1 is the first week... |
0 | Sunday | 0-53 | with a Sunday in this year |
1 | Monday | 0-53 | with more than 3 days this year |
2 | Sunday | 1-53 | with a Sunday in this year |
3 | Monday | 1-53 | with more than 3 days this year |
4 | Sunday | 0-53 | with more than 3 days this year |
5 | Monday | 0-53 | with a Monday in this year |
6 | Sunday | 1-53 | with more than 3 days this year |
7 | Monday | 1-53 | with a Monday in this year |
3
can be used as of MySQL 4.0.5.
Values of 4
and above can be used as of MySQL 4.0.17.
mysql> SELECT WEEK('1998-02-20'); -> 7 mysql> SELECT WEEK('1998-02-20',0); -> 7 mysql> SELECT WEEK('1998-02-20',1); -> 8 mysql> SELECT WEEK('1998-12-31',1); -> 53Note: In MySQL 4.0,
WEEK(date,0)
was changed to match the
calendar in the USA. Before that, WEEK()
was calculated incorrectly
for dates in the USA. (In effect, WEEK(date)
and WEEK(date,0)
were
incorrect for all cases.)
Note that if a date falls in the last week of the previous year, MySQL
returns 0
if you don't use 2
, 3
, 6
, or 7
as the optional mode
argument:
mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0); -> 2000, 0One might argue that MySQL should return
52
for the WEEK()
function, because the given date actually occurs in the 52nd week of 1999. We
decided to return 0
instead because we want the function to return ``the week
number in the given year.'' This makes use of the WEEK()
function reliable when combined with other functions that extract a
date part from a date.
If you would prefer the result to be evaluated with respect to the year
that contains the first day of the week for the given date, you should use
0
, 2
, 5
, or 7
as the optional mode
argument.
mysql> SELECT WEEK('2000-01-01',2); -> 52Alternatively, use the
YEARWEEK()
function:
mysql> SELECT YEARWEEK('2000-01-01'); -> 199952 mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2); -> '52'
WEEKDAY(date)
0
= Monday, 1
= Tuesday, ... 6
= Sunday).
mysql> SELECT WEEKDAY('1998-02-03 22:23:00'); -> 1 mysql> SELECT WEEKDAY('1997-11-05'); -> 2
WEEKOFYEAR(date)
1
to 53
. It is a compatibility function
that is equivalent to WEEK(date,3)
.
mysql> SELECT WEEKOFYEAR('1998-02-20'); -> 8
WEEKOFYEAR()
is available as of MySQL 4.1.1.
YEAR(date)
1000
to 9999
.
mysql> SELECT YEAR('98-02-03'); -> 1998
YEARWEEK(date)
YEARWEEK(date,start)
WEEK()
. The year in the
result may be
different from the year in the date argument for the first and the last
week of the year.
mysql> SELECT YEARWEEK('1987-01-01'); -> 198653Note that the week number is different from what the
WEEK()
function would return (0
) for optional arguments 0
or 1
,
as WEEK()
then returns the week in the context of the given year.
YEARWEEK()
was added in MySQL 3.23.8.
MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION])
FULLTEXT
. FULLTEXT
indexes are used with MyISAM
tables
only and can be created from CHAR
, VARCHAR
,
or TEXT
columns at CREATE TABLE
time or added later with
ALTER TABLE
or CREATE INDEX
. For large datasets, it will be
much faster to load your data into a table that has no FULLTEXT
index, then create the index with ALTER TABLE
(or
CREATE INDEX
). Loading data into a table that has an existing
FULLTEXT
index could be significantly slower.
Constraints on full-text searching are listed in section 12.6.3 Full-Text Restrictions.
Full-text searching is performed with the MATCH()
function.
mysql> CREATE TABLE articles ( -> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, -> title VARCHAR(200), -> body TEXT, -> FULLTEXT (title,body) -> ); Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO articles (title,body) VALUES -> ('MySQL Tutorial','DBMS stands for DataBase ...'), -> ('How To Use MySQL Well','After you went through a ...'), -> ('Optimizing MySQL','In this tutorial we will show ...'), -> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), -> ('MySQL vs. YourSQL','In the following database comparison ...'), -> ('MySQL Security','When configured properly, MySQL ...'); Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('database'); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec)
The MATCH()
function performs a natural language search for a string
against a text collection. A collection is a set of one or more columns
included in a FULLTEXT
index. The search string is given as the
argument to AGAINST()
.
For every row in the table, MATCH()
returns a relevance
value, that is, a similarity measure between the search string and the text
in that row in the columns named in the MATCH()
list.
By default, the search is performed in case-insensitive fashion. In MySQL
4.1 and up, you can make a full-text search by using a binary collation for
the indexed columns. For example, a column that has a character set of
latin1
can be assigned a collation of latin1_bin
to make it
case sensitive for full-text searches.
When MATCH()
is used in a WHERE
clause, as in the preceding
example,
the rows returned are automatically sorted with the highest relevance first.
Relevance values are non-negative floating-point numbers. Zero relevance
means no similarity. Relevance is computed based on the number of words
in the row, the number of unique words in that row, the total number of
words in the collection, and the number of documents (rows) that contain
a particular word.
For natural-language full-text searches, it is a requirement that the
columns named in the MATCH()
function be the same columns included in
some FULLTEXT
index in your table. For the preceding query, note
that the columns named in the MATCH()
function (title
and
body
) are the same as those named in the definition of the
article
table's FULLTEXT
index. If you wanted to search the
title
or body
separately, you would need to create
FULLTEXT
indexes for each column.
It is also possible to perform a boolean search or a search with query expansion. These search types are described in section 12.6.1 Boolean Full-Text Searches and section 12.6.2 Full-Text Searches with Query Expansion.
The preceding example is a basic illustration showing how to use the
MATCH()
function where rows are returned in order of decreasing
relevance. The next example shows how to retrieve the relevance values
explicitly. Returned rows are not ordered because the SELECT
statement includes neither WHERE
nor ORDER BY
clauses:
mysql> SELECT id, MATCH (title,body) AGAINST ('Tutorial') -> FROM articles; +----+-----------------------------------------+ | id | MATCH (title,body) AGAINST ('Tutorial') | +----+-----------------------------------------+ | 1 | 0.65545833110809 | | 2 | 0 | | 3 | 0.66266459226608 | | 4 | 0 | | 5 | 0 | | 6 | 0 | +----+-----------------------------------------+ 6 rows in set (0.00 sec)
The following example is more complex. The query returns the relevance values
and it also sorts the rows in order of decreasing relevance. To achieve
this result, you should specify MATCH()
twice: once in the
SELECT
list and once in the WHERE
clause. This causes no
additional overhead, because the MySQL optimizer notices that the
two MATCH()
calls are identical and invokes the full-text search
code only once.
mysql> SELECT id, body, MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root') AS score -> FROM articles WHERE MATCH (title,body) AGAINST -> ('Security implications of running MySQL as root'); +----+-------------------------------------+-----------------+ | id | body | score | +----+-------------------------------------+-----------------+ | 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 | | 6 | When configured properly, MySQL ... | 1.3114095926285 | +----+-------------------------------------+-----------------+ 2 rows in set (0.00 sec)
MySQL uses a very simple parser to split text into words. A ``word'' is any
sequence of true word characters (letters, digits, and underscores),
optionally separated by no more than one sequential `'' character.
For example, wasn't
is parsed as a single word, but wasn''t
is parsed as two words wasn
and t
. (And then t
would
be ignored as too short according to the rules following.) Also, single
quotes at the ends of words are stripped; only embedded single quotes
are retained.
Some words are ignored in full-text searches:
The default minimum word length and stopword list can be changed as described in section 12.6.4 Fine-Tuning MySQL Full-Text Search.
Every correct word in the collection and in the query is weighted according to its significance in the collection or query. This way, a word that is present in many documents has a lower weight (and may even have a zero weight), because it has lower semantic value in this particular collection. Conversely, if the word is rare, it receives a higher weight. The weights of the words are then combined to compute the relevance of the row.
Such a technique works best with large collections (in fact, it was
carefully tuned this way). For very small tables, word distribution
does not adequately reflect their semantic value, and this model
may sometimes produce bizarre results. For example, although the word
``MySQL'' is present in every row of the articles
table, a search for
the word produces no results:
mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('MySQL'); Empty set (0.00 sec)
The search result is empty because the word ``MySQL'' is present in at least 50% of the rows. As such, it is effectively treated as a stopword. For large datasets, this is the most desirable behavior--a natural language query should not return every second row from a 1GB table. For small datasets, it may be less desirable.
A word that matches half of rows in a table is less likely to locate relevant documents. In fact, it will most likely find plenty of irrelevant documents. We all know this happens far too often when we are trying to find something on the Internet with a search engine. It is with this reasoning that rows containing the word are assigned a low semantic value for the particular dataset in which they occur. A given word may exceed the 50% threshold in one dataset but not another.
The 50% threshold has a significant implication when you first try full-text searching to see how it works: If you create a table and insert only one or two rows of text into it, every word in the text occurs in at least 50% of the rows. As a result, no search returns any results. Be sure to insert at least three rows, and preferably many more.
As of Version 4.0.1, MySQL can also perform boolean full-text searches using
the IN BOOLEAN MODE
modifier.
mysql> SELECT * FROM articles WHERE MATCH (title,body) -> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE); +----+-----------------------+-------------------------------------+ | id | title | body | +----+-----------------------+-------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 2 | How To Use MySQL Well | After you went through a ... | | 3 | Optimizing MySQL | In this tutorial we will show ... | | 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | | 6 | MySQL Security | When configured properly, MySQL ... | +----+-----------------------+-------------------------------------+
This query retrieves all the rows that contain the word ``MySQL'' but that do not contain the word ``YourSQL''.
Boolean full-text searches have these characteristics:
FULLTEXT
index, although this would be
slow.
The boolean full-text search capability supports the following operators:
+
-
(no operator)
+
nor -
is specified) the word is optional,
but the rows that contain it will be rated higher. This mimics the
behavior of MATCH() ... AGAINST()
without the IN BOOLEAN
MODE
modifier.
> <
>
operator
increases the contribution and the <
operator decreases it.
See the example below.
( )
~
-
operator.
*
"
The following examples demonstrate some search strings that use boolean full-text operators:
'apple banana'
'+apple +juice'
'+apple macintosh'
'+apple -macintosh'
'+apple +(>turnover <strudel)'
'apple*'
'"some words"'
FULLTEXT
index for the words, and then performs a substring search
for the phrase in the records that are found. If the phrase contains no
words that are in the index, the result will be empty. For example, if all
words are either stopwords or shorter than the minimum length of indexed
words, the result will be empty.
As of MySQL 4.1.1, full-text search supports query expansion (in particular, its variant ``blind query expansion''). This is generally useful when a search phrase is too short, which often means that the user is relying on implied knowledge that the full-text search engine usually lacks. For example, a user searching for ``database'' may really mean that ``MySQL'', ``Oracle'', ``DB2'', and ``RDBMS'' all are phrases that should match ``databases'' and should be returned, too. This is implied knowledge.
Blind query expansion (also known as automatic relevance feedback) is
enabled by adding WITH QUERY EXPANSION
following the search phrase.
It works by performing the search twice, where the search phrase for the
second search is the original search phrase concatenated with the few top
found documents from the first search. Thus, if one of these documents
contains the word ``databases'' and the word ``MySQL'', the second search
will find the documents that contain the word ``MySQL'' even if they do not
contain the word ``database''. The following example shows this difference:
mysql> SELECT * FROM articles -> WHERE MATCH (title,body) AGAINST ('database'); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 1 | MySQL Tutorial | DBMS stands for DataBase ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec) mysql> SELECT * FROM articles -> WHERE MATCH (title,body) -> AGAINST ('database' WITH QUERY EXPANSION); +----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 5 | MySQL vs. YourSQL | In the following database comparison ... | | 3 | Optimizing MySQL | In this tutorial we will show ... | +----+-------------------+------------------------------------------+ 3 rows in set (0.00 sec)
Another example could be searching for books by Georges Simenon about Maigret, when a user is not sure how to spell ``Maigret''. A search for ``Megre and the reluctant witnesses'' will find only ``Maigret and the Reluctant Witnesses'' without query expansion. A search with query expansion will find all books with the word ``Maigret'' on the second pass.
Note: Because blind query expansion tends to increase noise significantly by returning non-relevant documents, it's only meaningful to use when a search phrase is rather short.
MyISAM
tables only.
utf8
character
set can be used, but not the ucs2
character set.
FULLTEXT
index must have
the same character set and collation.
MATCH()
column list must exactly match the column list in some
FULLTEXT
index definition for the table, unless this MATCH()
is IN BOOLEAN MODE
.
AGAINST()
must be a constant string.
The MySQL full-text search capability has few user-tunable parameters yet, although adding more is very high on the TODO. You can exert more control over full-text searching behavior if you have a MySQL source distribution because some changes require source code modfications. See section 2.8 MySQL Installation Using a Source Distribution.
Note that full-text search was carefully tuned for the best searching effectiveness. Modifying the default behavior will, in most cases, make the search results worse. Do not alter the MySQL sources unless you know what you are doing!
Most full-text variables described in the following items must be set at server startup time. For these variables, a server restart is required to change them and you cannot modify them dynamically while the server is running.
Some variable changes require that you rebuild the FULLTEXT
indexes
in your tables. Instructions for doing this are given at the end of this
section.
ft_min_word_len
and ft_max_word_len
system variables
(available as of MySQL 4.0.0).
See section 5.2.3 Server System Variables.
The default minimum value is four characters. The default maximum depends
on your version of MySQL. If you change either value, you must rebuild your
FULLTEXT
indexes. For example, if you want three-character words to
be searchable, you can set the ft_min_word_len
variable by putting
the following lines in an option file:
[mysqld] ft_min_word_len=3Then restart the server and rebuild your
FULLTEXT
indexes.
Also note particularly the remarks regarding myisamchk
in the
instructions following this list.
ft_stopword_file
system variable (available as of MySQL 4.0.10).
See section 5.2.3 Server System Variables.
The variable value should be the pathname of the file containing the stopword
list, or the empty string to disable stopword filtering. After changing the value, rebuild your FULLTEXT
indexes.
#define GWS_IN_USE GWS_PROBChange the line to this:
#define GWS_IN_USE GWS_FREQThen recompile MySQL. There is no need to rebuild the indexes in this case. Note: By doing this you severely decrease MySQL's ability to provide adequate relevance values for the
MATCH()
function.
If you really need to search for such common words, it would be better to
search using IN BOOLEAN MODE
instead, which does not observe the 50%
threshold.
ft_boolean_syntax
system variable (available as of MySQL 4.0.1). The
variable also can be changed while the server is running, but you must have
the SUPER
privilege to do so.
No index rebuilding is necessary.
section 5.2.3 Server System Variables describes the rules that define how to set this
variable.
If you modify full-text variables that affect indexing
(ft_min_word_len
, ft_max_word_len
, or
ft_stopword_file
), you must rebuild your FULLTEXT
indexes
after making the changes and restarting the server. To rebuild the indexes
in this case, it's sufficient to do a QUICK
repair operation:
mysql> REPAIR TABLE tbl_name QUICK;
With regard specifically to using the IN BOOLEAN MODE
capability, if
you upgrade from MySQL 3.23 to 4.0 or later, it's necessary to replace the
index header as well. To do this, do a USE_FRM
repair operation:
mysql> REPAIR TABLE tbl_name USE_FRM;
This is necessary because boolean full-text searches require a flag in the
index header that was not present in MySQL 3.23, and that is not added if
you do only a QUICK
repair. If you attempt a boolean full-text
search without rebuilding the indexes this way, the search will return
incorrect results.
Note that if you use myisamchk
to perform an operation that modifies
table indexes (such as repair or analyze), the FULLTEXT
indexes
are rebuilt using the default full-text parameter values for minimum and
maximum word length and the stopword file unless you specify otherwise.
This can result in queries failing.
The problem occurs because these parameters are known only by the server.
They are not stored in MyISAM
index files. To avoid the problem if
you have modified the minimum or maximum word length or the stopword file in
the server, specify the same ft_min_word_len
, ft_max_word_len
,
and ft_stopword_file
values to myisamchk
that you use for
mysqld
. For example, if you have set the minimum word length to 3,
you can repair a table with myisamchk
like this:
shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI
To ensure that myisamchk
and the server use the same values for
full-text parameters, you can place each one in both the [mysqld]
and [myisamchk]
sections of an option file:
[mysqld] ft_min_word_len=3 [myisamchk] ft_min_word_len=3
An alternative to using myisamchk
is to use the REPAIR TABLE
,
ANALYZE TABLE
, OPTIMIZE TABLE
, or ALTER TABLE
.
These statements are performed by the server, which knows the proper
full-text parameter values to use.
FULLTEXT
operations.
MERGE
tables.
ucs2
character set.
FULLTEXT
in CREATE TABLE
and ALTER TABLE
statements).
BINARY
BINARY
operator casts the string following it to a binary string.
This is an easy way to force a column comparison to be done byte by byte
rather than character by character. This causes the comparison to be
case sensitive even
if the column isn't defined as BINARY
or BLOB
.
BINARY
also causes trailing spaces to be significant.
mysql> SELECT 'a' = 'A'; -> 1 mysql> SELECT BINARY 'a' = 'A'; -> 0 mysql> SELECT 'a' = 'a '; -> 1 mysql> SELECT BINARY 'a' = 'a '; -> 0
BINARY
affects the entire comparison; it can be given before
either operand with the same result.
BINARY
was added in MySQL 3.23.0. As of MySQL 4.0.2,
BINARY str
is a shorthand for CAST(str AS BINARY)
.
Note that in some contexts, if you cast an indexed column to BINARY
,
MySQL will not be able to use the index efficiently.
If you want to compare a BLOB
value or other binary string
in case-insensitive fashion, you can do so as follows:
UPPER()
function to convert the binary
string to uppercase before performing the comparison:
SELECT 'A' LIKE UPPER(blob_col) FROM tbl_name;If the comparison value is lowercase, convert the string value using
LOWER()
instead.
CONVERT()
function to
convert the string value to a character set that
is not case sensitive. The result is a non-binary string, so the
LIKE
operation is not case sensitive:
SELECT 'A' LIKE CONVERT(blob_col USING latin1) FROM tbl_name;To use a different character set, substitute its name for
latin1
in the preceding statement.
CONVERT()
can be used more generally for comparing strings that
are represented in different character sets.
CAST(expr AS type)
CONVERT(expr,type)
CONVERT(expr USING transcoding_name)
CAST()
and CONVERT()
functions can be used to take a
value of one type and produce a value of another type.
The type can be one of the following values:
BINARY
CHAR
DATE
DATETIME
SIGNED [INTEGER]
TIME
UNSIGNED [INTEGER]
BINARY
produces a binary string. See the entry for the BINARY
operator in this section for a description of how this affects comparisons.
CAST()
and CONVERT()
are available as of MySQL 4.0.2.
The CHAR
conversion type is available as of 4.0.6.
The USING
form of CONVERT()
is available as of 4.1.0.
CAST()
and CONVERT(... USING ...)
are standard SQL syntax.
The non-USING
form of CONVERT()
is ODBC syntax.
CONVERT()
with USING
is used to convert data between different
character sets. In MySQL, transcoding names are the same as the
corresponding character set names. For example, this statement converts
the string 'abc'
in the server's default character set to the
corresponding string in the utf8
character set:
SELECT CONVERT('abc' USING utf8);
The cast functions are useful when you want to create a column with
a specific type in a CREATE ... SELECT
statement:
CREATE TABLE new_table SELECT CAST('2000-01-01' AS DATE);
The functions also can be useful for sorting ENUM
columns in lexical
order. Normally sorting of ENUM
columns occurs using the internal
numeric values. Casting the values to CHAR
results in a lexical
sort:
SELECT enum_col FROM tbl_name ORDER BY CAST(enum_col AS CHAR);
CAST(str AS BINARY)
is the same thing as BINARY str
.
CAST(expr AS CHAR)
treats the expression as a string with the
default character set.
Note: In MySQL 4.0, a CAST()
to DATE
,
DATETIME
, or TIME
only marks the column to be a specific
type but doesn't change the value of the column.
As of MySQL 4.1.0, the value is converted to the correct column type when it's sent to the user (this is a feature of how the new protocol in 4.1 sends date information to the client):
mysql> SELECT CAST(NOW() AS DATE); -> 2003-05-26
As of MySQL 4.1.1, CAST()
also changes the result if you use it as part of a more complex expression
such as CONCAT('Date: ',CAST(NOW() AS DATE))
.
You should not use CAST()
to extract data in different formats but
instead use string functions like LEFT()
or
EXTRACT()
. See section 12.5 Date and Time Functions.
To cast a string to a numeric value in numeric context, you don't normally have to do anything. Just use the string value as though it were a number:
mysql> SELECT 1+'1'; -> 2
If you use a number in string context, the number automatically is
converted to a BINARY
string.
mysql> SELECT CONCAT('hello you ',2); -> 'hello you 2'
MySQL supports arithmetic with both signed and unsigned 64-bit values.
If you are using numeric operators (such as +
) and one of the
operands is an unsigned integer, the result is unsigned.
You can override this by using the SIGNED
and UNSIGNED
cast operators to cast the operation to a signed or
unsigned 64-bit integer, respectively.
mysql> SELECT CAST(1-2 AS UNSIGNED) -> 18446744073709551615 mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED); -> -1
Note that if either operand is a floating-point value, the result is
a floating-point value and is not affected by the preceding rule.
(In this context, DECIMAL
column values are regarded as
floating-point values.)
mysql> SELECT CAST(1 AS UNSIGNED) - 2.0; -> -1.0
If you are using a string in an arithmetic operation, this is converted to a floating-point number.
The handing of unsigned values was changed in MySQL 4.0 to be able to
support BIGINT
values properly. If you have some code that you
want to run in both MySQL 4.0 and 3.23, you probably can't
use the CAST()
function. You can use the following technique to get
a signed result when subtracting two unsigned integer columns ucol1
and
ucol2
:
mysql> SELECT (ucol1+0.0)-(ucol2+0.0) FROM ...;
The idea is that the columns are converted to floating-point values before the subtraction occurs.
If you have a problem with UNSIGNED
columns in old MySQL
applications when porting them to MySQL 4.0, you can use the
--sql-mode=NO_UNSIGNED_SUBTRACTION
option when starting
mysqld
. However, as long as you use this option, you will not
be able to make efficient use of the BIGINT UNSIGNED
column type.
MySQL uses BIGINT
(64-bit) arithmetic for bit operations, so
these operators have a maximum range of 64 bits.
|
mysql> SELECT 29 | 15; -> 31The result is an unsigned 64-bit integer.
&
mysql> SELECT 29 & 15; -> 13The result is an unsigned 64-bit integer.
^
mysql> SELECT 1 ^ 1; -> 0 mysql> SELECT 1 ^ 0; -> 1 mysql> SELECT 11 ^ 3; -> 8The result is an unsigned 64-bit integer. Bitwise XOR was added in MySQL 4.0.2. Shifts a longlong (
BIGINT
) number to the left.
<<
mysql> SELECT 1 << 2; -> 4The result is an unsigned 64-bit integer.
>>
BIGINT
) number to the right.
mysql> SELECT 4 >> 2; -> 1The result is an unsigned 64-bit integer.
~
mysql> SELECT 5 & ~1; -> 4The result is an unsigned 64-bit integer.
BIT_COUNT(N)
mysql> SELECT BIT_COUNT(29); -> 4
The functions in this section encrypt and decrypt data values.
If you want to store results from an encryption function that might contain
arbitrary byte values, use a BLOB
column rather than a CHAR
or VARCHAR
column to avoid potential problems with trailing
space removal that would change data values.
AES_ENCRYPT(str,key_str)
AES_DECRYPT(crypt_str,key_str)
NULL
,
the result of this function is also NULL
.
Because AES is a block-level algorithm, padding is used to encode uneven length
strings and so the result string length may be calculated as
16*(trunc(string_length/16)+1)
.
If AES_DECRYPT()
detects invalid data or incorrect padding, it
returns NULL
. However, it is possible for AES_DECRYPT()
to return a non-NULL
value (possibly garbage) if the input data or
the key is invalid.
You can use the AES functions to store data in an encrypted form by
modifying your queries:
INSERT INTO t VALUES (1,AES_ENCRYPT('text','password'));You can get even more security by not transferring the key over the connection for each query, which can be accomplished by storing it in a server-side variable at connection time. For example:
SELECT @password:='my password'; INSERT INTO t VALUES (1,AES_ENCRYPT('text',@password));
AES_ENCRYPT()
and AES_DECRYPT()
were added in MySQL 4.0.2,
and can be considered the most cryptographically secure encryption
functions currently available in MySQL.
DECODE(crypt_str,pass_str)
ENCODE()
.
ENCODE(str,pass_str)
DECODE()
.
The result is a binary string of the same length as str.
If you want to save it in a column, use a BLOB
column type.
DES_DECRYPT(crypt_str[,key_str])
DES_ENCRYPT()
.
On error, this function returns NULL
.
Note that this function works only if MySQL has been configured with
SSL support. See section 5.6.7 Using Secure Connections.
If no key_str argument is given, DES_DECRYPT()
examines
the first byte of the encrypted string to determine the DES key number
that was used to encrypt the original string, and then reads the key
from the DES key file to decrypt the message. For this to work,
the user must have the SUPER
privilege. The key file can be specified
with the --des-key-file
server option.
If you pass this function a key_str argument, that string
is used as the key for decrypting the message.
If the crypt_str argument doesn't look like an encrypted string,
MySQL will return the given crypt_str.
DES_DECRYPT()
was added in MySQL 4.0.1.
DES_ENCRYPT(str[,(key_num|key_str)])
NULL
.
Note that this function works only if MySQL has been configured with
SSL support. See section 5.6.7 Using Secure Connections.
The encryption key to use is chosen based on the second argument to
DES_ENCRYPT()
, if one was given:
Argument | Description |
No argument | The first key from the DES key file is used. |
key_num | The given key number (0-9) from the DES key file is used. |
key_str | The given key string is used to encrypt str. |
--des-key-file
server option.
The return string is a binary string where the first character
is CHAR(128 | key_num)
.
The 128 is added to make it easier to recognize an encrypted key.
If you use a string key, key_num will be 127.
The string length for the result will be
new_len = orig_len + (8-(orig_len % 8))+1
.
Each line in the DES key file has the following format:
key_num des_key_strEach key_num must be a number in the range from
0
to 9
. Lines in
the file may be in any order. des_key_str is the string that
will be used to encrypt the message. Between the number and the key there
should be at least one space. The first key is the default key that is
used if you don't specify any key argument to DES_ENCRYPT()
You can tell MySQL to read new key values from the key file with the
FLUSH DES_KEY_FILE
statement. This requires the RELOAD
privilege.
One benefit of having a set of default keys is that it gives applications
a way to check for the existence of encrypted column values, without giving
the end user the right to decrypt those values.
mysql> SELECT customer_address FROM customer_table WHERE crypted_credit_card = DES_ENCRYPT('credit_card_number');
DES_ENCRYPT()
was added in MySQL 4.0.1.
ENCRYPT(str[,salt])
crypt()
system call. The
salt argument should be a string with two characters.
(As of MySQL 3.22.16, salt may be longer than two characters.)
If no salt argument is given, a random value is used.
mysql> SELECT ENCRYPT('hello'); -> 'VxuFAJXVARROc'
ENCRYPT()
ignores all but the first eight characters of str, at
least on some systems. This behavior is determined by the implementation
of the underlying crypt()
system call.
If crypt()
is not available on your system, ENCRYPT()
always
returns NULL
. Because of this, we recommend that you use MD5()
or SHA1()
instead, because those two functions exist on all platforms.
MD5(str)
NULL
if the argument was NULL
.
The return value can, for example, be used as a hash key.
mysql> SELECT MD5('testing'); -> 'ae2b1fca515949e5d54fb22b8ed95575'This is the "RSA Data Security, Inc. MD5 Message-Digest Algorithm." If you want to convert the value to uppercase, see the description of binary string conversion given in the entry for the
BINARY
operator in
section 12.7 Cast Functions and Operators.
MD5()
was added in MySQL 3.23.2.
OLD_PASSWORD(str)
OLD_PASSWORD()
is available as of MySQL 4.1, when the implementation of
PASSWORD()
was changed to improve security. OLD_PASSWORD()
returns the value of the pre-4.1 implementation of PASSWORD()
.
section 5.5.9 Password Hashing in MySQL 4.1.
PASSWORD(str)
NULL
if the argument was NULL
. This is
the function that is used for encrypting MySQL passwords for storage
in the Password
column of the user
grant table.
mysql> SELECT PASSWORD('badpwd'); -> '7f84554057dd964b'
PASSWORD()
encryption is one-way (not reversible).
PASSWORD()
does not perform password encryption in the same way that
Unix passwords are encrypted. See ENCRYPT()
.
Note:
The PASSWORD()
function is used by the authentication system in
MySQL Server, you should not use it in your own applications.
For that purpose, use MD5()
or SHA1()
instead.
Also see RFC 2195 for more information about handling passwords
and authentication securely in your application.
SHA1(str)
SHA(str)
NULL
if the argument was NULL
.
One of the possible uses for this function is as a hash key. You can
also use it as a cryptographically safe function for storing passwords.
mysql> SELECT SHA1('abc'); -> 'a9993e364706816aba3e25717850c26c9cd0d89d'
SHA1()
was added in MySQL 4.0.2, and can be considered
a cryptographically more secure equivalent of MD5()
.
SHA()
is synonym for SHA1()
.
BENCHMARK(count,expr)
BENCHMARK()
function executes the expression expr
repeatedly count times. It may be used to time how fast MySQL
processes the expression. The result value is always 0
. The intended
use is from within the mysql
client, which reports query execution times:
mysql> SELECT BENCHMARK(1000000,ENCODE('hello','goodbye')); +----------------------------------------------+ | BENCHMARK(1000000,ENCODE('hello','goodbye')) | +----------------------------------------------+ | 0 | +----------------------------------------------+ 1 row in set (4.74 sec)The time reported is elapsed time on the client end, not CPU time on the server end. It is advisable to execute
BENCHMARK()
several
times, and to interpret the result with regard to how heavily loaded the
server machine is.
CHARSET(str)
mysql> SELECT CHARSET('abc'); -> 'latin1' mysql> SELECT CHARSET(CONVERT('abc' USING utf8)); -> 'utf8' mysql> SELECT CHARSET(USER()); -> 'utf8'
CHARSET()
was added in MySQL 4.1.0.
COERCIBILITY(str)
mysql> SELECT COERCIBILITY('abc' COLLATE latin1_swedish_ci); -> 0 mysql> SELECT COERCIBILITY('abc'); -> 3 mysql> SELECT COERCIBILITY(USER()); -> 2The return values have the following meanings:
Coercibility | Meaning |
0 | Explicit collation |
1 | No collation |
2 | Implicit collation |
3 | Coercible |
COERCIBILITY()
was added in MySQL 4.1.1.
COLLATION(str)
mysql> SELECT COLLATION('abc'); -> 'latin1_swedish_ci' mysql> SELECT COLLATION(_utf8'abc'); -> 'utf8_general_ci'
COLLATION()
was added in MySQL 4.1.0.
CONNECTION_ID()
mysql> SELECT CONNECTION_ID(); -> 23786
CONNECTION_ID()
was added in MySQL 3.23.14.
CURRENT_USER()
USER()
.
mysql> SELECT USER(); -> 'davida@localhost' mysql> SELECT * FROM mysql.user; ERROR 1044: Access denied for user ''@'localhost' to database 'mysql' mysql> SELECT CURRENT_USER(); -> '@localhost'The example illustrates that although the client specified a username of
davida
(as indicated by the value of the USER()
function),
the server authenticated the client using an anonymous user account (as seen by
the empty username part of the CURRENT_USER()
value). One way this might
occur is that there is no account listed in the grant tables for
davida
.
CURRENT_USER()
was added in MySQL 4.0.6.
DATABASE()
mysql> SELECT DATABASE(); -> 'test'If there is no default database,
DATABASE()
returns NULL
as
of MySQL 4.1.1, and the empty string before that.
FOUND_ROWS()
SELECT
statement may include a LIMIT
clause to restrict the
number of rows the server returns to the client.
In some cases, it is desirable to know how many rows the statement would have
returned without the LIMIT
, but without running the statement again.
To get this row count, include a SQL_CALC_FOUND_ROWS
option in the
SELECT
statement, then invoke FOUND_ROWS()
afterward:
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name -> WHERE id > 100 LIMIT 10; mysql> SELECT FOUND_ROWS();The second
SELECT
will return a number indicating how many rows the
first SELECT
would have returned had it been written without the
LIMIT
clause.
(If the preceding SELECT
statement does not include the
SQL_CALC_FOUND_ROWS
option, then FOUND_ROWS()
may return
a different result when LIMIT
is used than when it is not.)
Note that if you are using SELECT SQL_CALC_FOUND_ROWS
, MySQL must
calculate how many rows are in the full result set. However, this is
faster than running the query again without LIMIT
, because the result
set need not be sent to the client.
SQL_CALC_FOUND_ROWS
and FOUND_ROWS()
can be useful in situations
when you want to restrict the number of rows that a query returns, but also
determine the number of rows in the full result set without running the query
again. An example is a Web script that presents a paged display containing
links to the pages that show other sections of a search result. Using
FOUND_ROWS()
allows you to determine how many other pages are needed
for the rest of the result.
The use of SQL_CALC_FOUND_ROWS
and FOUND_ROWS()
is more complex
for UNION
queries than for simple SELECT
statements, because
LIMIT
may occur at multiple places in a UNION
. It may be applied
to individual SELECT
statements in the UNION
, or global to the
UNION
result as a whole.
The intent of SQL_CALC_FOUND_ROWS
for UNION
is that it should
return the row count that would be returned without a global LIMIT
.
The conditions for use of SQL_CALC_FOUND_ROWS
with UNION
are:
SQL_CALC_FOUND_ROWS
keyword must appear in the first SELECT
of the UNION
.
FOUND_ROWS()
is exact only if UNION ALL
is used.
If UNION
without ALL
is used, duplicate removal occurs and the
value of FOUND_ROWS()
is only approximate.
LIMIT
is present in the UNION
, SQL_CALC_FOUND_ROWS
is ignored and returns the number of rows in the temporary table that is
created to process the UNION
.
SQL_CALC_FOUND_ROWS
and FOUND_ROWS()
are available starting
at MySQL 4.0.0.
LAST_INSERT_ID()
LAST_INSERT_ID(expr)
AUTO_INCREMENT
column.
mysql> SELECT LAST_INSERT_ID(); -> 195The last ID that was generated is maintained in the server on a per-connection basis. This means the value the function returns to a given client is the most recent
AUTO_INCREMENT
value generated by that
client. The value cannot be affected by other clients, even if they generate
AUTO_INCREMENT
values of their own. This behavior ensures that you can
retrieve your own ID without concern for the activity of other clients, and
without the need for locks or transactions.
The value of LAST_INSERT_ID()
is not changed if you
update the AUTO_INCREMENT
column of a row with a
non-magic value (that is, a value that is not NULL
and not 0
).
If you insert many rows at the same time with an insert statement,
LAST_INSERT_ID()
returns the value for the first inserted row.
The reason for this is to make it possible to easily reproduce
the same INSERT
statement against some other server.
If you use INSERT IGNORE
and the record is ignored, the
AUTO_INCREMENT
counter still is incremented and
LAST_INSERT_ID()
returns the new value.
If expr is given as an argument to LAST_INSERT_ID()
,
the value of the argument is returned by the function and is remembered as the
next value to be returned by LAST_INSERT_ID()
. This can be used
to simulate sequences:
mysql> CREATE TABLE sequence (id INT NOT NULL); mysql> INSERT INTO sequence VALUES (0);
mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1); mysql> SELECT LAST_INSERT_ID();The
UPDATE
statement increments the sequence counter and causes the
next call to LAST_INSERT_ID()
to return the updated value.
The SELECT
statement retrieves that value.
The mysql_insert_id()
C API function
can also be used to get the value.
See section 22.2.3.33 mysql_insert_id()
.
LAST_INSERT_ID()
, but the
utility of using the function this way is that the ID value is maintained in
the server as the last automatically generated value.
It is multi-user safe because multiple clients can issue the UPDATE
statement and get their own sequence value with the SELECT
statement
(or mysql_insert_id()
), without affecting or being affected by other
clients that generate their own sequence values.
Note that mysql_insert_id()
is only updated after INSERT
and UPDATE
statements, so you cannot use the C API function to
retrieve the value for LAST_INSERT_ID(expr)
after executing other
SQL statements like SELECT
or SET
.
ROW_COUNT()
ROW_COUNT()
returns the number of rows updated, inserted, or deleted
by the preceding statement. This is the same as the row count that the
mysql
client displays and the value from the
mysql_affected_rows()
C API function.
mysql> INSERT INTO t VALUES(1),(2),(3); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT ROW_COUNT(); +-------------+ | ROW_COUNT() | +-------------+ | 3 | +-------------+ 1 row in set (0.00 sec) mysql> DELETE FROM t WHERE i IN(1,2); Query OK, 2 rows affected (0.00 sec) mysql> SELECT ROW_COUNT(); +-------------+ | ROW_COUNT() | +-------------+ | 2 | +-------------+ 1 row in set (0.00 sec)
ROW_COUNT()
was added in MySQL 5.0.1.
SESSION_USER()
SESSION_USER()
is a synonym for USER()
.
SYSTEM_USER()
SYSTEM_USER()
is a synonym for USER()
.
USER()
mysql> SELECT USER(); -> 'davida@localhost'The value indicates the username you specified when connecting to the server, and the client host from which you connected. The value can be different than that of
CURRENT_USER()
.
Prior to MySQL 3.22.11, the function value does not include the client
hostname. You can extract just the username part, regardless of whether the
value includes a hostname part, like this:
mysql> SELECT SUBSTRING_INDEX(USER(),'@',1); -> 'davida'As of MySQL 4.1,
USER()
returns a value in the utf8
character
set, so you should also make sure that the '@'
string literal is
interpreted in that character set:
mysql> SELECT SUBSTRING_INDEX(USER(),_utf8'@',1); -> 'davida'
VERSION()
mysql> SELECT VERSION(); -> '4.1.3-beta-log'Note that if your version string ends with
-log
this means that
logging is enabled.
DEFAULT(col_name)
mysql> UPDATE t SET i = DEFAULT(i)+1 WHERE id < 100;
DEFAULT()
was added in MySQL 4.1.0.
FORMAT(X,D)
'#,###,###.##'
, rounded
to D decimals, and returns the result as a string.
If D is 0
, the result will have no
decimal point or fractional part.
mysql> SELECT FORMAT(12332.123456, 4); -> '12,332.1235' mysql> SELECT FORMAT(12332.1,4); -> '12,332.1000' mysql> SELECT FORMAT(12332.2,0); -> '12,332'
GET_LOCK(str,timeout)
1
if the lock was obtained
successfully, 0
if the attempt timed out (for example, because another
client has previously locked the name), or NULL
if an error
occurred (such as running out of memory or the thread was killed with
mysqladmin kill
). If you have a lock obtained with GET_LOCK()
,
it is released when you execute
RELEASE_LOCK()
, execute a new GET_LOCK()
, or your connection
terminates (either normally or abnormally).
This function can be used to implement application locks or to
simulate record locks. Names are locked on a server-wide basis.
If a name has been locked by one client, GET_LOCK()
blocks
any request by another client for a lock with the same name. This
allows clients that agree on a given lock name to use the name to
perform cooperative advisory locking.
mysql> SELECT GET_LOCK('lock1',10); -> 1 mysql> SELECT IS_FREE_LOCK('lock2'); -> 1 mysql> SELECT GET_LOCK('lock2',10); -> 1 mysql> SELECT RELEASE_LOCK('lock2'); -> 1 mysql> SELECT RELEASE_LOCK('lock1'); -> NULLNote that the second
RELEASE_LOCK()
call returns NULL
because
the lock 'lock1'
was automatically released by the second
GET_LOCK()
call.
INET_ATON(expr)
mysql> SELECT INET_ATON('209.207.224.40'); -> 3520061480The generated number is always in network byte order. For the example just shown, the number is calculated as
209*256^3 + 207*256^2 +
224*256 + 40
.
As of MySQL 4.1.2, INET_ATON()
also understands short-form IP
addresses:
mysql> SELECT INET_ATON('127.0.0.1'), INET_ATON('127.1'); -> 2130706433, 2130706433
INET_ATON()
was added in MySQL 3.23.15.
INET_NTOA(expr)
mysql> SELECT INET_NTOA(3520061480); -> '209.207.224.40'
INET_NTOA()
was added in MySQL 3.23.15.
IS_FREE_LOCK(str)
1
if the lock is free (no one is using the lock),
0
if the lock is in use, and
NULL
on errors (such as incorrect arguments).
IS_FREE_LOCK()
was added in MySQL 4.0.2.
IS_USED_LOCK(str)
NULL
.
IS_USED_LOCK()
was added in MySQL 4.1.0.
MASTER_POS_WAIT(log_name,log_pos[,timeout])
NULL
if the slave SQL thread
is not started, the slave's master information is not initialized, the
arguments are incorrect, or an error occurs. It returns -1
if the
timeout has been exceeded. If the slave SQL thread stops while
MASTER_POS_WAIT()
is waiting, the function returns NULL
.
If the slave is past the specified position, the function returns
immediately.
If a timeout value is specified, MASTER_POS_WAIT()
stops waiting when timeout seconds have elapsed. timeout must
be greater than 0; a zero or negative timeout means no timeout.
MASTER_POS_WAIT()
was added in MySQL 3.23.32.
The timeout argument was added in 4.0.10.
RELEASE_LOCK(str)
GET_LOCK()
. Returns 1
if the lock was released, 0
if the
lock wasn't locked by this thread (in which case the lock is not released),
and NULL
if the named lock didn't exist. The lock will not exist if
it was never obtained by a call to GET_LOCK()
or if it has previously
been released.
The DO
statement is convenient to use with RELEASE_LOCK()
.
See section 13.1.2 DO
Syntax.
UUID()
UUID()
are expected to generate two different
values, even if these calls are performed on two separate computers that are
not connected to each other.
A UUID is a 128-bit number represented by a string
of five hexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
format:
mysql> SELECT UUID(); -> '6ccd780c-baba-1026-9564-0040f4311e29'Note that
UUID()
does not yet work with replication.
UUID()
was added in MySQL 4.1.2.
GROUP BY
ClausesGROUP BY
(Aggregate) Functions
If you use a group function in a statement containing no GROUP BY
clause, it is equivalent to grouping on all rows.
AVG(expr)
expr
.
mysql> SELECT student_name, AVG(test_score) -> FROM student -> GROUP BY student_name;
BIT_AND(expr)
AND
of all bits in expr. The calculation is
performed with 64-bit (BIGINT
) precision.
As of MySQL 4.0.17, this function returns
18446744073709551615
if there were no matching rows.
(This is an unsigned BIGINT
value with all bits set to 1.)
Before 4.0.17, the function returns -1
if there were no matching rows.
BIT_OR(expr)
OR
of all bits in expr. The calculation is
performed with 64-bit (BIGINT
) precision.
This function returns 0
if there were no matching rows.
BIT_XOR(expr)
XOR
of all bits in expr. The calculation is
performed with 64-bit (BIGINT
) precision.
This function returns 0
if there were no matching rows.
This function is available as of MySQL 4.1.1.
COUNT(expr)
NULL
values in the rows
retrieved by a SELECT
statement.
mysql> SELECT student.student_name,COUNT(*) -> FROM student,course -> WHERE student.student_id=course.student_id -> GROUP BY student_name;
COUNT(*)
is somewhat different in that it returns a count of
the number of rows retrieved, whether or not they contain NULL
values.
COUNT(*)
is optimized to
return very quickly if the SELECT
retrieves from one table, no
other columns are retrieved, and there is no WHERE
clause.
For example:
mysql> SELECT COUNT(*) FROM student;This optimization applies only to
MyISAM
and ISAM
tables
only, because an exact record count is stored for these table types and
can be accessed very quickly. For transactional storage engines
(InnoDB
, BDB
), storing an exact row count is more problematic
because multiple transactions may be occurring, each of which may affect the
count.
COUNT(DISTINCT expr,[expr...])
NULL
values.
mysql> SELECT COUNT(DISTINCT results) FROM student;In MySQL, you can get the number of distinct expression combinations that don't contain
NULL
by giving a list of expressions.
In standard SQL, you would have to do a concatenation of all expressions
inside COUNT(DISTINCT ...)
.
COUNT(DISTINCT ...)
was added in MySQL 3.23.2.
GROUP_CONCAT(expr)
NULL
values from a group. It returns NULL
if there are no non-NULL
values. The full syntax is as follows:
GROUP_CONCAT([DISTINCT] expr [,expr ...] [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [,col_name ...]] [SEPARATOR str_val])
mysql> SELECT student_name, -> GROUP_CONCAT(test_score) -> FROM student -> GROUP BY student_name;Or:
mysql> SELECT student_name, -> GROUP_CONCAT(DISTINCT test_score -> ORDER BY test_score DESC SEPARATOR ' ') -> FROM student -> GROUP BY student_name;In MySQL, you can get the concatenated values of expression combinations. You can eliminate duplicate values by using
DISTINCT
.
If you want to sort values in the result, you should use ORDER BY
clause.
To sort in reverse order, add the DESC
(descending) keyword to the
name of the column you are sorting by in the ORDER BY
clause. The
default is ascending order; this may be specified explicitly using the
ASC
keyword.
SEPARATOR
is followed by the string value that should be inserted between
values of result. The default is a comma (`,'). You can remove
the separator altogether by specifying SEPARATOR ''
.
You can set a maximum allowed length with the
group_concat_max_len
system variable.
The syntax to do this at runtime is as follows, where val
is an
unsigned integer:
SET [SESSION | GLOBAL] group_concat_max_len = val;If a maximum length has been set, the result is truncated to this maximum length.
GROUP_CONCAT()
was added in MySQL 4.1.
Note: Before MySQL 4.1.6, there are some small limitations with
GROUP_CONCAT()
for BLOB
and TEXT
values when it comes
to using DISTINCT
together with ORDER BY
. To work around
this limitation, use MID(expr,1,255)
instead.
MIN(expr)
MAX(expr)
MIN()
and
MAX()
may take a string argument; in such cases they return the
minimum or maximum string value. See section 7.4.5 How MySQL Uses Indexes.
mysql> SELECT student_name, MIN(test_score), MAX(test_score) -> FROM student -> GROUP BY student_name;For
MIN()
, MAX()
, and other aggregate functions, MySQL
currently compares ENUM
and SET
columns by their string
value rather than by the string's relative position in the set.
This differs from how ORDER BY
compares them.
This will be rectified.
STD(expr)
STDDEV(expr)
VARIANCE()
). This is an extension to standard SQL. The STDDEV()
form of this function is provided for Oracle compatibility.
SUM(expr)
SUM()
returns NULL
.
VARIANCE(expr)
GROUP BY
Modifiers
As of MySQL 4.1.1, the GROUP BY
clause allows a WITH
ROLLUP
modifier that causes extra rows to be added to the summary
output. These rows represent higher-level (or super-aggregate) summary
operations. ROLLUP
thus allows you to answer questions at multiple
levels of analysis with a single query. It can be used, for example,
to provide support for OLAP (Online Analytical Processing) operations.
As an illustration, suppose that a table named sales
has year
,
country
,
product
, and profit
columns for recording sales profitability:
CREATE TABLE sales ( year INT NOT NULL, country VARCHAR(20) NOT NULL, product VARCHAR(32) NOT NULL, profit INT );
The table's contents can be summarized per year with a simple GROUP BY
like this:
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year; +------+-------------+ | year | SUM(profit) | +------+-------------+ | 2000 | 4525 | | 2001 | 3010 | +------+-------------+
This output shows the total profit for each year, but if you also want to determine the total profit summed over all years, you must add up the individual values yourself or run an additional query.
Or you can use ROLLUP
, which provides both levels of analysis with a
single query.
Adding a WITH ROLLUP
modifier to the GROUP BY
clause causes the query
to produce another row that shows the grand total over all year values:
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP; +------+-------------+ | year | SUM(profit) | +------+-------------+ | 2000 | 4525 | | 2001 | 3010 | | NULL | 7535 | +------+-------------+
The grand total super-aggregate line is identified by the value NULL
in
the year
column.
ROLLUP
has a more complex effect when there are multiple GROUP BY
columns. In this case, each time there is a ``break'' (change in value)
in any but the last grouping column, the query produces an extra
super-aggregate summary row.
For example, without ROLLUP
, a summary on the sales
table based
on year
,
country
, and product
might look like this:
mysql> SELECT year, country, product, SUM(profit) -> FROM sales -> GROUP BY year, country, product; +------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2001 | Finland | Phone | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | +------+---------+------------+-------------+
The output indicates summary values only at the year/country/product level of
analysis. When ROLLUP
is added, the query produces several extra rows:
mysql> SELECT year, country, product, SUM(profit) -> FROM sales -> GROUP BY year, country, product WITH ROLLUP; +------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | India | NULL | 1350 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2000 | USA | NULL | 1575 | | 2000 | NULL | NULL | 4525 | | 2001 | Finland | Phone | 10 | | 2001 | Finland | NULL | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | | 2001 | USA | NULL | 3000 | | 2001 | NULL | NULL | 3010 | | NULL | NULL | NULL | 7535 | +------+---------+------------+-------------+
For this query, adding ROLLUP
causes the output to include summary
information at four levels of analysis, not just one. Here's how to
interpret the ROLLUP
output:
product
column set to NULL
.
country
and products
columns set to NULL
.
year
, country
, and products
columns set to
NULL
.
Other Considerations When using ROLLUP
The following items list some behaviors specific to the MySQL implementation
of ROLLUP
:
When you use ROLLUP
, you cannot also use an ORDER BY
clause to
sort the results. In other words, ROLLUP
and ORDER BY
are mutually
exclusive. However, you still have some control over sort order.
GROUP BY
in MySQL sorts results, and you can use explicit ASC
and DESC
keywords
with columns named in the GROUP BY
list to specify sort order for
individual columns. (The higher-level summary rows added by ROLLUP
still appear after the rows from which they are calculated, regardless
of the sort order.)
LIMIT
can be used to restrict the number of rows returned to the
client. LIMIT
is applied after ROLLUP
, so the limit applies
against the extra rows added by ROLLUP
. For example:
mysql> SELECT year, country, product, SUM(profit) -> FROM sales -> GROUP BY year, country, product WITH ROLLUP -> LIMIT 5; +------+---------+------------+-------------+ | year | country | product | SUM(profit) | +------+---------+------------+-------------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | +------+---------+------------+-------------+
Using LIMIT
with ROLLUP
may produce results
that are more difficult to interpret, because you have less context
for understanding the super-aggregate rows.
The NULL
indicators in each super-aggregate row are produced when the
row is sent to the client. The server looks at the columns named in
the GROUP BY
clause following the leftmost one that has changed value.
For any column in the result set with a name that is a lexical match to
any of those names, its value is set to NULL
. (If you specify grouping
columns by column number, the server identifies which columns to set to
NULL
by number.)
Because the NULL
values in the super-aggregate rows are placed into the
result set at such a late stage in query processing, you cannot test them
as NULL
values within the query itself. For example, you cannot add
HAVING product IS NULL
to the query to eliminate from the output all
but the super-aggregate rows.
On the other hand, the NULL
values do appear as NULL
on the client side and can be tested as such using any MySQL client
programming interface.
GROUP BY
with Hidden Fields
MySQL extends the use of GROUP BY
so that you can use columns or
calculations in the SELECT
list that don't appear in
the GROUP BY
clause. This stands for any possible value for this
group. You can use this to get better performance by avoiding sorting and
grouping on unnecessary items. For example, you don't need to group on
customer.name
in the following query:
mysql> SELECT order.custid, customer.name, MAX(payments) -> FROM order,customer -> WHERE order.custid = customer.custid -> GROUP BY order.custid;
In standard SQL, you would have to add customer.name
to the
GROUP BY
clause. In MySQL, the name is redundant if you don't run in
ANSI mode.
Do not use this feature if the columns you omit from the
GROUP BY
part are not unique in the group! You will get
unpredictable results.
In some cases, you can use MIN()
and MAX()
to obtain a specific
column value even if it isn't unique. The following gives the value of
column
from the row containing the smallest value in the sort
column:
SUBSTR(MIN(CONCAT(RPAD(sort,6,' '),column)),7)
See section 3.6.4 The Rows Holding the Group-wise Maximum of a Certain Field.
Note that if you are using MySQL 3.22 (or earlier) or if
you are trying to follow standard SQL, you can't use expressions in GROUP
BY
or ORDER BY
clauses. You can work around this limitation by
using an alias for the expression:
mysql> SELECT id,FLOOR(value/100) AS val FROM tbl_name -> GROUP BY id, val ORDER BY val;
In MySQL 3.23 and up, aliases are unnecessary. You can use expressions
in GROUP BY
and ORDER BY
clauses. For example:
mysql> SELECT id, FLOOR(value/100) FROM tbl_name ORDER BY RAND();
This chapter describes the syntax for the SQL statements supported in MySQL.
DELETE
SyntaxSingle-table syntax:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [WHERE where_definition] [ORDER BY ...] [LIMIT row_count]
Multiple-table syntax:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] tbl_name[.*] [, tbl_name[.*] ...] FROM table_references [WHERE where_definition]
Or:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name[.*] [, tbl_name[.*] ...] USING table_references [WHERE where_definition]
DELETE
deletes rows from tbl_name that satisfy the condition
given by where_definition, and returns the number of records deleted.
If you issue a DELETE
statement with no WHERE
clause, all
rows are deleted. A faster way to do this, when you don't want to know
the number of deleted rows, is to use TRUNCATE TABLE
.
See section 13.1.9 TRUNCATE
Syntax.
In MySQL 3.23, DELETE
without a WHERE
clause returns zero
as the number of affected records.
In MySQL 3.23, if you really want to know how many records are deleted
when you are deleting all rows, and are willing to suffer a speed
penalty, you can use a DELETE
statement that includes a
WHERE
clause with an expression that is true for every row. For
example:
mysql> DELETE FROM tbl_name WHERE 1>0;
This is much slower than TRUNCATE tbl_name
, because it deletes
rows one at a time.
If you delete the row containing the maximum value for an
AUTO_INCREMENT
column, the value will be reused for an ISAM
or BDB
table, but not for a MyISAM
or InnoDB
table.
If you delete all rows in the table with DELETE FROM tbl_name
(without a WHERE
) in AUTOCOMMIT
mode, the sequence starts
over for all table types except for InnoDB
and (as of MySQL 4.0)
MyISAM
. There are some exceptions to this behavior for InnoDB
tables, discussed in
section 15.7.3 How an AUTO_INCREMENT
Column Works in InnoDB
.
For MyISAM
and BDB
tables, you can specify an
AUTO_INCREMENT
secondary column in a multiple-column key. In this
case, reuse of values deleted from the top of the sequence occurs even
for MyISAM
tables.
See section 3.6.9 Using AUTO_INCREMENT
.
The DELETE
statement supports the following modifiers:
LOW_PRIORITY
keyword, execution of the
DELETE
is delayed until no other clients are reading from the table.
MyISAM
tables, if you specify the QUICK
keyword, the
storage engine does not merge index leaves during delete, which may speed up
certain kind of deletes.
IGNORE
keyword causes MySQL to ignore all errors during the
process of deleting rows. (Errors encountered during the parsing stage are
processed in the usual manner.) Errors that are ignored due to the use of
this option are returned as warnings. This option first appeared in MySQL
4.1.1.
The speed of delete operations may also be affected by factors discussed in
section 7.2.16 Speed of DELETE
Statements.
In MyISAM
tables, deleted records are maintained in a linked list and
subsequent INSERT
operations reuse old record positions. To
reclaim unused space and reduce file sizes, use the OPTIMIZE
TABLE
statement or the myisamchk
utility to reorganize tables.
OPTIMIZE TABLE
is easier, but myisamchk
is faster. See
section 13.5.2.5 OPTIMIZE TABLE
Syntax and section 5.7.3.10 Table Optimization.
The QUICK
modifier affects whether index leaves are merged for
delete operations. DELETE QUICK
is most useful for applications
where index values for deleted rows will be replaced by similar index
values from rows inserted later. In this case, the holes left by deleted
values will be reused.
DELETE QUICK
is not useful when deleted values lead to underfilled
index blocks spanning a range of index values for which new inserts will
occur again. In this case, use of QUICK
can lead to wasted space in
the index that remains unreclaimed. Here is an example of such a scenario:
AUTO_INCREMENT
column.
DELETE QUICK
.
In this scenario, the index blocks associated with the deleted index
values become underfilled but are not merged with other index blocks due
to the use of QUICK
. They will remain underfilled when new inserts
occur, because new records will not have index values in the deleted range.
Furthermore, they will remain underfilled even if you later use DELETE
without QUICK
, unless some of the deleted index values happen
to lie in index blocks within or adjacent to the underfilled blocks.
To reclaim unused index space under these circumstances, you can use
OPTIMIZE TABLE
.
If you are going to delete many rows from a table, it might be faster to use
DELETE QUICK
followed by OPTIMIZE TABLE
. This rebuilds the index
rather than performing many index block merge operations.
The MySQL-specific LIMIT row_count
option to DELETE
tells
the server the maximum number of rows to be deleted before control is
returned to the client. This can be used to ensure that a specific
DELETE
statement doesn't take too much time. You can simply repeat
the DELETE
statement until the number of affected rows is less than
the LIMIT
value.
If the DELETE
statement includes an ORDER BY
clause, the rows
are deleted in the order specified by the clause. This is really useful only
in conjunction with LIMIT
. For example, the following statement
finds rows matching the WHERE
clause, sorts them in timestamp
order, and deletes the first (oldest) one:
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp LIMIT 1
ORDER BY
can be used with DELETE
beginning with MySQL 4.0.0.
From MySQL 4.0, you can specify multiple tables in the DELETE
statement to delete rows from one or more tables depending on a particular
condition in multiple tables. However, you cannot use ORDER BY
or LIMIT
in a multiple-table DELETE
.
The first multiple-table DELETE
syntax is supported starting from
MySQL 4.0.0. The second is supported starting from MySQL 4.0.2. The
table_references
part lists the tables involved in the join.
Its syntax is described in section 13.1.7.1 JOIN
Syntax.
For the first syntax, only matching rows from the tables listed before the
FROM
clause are deleted. For the second syntax, only matching rows
from the tables listed in the FROM
clause (before the USING
clause) are deleted. The effect is that you can delete rows from many
tables at the same time and also have additional tables that are used for
searching:
DELETE t1, t2 FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;
Or:
DELETE FROM t1, t2 USING t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;
These statements use all three files when searching for rows to delete, but
delete matching rows only from tables t1
and t2
.
The examples show inner joins using the comma operator, but
multiple-table DELETE
statements can use any type of
join allowed in SELECT
statements, such as LEFT JOIN
.
The syntax allows .*
after the table names for compatibility with
Access
.
If you use a multiple-table DELETE
statement involving
InnoDB
tables for which there are foreign key constraints,
the MySQL optimizer might process tables in an order that differs from
that of their parent/child relationship. In this case, the statement
fails and rolls back. Instead, delete from a single table and rely on the
ON DELETE
capabilities that InnoDB
provides to cause the
other tables to be modified accordingly.
Note: In MySQL 4.0, you should refer to the table names to be deleted with the true table name. In MySQL 4.1, you must use the alias (if one was given) when referring to a table name:
In MySQL 4.0:
DELETE test FROM test AS t1, test2 WHERE ...
In MySQL 4.1:
DELETE t1 FROM test AS t1, test2 WHERE ...
The reason we didn't make this change in 4.0 is that we didn't want to break any old 4.0 applications that were using the old syntax.
Currently, you cannot delete from a table and select from the same table in a subquery.
DO
SyntaxDO expr [, expr] ...
DO
executes the expressions but doesn't return any results. This is
shorthand for SELECT expr, ...
, but has the advantage that it's
slightly faster when you don't care about the result.
DO
is useful mainly with functions that have side effects, such as
RELEASE_LOCK()
.
DO
was added in MySQL 3.23.47.
HANDLER
SyntaxHANDLER tbl_name OPEN [ AS alias ] HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...) [ WHERE where_condition ] [LIMIT ... ] HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST } [ WHERE where_condition ] [LIMIT ... ] HANDLER tbl_name READ { FIRST | NEXT } [ WHERE where_condition ] [LIMIT ... ] HANDLER tbl_name CLOSE
The HANDLER
statement provides direct access to table storage engine
interfaces. It is available for MyISAM
tables as MySQL 4.0.0 and
InnoDB
tables as of MySQL 4.0.3.
The HANDLER ... OPEN
statement opens a table, making
it accessible via subsequent HANDLER ... READ
statements.
This table object is not shared by other threads and is not closed
until the thread calls HANDLER ... CLOSE
or the thread terminates.
If you open the table using an alias, further references to the table with
other HANDLER
statements must use the alias rather than the table
name.
The first HANDLER ... READ
syntax fetches a row where the index
specified satisfies the given values and the WHERE
condition is met.
If you have a multiple-column index, specify the index column values as a
comma-separated list. Either specify values for all the columns in the
index, or specify values for a leftmost prefix of the index columns. Suppose
that an index includes three columns named col_a
, col_b
, and
col_c
, in that order. The HANDLER
statement can specify
values for all three columns in the index, or for the columns in a leftmost
prefix. For example:
HANDLER ... index_name = (col_a_val,col_b_val,col_c_val) ... HANDLER ... index_name = (col_a_val,col_b_val) ... HANDLER ... index_name = (col_a_val) ...
The second HANDLER ... READ
syntax fetches a row from the table in
index order that matches WHERE
condition.
The third HANDLER ... READ
syntax fetches a row from the table in
natural row order that matches the WHERE
condition. It is faster than
HANDLER tbl_name READ index_name
when a full table scan is desired.
Natural row order is the order in which rows are stored in a MyISAM
table data file. This statement works for InnoDB
tables as well, but
there is no such concept because there is no separate data file.
Without a LIMIT
clause, all forms of HANDLER ... READ
fetch a
single row if one is available. To return a specific number of rows, include a
LIMIT
clause. It has the same syntax as for the SELECT
statement.
See section 13.1.7 SELECT
Syntax.
HANDLER ... CLOSE
closes a table that was opened with
HANDLER ... OPEN
.
Note: To use the HANDLER
interface to refer to a table's
PRIMARY KEY
, use the quoted identifier `PRIMARY`
:
HANDLER tbl_name READ `PRIMARY` > (...);
HANDLER
is a somewhat low-level statement. For example, it does not
provide consistency. That is, HANDLER ... OPEN
does not
take a snapshot of the table, and does not lock the table. This
means that after a HANDLER ... OPEN
statement is issued, table data
can be modified (by this or any other thread) and these modifications might
appear only partially in HANDLER ... NEXT
or HANDLER ... PREV
scans.
There are several reasons to use the HANDLER
interface instead of
normal SELECT
statements:
HANDLER
is faster than SELECT
:
HANDLER ... OPEN
. The object is reused for the following
HANDLER
statements for the table; it need not be reinitialized for
each one.
SELECT
doesn't normally allow.
HANDLER
makes it much easier to port applications that use an
ISAM
-like interface to MySQL.
HANDLER
allows you to traverse a database in a manner that is not
easy (or perhaps even impossible) to do with SELECT
. The HANDLER
interface is a more natural way to look at data when working with
applications that provide an interactive user interface to the database.
INSERT
SyntaxINSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [(col_name,...)] VALUES ({expr | DEFAULT},...),(...),... [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
Or:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name SET col_name={expr | DEFAULT}, ... [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
Or:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE] [INTO] tbl_name [(col_name,...)] SELECT ... [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
INSERT
inserts new rows into an existing table. The INSERT ...
VALUES
and INSERT ... SET
forms of the statement insert rows based
on explicitly specified values. The INSERT ... SELECT
form inserts
rows selected from another table or tables. The INSERT ... VALUES
form with multiple value lists is supported in MySQL 3.22.5 or
later. The INSERT ... SET
syntax is supported in MySQL
3.22.10 or later.
INSERT ... SELECT
is discussed further in
See section 13.1.4.1 INSERT ... SELECT
Syntax.
tbl_name is the table into which rows should be inserted. The columns for which the statement provides values can be specified as follows:
SET
clause indicates the columns
explicitly.
INSERT ... VALUES
or
INSERT ... SELECT
, values for every column in the table must be
provided in the VALUES()
list or by the SELECT
. If you don't
know the order of the columns in the table, use DESCRIBE tbl_name
to
find out.
Column values can be given in several ways:
CREATE TABLE
Syntax.
See section 1.5.6.2 Constraints on Invalid Data.
If you want INSERT
statements to generate an error unless you
explicitly specify values for all columns that don't have a default
value, you should use STRICT mode. See section 5.2.2 The Server SQL Mode.
DEFAULT
to explicitly set a column to its
default value. (New in MySQL 4.0.3.) This makes it easier to write
INSERT
statements that assign values to all but a few columns,
because it allows you to avoid writing an incomplete VALUES
list
that does not include a value for each column in the table.
Otherwise, you would have to write out the list of column names
corresponding to each value in the VALUES
list.
As of MySQL 4.1.0, you can use DEFAULT(col_name)
as a more
general form that can be used in expressions to produce a column's
default value.
VALUES
list are empty, INSERT
creates a row with each column set to its default value:
mysql> INSERT INTO tbl_name () VALUES();
'1999.0e-2'
into an INT
, FLOAT
,
DECIMAL(10,6)
, or YEAR
column results in the values 1999
,
19.9921
, 19.992100
, and 1999
. The reason the value
stored in the INT
and YEAR
columns is 1999
is that the
string-to-integer conversion looks only at as much of the initial part of
the string as may be considered a valid integer or year. For the
floating-point and fixed-point columns, the string-to-floating-point
conversion considers the entire string as a valid floating-point value.
An expression expr can refer to any column that was set earlier in a
value list. For example, you can do this because the value for col2
refers to col1
, which has previously been assigned:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);But you cannot do this because the value for
col1
refers to
col2
, which is assigned after col1
:
mysql> INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15);One exception involves columns that contain
AUTO_INCREMENT
values.
Because the AUTO_INCREMENT value is generated after other value assignments,
any reference to an AUTO_INCREMENT column in the assignment will return a 0.
The INSERT
statement supports the following modifiers:
DELAYED
keyword, the server puts the row or
rows to be inserted into a buffer, and the client issuing the INSERT
DELAYED
statement then can continue on. If the table is busy, the server
holds the rows. When the table becomes free, it begins inserting rows,
checking periodically to see whether there are new read requests for the
table. If there are, the delayed row queue is suspended until the table
becomes free again.
See section 13.1.4.2 INSERT DELAYED
Syntax.
DELAYED
was added in MySQL 3.22.5.
LOW_PRIORITY
keyword, execution of the
INSERT
is delayed until no other clients are reading from the
table. This includes other clients that began reading while existing
clients are reading, and while the INSERT LOW_PRIORITY
statement
is waiting. It is possible, therefore, for a client that issues an
INSERT LOW_PRIORITY
statement to wait for a very long time (or
even forever) in a read-heavy environment.
(This is in contrast to INSERT DELAYED
, which lets the client
continue at once.) See section 13.1.4.2 INSERT DELAYED
Syntax. Note
that LOW_PRIORITY
should normally not be used with MyISAM
tables because doing so disables concurrent inserts.
See section 14.1 The MyISAM
Storage Engine.
LOW_PRIORITY
was added in MySQL 3.22.5.
HIGH_PRIORITY
keyword, it overrides the
effect of the --low-priority-updates
option if the server was
started with that option. It also causes concurrent inserts not to be
used. HIGH_PRIORITY
was added in MySQL 3.23.11.
INSERT
can be obtained using the
mysql_affected_rows()
C API function.
See section 22.2.3.1 mysql_affected_rows()
.
IGNORE
keyword in an INSERT
statement,
errors that occur while executing the statement are treated as warnings
instead. For example, without IGNORE
, a row that duplicates an
existing UNIQUE
index or PRIMARY KEY
value in the table causes
a duplicate-key error and the statement is aborted. With IGNORE
,
the error is ignored and the row is not inserted. Data conversions that
would trigger errors abort the statement if IGNORE
is not specified. With IGNORE
, invalid values are adjusted to
the closest value values and inserted; warnings are produced but the
statement does not abort. You can determine with the mysql_info()
C API function how many rows were inserted into the table.
If you specify the ON DUPLICATE KEY UPDATE
clause (new in MySQL
4.1.0), and a row is inserted that would cause a duplicate value in a
UNIQUE
index or PRIMARY KEY
, an UPDATE
of the old row
is performed. For example, if column a
is declared as UNIQUE
and contains the value 1
, the following two statements have
identical effect:
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3) -> ON DUPLICATE KEY UPDATE c=c+1; mysql> UPDATE table SET c=c+1 WHERE a=1;
The rows-affected value is 1 if the row is inserted as a new record and 2 if an existing record is updated.
Note: If column b
is unique too, the INSERT
would be
equivalent to this UPDATE
statement instead:
mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
If a=1 OR b=2
matches several rows, only one row
is updated! In general, you should try to avoid using the
ON DUPLICATE KEY
clause on tables with multiple UNIQUE
keys.
As of MySQL 4.1.1, you can use the VALUES(col_name)
function in the
UPDATE
clause to refer to column values from the INSERT
part
of the INSERT ... UPDATE
statement. In other words,
VALUES(col_name)
in the UPDATE
clause refers to the value of
col_name that would be inserted if no duplicate-key conflict
occurred. This function is especially useful in multiple-row inserts. The
VALUES()
function is meaningful only in INSERT ... UPDATE
statements and returns NULL
otherwise.
Example:
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
That statement is identical to the following two statements:
mysql> INSERT INTO table (a,b,c) VALUES (1,2,3) -> ON DUPLICATE KEY UPDATE c=3; mysql> INSERT INTO table (a,b,c) VALUES (4,5,6) -> ON DUPLICATE KEY UPDATE c=9;
When you use ON DUPLICATE KEY UPDATE
, the DELAYED
option is
ignored.
You can find the value used for an AUTO_INCREMENT
column by using the
LAST_INSERT_ID()
function. From within the C API, use the
mysql_insert_id()
function. However, note that the two functions do
not behave quite identically under all circumstances.
The behavior of INSERT
statements with respect to AUTO_INCREMENT
columns is discussed further in section 12.8.3 Information Functions and
section 22.2.3.33 mysql_insert_id()
.
If you use an INSERT ... VALUES
statement with multiple value lists
or INSERT ... SELECT
, the statement returns an information string in
this format:
Records: 100 Duplicates: 0 Warnings: 0
Records
indicates the number of rows processed by the statement.
(This is not necessarily the number of rows actually inserted.
Duplicates
can be non-zero.)
Duplicates
indicates the number of rows that couldn't be inserted
because they would duplicate some existing unique index value.
Warnings
indicates the number of attempts to insert column values that
were problematic in some way. Warnings can occur under any of the following
conditions:
NULL
into a column that has been declared NOT NULL
.
For multiple-row INSERT
statements or INSERT ... SELECT
statements,
the column is set to the default value appropriate for the column type.
This is 0
for numeric types, the empty string (''
) for
string types, and the ``zero'' value for date and time types.
'10.34 a'
to a numeric column. The
trailing non-numeric text is stripped off and the remaining numeric part is
inserted. If the string value has no leading numeric part, the column is
set to 0
.
CHAR
, VARCHAR
, TEXT
, or
BLOB
) that exceeds the column's maximum length. The value is
truncated to the column's maximum length.
If you are using the C API, the information string can be obtained by invoking
the mysql_info()
function.
See section 22.2.3.31 mysql_info()
.
INSERT ... SELECT
SyntaxINSERT [LOW_PRIORITY] [IGNORE] [INTO] tbl_name [(column_list)] SELECT ...
With INSERT ... SELECT
, you can quickly insert many rows
into a table from one or many tables.
For example:
INSERT INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
The following conditions hold for an INSERT ... SELECT
statement:
INSERT ... SELECT
implicitly operates in
IGNORE
mode. As of MySQL 4.0.1, specify IGNORE
explicitly to ignore records that would cause duplicate-key violations.
DELAYED
with INSERT ... SELECT
.
INSERT
statement cannot appear in the
FROM
clause of the SELECT
part of the query.
This limitation is lifted in 4.0.14.
AUTO_INCREMENT
columns work as usual.
INSERT ... SELECT
.
You can use REPLACE
instead of INSERT
to overwrite old rows.
REPLACE
is the counterpart to INSERT IGNORE
in the treatment
of new rows that contain unique key values that duplicate old rows:
The new rows are used to replace the old rows rather than being discarded.
INSERT DELAYED
SyntaxINSERT DELAYED ...
The DELAYED
option for the INSERT
statement is a
MySQL extension to standard SQL that is very useful if you have clients
that can't wait for the INSERT
to complete. This is a common
problem when you use MySQL for logging and you also
periodically run SELECT
and UPDATE
statements that take a
long time to complete. DELAYED
was introduced in MySQL
3.22.15.
When a client uses INSERT DELAYED
, it gets an okay from the server at
once, and the row is queued to be inserted when the table is not in use by
any other thread.
Another major benefit of using INSERT DELAYED
is that inserts
from many clients are bundled together and written in one block. This is much
faster than doing many separate inserts.
There are some constraints on the use of DELAYED
:
INSERT DELAYED
works only with MyISAM
and ISAM
tables.
For MyISAM
tables, if there are no free blocks in the middle of the
data file, concurrent SELECT
and INSERT
statements are supported.
Under these circumstances, you very seldom need to use INSERT
DELAYED
with MyISAM
.
See section 14.1 The MyISAM
Storage Engine.
INSERT DELAYED
should be used only for INSERT
statements that
specify value lists. This is enforced as of MySQL 4.0.18. The server ignores
DELAYED
for INSERT DELAYED ... SELECT
statements.
DELAYED
for INSERT DELAYED ... ON DUPLICATE UPDATE
statements.
LAST_INSERT_ID()
to get the AUTO_INCREMENT
value the statement might generate.
DELAYED
rows are not visible to SELECT
statements until they
actually have been inserted.
Note that currently the queued rows are held only in memory until they are
inserted into the table. This means that if you terminate mysqld
forcibly (for example, with kill -9
) or if mysqld
dies
unexpectedly, any queued rows that have not been written to disk are lost!
The following describes in detail what happens when you use the
DELAYED
option to INSERT
or REPLACE
. In this
description, the ``thread'' is the thread that received an INSERT
DELAYED
statement and ``handler'' is the thread that handles all
INSERT DELAYED
statements for a particular table.
DELAYED
statement for a table, a handler
thread is created to process all DELAYED
statements for the table, if
no such handler previously exists.
DELAYED
lock; if not, it tells the handler thread to do so. The
DELAYED
lock can be obtained even if other threads have a READ
or WRITE
lock on the table. However, the handler will wait for all
ALTER TABLE
locks or FLUSH TABLES
to ensure that the table
structure is up to date.
INSERT
statement, but instead of writing
the row to the table, it puts a copy of the final row into a queue that
is managed by the handler thread. Any syntax errors are noticed by the
thread and reported to the client program.
AUTO_INCREMENT
value for the resulting row, because the
INSERT
returns before the insert operation has been completed. (If
you use the C API, the mysql_info()
function doesn't return anything
meaningful, for the same reason.)
delayed_insert_limit
rows are written, the handler checks
whether any SELECT
statements are still pending. If so, it
allows these to execute before continuing.
INSERT DELAYED
statements are received within
delayed_insert_timeout
seconds, the handler terminates.
delayed_queue_size
rows are pending in a
specific handler queue, the thread requesting INSERT DELAYED
waits until there is room in the queue. This is done to ensure that
the mysqld
server doesn't use all memory for the delayed memory
queue.
delayed_insert
in the Command
column. It will be killed if
you execute a FLUSH TABLES
statement or kill it with KILL
thread_id
. However, before exiting, it will first store all queued rows into
the table. During this time it will not accept any new INSERT
statements from another thread. If you execute an INSERT DELAYED
statement after this, a new handler thread will be created.
Note that this means that INSERT DELAYED
statements have higher
priority than normal INSERT
statements if there is an INSERT
DELAYED
handler running! Other update statements will have to wait
until the INSERT DELAYED
queue is empty, someone terminates the handler
thread (with KILL thread_id
), or someone executes FLUSH TABLES
.
INSERT
DELAYED
statements:
Status Variable | Meaning |
Delayed_insert_threads | Number of handler threads |
Delayed_writes | Number of rows written with INSERT DELAYED
|
Not_flushed_delayed_rows | Number of rows waiting to be written |
SHOW STATUS
statement or
by executing a mysqladmin extended-status
command.
Note that INSERT DELAYED
is slower than a normal INSERT
if the
table is not in use. There is also the additional overhead for the server
to handle a separate thread for each table for which there are delayed rows.
This means that you should use INSERT DELAYED
only when you are
really sure that you need it!
LOAD DATA INFILE
SyntaxLOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt' [REPLACE | IGNORE] INTO TABLE tbl_name [FIELDS [TERMINATED BY '\t'] [[OPTIONALLY] ENCLOSED BY ''] [ESCAPED BY '\\' ] ] [LINES [STARTING BY ''] [TERMINATED BY '\n'] ] [IGNORE number LINES] [(col_name,...)]
The LOAD DATA INFILE
statement reads rows from a text file into a
table at a very high speed.
For more information about the efficiency of INSERT
versus
LOAD DATA INFILE
and speeding up LOAD DATA INFILE
,
section 7.2.14 Speed of INSERT
Statements.
You can also load data files by using the mysqlimport
utility; it
operates by sending a LOAD DATA INFILE
statement to the server. The
--local
option causes mysqlimport
to read data files from the
client host. You can specify the --compress
option to get better
performance over slow networks if the client and server support the
compressed protocol.
See section 8.10 The mysqlimport
Data Import Program.
If you specify the LOW_PRIORITY
keyword, execution of the
LOAD DATA
statement is delayed until no other clients are reading
from the table.
If you specify the CONCURRENT
keyword with a MyISAM
table that
satisfies the condition for concurrent inserts (that is, it contains no free
blocks in the middle),
then other threads can retrieve data from the table while LOAD DATA
is executing. Using this option affects the performance of LOAD DATA
a bit, even if no other thread is using the table at the same time.
If the LOCAL
keyword is specified, it is
interpreted with respect to the client end of the connection:
LOCAL
is specified, the file is read by the client program on the
client host and sent to the server. The file can be given as a full pathname
to specify its exact location. If given as a relative pathname, the name is
interpreted relative to the directory in which the client program was started.
LOCAL
is not specified, the
file must be located on the server host and is read directly by the server.
LOCAL
is available in MySQL 3.22.6 or later.
When locating files on the server host, the server uses the following rules:
Note that these rules mean that a file named as `./myfile.txt' is read from
the server's data directory, whereas the same file named as `myfile.txt' is
read from the database directory of the default database. For example,
the following LOAD DATA
statement reads the file `data.txt'
from the database directory for db1
because db1
is the current
database, even though the statement explicitly loads the file into a
table in the db2
database:
mysql> USE db1; mysql> LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
Note that Windows pathnames are specified using forward slashes rather than backslashes. If you do use backslashes, you must double them.
For security reasons, when reading text files located on the server, the
files must either reside in the database directory or be readable by all.
Also, to use LOAD DATA INFILE
on server files, you must have the
FILE
privilege.
See section 5.5.3 Privileges Provided by MySQL.
Using LOCAL
is a bit slower than letting the server access the files
directly, because the contents of the file must be sent over the connection
by the client to the server. On the other hand, you do not need the
FILE
privilege to load local files.
As of MySQL 3.23.49 and MySQL 4.0.2 (4.0.13 on Windows),
LOCAL
works only if your server
and your client both have been enabled to allow it. For example, if
mysqld
was started with --local-infile=0
, LOCAL
will
not work.
See section 5.4.4 Security Issues with LOAD DATA LOCAL
.
If you need LOAD DATA
to read from a pipe, you can use the
following technique (here we load the listing of the '/' directory into a
table):
mkfifo /mysql/db/x/x chmod 666 /mysql/db/x/x find / -ls > /mysql/db/x/x mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x
If you are using a version of MySQL older than 3.23.25,
you can use this technique only with LOAD DATA LOCAL INFILE
.
If you are using MySQL before Version 3.23.24, you can't read from a
FIFO with LOAD DATA INFILE
. If you need to read from a FIFO (for
example, the output from gunzip
), use LOAD DATA LOCAL INFILE
instead.
The REPLACE
and IGNORE
keywords control handling of input
records that duplicate existing records on unique key values.
If you specify REPLACE
, input rows replace existing rows (in other
words, rows that have the same value for a primary or unique index as an
existing row). See section 13.1.6 REPLACE
Syntax.
If you specify IGNORE
, input rows that duplicate an existing row
on a unique key value are skipped. If you don't specify either option,
the behavior depends on whether or not the LOCAL
keyword is specified.
Without LOCAL
, an error occurs when a duplicate key value is
found, and the rest of the text file is ignored. With LOCAL
,
the default behavior is the same as if IGNORE
is specified;
this is because the server has no way to stop transmission of the file
in the middle of the operation.
If you want to ignore foreign key constraints during the load operation, you
can issue a SET FOREIGN_KEY_CHECKS=0
statement before executing
LOAD DATA
.
If you use LOAD DATA INFILE
on an empty MyISAM
table, all
non-unique indexes are created in a separate batch (as for
REPAIR TABLE
). This normally makes LOAD DATA INFILE
much faster
when you have many indexes. Normally this is very fast, but in some
extreme cases, you can create the indexes even faster by turning them off
with ALTER TABLE .. DISABLE KEYS
before loading the file into the
table and using ALTER TABLE .. ENABLE KEYS
to re-create the indexes
after loading the file.
See section 7.2.14 Speed of INSERT
Statements.
LOAD DATA INFILE
is the complement of SELECT ... INTO OUTFILE
.
See section 13.1.7 SELECT
Syntax.
To write data from a table to a file, use SELECT ... INTO OUTFILE
.
To read the file back into a table, use LOAD DATA INFILE
.
The syntax of the FIELDS
and LINES
clauses is the same for
both statements. Both clauses are optional, but FIELDS
must precede LINES
if both are specified.
If you specify a FIELDS
clause,
each of its subclauses (TERMINATED BY
, [OPTIONALLY] ENCLOSED
BY
, and ESCAPED BY
) is also optional, except that you must
specify at least one of them.
If you don't specify a FIELDS
clause, the defaults are the
same as if you had written this:
FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'
If you don't specify a LINES
clause, the default
is the same as if you had written this:
LINES TERMINATED BY '\n' STARTING BY ''
In other words, the defaults cause LOAD DATA INFILE
to act as follows
when reading input:
Conversely, the defaults cause SELECT ... INTO OUTFILE
to act as
follows when writing output:
Note that to write FIELDS ESCAPED BY '\\'
, you must specify two
backslashes for the value to be read as a single backslash.
Note: If you have generated the text file on a Windows system, you
might have to use LINES TERMINATED BY '\r\n'
to read the file
properly, because Windows programs typically use two characters as a line
terminator. Some programs, such as WordPad
, might use \r
as a line
terminator when writing files. To read such files, use LINES
TERMINATED BY '\r'
.
If all the lines you want to read in have a common prefix that you want
to ignore, you can use LINES STARTING BY 'prefix_string'
to skip
over the prefix (and anything before it). If a line doesn't include the
prefix, the entire line is skipped. Note that
prefix_string
may be in the middle of the line!
Example:
mysql> LOAD DATA INFILE '/tmp/test.txt' -> INTO TABLE test LINES STARTING BY "xxx";
With this you can read in a file that contains something like:
xxx"Row",1 something xxx"Row",2
And just get the data ("row",1)
and ("row",2)
.
The IGNORE number LINES
option can be used to ignore lines at
the start of the file. For example, you can use IGNORE 1 LINES
to skip over an initial header line containing column names:
mysql> LOAD DATA INFILE '/tmp/test.txt' -> INTO TABLE test IGNORE 1 LINES;
When you use SELECT ... INTO OUTFILE
in tandem with LOAD
DATA INFILE
to write data from a database into a file and then read
the file back into the database later, the field- and line-handling
options for both statements must match. Otherwise, LOAD DATA
INFILE
will not interpret the contents of the file properly. Suppose
that you use SELECT ... INTO OUTFILE
to write a file with
fields delimited by commas:
mysql> SELECT * INTO OUTFILE 'data.txt' -> FIELDS TERMINATED BY ',' -> FROM table2;
To read the comma-delimited file back in, the correct statement would be:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 -> FIELDS TERMINATED BY ',';
If instead you tried to read in the file with the statement shown here, it
wouldn't work because it instructs LOAD DATA INFILE
to look for
tabs between fields:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE table2 -> FIELDS TERMINATED BY '\t';
The likely result is that each input line would be interpreted as a single field.
LOAD DATA INFILE
can be used to read files obtained from
external sources, too. For example, a file in dBASE format will have
fields separated by commas and enclosed within double quotes. If lines in
the file are terminated by newlines, the statement shown here
illustrates the field- and line-handling options you would use to load
the file:
mysql> LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name -> FIELDS TERMINATED BY ',' ENCLOSED BY '"' -> LINES TERMINATED BY '\n';
Any of the field- or line-handling options can specify an empty string
(''
). If not empty, the FIELDS [OPTIONALLY] ENCLOSED BY
and FIELDS ESCAPED BY
values must be a single character. The
FIELDS TERMINATED BY
, LINES STARTING BY
, and LINES
TERMINATED BY
values can be more than one character. For example, to write
lines that are terminated by carriage return/linefeed pairs, or to read a
file containing such lines, specify a LINES TERMINATED BY '\r\n'
clause.
To read a file containing jokes that are separated by lines consisting
of %%
, you can do this
mysql> CREATE TABLE jokes -> (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -> joke TEXT NOT NULL); mysql> LOAD DATA INFILE '/tmp/jokes.txt' INTO TABLE jokes -> FIELDS TERMINATED BY '' -> LINES TERMINATED BY '\n%%\n' (joke);
FIELDS [OPTIONALLY] ENCLOSED BY
controls quoting of fields. For
output (SELECT ... INTO OUTFILE
), if you omit the word
OPTIONALLY
, all fields are enclosed by the ENCLOSED BY
character. An example of such output (using a comma as the field
delimiter) is shown here:
"1","a string","100.20" "2","a string containing a , comma","102.20" "3","a string containing a \" quote","102.20" "4","a string containing a \", quote and comma","102.20"
If you specify OPTIONALLY
, the ENCLOSED BY
character is
used only to enclose CHAR
and VARCHAR
fields:
1,"a string",100.20 2,"a string containing a , comma",102.20 3,"a string containing a \" quote",102.20 4,"a string containing a \", quote and comma",102.20
Note that occurrences of the ENCLOSED BY
character within a
field value are escaped by prefixing them with the ESCAPED BY
character. Also note that if you specify an empty ESCAPED BY
value, it is possible to generate output that cannot be read properly by
LOAD DATA INFILE
. For example, the preceding output just shown would
appear as follows if the escape character is empty. Observe that the
second field in the fourth line contains a comma following the quote, which
(erroneously) appears to terminate the field:
1,"a string",100.20 2,"a string containing a , comma",102.20 3,"a string containing a " quote",102.20 4,"a string containing a ", quote and comma",102.20
For input, the ENCLOSED BY
character, if present, is stripped
from the ends of field values. (This is true whether or not OPTIONALLY
is specified; OPTIONALLY
has no effect on input interpretation.)
Occurrences of the ENCLOSED BY
character preceded by the
ESCAPED BY
character are interpreted as part of the current
field value.
If the field begins with the ENCLOSED BY
character, instances
of that character are recognized as terminating a field value only
if followed by the field or line TERMINATED BY
sequence.
To avoid ambiguity, occurrences of the ENCLOSED BY
character
within a field value can be doubled and will be interpreted as a
single instance of the character. For example, if ENCLOSED
BY '"'
is specified, quotes are handled as shown here:
"The ""BIG"" boss" -> The "BIG" boss The "BIG" boss -> The "BIG" boss The ""BIG"" boss -> The ""BIG"" boss
FIELDS ESCAPED BY
controls how to write or read special characters.
If the FIELDS ESCAPED BY
character is not empty, it is used to prefix
the following characters on output:
FIELDS ESCAPED BY
character
FIELDS [OPTIONALLY] ENCLOSED BY
character
FIELDS TERMINATED BY
and
LINES TERMINATED BY
values
0
(what is actually written following the escape character is
ASCII `0', not a zero-valued byte)
If the FIELDS ESCAPED BY
character is empty, no characters are
escaped and NULL
is output as NULL
, not \N
. It is
probably not a good idea to specify an empty escape character,
particularly if field values in your data contain any of the characters
in the list just given.
For input, if the FIELDS ESCAPED BY
character is not empty, occurrences
of that character are stripped and the following character is taken literally
as part of a field value. The exceptions are an escaped `0' or
`N' (for example, \0
or \N
if the escape character is
`\'). These sequences are interpreted as ASCII NUL (a zero-valued
byte) and NULL
. The rules for NULL
handling are described later
in this section.
For more information about `\'-escape syntax, see section 9.1 Literal Values.
In certain cases, field- and line-handling options interact:
LINES TERMINATED BY
is an empty string and FIELDS
TERMINATED BY
is non-empty, lines are also terminated with
FIELDS TERMINATED BY
.
FIELDS TERMINATED BY
and FIELDS ENCLOSED BY
values
are both empty (''
), a fixed-row (non-delimited) format is used.
With fixed-row format, no delimiters are used between fields (but you
can still have a line terminator). Instead, column values are written
and read using the ``display'' widths of the columns. For example, if a
column is declared as INT(7)
, values for the column are written
using seven-character fields. On input, values for the column are obtained
by reading seven characters.
LINES TERMINATED BY
is still used to separate lines. If a line
doesn't contain all fields, the rest of the columns are set to their
default values. If you don't have a line terminator, you should set this
to ''
. In this case, the text file must contain all fields for
each row.
Fixed-row format also affects handling of NULL
values, as described
later.
Note that fixed-size format will not work if you are using a multi-byte
character set.
Handling of NULL
values varies according to the FIELDS
and
LINES
options in use:
FIELDS
and LINES
values, NULL
is
written as a field value of \N
for output, and a field value of
\N
is read as NULL
for input (assuming that the ESCAPED BY
character is `\').
FIELDS ENCLOSED BY
is not empty, a field containing the literal
word NULL
as its value is read as a NULL
value. This differs
from the word NULL
enclosed within FIELDS ENCLOSED BY
characters, which is read as the string 'NULL'
.
FIELDS ESCAPED BY
is empty, NULL
is written as the word
NULL
.
FIELDS TERMINATED BY
and
FIELDS ENCLOSED BY
are both empty), NULL
is written as an empty
string. Note that this causes both NULL
values and empty strings in
the table to be indistinguishable when written to the file because they are
both written as empty strings. If you need to be able to tell the two apart
when reading the file back in, you should not use fixed-row format.
Some cases are not supported by LOAD DATA INFILE
:
FIELDS TERMINATED BY
and FIELDS ENCLOSED
BY
both empty) and BLOB
or TEXT
columns.
LOAD DATA INFILE
won't be able to interpret the input properly.
For example, the following FIELDS
clause would cause problems:
FIELDS TERMINATED BY '"' ENCLOSED BY '"'
FIELDS ESCAPED BY
is empty, a field value that contains an occurrence
of FIELDS ENCLOSED BY
or LINES TERMINATED BY
followed by the FIELDS TERMINATED BY
value will cause LOAD
DATA INFILE
to stop reading a field or line too early.
This happens because LOAD DATA INFILE
cannot properly determine
where the field or line value ends.
The following example loads all columns of the persondata
table:
mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;
By default, when no column list is provided at the end of the LOAD
DATA INFILE
statement, input lines are expected to contain a field for each
table column. If you want to load only some of a table's columns, specify a
column list:
mysql> LOAD DATA INFILE 'persondata.txt' -> INTO TABLE persondata (col1,col2,...);
You must also specify a column list if the order of the fields in the input file differs from the order of the columns in the table. Otherwise, MySQL cannot tell how to match up input fields with table columns.
If an input line has too many fields, the extra fields are ignored and the number of warnings is incremented.
If an input line has too few fields, the table columns for which input
fields are missing are set to their default values. Default value assignment
is described in section 13.2.6 CREATE TABLE
Syntax.
An empty field value is interpreted differently than if the field value is missing:
0
.
These are the same values that result if you assign an empty
string explicitly to a string, numeric, or date or time type explicitly
in an INSERT
or UPDATE
statement.
TIMESTAMP
columns are set to the current date and time only if there
is a NULL
value for the column (that is, \N
), or (for the
first TIMESTAMP
column only) if the TIMESTAMP
column is
omitted from the field list when a field list is specified.
LOAD DATA INFILE
regards all input as strings, so you can't use
numeric values for ENUM
or SET
columns the way you can with
INSERT
statements. All ENUM
and SET
values must be
specified as strings!
When the LOAD DATA INFILE
statement finishes, it returns an information string in the following format:
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
If you are using the C API, you can get information about the statement by
calling the mysql_info()
function.
See section 22.2.3.31 mysql_info()
.
Warnings occur under the same circumstances as when values are inserted
via the INSERT
statement (see section 13.1.4 INSERT
Syntax), except
that LOAD DATA INFILE
also generates warnings when there are too few
or too many fields in the input row. The warnings are not stored anywhere;
the number of warnings can be used only as an indication of whether everything went
well.
From MySQL 4.1.1 on, you can use SHOW WARNINGS
to get a list of the
first max_error_count
warnings as information about what went wrong.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
Before MySQL 4.1.1, only a warning count is available to indicate that
something went wrong. If you get warnings and want to know exactly why you
got them, one way to do this is to dump the table into another file using
SELECT ... INTO OUTFILE
and compare the file to your original input
file.
REPLACE
SyntaxREPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] VALUES ({expr | DEFAULT},...),(...),...
Or:
REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name SET col_name={expr | DEFAULT}, ...
Or:
REPLACE [LOW_PRIORITY | DELAYED] [INTO] tbl_name [(col_name,...)] SELECT ...
REPLACE
works exactly like INSERT
, except that if an old
record in the table has the same value as a new record for a PRIMARY
KEY
or a UNIQUE
index, the old record is deleted before the new
record is inserted.
See section 13.1.4 INSERT
Syntax.
Note that unless the table has a PRIMARY KEY
or UNIQUE
index,
using a REPLACE
statement makes no sense. It becomes equivalent to
INSERT
, because there is no index to be used to determine whether a new
row duplicates another.
Values for all columns are taken from the values specified in the
REPLACE
statement. Any missing columns are set to their default
values, just as happens for INSERT
. You can't refer to values from
the old row and use them in the new row. It appeared that you could do this
in some old MySQL versions, but that was a bug that has been corrected.
To be able to use REPLACE
, you must have INSERT
and
DELETE
privileges for the table.
The REPLACE
statement returns a count to indicate the number of rows
affected. This is the sum of the rows deleted and inserted. If the count is 1
for a single-row REPLACE
, a row was inserted and no rows were deleted.
If the count is greater than 1, one or more old rows were deleted before the
new row was inserted. It is possible for a single row to replace more than one
old row if the table contains multiple unique indexes and the new row
duplicates values for different old rows in different unique indexes.
The affected-rows count makes it easy to determine whether REPLACE
only added a row or whether it also replaced any rows: Check whether the
count is 1 (added) or greater (replaced).
If you are using the C API, the affected-rows count can be obtained using the
mysql_affected_rows()
function.
Currently, you cannot replace into a table and select from the same table in a subquery.
Here follows in more detail the algorithm that is used
(it is also used with LOAD DATA ... REPLACE
):
SELECT
SyntaxSELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr, ... [INTO OUTFILE 'file_name' export_options | INTO DUMPFILE 'file_name'] [FROM table_references [WHERE where_definition] [GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]] [HAVING where_definition] [ORDER BY {col_name | expr | position} [ASC | DESC] , ...] [LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [FOR UPDATE | LOCK IN SHARE MODE]]
SELECT
is used to retrieve rows selected from one or more tables.
Support for UNION
statements and subqueries is available as of MySQL
4.0 and 4.1, respectively.
See section 13.1.7.2 UNION
Syntax and section 13.1.8 Subquery Syntax.
JOIN
Syntax.
WHERE
followed by
an expression that indicates the condition or conditions that rows
must satisfy to be selected.
SELECT
can also be used to retrieve rows computed without reference to
any table.
For example:
mysql> SELECT 1 + 1; -> 2
All clauses used must be given in exactly the order shown in the syntax
description. For example, a HAVING
clause must come after any
GROUP BY
clause and before any ORDER BY
clause.
AS alias_name
.
The alias is used as the expression's column name and can be used in
GROUP BY
, ORDER BY
, or HAVING
clauses. For example:
mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name -> FROM mytable ORDER BY full_name;The
AS
keyword is optional when aliasing a select_expr.
The preceding example could have been written like this:
mysql> SELECT CONCAT(last_name,', ',first_name) full_name -> FROM mytable ORDER BY full_name;Because the
AS
is optional, a subtle problem can occur
if you forget the comma between two select_expr expressions: MySQL
interprets the second as an alias name. For example, in the following
statement, columnb
is treated as an alias name:
mysql> SELECT columna columnb FROM mytable;
WHERE
clause,
because the column value might not yet be determined when the
WHERE
clause is executed.
See section A.5.4 Problems with Column Aliases.
FROM table_references
clause indicates the tables from which to
retrieve rows. If you name more than one table, you are performing a
join. For information on join syntax, see section 13.1.7.1 JOIN
Syntax.
For each table specified, you can optionally specify an alias.
tbl_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]The use of
USE INDEX
,
IGNORE INDEX
,
FORCE INDEX
to give the optimizer hints about how to choose indexes is described in
section 13.1.7.1 JOIN
Syntax.
In MySQL 4.0.14, you can use SET max_seeks_for_key=value
as an
alternative way to force MySQL to prefer key scans instead of table scans.
DUAL
as a dummy
table name in situations where no tables are referenced:
mysql> SELECT 1 + 1 FROM DUAL; -> 2
DUAL
is purely a compatibility feature. Some other servers require
this syntax.
tbl_name AS alias_name
or
tbl_name alias_name:
mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 -> WHERE t1.name = t2.name; mysql> SELECT t1.name, t2.salary FROM employee t1, info t2 -> WHERE t1.name = t2.name;
WHERE
clause, you can use any of the functions that
MySQL supports, except for aggregate (summary) functions.
See section 12 Functions and Operators.
ORDER BY
and
GROUP BY
clauses using column names, column aliases, or column
positions. Column positions are integers and begin with 1:
mysql> SELECT college, region, seed FROM tournament -> ORDER BY region, seed; mysql> SELECT college, region AS r, seed AS s FROM tournament -> ORDER BY r, s; mysql> SELECT college, region, seed FROM tournament -> ORDER BY 2, 3;To sort in reverse order, add the
DESC
(descending) keyword to the
name of the column in the ORDER BY
clause that you are sorting by.
The default is ascending order; this can be specified explicitly using
the ASC
keyword.
Use of column positions is deprecated because the syntax has been removed from
the SQL standard.
GROUP BY
, output rows are sorted according to the
GROUP BY
columns as if you had an ORDER BY
for the same columns.
MySQL has extended the GROUP BY
clause as of version 3.23.34 so that
you can also specify ASC
and DESC
after columns named in the
clause:
SELECT a, COUNT(b) FROM test_table GROUP BY a DESC
GROUP BY
to allow you to
select fields that are not mentioned in the GROUP BY
clause.
If you are not getting the results you expect from your query, please
read the GROUP BY
description.
See section 12.9 Functions and Modifiers for Use with GROUP BY
Clauses.
GROUP BY
allows a WITH ROLLUP
modifier.
See section 12.9.2 GROUP BY
Modifiers.
HAVING
clause is applied nearly last, just before items are sent
to the client, with no optimization. (LIMIT
is applied after
HAVING
.)
Before MySQL 5.0.2, a HAVING
clause can refer to any column or alias
named in a select_expr in the SELECT
list or in outer
subqueries, and to aggregate functions. Standard SQL requires that
HAVING
must reference only columns in the GROUP BY
clause or
columns used in aggregate functions. To accommodate both standard SQL and the
MySQL-specific behavior of being able to refer columns in the SELECT
list, MySQL 5.0.2 and up allows HAVING
to refer to columns in the
SELECT
list, columns in the GROUP BY
clause, columns in outer
subqueries, and to aggregate functions.
For example, the following statement works in MySQL 5.0.2 but produces an
error for earlier versions:
mysql> SELECT COUNT(*) FROM t GROUP BY col1 HAVING col1 = 2;If the
HAVING
clause refers to a column that is ambiguous, a warning
occurs. In the following statement, col2
is ambiguous because it is
used both as an alias and as a column name:
mysql> SELECT COUNT(col1) AS col2 FROM t GROUP BY col2 HAVING col2 = 2;Preference is given to standard SQL behavior, so that if a
HAVING
column name is used both in GROUP BY
and as an aliased column in the
output column list, preferences is given to the column in the GROUP
BY
column.
HAVING
for items that
should be in the WHERE
clause. For example, do not write this:
mysql> SELECT col_name FROM tbl_name HAVING col_name > 0;Write this instead:
mysql> SELECT col_name FROM tbl_name WHERE col_name > 0;
HAVING
clause can refer to aggregate functions, which the
WHERE
clause cannot:
mysql> SELECT user, MAX(salary) FROM users -> GROUP BY user HAVING MAX(salary)>10;However, that does not work in older MySQL servers (before version 3.22.5). Instead, you can use a column alias in the select list and refer to the alias in the
HAVING
clause:
mysql> SELECT user, MAX(salary) AS max_salary FROM users -> GROUP BY user HAVING max_salary>10;
LIMIT
clause can be used to constrain the number of rows returned
by the SELECT
statement. LIMIT
takes one or two numeric
arguments, which must be integer constants.
With two arguments, the first argument specifies the offset of the first row to
return, and the second specifies the maximum number of rows to return.
The offset of the initial row is 0 (not 1):
mysql> SELECT * FROM table LIMIT 5,10; # Retrieve rows 6-15For compatibility with PostgreSQL, MySQL also supports the
LIMIT row_count OFFSET offset
syntax.
To retrieve all rows from a certain offset up to the end of the result set,
you can use some large number for the second parameter. This statement
retrieves all rows from the 96th row to the last:
mysql> SELECT * FROM table LIMIT 95,18446744073709551615;With one argument, the value specifies the number of rows to return from the beginning of the result set:
mysql> SELECT * FROM table LIMIT 5; # Retrieve first 5 rowsIn other words,
LIMIT n
is equivalent to LIMIT 0,n
.
SELECT ... INTO OUTFILE 'file_name'
form of SELECT
writes
the selected rows to a file. The file is created on the server host, so you
must have the FILE
privilege to use this syntax. The
file cannot currently exist, which among other things prevents files such as
`/etc/passwd' and database tables from being destroyed.
The SELECT ... INTO OUTFILE
statement is intended primarily to let
you very quickly dump a table on the server machine. If you want to create
the resulting file on some client host other than the server host, you can't use
SELECT ... INTO OUTFILE
. In that case, you should instead use some
command like mysql -e "SELECT ..." > file_name
on the client host to generate the file.
SELECT ... INTO OUTFILE
is the complement of LOAD DATA
INFILE
; the syntax for the export_options
part of the statement
consists of the same FIELDS
and LINES
clauses that are used
with the LOAD DATA INFILE
statement.
See section 13.1.5 LOAD DATA INFILE
Syntax.
FIELDS ESCAPED BY
controls how to write special characters.
If the FIELDS ESCAPED BY
character is not empty, it is used to prefix
the following characters on output:
FIELDS ESCAPED BY
character
FIELDS [OPTIONALLY] ENCLOSED BY
character
FIELDS TERMINATED BY
and
LINES TERMINATED BY
values
0
(what is actually written following the escape character is
ASCII `0', not a zero-valued byte)
FIELDS ESCAPED BY
character is empty, no characters are
escaped and NULL
is output as NULL
, not \N
. It is
probably not a good idea to specify an empty escape character,
particularly if field values in your data contain any of the characters
in the list just given.
The reason for the above is that you must escape any FIELDS
TERMINATED BY
, ENCLOSED BY
, ESCAPED BY
, or LINES TERMINATED BY
characters to reliably be able to read the file back. ASCII NUL is
escaped to make it easier to view with some pagers.
The resulting file doesn't have to conform to SQL syntax, so nothing
else need be escaped.
Here is an example that produces a file in the comma-separated values format
used by many programs:
SELECT a,b,a+b INTO OUTFILE '/tmp/result.text' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM test_table;
INTO DUMPFILE
instead of INTO OUTFILE
, MySQL writes
only one row into the file, without any column or line termination and
without performing any escape processing. This is useful if you want to
store a BLOB
value in a file.
INTO OUTFILE
or INTO
DUMPFILE
is writable by all users on the server host. The reason for
this is that the MySQL server can't create a file that is owned by anyone
other than the user it's running as (you should never run mysqld
as
root
). The file thus must be world-writable so that you can
manipulate its contents.
PROCEDURE
clause names a procedure that should process the data
in the result set. For an example, see section 25.3.1 Procedure Analyse.
FOR UPDATE
on a storage engine that uses page or row locks,
rows examined by the query are write-locked until the end of the current
transaction. Using LOCK IN SHARE MODE
sets a shared lock that
prevents other transactions from updating or deleting the examined rows.
See section 15.11.4 Locking Reads SELECT ... FOR UPDATE
and SELECT ... LOCK IN SHARE MODE
.
Following the SELECT
keyword, you can give a number of options
that affect the operation of the statement.
The ALL
, DISTINCT
, and DISTINCTROW
options specify
whether duplicate rows should be returned. If none of these options are
given, the default is ALL
(all matching rows are returned).
DISTINCT
and DISTINCTROW
are synonyms and specify that
duplicate rows in the result set should be removed.
HIGH_PRIORITY
, STRAIGHT_JOIN
, and options beginning with
SQL_
are MySQL extensions to standard SQL.
HIGH_PRIORITY
will give the SELECT
higher priority than
a statement that updates a table. You should use this only for queries
that are very fast and must be done at once. A SELECT HIGH_PRIORITY
query that is issued while the table is locked for reading will run even if
there is an update statement waiting for the table to be free.
HIGH_PRIORITY
cannot be used with SELECT
statements that
are part of a UNION
.
STRAIGHT_JOIN
forces the optimizer to join the tables in the order in
which they are listed in the FROM
clause. You can use this to speed up
a query if the optimizer joins the tables in non-optimal order.
See section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
).
STRAIGHT_JOIN
also can be used in the table_references list.
See section 13.1.7.1 JOIN
Syntax.
SQL_BIG_RESULT
can be used with GROUP BY
or DISTINCT
to tell the optimizer that the result set will have many rows. In this case,
MySQL will directly use disk-based temporary tables if needed.
MySQL will also, in this case, prefer sorting to using a
temporary table with a key on the GROUP BY
elements.
SQL_BUFFER_RESULT
forces the result to be put into a temporary
table. This helps MySQL free the table locks early and helps
in cases where it takes a long time to send the result set to the client.
SQL_SMALL_RESULT
can be used
with GROUP BY
or DISTINCT
to tell the optimizer that the
result set will be small. In this case, MySQL uses fast
temporary tables to store the resulting table instead of using sorting. In
MySQL 3.23 and up, this shouldn't normally be needed.
SQL_CALC_FOUND_ROWS
(available in MySQL 4.0.0 and up) tells MySQL
to calculate how many rows there would be in the result set, disregarding
any LIMIT
clause. The number of rows can then be retrieved with
SELECT FOUND_ROWS()
.
See section 12.8.3 Information Functions.
Before MySQL 4.1.0, this option does not work with
LIMIT 0
, which is optimized to return instantly (resulting in a
row count of 0).
See section 7.2.12 How MySQL Optimizes LIMIT
.
SQL_CACHE
tells MySQL to store the query result in the query cache if
you are using a query_cache_type
value of 2
or DEMAND
.
For a query that uses UNION
or subqueries, this option takes effect
to be used in any SELECT
of the query.
See section 5.11 The MySQL Query Cache.
SQL_NO_CACHE
tells MySQL not to store the query result
in the query cache. See section 5.11 The MySQL Query Cache.
For a query that uses UNION
or subqueries, this
option takes effect to be used in any SELECT
of the query.
JOIN
Syntax
MySQL supports the following JOIN
syntaxes for the
table_references part of SELECT
statements and multiple-table
DELETE
and UPDATE
statements:
table_reference, table_reference table_reference [INNER | CROSS] JOIN table_reference [join_condition] table_reference STRAIGHT_JOIN table_reference table_reference LEFT [OUTER] JOIN table_reference [join_condition] table_reference NATURAL [LEFT [OUTER]] JOIN table_reference { OJ table_reference LEFT OUTER JOIN table_reference ON conditional_expr } table_reference RIGHT [OUTER] JOIN table_reference [join_condition] table_reference NATURAL [RIGHT [OUTER]] JOIN table_reference
table_reference is defined as:
tbl_name [[AS] alias] [[USE INDEX (key_list)] | [IGNORE INDEX (key_list)] | [FORCE INDEX (key_list)]]
join_condition is defined as:
ON conditional_expr | USING (column_list)
You should generally not have any conditions in the ON
part that are
used to restrict which rows you want in the result set, but rather specify
these conditions in the WHERE
clause. There are exceptions to this rule.
Note that INNER JOIN
syntax allows a join_condition
only from
MySQL 3.23.17 on. The same is true for JOIN
and CROSS JOIN
only
as of MySQL 4.0.11.
The { OJ ... LEFT OUTER JOIN ...}
syntax shown in the preceding list
exists only for compatibility with ODBC.
tbl_name AS alias_name
or
tbl_name alias_name:
mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2 -> WHERE t1.name = t2.name; mysql> SELECT t1.name, t2.salary FROM employee t1, info t2 -> WHERE t1.name = t2.name;
ON
conditional is any conditional expression of the form that can
be used in a WHERE
clause.
ON
or
USING
part in a LEFT JOIN
, a row with all columns set to
NULL
is used for the right table. You can use this fact to find
records in a table that have no counterpart in another table:
mysql> SELECT table1.* FROM table1 -> LEFT JOIN table2 ON table1.id=table2.id -> WHERE table2.id IS NULL;This example finds all rows in
table1
with an id
value that is
not present in table2
(that is, all rows in table1
with no
corresponding row in table2
). This assumes that table2.id
is
declared NOT NULL
.
See section 7.2.9 How MySQL Optimizes LEFT JOIN
and RIGHT JOIN
.
USING
(column_list)
clause names a list of columns that must
exist in both tables. The following two clauses are semantically identical:
a LEFT JOIN b USING (c1,c2,c3) a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3
NATURAL [LEFT] JOIN
of two tables is defined to be
semantically equivalent to an INNER JOIN
or a LEFT JOIN
with a USING
clause that names all columns that exist in both
tables.
INNER JOIN
and ,
(comma) are semantically equivalent in
the absence of a join condition: both will produce a Cartesian product
between the specified tables (that is, each and every row in the first table
will be joined onto all rows in the second table).
RIGHT JOIN
works analogously to LEFT JOIN
. To keep code
portable across databases, it's recommended to use LEFT JOIN
instead of RIGHT JOIN
.
STRAIGHT_JOIN
is identical to JOIN
, except that the left table
is always read before the right table. This can be used for those (few)
cases for which the join optimizer puts the tables in the wrong order.
As of MySQL 3.23.12, you can give hints about which index MySQL
should use when retrieving information from a table. By specifying
USE INDEX (key_list)
, you can tell MySQL to use only one of the
possible indexes to find rows in the table. The alternative syntax
IGNORE INDEX (key_list)
can be used to tell MySQL to not use some
particular index. These hints are useful if EXPLAIN
shows that MySQL
is using the wrong index from the list of possible indexes.
From MySQL 4.0.9 on, you can also use FORCE INDEX
. This acts likes
USE INDEX (key_list)
but with the addition that a table scan
is assumed to be very expensive. In other words, a table scan will
only be used if there is no way to use one of the given indexes to
find rows in the table.
USE KEY
, IGNORE KEY
, and FORCE KEY
are synonyms for
USE INDEX
, IGNORE INDEX
, and FORCE INDEX
.
Note: USE INDEX
, IGNORE INDEX
, and FORCE INDEX
only affect which indexes are used when MySQL decides how to find rows in
the table and how to do the join. They do not affect whether an index will
be used when resolving an ORDER BY
or GROUP BY
.
Some join examples:
mysql> SELECT * FROM table1,table2 WHERE table1.id=table2.id; mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id; mysql> SELECT * FROM table1 LEFT JOIN table2 USING (id); mysql> SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id -> LEFT JOIN table3 ON table2.id=table3.id; mysql> SELECT * FROM table1 USE INDEX (key1,key2) -> WHERE key1=1 AND key2=2 AND key3=3; mysql> SELECT * FROM table1 IGNORE INDEX (key3) -> WHERE key1=1 AND key2=2 AND key3=3;
See section 7.2.9 How MySQL Optimizes LEFT JOIN
and RIGHT JOIN
.
UNION
SyntaxSELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | DISTINCT] SELECT ...]
UNION
is used to combine the result from many SELECT
statements into one result set. UNION
is available from MySQL 4.0.0
on.
Selected columns listed in corresponding positions of each SELECT
statement should have the same type. (For example, the first column selected
by the first statement should have the same type as the first column selected
by the other statements.) The column names used in
the first SELECT
statement are used as the column names for the
results returned.
The SELECT
statements are normal select statements, but with the
following restrictions:
SELECT
statement can have INTO OUTFILE
.
HIGH_PRIORITY
cannot be used with SELECT
statements that
are part of a UNION
. If you specify it for the first SELECT
,
it has no effect. If you specify it for any subsequent SELECT
statements, a syntax error results.
If you don't use the keyword ALL
for the UNION
, all
returned rows will be unique, as if you had done a DISTINCT
for
the total result set. If you specify ALL
, you will get all
matching rows from all the used SELECT
statements.
The DISTINCT
keyword is an optional word (introduced in MySQL 4.0.17).
It does nothing, but is allowed in the syntax as required by the SQL standard.
Before MySQL 4.1.2, you cannot mix UNION ALL
and UNION
DISTINCT
in the same query. If you use ALL
for one
UNION
, it is used for all of them. As of MySQL 4.1.2, mixed
UNION
types are treated such that a DISTINCT
union overrides
any ALL
union to its left. A DISTINCT
union can be produced
explicitly by using UNION DISTINCT
or implicitly by using UNION
with no following DISTINCT
or ALL
keyword.
If you want to use an ORDER BY
or LIMIT
clause to sort or limit
the entire UNION
result, parenthesize the individual SELECT
statements and place the ORDER BY
or LIMIT
after the last one.
The following example uses both clauses:
(SELECT a FROM tbl_name WHERE a=10 AND B=1) UNION (SELECT a FROM tbl_name WHERE a=11 AND B=2) ORDER BY a LIMIT 10;
This kind of ORDER BY
cannot use column references that include a
table name (that is, names in tbl_name.col_name format). Instead,
provide a column alias in the first SELECT
statement and refer to the
alias in the ORDER BY
, or else refer to the column in the ORDER
BY
using its column position. (An alias is preferable because use of
column positions is deprecated.)
To apply ORDER BY
or LIMIT
to an individual SELECT
,
place the clause inside the parentheses that enclose the SELECT
:
(SELECT a FROM tbl_name WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION (SELECT a FROM tbl_name WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
The types and lengths of the columns in the result set of a UNION
take into account the values retrieved by all the SELECT
statements.
Before MySQL 4.1.1, a limitation of UNION
is that only the values from
the first SELECT
are used to determine result column types and lengths.
This could result in value truncation if, for example, the first
SELECT
retrieves shorter values than the second SELECT
:
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10); +---------------+ | REPEAT('a',1) | +---------------+ | a | | b | +---------------+
That limitation has been removed as of MySQL 4.1.1:
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10); +---------------+ | REPEAT('a',1) | +---------------+ | a | | bbbbbbbbbb | +---------------+
A subquery is a SELECT
statement inside another statement.
Starting with MySQL 4.1, all subquery forms and operations that the SQL standard requires are supported, as well as a few features that are MySQL-specific.
With MySQL versions prior to 4.1, it was necessary to work around or avoid the use of subqueries. In many cases, subqueries can successfully be rewritten using joins and other methods. See section 13.1.8.11 Rewriting Subqueries as Joins for Earlier MySQL Versions.
Here is an example of a subquery:
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
In this example, SELECT * FROM t1 ...
is the outer query
(or outer statement), and (SELECT column1 FROM t2)
is the
subquery.
We say that the subquery is nested in the outer query, and in fact
it's possible to nest subqueries within other subqueries, to a great depth.
A subquery must always appear within parentheses.
The main advantages of subqueries are:
Here is an example statement that shows the major points about subquery syntax as specified by the SQL standard and supported in MySQL:
DELETE FROM t1 WHERE s11 > ANY (SELECT COUNT(*) /* no hint */ FROM t2 WHERE NOT EXISTS (SELECT * FROM t3 WHERE ROW(5*t2.s1,77)= (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM (SELECT * FROM t5) AS t5)));
A subquery can return a scalar (a single value), a single row, a single column, or a table (one or more rows of one or more columns). These are called scalar, column, row, and table subqueries. Subqueries that return a particular kind of result often can be used only in certain contexts, as described in the following sections.
There are few restrictions on the type of statements in which subqueries can be used:
SELECT
, INSERT
, UPDATE
, DELETE
,
SET
, or DO
.
SELECT
can contain:
DISTINCT
, GROUP BY
, ORDER BY
, LIMIT
,
joins, index hints, UNION
constructs, comments, functions, and so on.
One restriction is that currently you cannot modify a table and select from
the same table in a subquery. This applies to statements such as
DELETE
, INSERT
, REPLACE
, and UPDATE
.
In its simplest form, a subquery is a scalar subquery that returns a single
value. A scalar subquery is a simple operand, and you can use it wherever a
single column value or literal is legal, and you can expect it to have those
characteristics that all operands have: a data type, a length, an indication
whether it can be NULL
, and so on. For example:
CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL); INSERT INTO t1 VALUES(100, 'abcde'); SELECT (SELECT s2 FROM t1);
The subquery in this SELECT
returns a single value ('abcde'
)
that has a data type of CHAR
, a length of 5, a character set and
collation equal to the defaults in effect at CREATE TABLE
time, and
an indication that the value in the column can be NULL
. In fact,
almost all subqueries can be NULL
. If the table used in the example
were empty, the value of the subquery would be NULL
.
When you see examples in the following sections that contain the rather
spartan construct (SELECT column1 FROM t1)
, imagine that your own
code will contain much more diverse and complex constructions.
For example, suppose that we make two tables:
CREATE TABLE t1 (s1 INT); INSERT INTO t1 VALUES (1); CREATE TABLE t2 (s1 INT); INSERT INTO t2 VALUES (2);
Then perform a SELECT
:
SELECT (SELECT s1 FROM t2) FROM t1;
The result will be 2
because there is a row in t2
containing a
column s1
that has a value of 2
.
A scalar subquery can be part of an expression. Don't forget the parentheses, even if the subquery is an operand that provides an argument for a function. For example:
SELECT UPPER((SELECT s1 FROM t1)) FROM t2;
The most common use of a subquery is in the form:
non_subquery_operand comparison_operator (subquery)
Where comparison_operator is one of these operators:
= > < >= <= <>
For example:
... 'a' = (SELECT column1 FROM t1)
At one time the only legal place for a subquery was on the right side of a comparison, and you might still find some old DBMSs that insist on this.
Here is an example of a common-form subquery comparison that you cannot do
with a join. It finds all the values in table t1
that are equal to a
maximum value in table t2
:
SELECT column1 FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2);
Here is another example, which again is impossible with a join because it
involves aggregating for one of the tables. It finds all rows in table
t1
containing a value that occurs twice in a given column:
SELECT * FROM t1 AS t WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
For a comparison performed with one of these comparison operators, the
subquery must return a scalar, with the exception that =
can be used
with row subqueries.
See section 13.1.8.5 Row Subqueries.
ANY
, IN
, and SOME
Syntax:
operand comparison_operator ANY (subquery) operand IN (subquery) operand comparison_operator SOME (subquery)
The ANY
keyword, which must follow a comparison operator, means
``return TRUE
if the comparison is TRUE
for ANY
of the
values in the column that the subquery returns.''
For example:
SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);
Suppose that there is a row in table t1
containing (10)
.
The expression is TRUE
if table t2
contains (21,14,7)
because there is a value 7
in t2
that is less than 10
.
The expression is FALSE
if table t2
contains (20,10)
,
or if table t2
is empty. The expression is UNKNOWN
if table
t2
contains (NULL,NULL,NULL)
.
The word IN
is an alias for = ANY
. Thus these two statements
are the same:
SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 IN (SELECT s1 FROM t2);
However, NOT IN
is not an alias for <> ANY
, but for
<> ALL
. See section 13.1.8.4 Subqueries with ALL
.
The word SOME
is an alias for ANY
. Thus these two statements
are the same:
SELECT s1 FROM t1 WHERE s1 <> ANY (SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);
Use of the word SOME
is rare, but this example shows why it might be
useful. To most people's ears, the English phrase ``a is not equal to any
b'' means ``there is no b which is equal to a,'' but that isn't what is
meant by the SQL syntax. The syntax means ``there is some b to which a is not
equal.'' Using <> SOME
instead helps ensure that
everyone understands the true meaning of the query.
ALL
Syntax:
operand comparison_operator ALL (subquery)
The word ALL
, which must follow a comparison operator, means
``return TRUE
if the comparison is TRUE
for ALL
of
the values in the column that the subquery returns.''
For example:
SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);
Suppose that there is a row in table t1
containing (10)
.
The expression is TRUE
if table t2
contains (-5,0,+5)
because 10
is greater than all three values in t2
.
The expression is FALSE
if table t2
contains
(12,6,NULL,-100)
because there is a single value 12
in table t2
that is greater than 10
.
The expression is UNKNOWN
if table t2
contains (0,NULL,1)
.
Finally, if table t2
is empty, the result is TRUE
.
You might think the result should be UNKNOWN
, but
sorry, it's TRUE
. So, rather oddly, the following statement
is TRUE
when table t2
is empty:
SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);
But this statement is UNKNOWN
when table t2
is empty:
SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);
In addition, the following statement is UNKNOWN
when table t2
is empty:
SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);
In general, tables with NULL
values and empty tables are
edge cases. When writing subquery code, always consider whether
you have taken those two possibilities into account.
NOT IN
is an alias for <> ALL
. Thus these two statements
are the same:
SELECT s1 FROM t1 WHERE s1 <> ALL (SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);
The discussion to this point has been of scalar or column subqueries, that is, subqueries that return a single value or a column of values. A row subquery is a subquery variant that returns a single row and can thus return more than one column value. Here are two examples:
SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2); SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);
The queries here are both TRUE
if table t2
has
a row where column1 = 1
and column2 = 2
.
The expressions (1,2)
and ROW(1,2)
are sometimes called
row constructors. The two are equivalent.
They are legal in other contexts, too. For example, the following two
statements are semantically equivalent (although currently only the second one
can be optimized):
SELECT * FROM t1 WHERE (column1,column2) = (1,1); SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
The normal use of row constructors, though, is for comparisons with
subqueries that return two or more columns. For example, the following query answers
the request, ``find all rows in table t1
that also exist in table
t2
'':
SELECT column1,column2,column3 FROM t1 WHERE (column1,column2,column3) IN (SELECT column1,column2,column3 FROM t2);
EXISTS
and NOT EXISTS
If a subquery returns any rows at all, then EXISTS subquery
is
TRUE
, and NOT EXISTS subquery
is FALSE
.
For example:
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
Traditionally, an EXISTS
subquery starts with SELECT *
, but it
could begin with SELECT 5
or SELECT column1
or anything at
all. MySQL ignores the SELECT
list in such a subquery, so it
doesn't matter.
For the preceding example, if t2
contains any rows, even rows with
nothing but NULL
values, then the EXISTS
condition is
TRUE
. This is actually an unlikely example, since almost always a
[NOT] EXISTS
subquery will contain correlations.
Here are some more realistic examples:
SELECT DISTINCT store_type FROM Stores WHERE EXISTS (SELECT * FROM Cities_Stores WHERE Cities_Stores.store_type = Stores.store_type);
SELECT DISTINCT store_type FROM Stores WHERE NOT EXISTS (SELECT * FROM Cities_Stores WHERE Cities_Stores.store_type = Stores.store_type);
SELECT DISTINCT store_type FROM Stores S1 WHERE NOT EXISTS ( SELECT * FROM Cities WHERE NOT EXISTS ( SELECT * FROM Cities_Stores WHERE Cities_Stores.city = Cities.city AND Cities_Stores.store_type = Stores.store_type));
The last example is a double-nested NOT EXISTS
query. That is, it has a
NOT EXISTS
clause within a NOT EXISTS
clause. Formally, it
answers the question ``does a city exist with a store that is not in
Stores
?'' But it's easier to say that a nested NOT EXISTS
answers
the question ``is x TRUE for all y?''
A correlated subquery is a subquery that contains a reference to a table that also appears in the outer query. For example:
SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);
Notice that the subquery contains a reference to a column
of t1
, even though the subquery's FROM
clause doesn't mention
a table t1
. So, MySQL looks outside the subquery, and finds t1
in the
outer query.
Suppose that table t1
contains a row where column1 = 5
and
column2 = 6
; meanwhile, table t2
contains a row where
column1 = 5
and column2 = 7
. The simple expression
... WHERE column1 = ANY (SELECT column1 FROM t2)
would be
TRUE
, but in this example, the WHERE
clause within the
subquery is FALSE
(because (5,6)
is not equal to (5,7)
),
so the subquery as a whole is FALSE
.
Scoping rule: MySQL evaluates from inside to outside. For example:
SELECT column1 FROM t1 AS x WHERE x.column1 = (SELECT column1 FROM t2 AS x WHERE x.column1 = (SELECT column1 FROM t3 WHERE x.column2 = t3.column1));
In this statement, x.column2
must be a column in table t2
because
SELECT column1 FROM t2 AS x ...
renames t2
. It is not a
column in table t1
because SELECT column1 FROM t1 ...
is an
outer query that is farther out.
For subqueries in HAVING
or ORDER BY
clauses, MySQL also
looks for column names in the outer select list.
For certain cases, a correlated subquery is optimized. For example:
val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)
Otherwise, they are inefficient and likely to be slow. Rewriting the query as a join might improve performance.
FROM
clause
Subqueries are legal in a SELECT
statement's FROM
clause.
The syntax that you'll actually see is:
SELECT ... FROM (subquery) AS name ...
The AS name
clause is mandatory, because every table in a
FROM
clause must have a name. Any columns in the subquery
select list must have unique names. You can find this syntax described
elsewhere in this manual, where the term used is ``derived tables.''
For illustration, assume that you have this table:
CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
Here's how to use a subquery in the FROM
clause, using
the example table:
INSERT INTO t1 VALUES (1,'1',1.0); INSERT INTO t1 VALUES (2,'2',2.0); SELECT sb1,sb2,sb3 FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb WHERE sb1 > 1;
Result: 2, '2', 4.0
.
Here's another example: Suppose that you want to know the average of a set of sums for a grouped table. This won't work:
SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;
But this query will provide the desired information:
SELECT AVG(sum_column1) FROM (SELECT SUM(column1) AS sum_column1 FROM t1 GROUP BY column1) AS t1;
Notice that the column name used within the subquery
(sum_column1)
is recognized in the outer query.
Subqueries in the FROM
clause can return a scalar, column, row, or
table. At the moment, subqueries in the FROM
clause cannot be
correlated subqueries.
Subqueries in the FROM
clause will be executed even for the
EXPLAIN
statement (that is, derived temporary tables will be built).
This occurs because upper level queries need information about all tables
during optimization phase.
There are some new error returns that apply only to subqueries. This section groups them together because reviewing them will help remind you of some points.
ERROR 1235 (ER_NOT_SUPPORTED_YET) SQLSTATE = 42000 Message = "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'"This means that statements of the following form will not work, although this happens only in some early versions, such as MySQL 4.1.1:
SELECT * FROM t1 WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1)
ERROR 1241 (ER_OPERAND_COL) SQLSTATE = 21000 Message = "Operand should contain 1 column(s)"This error will occur in cases like this:
SELECT (SELECT column1, column2 FROM t2) FROM t1;It's okay to use a subquery that returns multiple columns, if the purpose is comparison. See section 13.1.8.5 Row Subqueries. But in other contexts, the subquery must be a scalar operand.
ERROR 1242 (ER_SUBSELECT_NO_1_ROW) SQLSTATE = 21000 Message = "Subquery returns more than 1 row"This error will occur for statements such as the following one, but only when there is more than one row in
t2
:
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);That means this error might occur in code that had been working for years, because somebody happened to make a change that affected the number of rows that the subquery can return. Remember that if the object is to find any number of rows, not just one, then the correct statement would look like this:
SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);
Error 1093 (ER_UPDATE_TABLE_USED) SQLSTATE = HY000 Message = "You can't specify target table 'x' for update in FROM clause"This error will occur in cases like this:
UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);It's okay to use a subquery for assignment within an
UPDATE
statement, since subqueries are legal in UPDATE
and DELETE
statements as well as in SELECT
statements.
However, you cannot use the same table, in this case table t1
, for
both the subquery's FROM
clause and the update target.
For transactional storage engines, a failure of a subquery causes the entire statement to fail. For non-transactional storage engines, data modifications made before the error was encountered are preserved.
Development is ongoing, so no optimization tip is reliable for the long term. Some interesting tricks that you might want to play with are:
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN ( SELECT column1 FROM t2);Instead of this query:
SELECT DISTINCT t1.column1 FROM t1, t2 WHERE t1.column1 = t2.column1;
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);Instead of this query:
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);For another example, use this query:
SELECT (SELECT column1 + 5 FROM t1) FROM t2;Instead of this query:
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
SELECT * FROM t1 WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);Instead of this query:
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1 AND t2.column2=t1.column2);
NOT (a = ANY (...))
rather than a <> ALL (...)
.
x = ANY (table containing (1,2))
rather than
x=1 OR x=2
.
= ANY
rather than EXISTS
.
These tricks might cause programs to go faster or slower. Using MySQL
facilities like the BENCHMARK()
function, you can get an idea about
what helps in your own situation. Don't worry too much about transforming
to joins except for compatibility with older versions of MySQL before 4.1
that do not support subqueries.
Some optimizations that MySQL itself makes are:
EXPLAIN
to make sure that a given subquery really is non-correlated.
IN
/ALL
/ANY
/SOME
subqueries
in an attempt to take advantage of the possibility that the select-list
columns in the subquery are indexed.
EXPLAIN
will describe as a
special join type:
... IN (SELECT indexed_column FROM single_table ...)
MIN()
or MAX()
, unless NULL
values or empty sets are involved:
value {ALL|ANY|SOME} {> | < | >= | <=} (non-correlated subquery)For example, this
WHERE
clause:
WHERE 5 > ALL (SELECT x FROM t)might be treated by the optimizer like this:
WHERE 5 > (SELECT MAX(x) FROM t)
There is a chapter titled ``How MySQL Transforms Subqueries'' in the MySQL Internals Manual. You can obtain this document by downloading the MySQL source package and looking for a file named `internals.texi' in the `Docs' directory.
Before MySQL 4.1, only nested queries of the form
INSERT ... SELECT ...
and REPLACE ... SELECT ...
are supported.
The IN()
construct can be used in other contexts to test membership in
a set of values.
It is often possible to rewrite a query without a subquery:
SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
This can be rewritten as:
SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;
The queries:
SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2); SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);
Can be rewritten as:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;
A LEFT [OUTER] JOIN
can be faster than an equivalent subquery
because the server might be able to optimize it better--a fact that is
not specific to MySQL Server alone.
Prior to SQL-92, outer joins did not exist, so subqueries were the only way
to do certain things in those bygone days. Today, MySQL Server and many
other modern database systems offer a whole range of outer join types.
For more complicated subqueries, you can often create temporary tables
to hold the subquery. In some cases, however, this option will not
work. The most frequently encountered of these cases arises with
DELETE
statements, for which standard SQL does not support joins
(except in subqueries). For this situation, there are three options
available:
DELETE
statements.
SELECT
query to obtain the primary keys
for the records to be deleted, and then use these values to construct
the DELETE
statement (DELETE FROM ... WHERE key_col IN (key1,
key2, ...)
).
DELETE
statements automatically, using the MySQL
extension CONCAT()
(in lieu of the standard ||
operator).
For example:
SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', "'", tab1.pkid, "'", ';') FROM tab1, tab2 WHERE tab1.col1 = tab2.col2;You can place this query in a script file, use the file as input to one instance of the
mysql
program, and use the program output
as input to a second instance of mysql
:
shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb
MySQL Server 4.0 supports multiple-table DELETE
statements that can be used to
efficiently delete rows based on information from one table or even
from many tables at the same time.
Multiple-table UPDATE
statements are also supported as of MySQL 4.0.
TRUNCATE
SyntaxTRUNCATE TABLE tbl_name
TRUNCATE TABLE
empties a table completely.
Logically, this is equivalent to a DELETE
statement that deletes all
rows, but there are practical differences under some circumstances.
For InnoDB
before version 5.0.3, TRUNCATE TABLE
is
mapped to DELETE
, so there is no difference. Starting with
MySQL/InnoDB-5.0.3, fast TRUNCATE TABLE
is available. The
operation will still be mapped to DELETE
if there are foreign
key constraints that reference the table.
For other storage engines, TRUNCATE TABLE
differs from
DELETE FROM
in the following ways from MySQL 4.0 and up:
TRUNCATE
TABLE
, even if the data or index files have become corrupted.
AUTO_INCREMENT
value, but starts counting from the beginning. This is true even for
MyISAM
and InnoDB
, which normally does not reuse sequence values.
In MySQL 3.23, TRUNCATE TABLE
is mapped to
COMMIT; DELETE FROM tbl_name
, so it behaves like DELETE
.
See section 13.1.1 DELETE
Syntax.
TRUNCATE TABLE
is an Oracle SQL extension.
This statement was added in MySQL 3.23.28, although from 3.23.28
to 3.23.32, the keyword TABLE
must be omitted.
UPDATE
SyntaxSingle-table syntax:
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition] [ORDER BY ...] [LIMIT row_count]
Multiple-table syntax:
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name [, tbl_name ...] SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition]
The UPDATE
statement updates columns in existing table rows with
new values. The SET
clause indicates which columns to modify
and the values they should be given. The WHERE
clause, if given,
specifies which rows should be updated. Otherwise, all rows are updated. If
the ORDER BY
clause is specified, the rows will be updated in the
order that is specified. The LIMIT
clause places a limit on the
number of rows that can be updated.
The UPDATE
statement supports the following modifiers:
LOW_PRIORITY
keyword, execution of the
UPDATE
is delayed until no other clients are reading from the table.
IGNORE
keyword, the update statement will not
abort even if errors occur during the update. Rows for which duplicate-key
conflicts occur are not updated. Rows for which columns are updated to
values that would cause data conversion errors are updated to the closet
valid values instead.
If you access a column from tbl_name in an expression,
UPDATE
uses the current value of the column. For example, the
following statement sets the age
column to one more than its
current value:
mysql> UPDATE persondata SET age=age+1;
UPDATE
assignments are evaluated from left to right. For example, the
following statement doubles the age
column, then increments it:
mysql> UPDATE persondata SET age=age*2, age=age+1;
If you set a column to the value it currently has, MySQL notices this and doesn't update it.
If you update a column that has been declared NOT NULL
by
setting to NULL
, the column is set to the default value appropriate
for the column type and the warning count is incremented. The default
value is 0
for numeric types, the empty string (''
)
for string types, and the ``zero'' value for date and time types.
UPDATE
returns the number of rows that were actually changed.
In MySQL 3.22 or later, the mysql_info()
C API function
returns the number of rows that were matched and updated and the number of
warnings that occurred during the UPDATE
.
Starting from MySQL 3.23, you can use LIMIT row_count
to
restrict the scope of the UPDATE
. A LIMIT
clause works as
follows:
LIMIT
is a rows-affected restriction.
The statement stops as soon as it has changed row_count rows that
satisfy the WHERE
clause.
LIMIT
is a rows-matched restriction. The statement
stops as soon as it has found row_count rows that satisfy the
WHERE
clause, whether or not they actually were changed.
If an UPDATE
statement includes an ORDER BY
clause, the rows
are updated in the order specified by the clause.
ORDER BY
can be used from MySQL 4.0.0.
Starting with MySQL 4.0.4, you can also perform UPDATE
operations that cover multiple tables:
UPDATE items,month SET items.price=month.price WHERE items.id=month.id;
The example shows an inner join using the comma operator, but
multiple-table UPDATE
statements can use any type of
join allowed in SELECT
statements, such as LEFT JOIN
.
Note: You cannot use ORDER BY
or LIMIT
with multiple-table
UPDATE
.
Before MySQL 4.0.18, you need the UPDATE
privilege for all
tables used in a multiple-table UPDATE
, even if they were not
updated. As of MySQL 4.0.18, you need only the SELECT
privilege for
any columns that are read but not modified.
If you use a multiple-table UPDATE
statement involving
InnoDB
tables for which there are foreign key constraints,
the MySQL optimizer might process tables in an order that differs from
that of their parent/child relationship. In this case, the statement will
fail and roll back. Instead, update a single table and rely on the
ON UPDATE
capabilities that InnoDB
provides to cause the
other tables to be modified accordingly.
Currently, you cannot update a table and select from the same table in a subquery.
ALTER DATABASE
SyntaxALTER {DATABASE | SCHEMA} [db_name] alter_specification [, alter_specification] ... alter_specification: [DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name
ALTER DATABASE
allows you to change the overall characteristics of a
database. These characteristics are stored in the `db.opt' file in the
database directory.
To use ALTER DATABASE
, you need the ALTER
privilege on the
database.
The CHARACTER SET
clause changes the default database character set.
The COLLATE
clause changes the default database collation.
Character set and collation names are discussed in
section 10 Character Set Support.
ALTER DATABASE
was added in MySQL 4.1.1.
Beginning with MySQL 4.1.8, the database name can be omitted.
The statement applies to the default database in this case.
ALTER SCHEMA
can be used as of MySQL 5.0.2.
ALTER TABLE
SyntaxALTER [IGNORE] TABLE tbl_name alter_specification [, alter_specification] ... alter_specification: ADD [COLUMN] column_definition [FIRST | AFTER col_name ] | ADD [COLUMN] (column_definition,...) | ADD INDEX [index_name] [index_type] (index_col_name,...) | ADD [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...) | ADD [CONSTRAINT [symbol]] UNIQUE [index_name] [index_type] (index_col_name,...) | ADD [FULLTEXT|SPATIAL] [index_name] (index_col_name,...) | ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...) [reference_definition] | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT} | CHANGE [COLUMN] old_col_name column_definition [FIRST|AFTER col_name] | MODIFY [COLUMN] column_definition [FIRST | AFTER col_name] | DROP [COLUMN] col_name | DROP PRIMARY KEY | DROP INDEX index_name | DROP FOREIGN KEY fk_symbol | DISABLE KEYS | ENABLE KEYS | RENAME [TO] new_tbl_name | ORDER BY col_name | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name] | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name] | DISCARD TABLESPACE | IMPORT TABLESPACE | table_options
ALTER TABLE
allows you to change the structure of an existing table.
For example, you can add or delete columns, create or destroy indexes, change
the type of existing columns, or rename columns or the table itself. You can
also change the comment for the table and type of the table.
The syntax for many of the allowable alterations is similar to clauses of the
CREATE TABLE
statement.
See section 13.2.6 CREATE TABLE
Syntax.
Some operations may result in warnings if attempted on a table for which
the storage engine does not support the operation. In MySQL 4.1 and up,
these warnings can be displayed with SHOW WARNINGS
.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
If you use ALTER TABLE
to change a column specification but
DESCRIBE tbl_name
indicates that your column was not changed, it is
possible that MySQL ignored your modification for one of the reasons
described in section 13.2.6.1 Silent Column Specification Changes. For example, if you try to change
a VARCHAR
column to CHAR
, MySQL will still use
VARCHAR
if the table contains other variable-length columns.
ALTER TABLE
works by making a temporary copy of the original table.
The alteration is performed on the copy, then the original table is deleted
and the new one is renamed. While ALTER TABLE
is executing, the
original table is readable by other clients. Updates and writes to the
table are stalled until the new table is ready, then are automatically
redirected to the new table without any failed updates.
Note that if you use any other option to ALTER TABLE
than
RENAME
, MySQL always creates a temporary table, even if the data
wouldn't strictly need to be copied (such as when you change the name of a
column). We plan to fix this in the future, but because ALTER TABLE
is not a statement that is normally used frequently, this isn't high on our
TODO list. For MyISAM
tables, you can speed up the index re-creation
operation (which is the slowest part of the alteration process) by setting
the myisam_sort_buffer_size
system variable to a high value.
ALTER TABLE
, you need ALTER
, INSERT
,
and CREATE
privileges for the table.
IGNORE
is a MySQL extension to standard SQL.
It controls how ALTER TABLE
works if there are duplicates on
unique keys in the new table.
If IGNORE
isn't specified, the copy is aborted and rolled back if
duplicate-key errors occur.
If IGNORE
is specified, then for rows with duplicates on a unique
key, only the first row is used. The others are deleted.
ADD
, ALTER
, DROP
, and
CHANGE
clauses in a single ALTER TABLE
statement. This is a
MySQL extension to standard SQL, which allows only one of each clause
per ALTER TABLE
statement. For example, to drop multiple columns in a single statement:
mysql> ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
CHANGE col_name
, DROP col_name
, and DROP
INDEX
are MySQL extensions to standard SQL.
MODIFY
is an Oracle extension to ALTER TABLE
.
COLUMN
is purely optional and can be omitted.
ALTER TABLE tbl_name RENAME TO new_tbl_name
without any other
options, MySQL simply renames any files that correspond to the table
tbl_name. There is no need to create a temporary table.
(You can also use the RENAME TABLE
statement to rename tables.
See section 13.2.12 RENAME TABLE
Syntax.)
ADD
and
CHANGE
as for CREATE TABLE
. Note that this syntax includes
the column name, not just the column type.
See section 13.2.6 CREATE TABLE
Syntax.
CHANGE old_col_name column_definition
clause. To do so, specify the old and new column names and the type that
the column currently has. For example, to rename an INTEGER
column
from a
to b
, you can do this:
mysql> ALTER TABLE t1 CHANGE a b INTEGER;If you want to change a column's type but not the name,
CHANGE
syntax still requires an old and new column name, even if they are the same.
For example:
mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;However, as of MySQL 3.22.16a, you can also use
MODIFY
to change a column's type without renaming it:
mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;
CHANGE
or MODIFY
to shorten a column for which
an index exists on part of the column (for example, if you have an index
on the first 10 characters of a VARCHAR
column), you cannot make
the column shorter than the number of characters that are indexed.
CHANGE
or MODIFY
, MySQL
tries to convert existing column values to the new type as well as possible.
FIRST
or
AFTER col_name
to add a column at a specific position
within a table row. The default is to add the column last.
From MySQL 4.0.1 on, you can also use FIRST
and
AFTER
in CHANGE
or MODIFY
operations.
ALTER COLUMN
specifies a new default value for a column
or removes the old default value.
If the old default is removed and the column can be NULL
, the new
default is NULL
. If the column cannot be NULL
, MySQL
assigns a default value, as described in
section 13.2.6 CREATE TABLE
Syntax.
DROP INDEX
removes an index. This is a MySQL extension to
standard SQL. See section 13.2.9 DROP INDEX
Syntax.
DROP TABLE
instead.
DROP PRIMARY KEY
drops the primary index. (Prior to MySQL 4.1.2,
if no primary index exists, DROP PRIMARY KEY
drops the first
UNIQUE
index in the table.
MySQL marks the first UNIQUE
key as the PRIMARY KEY
if no PRIMARY KEY
was specified explicitly.)
If you add a UNIQUE INDEX
or PRIMARY KEY
to a table, it
is stored before any non-unique index so that MySQL can detect
duplicate keys as early as possible.
ORDER BY
allows you to create the new table with the rows in a
specific order. Note that the table will not remain in this order after
inserts and deletes. This option is mainly useful when you know that you
are mostly going to query the rows in a certain order; by using this option
after big changes to the table, you might be able to get higher performance.
In some cases, it might make sorting easier for MySQL if the table is in
order by the column that you want to order it by later.
ALTER TABLE
on a MyISAM
table, all non-unique
indexes are created in a separate batch (as for REPAIR TABLE
).
This should make ALTER TABLE
much faster when you have many indexes.
As of MySQL 4.0, this feature can be activated explicitly. ALTER
TABLE ... DISABLE KEYS
tells MySQL to stop updating non-unique indexes for a
MyISAM
table. ALTER TABLE ... ENABLE KEYS
then should be used
to re-create missing indexes. MySQL does this with a special algorithm that
is much faster than inserting keys one by one, so disabling keys before
performing bulk insert operations should give a considerable speedup. Using
ALTER TABLE ... DISABLE KEYS
will require the INDEX
privilege
in addition to the privileges mentioned earlier.
FOREIGN KEY
and REFERENCES
clauses are supported by the
InnoDB
storage engine, which implements
ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...)
.
See section 15.7.4 FOREIGN KEY
Constraints.
For other storage engines, the clauses are parsed but ignored.
The CHECK
clause is parsed but ignored by all storage engines.
See section 13.2.6 CREATE TABLE
Syntax.
The reason for accepting but ignoring syntax clauses is for compatibility,
to make it easier to port code from other SQL servers, and to run applications
that create tables with references.
See section 1.5.5 MySQL Differences from Standard SQL.
InnoDB
supports the use of ALTER
TABLE
to drop foreign keys:
ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;For more information, see section 15.7.4
FOREIGN KEY
Constraints.
ALTER TABLE
ignores the DATA DIRECTORY
and INDEX
DIRECTORY
table options.
CHAR
, VARCHAR
,
TEXT
) to a new character set, use a statement like this:
ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;This is useful, for example, after upgrading from MySQL 4.0.x to 4.1.x. See section 10.10 Upgrading Character Sets from MySQL 4.0. Warning: The preceding operation will convert column values between the character sets. This is not what you want if you have a column in one character set (like
latin1
) but the stored values actually use
some other, incompatible character set (like utf8
). In this case,
you have to do the following for each such column:
ALTER TABLE t1 CHANGE c1 c1 BLOB; ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;The reason this works is that there is no conversion when you convert to or from
BLOB
columns.
To change only the default character set for a table, use this
statement:
ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;The word
DEFAULT
is optional.
The default character set is the character set that is used if
you don't specify the character set for a new column you add to a table
(for example, with ALTER TABLE ... ADD column
).
Warning: From MySQL 4.1.2 and up, ALTER TABLE ... DEFAULT
CHARACTER SET
and ALTER TABLE ... CHARACTER SET
are equivalent and
change only the default table character set. In MySQL 4.1 releases before
4.1.2, ALTER TABLE ... DEFAULT CHARACTER SET
changes the default
character set, but ALTER TABLE ... CHARACTER SET
(without
DEFAULT
) changes the default character set and also converts
all columns to the new character set.
InnoDB
table that is created with its own tablespace in an
`.ibd' file, that file can be discarded and imported. To discard the
`.ibd' file, use this statement:
ALTER TABLE tbl_name DISCARD TABLESPACE;This deletes the current `.ibd' file, so be sure that you have a backup first. Attempting to access the table while the tablespace file is discarded results in an error. To import the backup `.ibd' file back into the table, copy it into the database directory, then issue this statement:
ALTER TABLE tbl_name IMPORT TABLESPACE;See section 15.7.6 Using Per-Table Tablespaces.
mysql_info()
C API function, you can find out how many
records were copied, and (when IGNORE
is used) how many records were
deleted due to duplication of unique key values.
See section 22.2.3.31 mysql_info()
.
Here are some examples that show uses of ALTER TABLE
.
Begin with a table t1
that is created as shown here:
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
To rename the table from t1
to t2
:
mysql> ALTER TABLE t1 RENAME t2;
To change column a
from INTEGER
to TINYINT NOT NULL
(leaving the name the same), and to change column b
from
CHAR(10)
to CHAR(20)
as well as renaming it from b
to
c
:
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
To add a new TIMESTAMP
column named d
:
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
To add indexes on column d
and on column a
:
mysql> ALTER TABLE t2 ADD INDEX (d), ADD INDEX (a);
To remove column c
:
mysql> ALTER TABLE t2 DROP COLUMN c;
To add a new AUTO_INCREMENT
integer column named c
:
mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, -> ADD PRIMARY KEY (c);
Note that we indexed c
(as a PRIMARY KEY
), because
AUTO_INCREMENT
columns must be indexed, and also that we declare
c
as NOT NULL
, because primary key columns cannot be
NULL
.
When you add an AUTO_INCREMENT
column, column values are filled in
with sequence numbers for you automatically. For MyISAM
tables,
you can set the first
sequence number by executing SET INSERT_ID=value
before
ALTER TABLE
or by using the AUTO_INCREMENT=value
table option.
See section 13.5.3 SET
Syntax.
From MySQL 5.0.3, you can use the ALTER TABLE ...
AUTO_INCREMENT=value
table option for InnoDB
tables
to set the sequence number for new rows if the value is greater than the
maximum value in the AUTO_INCREMENT
column. If the value is less
than the maximum column value, no error message is given and the current
sequence value is not changed.
With MyISAM
tables, if you don't change the AUTO_INCREMENT
column, the sequence number will not be affected. If you drop an
AUTO_INCREMENT
column and then add another AUTO_INCREMENT
column, the numbers are resequenced beginning with 1.
See section A.7.1 Problems with ALTER TABLE
.
ALTER VIEW
SyntaxALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
This statement changes the definition of an existing view.
The syntax is similar to that for CREATE VIEW
.
See section 13.2.7 CREATE VIEW
Syntax.
This statement was added in MySQL 5.0.1.
CREATE DATABASE
SyntaxCREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [create_specification [, create_specification] ...] create_specification: [DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name
CREATE DATABASE
creates a database with the given name. To use
CREATE DATABASE
, you need the CREATE
privilege on the database.
Rules for allowable database names are given in section 9.2 Database, Table, Index, Column, and Alias Names. An error
occurs if the database exists and you didn't specify IF NOT EXISTS
.
As of MySQL 4.1.1, create_specification
options can be given to
specify database characteristics. Database characteristics are stored in
the `db.opt' file in the database directory. The CHARACTER SET
clause specifies the default database character set. The COLLATE
clause specifies the default database collation. Character set and
collation names are discussed in section 10 Character Set Support.
Databases in MySQL are implemented as directories containing files
that correspond to tables in the database. Because there are no tables in a
database when it is initially created, the CREATE DATABASE
statement
only creates a directory under the MySQL data directory (and the `db.opt'
file, for MySQL 4.1.1 and up).
If you manually create a directory under the data directory (for example, with
mkdir
), the server considers it a database directory and it will show
up in the output of SHOW DATABASES
.
CREATE SCHEMA
can be used as of MySQL 5.0.2.
You can also use the mysqladmin
program to create databases.
See section 8.4 mysqladmin
, Administering a MySQL Server.
CREATE INDEX
SyntaxCREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [USING index_type] ON tbl_name (index_col_name,...) index_col_name: col_name [(length)] [ASC | DESC]
In MySQL 3.22 or later, CREATE INDEX
is mapped to an
ALTER TABLE
statement to create indexes.
See section 13.2.2 ALTER TABLE
Syntax.
The CREATE INDEX
statement doesn't do anything prior
to MySQL 3.22.
Normally, you create all indexes on a table at the time the table itself
is created with CREATE TABLE
.
See section 13.2.6 CREATE TABLE
Syntax.
CREATE INDEX
allows you to add indexes to existing tables.
A column list of the form (col1,col2,...)
creates a multiple-column
index. Index values are formed by concatenating the values of the given
columns.
For CHAR
and VARCHAR
columns, indexes can be created that
use only part of a column, using col_name(length)
syntax to index
a prefix consisting of the first length characters of each column
value. BLOB
and TEXT
columns also can be indexed, but a prefix
length must be given.
The statement shown here creates an index using the first 10 characters
of the name
column:
CREATE INDEX part_of_name ON customer (name(10));
Because most names usually differ in the first 10 characters, this index should
not be much slower than an index created from the entire name
column.
Also, using partial columns for indexes can make the index file much smaller,
which could save a lot of disk space and might also speed up INSERT
operations!
Prefixes can be up to 255 bytes long (or 1000 bytes for MyISAM
and InnoDB
tables as of MySQL 4.1.2). Note that prefix limits
are measured in bytes, whereas the prefix length in CREATE INDEX
statements is interpreted as number of characters. Take this into account
when specifying a prefix length for a column that uses a multi-byte
character set.
You can add an index on a column that can have NULL
values only if you are using MySQL 3.23.2 or newer and are using the
MyISAM
, InnoDB
, or BDB
table type. You can only add an
index on a BLOB
or TEXT
column if you are using
MySQL 3.23.2 or newer and are using the MyISAM
or BDB
table type, or MySQL 4.0.14 or newer and the InnoDB
table type.
An index_col_name specification can end with ASC
or DESC
.
These keywords are allowed for future extensions for specifying ascending
or descending index value storage. Currently they are parsed but ignored;
index values are always stored in ascending order.
From MySQL 4.1.0 on, some storage engines allow you to specify an index
type when creating an index. The syntax for the index_type
specifier is USING type_name
. The allowable type_name
values supported by different storage engines are shown in the following
table. Where multiple index types are listed, the first one is the
default when no index_type specifier is given.
Storage Engine | Allowable Index Types |
MyISAM | BTREE
|
InnoDB | BTREE
|
MEMORY/HEAP | HASH , BTREE
|
Example:
CREATE TABLE lookup (id INT) ENGINE = MEMORY; CREATE INDEX id_index USING BTREE ON lookup (id);
TYPE type_name
can be used as a synonym for USING type_name
to specify an index type. However, USING
is the preferred form.
Also, the index name that precedes the index type in the index
specification syntax is not optional with TYPE
. This is because,
unlike USING
, TYPE
is not a reserved word and thus is
interpreted as an index name.
If you specify an index type that is not legal for a storage engine, but there is another index type available that the engine can use without affecting query results, the engine will use the available type.
For more information about how MySQL uses indexes, see section 7.4.5 How MySQL Uses Indexes.
FULLTEXT
indexes can index only CHAR
, VARCHAR
, and
TEXT
columns, and only in MyISAM
tables. FULLTEXT
indexes
are available in MySQL 3.23.23 or later.
section 12.6 Full-Text Search Functions.
SPATIAL
indexes can index only spatial columns,
and only in MyISAM
tables. SPATIAL
indexes
are available in MySQL 4.1 or later. Spatial column types are described in
section 18 Spatial Extensions in MySQL.
CREATE TABLE
SyntaxCREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [select_statement]
Or:
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(] LIKE old_tbl_name [)]; create_definition: column_definition | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...) | KEY [index_name] [index_type] (index_col_name,...) | INDEX [index_name] [index_type] (index_col_name,...) | [CONSTRAINT [symbol]] UNIQUE [INDEX] [index_name] [index_type] (index_col_name,...) | [FULLTEXT|SPATIAL] [INDEX] [index_name] (index_col_name,...) | [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name,...) [reference_definition] | CHECK (expr) column_definition: col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string'] [reference_definition] type: TINYINT[(length)] [UNSIGNED] [ZEROFILL] | SMALLINT[(length)] [UNSIGNED] [ZEROFILL] | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL] | INT[(length)] [UNSIGNED] [ZEROFILL] | INTEGER[(length)] [UNSIGNED] [ZEROFILL] | BIGINT[(length)] [UNSIGNED] [ZEROFILL] | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL] | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL] | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL] | DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL] | NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL] | DATE | TIME | TIMESTAMP | DATETIME | CHAR(length) [BINARY | ASCII | UNICODE] | VARCHAR(length) [BINARY] | TINYBLOB | BLOB | MEDIUMBLOB | LONGBLOB | TINYTEXT [BINARY] | TEXT [BINARY] | MEDIUMTEXT [BINARY] | LONGTEXT [BINARY] | ENUM(value1,value2,value3,...) | SET(value1,value2,value3,...) | spatial_type index_col_name: col_name [(length)] [ASC | DESC] reference_definition: REFERENCES tbl_name [(index_col_name,...)] [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE] [ON DELETE reference_option] [ON UPDATE reference_option] reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT table_options: table_option [table_option] ... table_option: {ENGINE|TYPE} = {BDB|HEAP|ISAM|InnoDB|MERGE|MRG_MYISAM|MYISAM} | AUTO_INCREMENT = value | AVG_ROW_LENGTH = value | CHECKSUM = {0 | 1} | COMMENT = 'string' | MAX_ROWS = value | MIN_ROWS = value | PACK_KEYS = {0 | 1 | DEFAULT} | PASSWORD = 'string' | DELAY_KEY_WRITE = {0 | 1} | ROW_FORMAT = {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT} | RAID_TYPE = { 1 | STRIPED | RAID0 } RAID_CHUNKS = value RAID_CHUNKSIZE = value | UNION = (tbl_name[,tbl_name]...) | INSERT_METHOD = { NO | FIRST | LAST } | DATA DIRECTORY = 'absolute path to directory' | INDEX DIRECTORY = 'absolute path to directory' | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name] select_statement: [IGNORE | REPLACE] [AS] SELECT ... (Some legal select statement)
CREATE TABLE
creates a table with the given name.
You must have the CREATE
privilege for the table.
Rules for allowable table names are given in section 9.2 Database, Table, Index, Column, and Alias Names. By default, the table is created in the current database. An error occurs if the table exists, if there is no current database, or if the database does not exist.
In MySQL 3.22 or later, the table name can be specified as
db_name.tbl_name to create the table in a specific database.
This works whether or not there is a current database.
If you use quoted identifiers, quote the database and table names
separately. For example, `mydb`.`mytbl`
is legal, but
`mydb.mytbl`
is not.
From MySQL 3.23 on, you can use the TEMPORARY
keyword when
creating a table. A TEMPORARY
table is visible only to the
current connection, and is dropped automatically when the
connection is closed. This means that two different
connections can use the same temporary table name without conflicting
with each other or with an existing non-TEMPORARY
table of the same
name. (The existing table is hidden until the temporary table is dropped.)
From MySQL 4.0.2 on, you must have the CREATE TEMPORARY TABLES
privilege to be able to create temporary tables.
In MySQL 3.23 or later, you can use the keywords
IF NOT EXISTS
so that an error does not occur if the table
exists. Note that there is no verification that the existing table has a
structure identical to that indicated by the CREATE TABLE
statement.
MySQL represents each table by an `.frm' table format
(definition) file in the database directory. The storage engine for the table
might create other files as well.
In the case of MyISAM
tables, the storage engine creates three files
for a table named tbl_name:
File | Purpose |
tbl_name.frm | Table format (definition) file |
tbl_name.MYD | Data file |
tbl_name.MYI | Index file |
The files created by each storage engine to represent tables are described in section 14 MySQL Storage Engines and Table Types.
For general information on the properties of the various column types, see section 11 Column Types. For information about spatial column types, see section 18 Spatial Extensions in MySQL.
NULL
nor NOT NULL
is specified, the column
is treated as though NULL
had been specified.
AUTO_INCREMENT
.
When you insert a value of NULL
(recommended) or 0
into an
indexed
AUTO_INCREMENT
column, the column is set to the next sequence value.
Typically this is value+1
, where
value is the largest value for the column currently in the table.
AUTO_INCREMENT
sequences begin with 1
.
See section 22.2.3.33 mysql_insert_id()
.
As of MySQL 4.1.1, specifying the NO_AUTO_VALUE_ON_ZERO
flag for the
--sql-mode
server option or the sql_mode
system variable allows
you to store 0
in AUTO_INCREMENT
columns as 0
without
generating a new sequence value.
See section 5.2.1 mysqld
Command-Line Options.
Note: There can be only one AUTO_INCREMENT
column per
table, it must be indexed, and it cannot have a DEFAULT
value.
As of MySQL 3.23, an AUTO_INCREMENT
column will work properly
only if it contains only positive values. Inserting a
negative number is regarded as inserting a very large positive number.
This is done to avoid precision problems when numbers ``wrap'' over from
positive to negative and also to ensure that you don't accidentally
get an AUTO_INCREMENT
column that contains 0
.
For MyISAM
and BDB
tables, you can specify an
AUTO_INCREMENT
secondary column in a multiple-column key.
See section 3.6.9 Using AUTO_INCREMENT
.
To make MySQL compatible with some ODBC applications, you can find the
AUTO_INCREMENT
value for the last inserted row with the following query:
SELECT * FROM tbl_name WHERE auto_col IS NULL
CHARACTER
SET
attribute to specify the character set and, optionally, a collation
for the column. For details, see section 10 Character Set Support.
CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);Also as of 4.1, MySQL interprets length specifications in character column definitions in characters. (Earlier versions interpret them in bytes.)
NULL
values are handled differently for TIMESTAMP
columns
than for other column types. Before MySQL 4.1.6, you cannot store a
literal NULL
in a TIMESTAMP
column; setting the column to
NULL
sets it to the current date and time. Because TIMESTAMP
columns behave this way, the NULL
and NOT NULL
attributes do
not apply in the normal way and are ignored if you specify them. On the
other hand, to make it easier for MySQL clients to use TIMESTAMP
columns, the server reports that such columns can be assigned NULL
values (which is true), even though TIMESTAMP
never actually will
contain a NULL
value. You can see this when you use DESCRIBE
tbl_name
to get a description of your table.
Note that setting a TIMESTAMP
column to 0
is not the same
as setting it to NULL
, because 0
is a valid TIMESTAMP
value.
DEFAULT
clause specifies a default value for a column.
With one exception, the default value must be a constant; it cannot be
a function or an expression. This means, for example, that you cannot
set the default for a date column to be the value of a function such as
NOW()
or CURRENT_DATE
. The exception is that you can specify
CURRENT_TIMESTAMP
as the default for a TIMESTAMP
column as
of MySQL 4.1.2.
See section 11.3.1.2 TIMESTAMP
Properties as of MySQL 4.1.
Prior to MySQL 5.0.2, if a column definition includes no explicit
DEFAULT
value, MySQL determines the default value as follows:
If the column can take NULL
as a value, the column is defined with
an explicit DEFAULT NULL
clause.
If the column cannot take NULL
as the value, MySQL defines the
column with an explicit DEFAULT
clause, using the implicit default
value for the column data type. Implicit defaults are defined as follows:
AUTO_INCREMENT
attribute, the default is 0
. For an AUTO_INCREMENT
column, the
default value is the next value in the sequence.
TIMESTAMP
, the default is the
appropriate ``zero'' value for the type. For the first TIMESTAMP
column in a table, the default value is the current date and time.
See section 11.3 Date and Time Types.
ENUM
, the default value is the empty
string. For ENUM
, the default is the first enumeration value.
BLOB
and TEXT
columns cannot be assigned a default value.
As of MySQL 5.0.2, if a column definition includes no explicit
DEFAULT
value, MySQL determines the default value as follows:
If the column can take NULL
as a value, the column is defined with
an explicit DEFAULT NULL
clause. This is the same as before 5.0.2.
If the column cannot take NOT NULL
as the value, MySQL defines
the column with no explicit DEFAULT
clause. For data entry, if an
INSERT
or REPLACE
statement includes no value for the column,
MySQL handles the column according to the SQL mode in effect at the time:
SHOW CREATE TABLE
statement to
see which columns have an explicit DEFAULT
clause.
COMMENT
option.
The comment is displayed by the
SHOW CREATE TABLE
and SHOW FULL COLUMNS
statements.
This option is operational as of MySQL 4.1.
(It is allowed but ignored in earlier versions.)
SERIAL
can be used as an alias
for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE
.
KEY
is normally a synonym for INDEX
. From MySQL 4.1, the key
attribute PRIMARY KEY
can also be specified as just KEY
when
given in a column definition. This was implemented for compatibility with
other database systems.
UNIQUE
index is one in which all values in the index
must be distinct. An error occurs if you try to add a new row with a key
that matches an existing row. The exception to this is that if a column
in the index is allowed to contain NULL
values, it can contain
multiple NULL
values. This exception does not apply to BDB
tables, for which an indexed column allows only a single NULL
.
PRIMARY KEY
is a unique KEY
where all key columns must be
defined as NOT NULL
. If they are not explicitly declared as NOT
NULL
, MySQL will declare them so implicitly (and silently). A table can
have only one PRIMARY KEY
. If you don't have a PRIMARY KEY
and an application asks for the PRIMARY KEY
in your tables, MySQL
returns the first UNIQUE
index that has no NULL
columns as
the PRIMARY KEY
.
PRIMARY KEY
is placed first, followed
by all UNIQUE
indexes, and then the non-unique indexes. This helps the
MySQL optimizer to prioritize which index to use and also more quickly
to detect duplicated UNIQUE
keys.
PRIMARY KEY
can be a multiple-column index. However, you cannot
create a multiple-column index using the PRIMARY KEY
key attribute in a
column specification. Doing so will mark only that single column as primary.
You must use a separate PRIMARY KEY(index_col_name, ...)
clause.
PRIMARY KEY
or UNIQUE
index consists of only one column
that has an integer type, you can also refer to the column as _rowid
in SELECT
statements (new in MySQL 3.23.11).
PRIMARY KEY
is PRIMARY
. For other
indexes, if you don't assign a name, the index is assigned the same name as
the first indexed column, with an optional suffix (_2
, _3
,
...
) to make it unique. You can see index names for a table using
SHOW INDEX FROM tbl_name
.
See section 13.5.4.11 SHOW INDEX
Syntax.
USING type_name
.
Example:
CREATE TABLE lookup (id INT, INDEX USING BTREE (id)) ENGINE = MEMORY;For details about
USING
, see
section 13.2.5 CREATE INDEX
Syntax.
For more information about how MySQL uses indexes, see
section 7.4.5 How MySQL Uses Indexes.
MyISAM
, InnoDB
, BDB
, and (as of MySQL 4.0.2)
MEMORY
storage engines support indexes on columns that can have
NULL
values. In other cases, you must declare indexed columns
as NOT NULL
or an error results.
col_name(length)
syntax in an index specification, you can create
an index that uses only the first length characters of a CHAR
or VARCHAR
column. Indexing only a prefix of column values like this
can make the index file much smaller.
See section 7.4.3 Column Indexes.
The MyISAM
and (as of MySQL 4.0.14) InnoDB
storage engines also
support indexing on BLOB
and TEXT
columns. When indexing
a BLOB
or TEXT
column, you must specify a prefix
length for the index. For example:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));Prefixes can be up to 255 bytes long (or 1000 bytes for
MyISAM
and InnoDB
tables as of MySQL 4.1.2). Note that prefix limits
are measured in bytes, whereas the prefix length in CREATE TABLE
statements is interpreted as number of characters. Take this into account
when specifying a prefix length for a column that uses a multi-byte
character set.
ASC
or DESC
.
These keywords are allowed for future extensions for specifying ascending
or descending index value storage. Currently they are parsed but ignored;
index values are always stored in ascending order.
ORDER BY
or GROUP BY
with a TEXT
or
BLOB
column, the server sorts values using only the initial number of
bytes indicated by the max_sort_length
system variable.
See section 11.4.3 The BLOB
and TEXT
Types.
FULLTEXT
indexes. They are used for full-text search. Only the
MyISAM
table type supports FULLTEXT
indexes. They can be created
only from CHAR
, VARCHAR
, and TEXT
columns.
Indexing always happens over the entire column; partial indexing is not
supported and any prefix length is ignored if specified. See section 12.6 Full-Text Search Functions for details of operation.
SPATIAL
indexes on
spatial column types. Spatial types are supported only for MyISAM
tables and indexed columns must be declared as NOT NULL
. See
section 18 Spatial Extensions in MySQL.
InnoDB
tables support checking of
foreign key constraints. See section 15 The InnoDB
Storage Engine. Note that the
FOREIGN KEY
syntax in InnoDB
is more restrictive than
the syntax presented for the CREATE TABLE
statement at the beginning of
this section: The columns of the referenced
table must always be explicitly named.
InnoDB
supports both ON DELETE
and ON UPDATE
actions on foreign keys as of MySQL 3.23.50 and 4.0.8, respectively.
For the precise syntax, see
section 15.7.4 FOREIGN KEY
Constraints.
For other storage engines, MySQL Server parses the FOREIGN KEY
and REFERENCES
syntax in CREATE TABLE
statements,
but without further action being taken.
The CHECK
clause is parsed but ignored by all storage engines.
See section 1.5.5.5 Foreign Keys.
MyISAM
and ISAM
tables,
each NULL
column takes one bit extra, rounded up to the nearest byte.
The maximum record length in bytes can be calculated as follows:
row length = 1 + (sum of column lengths) + (number of NULL columns + delete_flag + 7)/8 + (number of variable-length columns)delete_flag is 1 for tables with static record format. Static tables use a bit in the row record for a flag that indicates whether the row has been deleted. delete_flag is 0 for dynamic tables because the flag is stored in the dynamic row header. These calculations do not apply for
InnoDB
tables, for which
storage size is no different for NULL
columns than for NOT
NULL
columns.
The table_options part of the CREATE TABLE
syntax can be used
in MySQL 3.23 and above.
The ENGINE
and TYPE
options specify the storage engine for the
table. ENGINE
was added in MySQL 4.0.18 (for 4.0) and 4.1.2 (for 4.1).
It is the preferred option name as of those versions, and TYPE
has
become deprecated. TYPE
will be supported throughout the 4.x series,
but likely will be removed in MySQL 5.1.
The ENGINE
and TYPE
options take the following values:
Storage Engine | Description |
BDB | Transaction-safe tables with page locking. See section 14.4 The BDB (BerkeleyDB ) Storage Engine.
|
BerkeleyDB | An alias for BDB .
|
HEAP | The data for this table is stored only in memory. See section 14.3 The MEMORY (HEAP ) Storage Engine.
|
ISAM | The original MySQL storage engine. See section 14.9 The ISAM Storage Engine.
|
InnoDB | Transaction-safe tables with row locking and foreign keys. See section 15 The InnoDB Storage Engine.
|
MEMORY | An alias for HEAP . (Actually, as of MySQL 4.1, MEMORY is the preferred term.)
|
MERGE | A collection of MyISAM tables used as one table. See section 14.2 The MERGE Storage Engine.
|
MRG_MyISAM | An alias for MERGE .
|
MyISAM | The binary portable storage engine that is the improved replacement for ISAM . See section 14.1 The MyISAM Storage Engine.
|
See section 14 MySQL Storage Engines and Table Types.
If a storage engine is specified that is not available,
MySQL uses MyISAM
instead.
For example, if a table definition includes the ENGINE=BDB
option but the
MySQL server does not support BDB
tables, the table is created
as a MyISAM
table. This makes it possible to have a replication
setup where you have transactional tables on the master but tables created
on the slave are non-transactional (to get more speed). In MySQL 4.1.1, a
warning occurs if the storage engine specification is not honored.
The other table options are used to optimize the behavior of the table. In most cases, you don't have to specify any of them. The options work for all storage engines unless otherwise indicated:
AUTO_INCREMENT
AUTO_INCREMENT
value for the table. This works for
MyISAM
only. To set the first auto-increment value for an InnoDB
table, insert a dummy row with a value one less than the desired value after
creating the table, and then delete the dummy row.
In MySQL 5.0.3 or later, the initial AUTO_INCREMENT
value for the table
works also for the InnoDB
table.
AVG_ROW_LENGTH
MyISAM
table, MySQL uses the product of the
MAX_ROWS
and AVG_ROW_LENGTH
options to decide how big the
resulting table will be. If you don't specify either option, the maximum
size for a table will be 4GB (or 2GB if your operating system only supports
2GB tables). The reason for this is just to keep down the pointer sizes to
make the index smaller and faster if you don't really need big files. If
you want all your tables to be able to grow above the 4GB limit and are
willing to have your smaller tables slightly slower and larger than
necessary, you may increase the default pointer size by setting the
myisam_data_pointer_size
system variable, which was added in MySQL
4.1.2.
See section 5.2.3 Server System Variables.
CHECKSUM
CHECKSUM TABLE
statement reports the
checksum. (MyISAM
only.)
COMMENT
MAX_ROWS
MIN_ROWS
PACK_KEYS
DEFAULT
(MySQL 4.0) tells the storage engine to only pack long
CHAR
/VARCHAR
columns.
(MyISAM
and ISAM
only.)
If you don't use PACK_KEYS
, the default is to only pack strings,
not numbers. If you use PACK_KEYS=1
, numbers will be packed as well.
When packing binary number keys, MySQL uses prefix compression:
storage_size_for_key + pointer_size
(where the pointer
size is usually 4). Conversely,
you will get a big benefit from prefix compression only if you have many
numbers that are the same. If all keys are totally different, you will
use one byte more per key, if the key isn't a key that can have NULL
values. (In this case, the packed key length will be stored in the same
byte that is used to mark if a key is NULL
.)
PASSWORD
DELAY_KEY_WRITE
MyISAM
only.)
ROW_FORMAT
MyISAM
tables. The option value can FIXED
or DYNAMIC
for
static or variable-length row format. myisampack
sets the type to
COMPRESSED
.
See section 14.1.3 MyISAM
Table Storage Formats.
Starting with MySQL/InnoDB-5.0.3, InnoDB records are stored in a more
compact format (ROW_FORMAT=COMPACT
) by default. The old format
can be requested by specifying ROW_FORMAT=REDUNDANT
.
RAID_TYPE
RAID_TYPE
option can help you to exceed the 2GB/4GB limit for
the MyISAM
data file (not the index file) on operating systems that
don't support big files. This option is unnecessary and not recommended for
filesystems that support big files.
You can get more speed from the I/O bottleneck by putting RAID
directories on different physical disks. The only allowed
RAID_TYPE
is STRIPED
. 1
and RAID0
are aliases
for STRIPED
.
If you specify the RAID_TYPE
option for a MyISAM
table,
specify the RAID_CHUNKS
and RAID_CHUNKSIZE
options as well.
The maximum RAID_CHUNKS
value is 255.
MyISAM
will create RAID_CHUNKS
subdirectories named `00',
`01', `02', ... `09', `0a', `0b', ...
in the database directory. In each of these directories, MyISAM
will create a file `tbl_name.MYD'. When writing data to the data file,
the RAID
handler maps the first RAID_CHUNKSIZE*1024
bytes to
the first file, the next RAID_CHUNKSIZE*1024
bytes to the next file,
and so on.
RAID_TYPE
works on any operating system, as long as you have built
MySQL with the --with-raid
option to configure
. To determine
whether a server supports RAID
tables, use SHOW VARIABLES LIKE
'have_raid'
to see whether the variable value is YES
.
UNION
UNION
is used when you want to use a collection of identical
tables as one. This works only with MERGE
tables.
See section 14.2 The MERGE
Storage Engine.
For the moment, you must have SELECT
, UPDATE
, and
DELETE
privileges for the tables you map to a MERGE
table.
Originally, all used tables had to be in the same database
as the MERGE
table itself. This restriction has been lifted as of
MySQL 4.1.1.
INSERT_METHOD
MERGE
table, you have to specify with
INSERT_METHOD
into which table the row should be inserted.
INSERT_METHOD
is an option useful for MERGE
tables only.
This option was introduced in MySQL 4.0.0.
See section 14.2 The MERGE
Storage Engine.
DATA DIRECTORY
INDEX DIRECTORY
DATA DIRECTORY='directory'
or INDEX
DIRECTORY='directory'
you can specify where the MyISAM
storage engine should
put a table's data file and index file. Note that the directory should be a full
path to the directory (not a relative path).
These options work only for MyISAM
tables from MySQL 4.0 on, when
you are not using the --skip-symbolic-links
option. Your operating
system must also have a working, thread-safe realpath()
call.
See section 7.6.1.2 Using Symbolic Links for Tables on Unix.
As of MySQL 3.23, you can create one table from another by adding a
SELECT
statement at the end of the CREATE TABLE
statement:
CREATE TABLE new_tbl SELECT * FROM orig_tbl;
MySQL will create new column for all elements
in the SELECT
. For example:
mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT, -> PRIMARY KEY (a), KEY(b)) -> TYPE=MyISAM SELECT b,c FROM test2;
This creates a MyISAM
table with three columns, a
, b
,
and c
. Notice that the columns from the SELECT
statement
are appended to the right side of the table, not overlapped onto it.
Take the following example:
mysql> SELECT * FROM foo; +---+ | n | +---+ | 1 | +---+ mysql> CREATE TABLE bar (m INT) SELECT n FROM foo; Query OK, 1 row affected (0.02 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM bar; +------+---+ | m | n | +------+---+ | NULL | 1 | +------+---+ 1 row in set (0.00 sec)
For each row in table foo
, a row is inserted in bar
with
the values from foo
and default values for the new columns.
If any errors occur while copying the data to the table, it is automatically dropped and not created.
CREATE TABLE ... SELECT
will not automatically create any indexes
for you. This is done intentionally to make the statement as flexible as
possible. If you want to have indexes in the created table, you should
specify these before the SELECT
statement:
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
Some conversion of column types might occur. For example, the
AUTO_INCREMENT
attribute is not preserved, and VARCHAR
columns can become CHAR
columns.
When creating a table with CREATE ... SELECT
, make sure to alias any
function calls or expressions in the query. If you do not, the CREATE
statement might fail or result in undesirable column names.
CREATE TABLE artists_and_works SELECT artist.name, COUNT(work.artist_id) AS number_of_works FROM artist LEFT JOIN work ON artist.id = work.artist_id GROUP BY artist.id;
As of MySQL 4.1, you can explicitly specify the type for a generated column:
CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;
In MySQL 4.1, you can also use LIKE
to create an empty table based on the
definition of another table, including any column attributes and
indexes the original table has:
CREATE TABLE new_tbl LIKE orig_tbl;
CREATE TABLE ... LIKE
does not copy any DATA DIRECTORY
or
INDEX DIRECTORY
table options that were specified for the original
table, or any foreign key definitions.
You can precede the SELECT
by IGNORE
or REPLACE
to indicate how to handle records that duplicate unique key values.
With IGNORE
, new records that duplicate an existing record on a
unique key value are discarded. With REPLACE
, new records replace
records that have the same unique key value. If neither IGNORE
nor REPLACE
is specified, duplicate unique key values result in
an error.
To ensure that the update log/binary log can be used to re-create the
original tables, MySQL will not allow concurrent inserts during
CREATE TABLE ... SELECT
.
In some cases, MySQL silently changes column specifications from
those given in a CREATE TABLE
or ALTER TABLE
statement:
VARCHAR
columns with a length less than four are changed to
CHAR
.
VARCHAR
, TEXT
, or BLOB
),
all CHAR
columns longer than three characters are changed to
VARCHAR
columns. This doesn't affect how you use the columns in
any way; in MySQL, VARCHAR
is just a different way to
store characters. MySQL performs this conversion because it
saves space and makes table operations faster. See section 14 MySQL Storage Engines and Table Types.
CHAR
or VARCHAR
column with a
length specification greater than 255 is converted to the smallest TEXT
type that can hold values of the given length.
For example, VARCHAR(500)
is converted to TEXT
, and
VARCHAR(200000)
is converted to MEDIUMTEXT
.
This is a compatibility feature.
TIMESTAMP
display sizes are discarded from MySQL 4.1 on, due
to changes made to the TIMESTAMP
column type in that version.
Before MySQL 4.1, TIMESTAMP
display sizes must be even and in the
range from 2 to 14. If you specify a display size of 0 or greater than
14, the size is coerced to 14. Odd-valued sizes in the range from 1 to
13 are coerced to the next higher even number.
NULL
in a TIMESTAMP
column; setting
it to NULL
sets it to the current date and time. Because
TIMESTAMP
columns behave this way, the NULL
and NOT NULL
attributes do not apply in the normal way and are ignored if you specify
them. DESCRIBE tbl_name
always reports that a TIMESTAMP
column can be assigned NULL
values.
PRIMARY KEY
are made NOT NULL
even if
not declared that way.
ENUM
and SET
member values when the table is created.
USING
clause to specify an index type that is not
legal for a storage engine, but there is another index type available that
the engine can use without affecting query results, the engine will use the
available type.
To see whether MySQL used a column type other
than the one you specified, issue a DESCRIBE
or SHOW
CREATE TABLE
statement after creating or altering your table.
Certain other column type changes can occur if you compress a table
using myisampack
. See section 14.1.3.3 Compressed Table Characteristics.
CREATE VIEW
SyntaxCREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
This statement creates a new view, or replaces an existing one if the
OR REPLACE
clause is given. The select_statement is a
SELECT
statement that provides the definition of the view.
The statement can select from base tables or other views.
A view belongs to a database. By default, a new view is created in the current database. To create the view explicitly in a given database, specify the name as db_name.view_name when you create it.
mysql> CREATE VIEW test.v AS SELECT * FROM t;
Tables and views share the same namespace within a database, so a database cannot contain a table and a view that have the same name.
Views must have unique column names with no duplicates, just like base
tables. By default, the names of the columns retrieved by the SELECT
statement are used for the view column names. To define explicit names for
the view columns, the optional column list can be given. In this case, the
number of names in column_list must be the same as the number of
columns retrieved by the SELECT
statement.
Columns retrieved by the SELECT
statement can be simple references to
table columns. They can also be expressions that use operators, functions,
constant values, and so forth.
A view can refer to columns of tables or views in other databases by qualifying the table or view name with the proper database name.
A view definition is subject to the following constraints:
SELECT
statement cannot contain a subquery in the FROM
clause.
SELECT
statement cannot refer to user variables.
CHECK TABLE
statement.
TEMPORARY
table, and you cannot
create a TEMPORARY
view.
The WITH CHECK OPTION
clause can be given for an updatable view to
prevent inserts or updates to rows except those for which the WHERE
clause in the select_statement is true.
A view can be created from many kinds of SELECT
statements.
For example, the SELECT
can refer to a single table, a join of
multiple tables, or a UNION
. The SELECT
need not even
refer to any tables. The following example defines a view that
selects two columns from another table, as well as an expression calculated
from those columns:
mysql> CREATE TABLE t (qty INT, price INT); mysql> INSERT INTO t VALUES(3, 50); mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t; mysql> SELECT * FROM v; +------+-------+-------+ | qty | price | value | +------+-------+-------+ | 3 | 50 | 150 | +------+-------+-------+
In a WITH CHECK OPTION
clause for an updatable view, the LOCAL
and CASCADED
keywords determine the scope of check testing when the
view is defined in terms of another view. LOCAL
keyword restricts
the CHECK OPTION
only to the view being defined. CASCADED
causes the checks for underlying views to be evaluated as well. When neither
keyword is given, the default is CASCADED
. Consider the definitions
for the following table and set of views:
mysql> CREATE TABLE t1 (a INT); mysql> CREATE VIEW v1 AS SELECT * FROM t1 WHERE a < 2 -> WITH CHECK OPTION; mysql> CREATE VIEW v2 AS SELECT * FROM v1 WHERE a > 0 -> WITH LOCAL CHECK OPTION; mysql> CREATE VIEW v3 AS SELECT * FROM v1 WHERE a > 0 -> WITH CASCADED CHECK OPTION;
Here the v2
and v3
views are defined in terms of another view,
v1
. v2
has a LOCAL
check option, so inserts are tested
only against the v2
check. v3
has a CASCADED
check
option, so inserts are tested not only against its own check, but against
those of underlying views. The following statements illustrate these
differences:
ql> INSERT INTO v2 VALUES (2); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO v3 VALUES (2); ERROR 1369 (HY000): CHECK OPTION failed 'test.v3'
The CREATE VIEW
statement was added in MySQL 5.0.1. The WITH
CHECK OPTION
clause was implemented in MySQL 5.0.2.
DROP DATABASE
SyntaxDROP {DATABASE | SCHEMA} [IF EXISTS] db_name
DROP DATABASE
drops all tables in the database and deletes the
database. Be very careful with this statement!
To use DROP DATABASE
, you need the DROP
privilege on the
database.
In MySQL 3.22 or later, you can use the keywords IF EXISTS
to prevent an error from occurring if the database doesn't exist.
DROP SCHEMA
can be used as of MySQL 5.0.2.
If you use DROP DATABASE
on a symbolically linked
database, both the link and the original database are deleted.
As of MySQL 4.1.2, DROP DATABASE
returns the number of tables that
were removed. This corresponds to the number of `.frm' files removed.
The DROP DATABASE
statement removes from the given database directory
those files and directories that MySQL itself may create during normal
operation:
.BAK | .DAT | .HSH | .ISD
|
.ISM | .ISM | .MRG | .MYD
|
.MYI | .db | .frm |
00
-ff
. These are subdirectories used for RAID
tables.
If other files or directories remain in the database directory after MySQL
removes those just listed, the database directory cannot be removed. In this
case, you must remove any remaining files or directories manually and issue
the DROP DATABASE
statement again.
You can also drop databases with mysqladmin
.
See section 8.4 mysqladmin
, Administering a MySQL Server.
DROP INDEX
SyntaxDROP INDEX index_name ON tbl_name
DROP INDEX
drops the index named index_name from the table
tbl_name. In MySQL 3.22 or later, DROP INDEX
is mapped to an
ALTER TABLE
statement to drop the index. See section 13.2.2 ALTER TABLE
Syntax. DROP INDEX
doesn't do anything prior to MySQL
3.22.
DROP TABLE
SyntaxDROP [TEMPORARY] TABLE [IF EXISTS] tbl_name [, tbl_name] ... [RESTRICT | CASCADE]
DROP TABLE
removes one or more tables. You must have the DROP
privilege for each table. All table data and the table
definition are removed, so be careful with this statement!
In MySQL 3.22 or later, you can use the keywords IF EXISTS
to prevent an error from occurring for tables that don't exist. As of
MySQL 4.1, a NOTE
is generated for each non-existent table when
using IF EXISTS
.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
RESTRICT
and CASCADE
are allowed to make porting easier.
For the moment, they do nothing.
Note: DROP TABLE
automatically commits the current
active transaction, unless you are using MySQL 4.1 or higher and the
TEMPORARY
keyword.
The TEMPORARY
keyword is ignored in MySQL 4.0. As of 4.1, it has the
following effect:
TEMPORARY
tables.
TEMPORARY
table is visible
only to the client that created it, so no check is necessary.)
Using TEMPORARY
is a good way to ensure that you don't accidentally
drop a non-TEMPORARY
table.
DROP VIEW
SyntaxDROP VIEW [IF EXISTS] view_name [, view_name] ... [RESTRICT | CASCADE]
DROP VIEW
removes one or more views. You must have the DROP
privilege for each view.
You can use the keywords IF EXISTS
to prevent an error from occurring
for views that don't exist. When this clause is given, a NOTE
is
generated for each non-existent view.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
RESTRICT
and CASCADE
, if given, are parsed and ignored.
This statement was added in MySQL 5.0.1.
RENAME TABLE
SyntaxRENAME TABLE tbl_name TO new_tbl_name [, tbl_name2 TO new_tbl_name2] ...
This statement renames one or more tables. It was added in MySQL 3.23.23.
The rename operation is done atomically, which means that no other thread
can access any of the tables while the rename is running. For example,
if you have an existing table old_table
, you can create another
table new_table
that has the same structure but is empty, and then
replace the existing table with the empty one as follows:
CREATE TABLE new_table (...); RENAME TABLE old_table TO backup_table, new_table TO old_table;
If the statement renames more than one table, renaming operations are done
from left to right. If you want to swap two table names, you can do so
like this (assuming that no table named tmp_table
currently exists):
RENAME TABLE old_table TO tmp_table, new_table TO old_table, tmp_table TO new_table;
As long as two databases are on the same filesystem you can also rename a table to move it from one database to another:
RENAME TABLE current_db.tbl_name TO other_db.tbl_name;
When you execute RENAME
, you can't have any locked tables or
active transactions. You must also have the ALTER
and DROP
privileges on the original table, and the CREATE
and INSERT
privileges on the new table.
If MySQL encounters any errors in a multiple-table rename, it will do a reverse rename for all renamed tables to get everything back to the original state.
DESCRIBE
Syntax (Get Information About Columns){DESCRIBE | DESC} tbl_name [col_name | wild]
DESCRIBE
provides information about a table's columns. It is a
shortcut for SHOW COLUMNS FROM
.
See section 13.5.4.3 SHOW COLUMNS
Syntax.
col_name can be a column name, or a string containing the SQL `%' and `_' wildcard characters to obtain output only for the columns with names matching the string. There is no need to enclose the string in quotes unless it contains spaces or other special characters.
mysql> DESCRIBE city; +------------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+----------+------+-----+---------+----------------+ | Id | int(11) | | PRI | NULL | auto_increment | | Name | char(35) | | | | | | Country | char(3) | | UNI | | | | District | char(20) | YES | MUL | | | | Population | int(11) | | | 0 | | +------------+----------+------+-----+---------+----------------+ 5 rows in set (0.00 sec)
The Null
column indicates whether NULL values can be stored,
with YES displayed when NULL values are allowed.
The Key
column indicates whether the field is indexed. A value of PRI
indicates that the field is part of the table's primary key. UNI
indicates that
the field is part of a UNIQUE
index. The MUL
value
indicates that multiple occurrences of a given value allowed within the field.
A field can be designated as MUL
even if a UNIQUE
index is used if
NULL
values are allowed, as multiple rows in a UNIQUE
index can hold
a NULL
value if the column is not declared NOT NULL
. Another cause
for MUL
on a UNIQUE
index is when two columns form a composite
UNIQUE
index; while the combination of the columns will be unique, each
column can still hold multiple occurences of a given value. Note that in a composite index only the leftmost field of the index will have an entry in the Key
column.
The Default
column indicates the default value that is assigned to the field.
The Extra
column contains any additional information that is available about
a given field. In our example the Extra
column indicates that our Id
column
was created with the AUTO_INCREMENT
keyword.
If the column types are different from what you expect them to be based on a
CREATE TABLE
statement, note that MySQL sometimes
changes column types. See section 13.2.6.1 Silent Column Specification Changes.
The DESCRIBE
statement is provided for Oracle compatibility.
The SHOW CREATE TABLE
and SHOW TABLE STATUS
statements also
provide information about tables.
See section 13.5.4 SHOW
Syntax.
USE
SyntaxUSE db_name
The USE db_name
statement tells MySQL to use the db_name
database as the default (current) database for subsequent statements.
The database remains the default until the end of the session or until
another USE
statement is issued:
mysql> USE db1; mysql> SELECT COUNT(*) FROM mytable; # selects from db1.mytable mysql> USE db2; mysql> SELECT COUNT(*) FROM mytable; # selects from db2.mytable
Making a particular database current by means of the USE
statement
does not preclude you from accessing tables in other databases. The following example
accesses the author
table from the db1
database and the
editor
table from the db2
database:
mysql> USE db1; mysql> SELECT author_name,editor_name FROM author,db2.editor -> WHERE author.editor_id = db2.editor.editor_id;
The USE
statement is provided for Sybase compatibility.
START TRANSACTION
, COMMIT
, and ROLLBACK
SyntaxBy default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update on disk.
If you are using transaction-safe tables (like InnoDB
or BDB
),
you can disable autocommit mode with the following statement:
SET AUTOCOMMIT=0;
After disabling autocommit mode by setting the AUTOCOMMIT
variable to
zero, you must use COMMIT
to store your changes to disk or
ROLLBACK
if you want to ignore the changes you have made since
the beginning of your transaction.
If you want to disable autocommit mode for a single series of
statements, you can use the START TRANSACTION
statement:
START TRANSACTION; SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET summary=@A WHERE type=1; COMMIT;
With START TRANSACTION
, autocommit remains disabled until you end the
transaction with COMMIT
or ROLLBACK
. The autocommit mode then
reverts to its previous state.
BEGIN
and BEGIN WORK
can be used instead of START
TRANSACTION
to initiate a transaction. START TRANSACTION
was
added in MySQL 4.0.11. This is standard SQL syntax and is the recommended way
to start an ad-hoc transaction. BEGIN
and BEGIN WORK
are
available from MySQL 3.23.17 and 3.23.19, respectively.
As of MySQL 4.1.8, you can begin a transaction like this:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
The WITH CONSISTENT SNAPSHOT
clause starts a consistent read for
storage engines that are capable of it. Currently, this applies only
to InnoDB
. The effect is the same as issuing a START
TRANSACTION
followed by a SELECT
from any InnoDB
table.
See section 15.11.3 Consistent Non-Locking Read.
Beginning a transaction causes an implicit UNLOCK TABLES
to be
performed.
Note that if you are not using transaction-safe tables, any changes are stored at once, regardless of the status of autocommit mode.
If you issue a ROLLBACK
statement after updating a non-transactional
table within a transaction, an ER_WARNING_NOT_COMPLETE_ROLLBACK
warning occurs. Changes to transaction-safe tables will be rolled back, but
not changes to non-transaction-safe tables.
If you are using START TRANSACTION
or SET AUTOCOMMIT=0
, you
should use the MySQL binary log for backups instead of the
older update log. Transactions are stored in the binary log
in one chunk, upon COMMIT
. Transactions that are
rolled back are not logged.
(Exception: Modifications to non-transactional tables cannot be rolled
back. If a transaction that is rolled back includes modifications
to non-transactional tables, the entire transaction is logged with a
ROLLBACK
statement at the end to ensure that the modifications to
those tables are replicated. This is true as of MySQL 4.0.15.)
See section 5.9.4 The Binary Log.
You can change the isolation level for transactions with
SET TRANSACTION ISOLATION LEVEL
.
See section 13.4.6 SET TRANSACTION
Syntax.
Rolling back can be a slow operation that can occur without the user having
explicitly asked for it (for example, when an error occurs). Because of
this, SHOW PROCESSLIST
will display Rolling back
in the
State
column for the connection during implicit rollback and explicit
(ROLLBACK
SQL command) rollbacks, starting from MySQL 4.1.8.
Some statements cannot be rolled back. In general, these include data definition language (DDL) statements, such as those that create or drop databases, or those that create, drop, or alter tables.
You should design your transactions not to include such statements.
If you issue a statement early in a transaction that cannot be rolled back,
and then another statement later fails, the full effect of the transaction
cannot be rolled back by issuing a ROLLBACK
statement.
Each of the following statements (and any synonyms for them) implicitly end
a transaction, as if you had done a COMMIT
before executing the
statement:
ALTER TABLE | BEGIN | CREATE INDEX
|
DROP DATABASE | DROP INDEX | DROP TABLE
|
LOAD MASTER DATA | LOCK TABLES | RENAME TABLE
|
SET AUTOCOMMIT=1 | START TRANSACTION | TRUNCATE TABLE
|
UNLOCK TABLES
also ends a transaction if any tables currently are
locked. Prior to MySQL 4.0.13, CREATE TABLE
ends a transaction if
the binary update log is enabled.
Transactions cannot be nested. This is a consequence of the implicit
COMMIT
performed for any current transaction when you issue a
START TRANSACTION
statement or one of its synonyms.
SAVEPOINT
and ROLLBACK TO SAVEPOINT
SyntaxSAVEPOINT identifier ROLLBACK TO SAVEPOINT identifier
Starting from MySQL 4.0.14 and 4.1.1, InnoDB
supports the SQL statements
SAVEPOINT
and ROLLBACK TO SAVEPOINT
.
The SAVEPOINT
statement sets a named transaction savepoint with a name
of identifier
. If the current transaction has a savepoint
with the same name, the old savepoint is deleted and a new one is set.
The ROLLBACK TO SAVEPOINT
statement rolls back a transaction to the
named savepoint. Modifications that the current transaction made to rows
after the savepoint was set are undone in the rollback, but InnoDB
does not release the row locks that were stored in memory after
the savepoint. (Note that for a new inserted row, the lock information is
carried by the transaction ID stored in the row; the lock is not separately
stored in memory. In this case, the row lock is released in the undo.)
Savepoints that were set at a later time than the named savepoint are
deleted.
If the statement returns the following error, it means that no savepoint with the specified name exists:
ERROR 1181: Got error 153 during ROLLBACK
All savepoints of the current transaction are deleted if you execute a
COMMIT
, or a ROLLBACK
that does not name a savepoint.
LOCK TABLES
and UNLOCK TABLES
SyntaxLOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ... UNLOCK TABLES
LOCK TABLES
locks tables for the current thread. UNLOCK
TABLES
releases any locks held by the current thread. All tables that
are locked by the current thread are implicitly unlocked when the
thread issues another LOCK TABLES
, or when the connection to the
server is closed.
Note the following regarding the use of LOCK TABLES
with transactional
tables:
LOCK TABLES
is not transaction-safe and implicitly
commits any active transactions before attempting to lock the tables.
Also, beginning a transaction (for example, with START TRANSACTION
)
implicitly performs an UNLOCK TABLES
.
LOCK TABLES
with transactional
tables, like InnoDB, is to set AUTOCOMMIT = 0
and not to call
UNLOCK TABLES
until you commit the transaction explicitly.
When you call LOCK TABLES
, InnoDB internally takes its own table
lock, and MySQL takes its own table lock. InnoDB releases its table lock at
the next commit, but for MySQL to release its table lock, you have to call
UNLOCK TABLES
. You should not have AUTOCOMMIT = 1
, because
then InnoDB releases its table lock immediately after the call of
LOCK TABLES
, and deadlocks will very easily happen.
Starting from 4.1.9, we do not acquire the InnoDB table lock at all
if AUTOCOMMIT=1
. That helps old applications to avoid unnecessary
deadlocks.
As of MySQL 4.0.2, to use LOCK TABLES
you must have the
LOCK TABLES
privilege and a SELECT
privilege for the
involved tables. In MySQL 3.23, you must have SELECT
,
INSERT
, DELETE
, and UPDATE
privileges for the
tables.
The main reasons to use LOCK TABLES
are for emulating transactions
or to get more speed when updating tables. This is explained in more
detail later.
If a thread obtains a READ
lock on a table, that thread (and all other
threads) can only read from the table. If a thread obtains a WRITE
lock on a table, only the thread holding the lock can
write to the table. Other threads are blocked from doing so until the
lock has been released.
The difference between READ LOCAL
and READ
is that READ
LOCAL
allows non-conflicting INSERT
statements (concurrent inserts)
to execute while the lock is held. However, this can't be used if you are
going to manipulate the database files outside MySQL while you hold the
lock. For InnoDB, READ LOCAL
essentially does nothing: it does
not lock the table at all. The use of READ LOCAL
for InnoDB
tables is deprecated, because for InnoDB, a plain consistent read
SELECT
does the same thing, and no locks are needed.
When you use LOCK TABLES
, you must lock all tables that you are going to
use in your queries. While the locks obtained with a LOCK TABLES
statement are in effect, you cannot access any tables that were not locked by
the statement. Also, you cannot use a locked table multiple times in one query
- use aliases for that. Note that in that case you must get a lock for each
alias separately.
mysql> LOCK TABLE t WRITE, t AS t1 WRITE; mysql> INSERT INTO t SELECT * FROM t; ERROR 1100: Table 't' was not locked with LOCK TABLES mysql> INSERT INTO t SELECT * FROM t AS t1;
If your queries refer to a table using an alias, then you must lock the table using that same alias. It will not work to lock the table without specifying the alias:
mysql> LOCK TABLE t READ; mysql> SELECT * FROM t AS myalias; ERROR 1100: Table 'myalias' was not locked with LOCK TABLES
Conversely, if you lock a table using an alias, you must refer to it in your queries using that alias:
mysql> LOCK TABLE t AS myalias READ; mysql> SELECT * FROM t; ERROR 1100: Table 't' was not locked with LOCK TABLES mysql> SELECT * FROM t AS myalias;
WRITE
locks normally have higher priority than READ
locks to
ensure that updates are processed as soon as possible. This means that if one
thread obtains a READ
lock and then another thread requests a
WRITE
lock, subsequent READ
lock requests will wait until the
WRITE
thread has gotten the lock and released it. You can use
LOW_PRIORITY WRITE
locks to allow other threads to obtain READ
locks while the thread is waiting for the WRITE
lock. You should
use LOW_PRIORITY WRITE
locks only if you are sure that there will
eventually be a time when no threads will have a READ
lock.
LOCK TABLES
works as follows:
This policy ensures that table locking is deadlock free. There are, however, other things you need to be aware of about this policy:
If you are using a LOW_PRIORITY WRITE
lock for a table, it
means only that MySQL will wait for this particular lock until
there are no threads that want a READ
lock. When the thread has
gotten the WRITE
lock and is waiting to get the lock for the next
table in the lock table list, all other threads will wait for the
WRITE
lock to be released. If this becomes a serious problem
with your application, you should consider converting some of your
tables to transaction-safe tables.
You can safely use KILL
to terminate a thread that is waiting for a
table lock.
See section 13.5.5.3 KILL
Syntax.
Note that you should not lock any tables that you are using with
INSERT DELAYED
because in that case the INSERT
is done by a
separate thread.
Normally, you don't have to lock tables, because all single UPDATE
statements
are atomic; no other thread can interfere with any other currently executing
SQL statement. There are a few cases when you would like to lock tables
anyway:
MyISAM
tables,
it's much faster to lock the tables you are going to use. Locking
MyISAM
tables speeds up inserting, updating, or deleting on them.
The downside is that no thread can update a READ
-locked table
(including the one holding the lock) and no thread can access a
WRITE
-locked table other than the one holding the lock.
The reason some MyISAM
operations are faster under LOCK TABLES
is that MySQL will not flush the key cache for the locked tables until
UNLOCK TABLES
is called. Normally, the key cache is flushed after
each SQL statement.
LOCK TABLES
if you want to ensure that
no other thread comes between a SELECT
and an UPDATE
. The
example shown here requires LOCK TABLES
to execute safely:
mysql> LOCK TABLES trans READ, customer WRITE; mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id; mysql> UPDATE customer -> SET total_value=sum_from_previous_statement -> WHERE customer_id=some_id; mysql> UNLOCK TABLES;Without
LOCK TABLES
, it is possible that another thread might
insert a new row in the trans
table between execution of the
SELECT
and UPDATE
statements.
You can avoid using LOCK TABLES
in many cases
by using relative updates (UPDATE customer SET
value=value+new_value
) or the LAST_INSERT_ID()
function,
See section 1.5.5.3 Transactions and Atomic Operations.
You can also avoid locking tables in some cases by using the user-level
advisory lock functions GET_LOCK()
and RELEASE_LOCK()
.
These locks are saved in a hash table in the server and implemented with
pthread_mutex_lock()
and pthread_mutex_unlock()
for high speed.
See section 12.8.4 Miscellaneous Functions.
See section 7.3.1 Locking Methods, for more information on locking policy.
You can lock all tables in all databases with read locks with the FLUSH
TABLES WITH READ LOCK
statement. See section 13.5.5.2 FLUSH
Syntax. This
is a very convenient way to get backups if you have a filesystem such as
Veritas that can take snapshots in time.
Note: If you use ALTER TABLE
on a locked table, it may become
unlocked. See section A.7.1 Problems with ALTER TABLE
.
SET TRANSACTION
SyntaxSET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
This statement sets the transaction isolation level for the next transaction, globally, or for the current session.
The default behavior of SET TRANSACTION
is to set the isolation level
for the next (not yet
started) transaction. If you use the GLOBAL
keyword, the statement
sets the default transaction level globally for all new connections
created from that point on. Existing connections are unaffected.
You need the SUPER
privilege to do this. Using the SESSION
keyword sets the
default transaction level for all future transactions performed on the
current connection.
For descriptions of each InnoDB
transaction isolation level, see
section 15.11.2 InnoDB
and TRANSACTION ISOLATION LEVEL
.
InnoDB
supports each of these levels
from MySQL 4.0.5 on. The default level is REPEATABLE READ
.
You can set the initial default global isolation level for mysqld
with
the --transaction-isolation
option.
See section 5.2.1 mysqld
Command-Line Options.
CREATE USER
SyntaxCREATE USER user [IDENTIFIED BY [PASSWORD] 'password'] [, user [IDENTIFIED BY [PASSWORD] 'password']] ...
The CREATE USER
statement creates new MySQL accounts. To use it, you
must have the GRANT OPTION
privilege for the mysql
database.
For each account, CREATE USER
creates a new record in the
mysql.user
table that has no privileges. An error occurs if the
account already exists. The account can be given a password with the
optional IDENTIFIED BY
clause. The user value and the password
are given the same way as for the GRANT
statement.
The CREATE USER
statement was added in MySQL 5.0.2.
DROP USER
SyntaxDROP USER user [, user] ...
The DROP USER
statement deletes one or more MySQL accounts. To use
it, you must have the GRANT OPTION
privilege for the mysql
database. Each account is named using the same format as for GRANT
or REVOKE
; for example, 'jeffrey'@'localhost'
. The user and
host parts of the account name correspond to the User
and Host
column values of the user
table record for the account.
DROP USER
was added in MySQL 4.1.1 and originally removed only
accounts that have no privileges. In MySQL 5.0.2, it was modified to also
remove account privileges. This means that the procedure for removing an
account depends on your version of MySQL.
As of MySQL 5.0.2, remove an account and its privileges as follows:
DROP USER user;
The statement removes privilege records for the account from all grant tables.
From MySQL 4.1.1 to 5.0.1, DROP USER
deletes only MySQL accounts that
don't have any privileges. It serves to remove each account record from the
user
table. To remove a MySQL account, you should use the following
procedure, performing the steps in the order shown:
SHOW GRANTS
to determine what privileges the account has.
See section 13.5.4.10 SHOW GRANTS
Syntax.
REVOKE
to revoke the privileges displayed by SHOW GRANTS
.
This removes records for the account from all the grant tables except the
user
table, and revokes any global privileges listed in the user
table.
See section 13.5.1.3 GRANT
and REVOKE
Syntax.
DROP USER
to remove the user
table
record.
Before MySQL 4.1.1, DROP USER
is not available. You should first
revoke the account privileges as just described. Then delete the user
table record and flush the grant tables like this:
mysql> DELETE FROM mysql.user -> WHERE User='user_name' and Host='host_name'; mysql> FLUSH PRIVILEGES;
GRANT
and REVOKE
SyntaxGRANT priv_type [(column_list)] [, priv_type [(column_list)]] ... ON {tbl_name | * | *.* | db_name.*} TO user [IDENTIFIED BY [PASSWORD] 'password'] [, user [IDENTIFIED BY [PASSWORD] 'password']] ... [REQUIRE NONE | [{SSL| X509}] [CIPHER 'cipher' [AND]] [ISSUER 'issuer' [AND]] [SUBJECT 'subject']] [WITH [GRANT OPTION | MAX_QUERIES_PER_HOUR count | MAX_UPDATES_PER_HOUR count | MAX_CONNECTIONS_PER_HOUR count | MAX_USER_CONNECTIONS count]]
REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ... ON {tbl_name | * | *.* | db_name.*} FROM user [, user] ... REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...
The GRANT
and REVOKE
statements allow system administrators to
create MySQL user accounts and to grant rights to and revoke them from
accounts. GRANT
and REVOKE
are implemented in MySQL 3.22.11
or later. For earlier MySQL versions, these statements do nothing.
MySQL account information is stored in the tables of the mysql
database. This database and the access control system are discussed
extensively in section 5 Database Administration, which you should consult
for additional details.
Privileges can be granted at several levels:
mysql.user
table.
GRANT ALL ON *.*
and
REVOKE ALL ON *.*
grant and revoke only global privileges.
mysql.db
and mysql.host
tables.
GRANT ALL ON db_name.*
and
REVOKE ALL ON db_name.*
grant and revoke only database privileges.
mysql.tables_priv
table.
GRANT ALL ON db_name.tbl_name
and
REVOKE ALL ON db_name.tbl_name
grant and revoke only table privileges.
mysql.columns_priv
table.
When using REVOKE
, you must specify the same columns that were granted.
CREATE ROUTINE
, ALTER ROUTINE
, EXECUTE
, and
GRANT
privileges apply to stored routines. They can be granted at the
global and database levels. Also, except for CREATE ROUTINE
, these
privileges can be granted at the routine level for individual routines and
are stored in the mysql.procs_priv
table.
To make it easy to revoke all privileges, MySQL 4.1.2 has added the following syntax, which drops all global, database-, table-, and column-level privileges for the named users:
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...
Before MySQL 4.1.2, all privileges cannot be dropped at once. Two statements are necessary:
REVOKE ALL PRIVILEGES ON *.* FROM user [, user] ... REVOKE GRANT OPTION ON *.* FROM user [, user] ...
For the GRANT
and REVOKE
statements, priv_type
can be
specified as any of the following:
Privilege | Meaning |
ALL [PRIVILEGES] | Sets all simple privileges except GRANT OPTION
|
ALTER | Allows use of ALTER TABLE
|
ALTER ROUTINE | Alter or drop stored routines |
CREATE | Allows use of CREATE TABLE
|
CREATE ROUTINE | Create stored routines |
CREATE TEMPORARY TABLES | Allows use of CREATE TEMPORARY TABLE
|
CREATE VIEW | Allows use of CREATE VIEW
|
DELETE | Allows use of DELETE
|
DROP | Allows use of DROP TABLE
|
EXECUTE | Allows the user to run stored routines |
FILE | Allows use of SELECT ... INTO OUTFILE and LOAD DATA INFILE
|
INDEX | Allows use of CREATE INDEX and DROP INDEX
|
INSERT | Allows use of INSERT
|
LOCK TABLES | Allows use of LOCK TABLES on tables for which you have the SELECT privilege
|
PROCESS | Allows use of SHOW FULL PROCESSLIST
|
REFERENCES | Not implemented |
RELOAD | Allows use of FLUSH
|
REPLICATION CLIENT | Allows the user to ask where slave or master servers are |
REPLICATION SLAVE | Needed for replication slaves (to read binary log events from the master) |
SELECT | Allows use of SELECT
|
SHOW DATABASES | SHOW DATABASES shows all databases
|
SHOW VIEW | Allows use of SHOW CREATE VIEW
|
SHUTDOWN | Allows use of mysqladmin shutdown
|
SUPER | Allows use of CHANGE MASTER , KILL ,
PURGE MASTER LOGS , and SET GLOBAL statements, the mysqladmin debug command; allows you to connect (once) even if max_connections is reached
|
UPDATE | Allows use of UPDATE
|
USAGE | Synonym for ``no privileges'' |
GRANT OPTION | Allows privileges to be granted |
The CREATE TEMPORARY TABLES
, EXECUTE
, LOCK TABLES
,
REPLICATION CLIENT
, REPLICATION SLAVE
, SHOW DATABASES
,
and SUPER
privileges were added in MySQL 4.0.2. (EXECUTE
is
not operational until MySQL 5.0.3.) CREATE VIEW
and SHOW VIEW
were added in MySQL 5.0.1. CREATE ROUTINE
and ALTER ROUTINE
were added in MySQL 5.0.3. To use these privileges when upgrading from an
earlier version of MySQL that does not have them, , you must upgrade your
grant tables. See section 2.10.7 Upgrading the Grant Tables.
The REFERENCES
privilege currently is unused.
In older MySQL versions that do not have the SUPER
privilege, specify
the PROCESS
privilege instead.
USAGE
can be specified when you want to create a user that has no
privileges.
Use SHOW GRANTS
to determine what privileges the account has.
See section 13.5.4.10 SHOW GRANTS
Syntax.
You can assign global privileges by using ON *.*
syntax or database
privileges by using ON db_name.*
syntax. If you specify
ON *
and you have selected a default database, the privileges are
granted in that database. (Warning: If you specify ON *
and
you have not selected a default database, the privileges granted are
global!)
The EXECUTION
, FILE
, PROCESS
, RELOAD
,
REPLICATION CLIENT
, REPLICATION SLAVE
, SHOW DATABASES
,
SHUTDOWN
, and SUPER
privileges are administrative privileges
that can only be granted globally (using ON *.*
syntax).
Other privileges can be granted globally or at more specific levels.
The only priv_type
values you can specify for a table are SELECT
,
INSERT
, UPDATE
, DELETE
, CREATE
, DROP
,
GRANT OPTION
, INDEX
, and ALTER
.
The only priv_type
values you can specify for a column (that is, when
you use a column_list
clause) are SELECT
, INSERT
, and
UPDATE
.
The only priv_type
values you can specify at the routine level are
ALTER ROUTINE
, EXECUTE
, and GRANT
. CREATE ROUTINE
is not a routine-level privilege because you must have this privilege to be
able to create a routine in the first place.
For the global, database, table, and routine levels,
GRANT ALL
assigns only the privileges that exist at the level you are
granting. For example, if you use GRANT ALL ON db_name.*
, that is a
database-level statement, so none of the global-only privileges such as
FILE
will be granted.
For column-level privileges (that is, when you specify column_list),
you must explicitly name the privileges to be granted. You cannot use
ALL
as a privilege specifier.
MySQL allows you to grant database-level privileges even if the database doesn't exist, to make it easy to prepare for database use. However, MySQL currently does not allow you to grant table-level or column-level privileges if the table doesn't exist. Similarly, you cannot grant routine-level privileges to a non-existent routine.
MySQL does not automatically revoke any privileges even if you drop a table or drop a database. If you drop a routine, and routine-level privileges granted for the routine are revoked.
Note: the `_' and `%' wildcards are allowed when
specifying database names in GRANT
statements that grant privileges at
the global or database levels. This means, for example, that if you
want to use a `_' character as part of a database name,
you should specify it as `\_' in the GRANT
statement, to prevent
the user from being able to access additional databases matching the
wildcard pattern; for example, GRANT ... ON `foo\_bar`.* TO ...
.
In order to accommodate granting rights to users from arbitrary hosts,
MySQL supports specifying the user value in the form
user_name@host_name
. If a user_name or
host_name value is legal as an unquoted identifier, you need not quote
it. However, quotes are necessary to specify a user_name string
containing special characters (such as `-'), or a host_name string
containing special characters or wildcard characters (such as `%');
for example, 'test-user'@'test-hostname'
. Quote the username and
hostname separately.
You can specify wildcards in the hostname. For example,
user_name@'%.loc.gov'
applies to user_name for any host in the
loc.gov
domain, and user_name@'144.155.166.%'
applies to
user_name for any host in the 144.155.166
class C subnet.
The simple form user_name is a synonym for user_name@'%'
.
MySQL doesn't support wildcards in usernames. Anonymous users are
defined by inserting entries with User=''
into the
mysql.user
table or creating a user with an empty name with the
GRANT
statement:
mysql> GRANT ALL ON test.* TO ''@'localhost' ...
When specifying quoted values, quote database, table, column, and routine names as identifiers, using backticks (``'). Quote hostnames, usernames, and passwords as strings, using apostrophes (`'').
Warning: If you allow anonymous users to connect to the MySQL
server, you should also grant privileges to all local users as
user_name@localhost
. Otherwise, the anonymous-user account for
the local host in the mysql.user
table will be used when named users
try to log in to the MySQL server from the local machine!
(This anonymous-user account is created during MySQL installation.)
You can determine whether this applies to you by executing the following query:
mysql> SELECT Host, User FROM mysql.user WHERE User='';
If you want to delete the local anonymous-user account to avoid the problem just described, use these statements:
mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User=''; mysql> FLUSH PRIVILEGES;
GRANT
supports hostnames up to 60 characters long. Database, table,
column, and routine names can be up to 64 characters. Usernames can be up
to 16 characters.
The privileges for a table or column are formed additively from the
logical OR of the privileges at each of the four privilege
levels. For example, if the mysql.user
table specifies that a
user has a global SELECT
privilege, the privilege cannot be denied by an
entry at the database, table, or column level.
The privileges for a column can be calculated as follows:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
In most cases, you grant rights to a user at only one of the privilege levels, so life isn't normally this complicated. The details of the privilege-checking procedure are presented in section 5.5 The MySQL Access Privilege System.
If you grant privileges for a username/hostname combination that does not exist
in the mysql.user
table, an entry is added and remains there until
deleted with a DELETE
statement. In other words, GRANT
may
create user
table entries, but REVOKE
will not remove them;
you must do that explicitly using DROP USER
or DELETE
.
In MySQL 3.22.12 or later,
if a new user is created or if you have global grant privileges, the user's
password is set to the password specified by the IDENTIFIED BY
clause, if one is given. If the user had a password, it is replaced
by the new one.
Warning: If you create a new user but do not specify an
IDENTIFIED BY
clause, the user has no password. This is insecure.
As of MySQL 5.0.2, you can enable the NO_AUTO_CREATE_USER
SQL mode
to prevent GRANT
from creating new users if it would otherwise do so,
unless IDENTIFIED BY
is given to provide a password.
Passwords can also be set with the SET PASSWORD
statement.
See section 13.5.1.5 SET PASSWORD
Syntax.
In the IDENTIFIED BY
clause, the password should be given as the
literal password value. It is unnecessary to use the PASSWORD()
function as it is for the SET PASSWORD
statement. For example:
GRANT ... IDENTIFIED BY 'mypass';
If you don't want to send the password in clear text and you know the hashed
value that PASSWORD()
would return for the password, you can specify
the hashed value preceded by the keyword PASSWORD
:
GRANT ... IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
In a C program, you can get the hashed value by using the
make_scrambled_password()
C API function.
If you grant privileges for a database, an entry in the mysql.db
table is created if needed. If all privileges for the database are
removed with REVOKE
, this entry is deleted.
If a user has no privileges for a table, the table name is not displayed
when the user requests a list of tables (for example, with a SHOW TABLES
statement).
The SHOW DATABASES
privilege allows the account to see database names
by issuing the SHOW DATABASE
statement. Accounts that do not have this
privilege see only databases for which they have some privileges, and cannot
use the statement at all if the server was started with the
--skip-show-database
option.
The WITH GRANT OPTION
clause gives the user the ability to give
to other users any privileges the user has at the specified privilege level.
You should be careful to whom you give the GRANT OPTION
privilege,
because two users with different privileges may be able to join privileges!
You cannot grant another user a privilege you don't have yourself; the
GRANT OPTION
privilege allows you to give away only those privileges
you possess.
Be aware that when you grant a user the GRANT OPTION
privilege at a
particular privilege level, any privileges the user possesses (or
is given in the future!) at that level are also grantable by that user.
Suppose that you grant a user the INSERT
privilege on a database. If
you then grant the SELECT
privilege on the database and specify
WITH GRANT OPTION
, the user can give away not only the SELECT
privilege, but also INSERT
. If you then grant the UPDATE
privilege to the user on the database, the user can give away
INSERT
, SELECT
, and UPDATE
.
You should not grant ALTER
privileges to a normal user. If you
do that, the user can try to subvert the privilege system by renaming
tables!
The MAX_QUERIES_PER_HOUR count
, MAX_UPDATES_PER_HOUR
count
, and MAX_CONNECTIONS_PER_HOUR count
options are
new in MySQL 4.0.2. They limit the number of queries, updates, and logins a
user can perform during one hour. If count is 0 (the default), this
means there is no limitation for that user.
The MAX_USER_CONNECTIONS count
option is new in MySQL 5.0.3.
It limits the maximum number of simultaneous connections that the account
can make. If count is 0 (the default), the
max_user_connections
system variable determines the number of
simultaneous connections for the account.
Note: To specify any of these resource-limit options for an existing user
without affecting existing privileges, use GRANT USAGE ON *.* ... WITH
MAX_...
.
See section 5.6.4 Limiting Account Resources.
MySQL can check X509 certificate attributes in addition to the usual
authentication that is based on the username and password. To specify
SSL-related options for a MySQL account, use the REQUIRE
clause of
the GRANT
statement.
(For background on the use of SSL with MySQL, see section 5.6.7 Using Secure Connections.)
There are different possibilities for limiting connection types for an account:
REQUIRE SSL
option tells the server to allow only SSL-encrypted
connections for the account. Note that this option can be omitted
if there are any access-control records that allow non-SSL connections.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;
REQUIRE X509
means that the client must have a valid certificate
but that the exact certificate, issuer, and subject do not matter.
The only requirement is that it should be possible to verify its
signature with one of the CA certificates.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' REQUIRE X509;
REQUIRE ISSUER 'issuer'
places the restriction on connection attempts
that the client must present a valid X509 certificate issued by CA
'issuer'
. If the client presents a certificate that is valid but has
a different issuer, the server rejects the connection. Use of X509
certificates always implies encryption, so the SSL
option is
unnecessary.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/ O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';Note that the
ISSUER
value should be entered as a single string.
REQUIRE SUBJECT 'subject'
places the restriction on connection
attempts that the client must present a valid X509 certificate with subject
'subject'
in it. If the client presents a certificate that is valid
but has a different subject, the server rejects the connection.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/ O=MySQL demo client certificate/ CN=Tonu Samuel/Email=tonu@example.com';Note that the
SUBJECT
value should be entered as a single string.
REQUIRE CIPHER 'cipher'
is needed to ensure that strong enough ciphers
and key lengths will be used. SSL itself can be weak if old algorithms
with short encryption keys are used. Using this option, you can ask for
some exact cipher method to allow a connection.
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';
The SUBJECT
, ISSUER
, and CIPHER
options can be
combined in the REQUIRE
clause like this:
mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost' -> IDENTIFIED BY 'goodsecret' -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/ O=MySQL demo client certificate/ CN=Tonu Samuel/Email=tonu@example.com' -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/ O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com' -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';
Note that the SUBJECT
and ISSUER
values each should be entered
as a single string.
Starting from MySQL 4.0.4, the AND
keyword is optional between
REQUIRE
options.
The order of the options does not matter, but no option can be specified twice.
When mysqld
starts, all privileges are read into memory.
Database, table, and column privileges take effect at once, and
user-level privileges take effect the next time the user connects.
Modifications to the grant tables that you perform using GRANT
or
REVOKE
are noticed by the server immediately.
If you modify the grant tables manually (using INSERT
, UPDATE
,
and so on), you should execute a FLUSH PRIVILEGES
statement or run
mysqladmin flush-privileges
to tell the server to reload the grant
tables.
See section 5.5.7 When Privilege Changes Take Effect.
Note that if you are using table or column privileges for even one user, the server examines table and column privileges for all users and this slows down MySQL a bit. Similarly, if you limit the number of queries, updates, or connections for any users, the server must monitor these values.
The biggest differences between the standard SQL and MySQL versions of
GRANT
are:
TRIGGER
or UNDER
privileges.
DROP USER
. Before 5.0.2,
the granted privileges are not automatically revoked; you must revoke them
yourself.
See section 13.5.1.2 DROP USER
Syntax.
REVOKE
statements or
by manipulating the MySQL grant tables.
INSERT
privilege on only some of the
columns in a table, you can execute INSERT
statements on the
table; the columns for which you don't have the INSERT
privilege
will be set to their default values. Standard SQL requires you to have the
INSERT
privilege on all columns.
RENAME USER
SyntaxRENAME USER old_user TO new_user [, old_user TO new_user] ...
The RENAME USER
statement renames existing MySQL accounts. To use
it, you must have the GRANT OPTION
privilege for the mysql
database. An error occurs if any old account does not exist or any new
account exists. The old_user and new_user values are given the
same way as for the GRANT
statement.
The RENAME USER
statement was added in MySQL 5.0.2.
SET PASSWORD
SyntaxSET PASSWORD = PASSWORD('some password') SET PASSWORD FOR user = PASSWORD('some password')
The SET PASSWORD
statement assigns a password to an existing
MySQL user account.
The first syntax sets the password for the current user. Any client that has connected to the server using a non-anonymous account can change the password for that account.
The second syntax sets the password for a specific account on the current
server host. Only clients with the UPDATE
privilege for the
mysql
database can do this. The user value should be given in
user_name@host_name
format, where user_name and
host_name are exactly as they are listed in the User
and
Host
columns of the mysql.user
table entry. For example, if
you had an entry with User
and Host
column values of
'bob'
and '%.loc.gov'
, you would write the statement like
this:
mysql> SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');
That is equivalent to the following statements:
mysql> UPDATE mysql.user SET Password=PASSWORD('newpass') -> WHERE User='bob' AND Host='%.loc.gov'; mysql> FLUSH PRIVILEGES;
Note: If you are connecting to a MySQL 4.1 or later server using a
pre-4.1 client program, do not use the preceding SET PASSWORD
or
UPDATE
statement without reading section 5.5.9 Password Hashing in MySQL 4.1 first. The
password format changed in MySQL 4.1, and under certain circumstances it is
possible that if you change your password, you might not be able to connect
to the server afterward.
Starting from MySQL 4.1, you can check what your current authentication
user@host
entry is by executing SELECT CURRENT_USER()
.
ANALYZE TABLE
SyntaxANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
This statement analyzes and stores the key distribution for a table.
During the analysis, the table is locked with a read lock. This works on
MyISAM
and BDB
tables and (as of MySQL 4.0.13) InnoDB
tables. For MyISAM
tables, this
statement is equivalent to using myisamchk -a
.
MySQL uses the stored key distribution to decide the order in which tables should be joined when you perform a join on something other than a constant.
The statement returns a table with the following columns:
Column | Value |
Table | The table name |
Op | Always analyze
|
Msg_type | One of status , error , info , or warning
|
Msg_text | The message |
You can check the stored key distribution with the SHOW INDEX
statement.
See section 13.5.4.11 SHOW INDEX
Syntax.
If the table hasn't changed since the last ANALYZE TABLE
statement,
the table will not be analyzed again.
Before MySQL 4.1.1, ANALYZE TABLE
statements are not written
to the binary log. As of MySQL 4.1.1, they are written to the binary
log unless the optional NO_WRITE_TO_BINLOG
keyword
(or its alias LOCAL
) is used.
BACKUP TABLE
SyntaxBACKUP TABLE tbl_name [, tbl_name] ... TO '/path/to/backup/directory'
Note: This statement is deprecated. We are working on a better
replacement for it that will provide online backup capabilities.
In the meantime, the mysqlhotcopy
script can be used instead.
BACKUP TABLE
copies to the backup directory the minimum number of
table files needed to restore the table, after flushing any buffered changes
to disk. The statement works only for MyISAM
tables. It copies the
`.frm' definition and `.MYD' data files. The `.MYI'
index file can be rebuilt from those two files.
The directory should be specified as a full pathname.
Before using this statement, please see section 5.7.1 Database Backups.
During the backup, a read lock is held for each table, one at time,
as they are being backed up. If you want to back up several tables as
a snapshot (preventing any of them from being changed during the backup
operation), you must first issue a LOCK TABLES
statement to obtain a read
lock for every table in the group.
The statement returns a table with the following columns:
Column | Value |
Table | The table name |
Op | Always backup
|
Msg_type | One of status , error , info , or warning
|
Msg_text | The message |
BACKUP TABLE
is available in MySQL 3.23.25 and later.
CHECK TABLE
SyntaxCHECK TABLE tbl_name [, tbl_name] ... [option] ... option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}
Checks a table or tables for errors. CHECK TABLE
works for
MyISAM
and InnoDB
tables. For MyISAM
tables, the key statistics are updated.
As of MySQL 5.0.2, CHECK TABLE
also can check views for problems, such
as tables that are referenced in the view definition that no longer exist.
The CHECK TABLE
statement returns a table with the following columns:
Column | Value |
Table | The table name |
Op | Always check
|
Msg_type | One of status , error , info , or warning
|
Msg_text | The message |
Note that the statement might produce many rows of information for each
checked table. The last row will have a Msg_type
value of
status
and the Msg_text
normally should be OK
. If you
don't get OK
, or Table is already up to date
you should
normally run a repair of the table. See section 5.7.3 Table Maintenance and Crash Recovery. Table is
already up to date
means that the storage engine for the table indicated
that there was no need to check the table.
The different check options that can be given are shown in the following
table. These options apply only to checking MyISAM
tables and are
ignored for InnoDB
tables and views.
Type | Meaning |
QUICK | Don't scan the rows to check for incorrect links. |
FAST | Only check tables that haven't been closed properly. |
CHANGED | Only check tables that have been changed since the last check or haven't been closed properly. |
MEDIUM | Scan rows to verify that deleted links are okay. This also calculates a key checksum for the rows and verifies this with a calculated checksum for the keys. |
EXTENDED | Do a full key lookup for all keys for each row. This ensures that the table is 100% consistent, but will take a long time! |
If none of the options QUICK
, MEDIUM
, or EXTENDED
are
specified, the default check type for dynamic-format MyISAM
tables
is MEDIUM
. This is the same thing as running myisamchk
--medium-check tbl_name
on the table. The default check type
also is MEDIUM
for static-format MyISAM
tables, unless
CHANGED
or FAST
is specified. In that case, the default is
QUICK
. The row scan is skipped for CHANGED
and FAST
because the rows are very seldom corrupted.
You can combine check options, as in the following example, which does a quick check on the table to see whether it was closed properly:
CHECK TABLE test_table FAST QUICK;
Note: In some cases, CHECK TABLE
will change the
table! This happens if the table is marked as ``corrupted'' or ``not
closed properly'' but CHECK TABLE
doesn't find any problems in the
table. In this case, CHECK TABLE
marks the table as okay.
If a table is corrupted, it's most likely that the problem is in the indexes and not in the data part. All of the preceding check types check the indexes thoroughly and should thus find most errors.
If you just want to check a table that you assume is okay, you should use
no check options or the QUICK
option. The latter should be used
when you are in a hurry and can take the very small risk that
QUICK
doesn't find an error in the data file. (In most cases,
MySQL should find, under normal usage, any error in the data file.
If this happens, the table is marked as ``corrupted'' and cannot
be used until it's repaired.)
FAST
and CHANGED
are mostly intended to be used from a
script (for example, to be executed from cron
) if you want to check your
table from time to time. In most cases, FAST
is to be preferred
over CHANGED
. (The only case when it isn't preferred is when you suspect
that you have found a bug in the MyISAM
code.)
EXTENDED
is to be used only after you have run a normal check but
still get strange errors from a table when MySQL tries to
update a row or find a row by key. (This is very unlikely if a
normal check has succeeded!)
Some problems reported by CHECK TABLE
can't be corrected automatically:
Found row where the auto_increment column has the value 0
.
This means that you have a row in the table where the
AUTO_INCREMENT
index column contains the value 0.
(It's possible to create a row where the AUTO_INCREMENT
column is 0 by
explicitly setting the column to 0 with an UPDATE
statement.)
This isn't an error in itself, but could cause trouble if you decide to
dump the table and restore it or do an ALTER TABLE
on the
table. In this case, the AUTO_INCREMENT
column will change value
according to the rules of AUTO_INCREMENT
columns, which could cause
problems such as a duplicate-key error.
To get rid of the warning, just execute an UPDATE
statement
to set the column to some other value than 0.
CHECKSUM TABLE
SyntaxCHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]
Reports a table checksum.
If QUICK
is specified, the live table checksum is reported if it is
available, or NULL
otherwise. This is very fast. A live checksum
is enabled by specifying the CHECKSUM=1
table option, currently
supported only for MyISAM
tables.
See section 13.2.6 CREATE TABLE
Syntax.
In EXTENDED
mode the whole table is read row by row and the checksum
is calculated. This can be very slow for large tables.
By default, if neither QUICK
nor EXTENDED
is specified, MySQL
returns a live checksum if the table storage engine supports it and scans
the table otherwise.
This statement is implemented in MySQL 4.1.1.
OPTIMIZE TABLE
SyntaxOPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
OPTIMIZE TABLE
should be used if you have deleted a large part of a
table or if you have made many changes to a table with variable-length rows
(tables that have VARCHAR
, BLOB
, or TEXT
columns).
Deleted records are maintained in a linked list and subsequent INSERT
operations reuse old record positions. You can use OPTIMIZE TABLE
to
reclaim the unused space and to defragment the data file.
In most setups, you need not run OPTIMIZE TABLE
at all. Even
if you do a lot of updates to variable-length rows, it's not likely that
you need to do this more than once a week or month and only on certain
tables.
For the moment, OPTIMIZE TABLE
works only on MyISAM
,
BDB
and InnoDB
tables. For BDB
tables, OPTIMIZE
TABLE
is currently mapped to ANALYZE TABLE
. It was also the case for
InnoDB
tables before MySQL 4.1.3; starting from this version it is
mapped to ALTER TABLE
.
See section 13.5.2.1 ANALYZE TABLE
Syntax.
You can get OPTIMIZE TABLE
to work on other table types by starting
mysqld
with the --skip-new
or --safe-mode
option;
in this case, OPTIMIZE TABLE
is just mapped to ALTER TABLE
.
OPTIMIZE TABLE
works as follows:
Note that MySQL locks the table during the time OPTIMIZE TABLE
is
running.
Before MySQL 4.1.1, OPTIMIZE TABLE
statements are not written
to the binary log. As of MySQL 4.1.1, they are written to the binary
log unless the optional NO_WRITE_TO_BINLOG
keyword
(or its alias LOCAL
) is used.
REPAIR TABLE
SyntaxREPAIR [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ... [QUICK] [EXTENDED] [USE_FRM]
REPAIR TABLE
repairs a possibly corrupted table.
By default,
it has the same effect as myisamchk --recover tbl_name
.
REPAIR TABLE
works only on MyISAM
tables.
Normally you should never have to run this statement. However, if disaster
strikes, REPAIR TABLE
is very likely to get back all your data from
a MyISAM
table. If your tables become corrupted often, you should try
to find the reason for it, to eliminate the need to use REPAIR TABLE
.
See section A.4.2 What to Do If MySQL Keeps Crashing. See section 14.1.4 MyISAM
Table Problems.
The statement returns a table with the following columns:
Column | Value |
Table | The table name |
Op | Always repair
|
Msg_type | One of status , error , info , or warning
|
Msg_text | The message |
The REPAIR TABLE
statement might produce many rows of information
for each repaired table. The last row will have a Msg_type
value of
status
and Msg_test
normally should be OK
. If you
don't get OK
, you should try repairing the table with myisamchk
--safe-recover
, because REPAIR TABLE
does not yet implement all the
options of myisamchk
. We plan to make it more flexible in the future.
If QUICK
is given, REPAIR TABLE
tries to repair
only the index tree. This type of repair is like that done by
myisamchk --recover --quick
.
If you use EXTENDED
, MySQL creates the index row by row instead of
creating one index at a time with sorting. (Before MySQL 4.1, this might
be better than sorting on fixed-length keys if you have long CHAR
keys that compress very well.) This type of repair is like that done by
myisamchk --safe-recover
.
As of MySQL 4.0.2, there is a USE_FRM
mode for REPAIR TABLE
.
Use it if the `.MYI' index file is missing or if its header is
corrupted. In this mode, MySQL will re-create the `.MYI' file using
information from the `.frm' file. This kind of repair cannot be done
with myisamchk
. Note: Use this mode only if you cannot
use regular REPAIR
modes. `.MYI' header contains important
table metadata (in particular, current AUTO_INCREMENT
value
and Delete link
) that will be lost in REPAIR ... USE_FRM
.
Don't use USE_FRM
if the table is compressed, as this information
is also stored in `.MYI' file.
Before MySQL 4.1.1, REPAIR TABLE
statements are not written
to the binary log. As of MySQL 4.1.1, they are written to the binary
log unless the optional NO_WRITE_TO_BINLOG
keyword
(or its alias LOCAL
) is used.
Warning: If the server dies during a REPAIR TABLE
operation,
it's essential after restarting it that you immediately execute another
REPAIR TABLE
statement for the table before performing any other
operations on it. (It's always good to start by making a backup.) In the
worst case, you might have a new clean index file without information about
the data file, and then the next operation you perform could overwrite the
data file. This is an unlikely, but possible scenario.
RESTORE TABLE
SyntaxRESTORE TABLE tbl_name [, tbl_name] ... FROM '/path/to/backup/directory'
Restores the table or tables from a backup that was made with BACKUP
TABLE
. Existing tables will not be overwritten; if you try to restore over
an existing table, you will get an error. Just as BACKUP TABLE
,
RESTORE TABLE
currently works only for MyISAM
tables.
The directory should be specified as a full pathname.
The backup for each table consists of its `.frm' format file and `.MYD' data file. The restore operation restores those files, then uses them to rebuild the `.MYI' index file. Restoring takes longer than backing up due to the need to rebuild the indexes. The more indexes the table has, the longer it will take.
The statement returns a table with the following columns:
Column | Value |
Table | The table name |
Op | Always restore
|
Msg_type | One of status , error , info , or warning
|
Msg_text | The message |
SET
SyntaxSET variable_assignment [, variable_assignment] ... variable_assignment: user_var_name = expr | [GLOBAL | SESSION] system_var_name = expr | @@[global. | session.]system_var_name = expr
SET
sets different types of variables that affect the operation of the
server or your client. It can be used to assign values to user variables or
system variables.
The SET PASSWORD
statement for assigning account passwords is
described in
See section 13.5.1.5 SET PASSWORD
Syntax.
In MySQL 4.0.3, we added the GLOBAL
and SESSION
options
and allowed most important system variables to be changed dynamically at
runtime.
The system variables that you can set at runtime are described in
section 5.2.3.1 Dynamic System Variables.
In older versions of MySQL, SET OPTION
is used instead of SET
,
but this is deprecated; just leave out the word OPTION
.
The following example show the different syntaxes you can use to set variables.
A user variable is written as @var_name
and can be set as follows:
SET @var_name = expr;
Further information about user variables is given in section 9.3 User Variables.
System variables can be referred to in SET
statements as
var_name. The name optionally can be preceded by GLOBAL
or
@@global.
to indicate explicitly that the variable is a global
variable, or by SESSION
, @@session.
, or @@
to
indicate that it is a session variable. LOCAL
and @@local.
are synonyms for SESSION
and @@session.
. If no modifier is
present, SET
sets the session variable.
The @@var_name
syntax for system variables is supported to make
MySQL syntax compatible with some other database systems.
If you set several system variables in the same statement, the last used
GLOBAL
or SESSION
option is used for variables that have no mode
specified.
SET sort_buffer_size=10000; SET @@local.sort_buffer_size=10000; SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000; SET @@sort_buffer_size=1000000; SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;
If you set a system variable using SESSION
(the default), the value
remains in effect until the current session ends or until you set the
variable to a different value. If you set a system variable using
GLOBAL
, which requires the SUPER
privilege, the value is
remembered and used for new connections until the server restarts. If you
want to make a variable setting permanent, you should put it in an option
file. See section 4.3.2 Using Option Files.
To prevent incorrect usage, MySQL produces an error if you use SET
GLOBAL
with a variable that can only be used with SET SESSION
or if
you do not specify GLOBAL
when setting a global variable.
If you want to set a SESSION
variable to the GLOBAL
value or a
GLOBAL
value to the compiled-in MySQL default value, you can set it to
DEFAULT
. For example, the following two statements are identical in
setting the session value of max_join_size
to the global value:
SET max_join_size=DEFAULT; SET @@session.max_join_size=@@global.max_join_size;
You can get a list of most system variables with SHOW VARIABLES
.
See section 13.5.4.19 SHOW VARIABLES
Syntax.
To get a specific variable name or list of names that match a pattern, use a
LIKE
clause:
SHOW VARIABLES LIKE 'max_join_size'; SHOW GLOBAL VARIABLES LIKE 'max_join_size';
You can also get the value for a specific value by using the
@@[global.|local.]var_name
syntax with SELECT
:
SELECT @@max_join_size, @@global.max_join_size;
When you retrieve a variable with SELECT @@var_name
(that is, you
do not specify global.
, session.
, or local.
), MySQL returns
the SESSION
value if it exists and the GLOBAL
value otherwise.
The following list describes variables that have non-standard syntax or that are
not described in the list of system variables that is found in
section 5.2.3 Server System Variables.
Although these variables are not displayed by SHOW VARIABLES
, you can
obtain their values with SELECT
(with the exception of CHARACTER
SET
and SET NAMES
). For example:
mysql> SELECT @@AUTOCOMMIT; +--------------+ | @@autocommit | +--------------+ | 1 | +--------------+
AUTOCOMMIT = {0 | 1}
1
, all changes to a table take effect immediately.
If set to 0
, you have to use COMMIT
to accept a transaction or
ROLLBACK
to cancel it. If you change AUTOCOMMIT
mode from 0
to 1
, MySQL performs an automatic COMMIT
of any open transaction. Another way to begin a transaction is to use a
START TRANSACTION
or BEGIN
statement.
See section 13.4.1 START TRANSACTION
, COMMIT
, and ROLLBACK
Syntax.
BIG_TABLES = {0 | 1}
1
, all temporary tables are stored on disk rather than in
memory. This is a little slower, but the error The table tbl_name is
full
will not occur for SELECT
operations that require a large
temporary table. The default value for a new connection is
0
(use in-memory temporary tables). As of MySQL 4.0, you
should normally never need to set this variable, because MySQL automatically
converts in-memory tables to disk-based tables as necessary. This variable
previously was named SQL_BIG_TABLES
.
CHARACTER SET {charset_name | DEFAULT}
cp1251_koi8
, but you can add new mappings by editing the
`sql/convert.cc' file in the MySQL source distribution. As of MySQL
4.1.1, SET CHARACTER SET
sets three session system variables:
character_set_client
and character_set_results
are set to
the given character set, and character_set_connection
to the value
of character_set_database
.
The default mapping can be restored by using a value of DEFAULT
.
Note that the syntax for SET CHARACTER SET
differs
from that for setting most other options.
FOREIGN_KEY_CHECKS = {0 | 1}
1
(the default), foreign key constraints for InnoDB
tables are checked. If set to 0
, they are ignored. Disabling foreign
key checking can be useful for reloading InnoDB
tables in an order
different than that required by their parent/child relationships.
This variable was added in MySQL 3.23.52.
See section 15.7.4 FOREIGN KEY
Constraints.
IDENTITY = value
LAST_INSERT_ID
variable.
It exists for compatibility with other databases.
As of MySQL 3.23.25, you can read its value with SELECT @@IDENTITY
.
As of MySQL 4.0.3, you can also set its value with SET IDENTITY
.
INSERT_ID = value
INSERT
or ALTER TABLE
statement when inserting an AUTO_INCREMENT
value. This is mainly used
with the binary log.
LAST_INSERT_ID = value
LAST_INSERT_ID()
. This is stored in
the binary log when you use LAST_INSERT_ID()
in a statement that updates
a table. Setting this variable does not update theh value returned by the
mysql_insert_id()
C API function.
NAMES {'charset_name' | DEFAULT}
SET NAMES
sets the three session system variables
character_set_client
, character_set_connection
, and
character_set_results
to the given character set.
Setting character_set_connection
to charset_name
also sets
collation_connection
to the default collation for charset_name
.
The default mapping can be restored by using a value of DEFAULT
.
Note that the syntax for SET NAMES
differs
from that for setting most other options.
This statement is available as of MySQL 4.1.0.
SQL_AUTO_IS_NULL = {0 | 1}
1
(the default), you can find the last inserted row for a table
that contains an AUTO_INCREMENT
column by using the following construct:
WHERE auto_increment_column IS NULLThis behavior is used by some ODBC programs, such as Access.
SQL_AUTO_IS_NULL
was added in MySQL 3.23.52.
SQL_BIG_SELECTS = {0 | 1}
0
, MySQL aborts SELECT
statements
that probably will take a very long time (that is, statements for which
the optimizer estimates that the number of examined rows will
exceed the value of max_join_size
).
This is useful when an inadvisable WHERE
statement has been
issued. The default value for a new connection is 1
, which allows
all SELECT
statements.
If you set the max_join_size
system variable to a value other than
DEFAULT
, SQL_BIG_SELECTS
will be set to 0
.
SQL_BUFFER_RESULT = {0 | 1}
SQL_BUFFER_RESULT
forces results from SELECT
statements
to be put into temporary tables. This helps MySQL free the
table locks early and can be beneficial in cases where it takes a long time to
send results to the client.
This variable was added in MySQL 3.23.13.
SQL_LOG_BIN = {0 | 1}
0
, no logging is done to the binary log for the client.
The client must have the SUPER
privilege to set this option.
This variable was added in MySQL 3.23.16.
SQL_LOG_OFF = {0 | 1}
1
, no logging is done to the general query log for this
client. The client must have the SUPER
privilege to set this option.
SQL_LOG_UPDATE = {0 | 1}
0
, no logging is done to the update log for the client.
The client must have the SUPER
privilege to set this option.
This variable was added in MySQL 3.22.5.
Starting from MySQL 5.0.0, it is deprecated and is mapped to
SQL_LOG_BIN
(see section D.1.4 Changes in release 5.0.0 (22 Dec 2003: Alpha)).
SQL_QUOTE_SHOW_CREATE = {0 | 1}
1
, SHOW CREATE TABLE
quotes table and column
names. If set to 0
, quoting is disabled. This option is enabled
by default so that replication will work for tables with table and column
names that require quoting.
This variable was added in MySQL 3.23.26.
section 13.5.4.5 SHOW CREATE TABLE
Syntax.
SQL_SAFE_UPDATES = {0 | 1}
1
, MySQL aborts UPDATE
or DELETE
statements
that do not use a key in the WHERE
clause or a LIMIT
clause.
This makes it possible to catch UPDATE
or DELETE
statements
where keys are not used properly and that would probably change or delete a
large number of rows.
This variable was added in MySQL 3.22.32.
SQL_SELECT_LIMIT = {value | DEFAULT}
SELECT
statements. The
default value for a new connection is ``unlimited.'' If you have changed the
limit, the default value can be restored by using a SQL_SELECT_LIMIT
value of DEFAULT
.
If a SELECT
has a LIMIT
clause, the LIMIT
takes
precedence over the value of SQL_SELECT_LIMIT
.
SQL_SELECT_LIMIT
does not apply to SELECT
statements executed
within stored routines. It also does not apply to SELECT
statements
that do not produce a result set to be returned to the client. These include
SELECT
statements in subqueries, CREATE TABLE ... SELECT
, and
INSERT INTO ... SELECT
.
SQL_WARNINGS = {0 | 1}
INSERT
statements produce
an information string if warnings occur. The default is 0. Set the value
to 1 to produce an information string.
This variable was added in MySQL 3.22.11.
TIMESTAMP = {timestamp_value | DEFAULT}
timestamp_value
should be a
Unix epoch timestamp, not a MySQL timestamp.
UNIQUE_CHECKS = {0 | 1}
1
(the default), uniqueness checks for secondary indexes in
InnoDB
tables are performed. If set to 0
, uniqueness
checks are not done for index entries inserted into InnoDB's insert
buffer. If you know for certain that your data does not contain
uniqueness violations, you can set this to 0 to speed up large table
imports to InnoDB. This variable was added in MySQL 3.23.52.
SHOW
Syntax
SHOW
has many forms that provide information about databases,
tables, columns, or status information about the server.
This section describes those following:
SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern'] SHOW CREATE DATABASE db_name SHOW CREATE TABLE tbl_name SHOW DATABASES [LIKE 'pattern'] SHOW [STORAGE] ENGINES SHOW ERRORS [LIMIT [offset,] row_count] SHOW GRANTS FOR user SHOW INDEX FROM tbl_name [FROM db_name] SHOW INNODB STATUS SHOW [BDB] LOGS SHOW PRIVILEGES SHOW [FULL] PROCESSLIST SHOW STATUS [LIKE 'pattern'] SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern'] SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern'] SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern'] SHOW WARNINGS [LIMIT [offset,] row_count]
If the syntax for a given SHOW
statement includes a LIKE
'pattern'
part, 'pattern'
is a string that can contain the SQL `%'
and `_' wildcard characters.
The pattern is useful for restricting statement output to matching values.
Note that there are other forms of these statements described elsewhere:
SHOW
statement has forms that provide information about
replication master and slave servers:
SHOW BINLOG EVENTS SHOW MASTER LOGS SHOW MASTER STATUS SHOW SLAVE HOSTS SHOW SLAVE STATUSThese forms of
SHOW
are described in section 13.6 Replication Statements.
SHOW CHARACTER SET
SyntaxSHOW CHARACTER SET [LIKE 'pattern']
The SHOW CHARACTER SET
statement shows all available character sets.
It takes an optional LIKE
clause that indicates which character set
names to match. For example:
mysql> SHOW CHARACTER SET LIKE 'latin%'; +---------+-----------------------------+-------------------+--------+ | Charset | Description | Default collation | Maxlen | +---------+-----------------------------+-------------------+--------+ | latin1 | ISO 8859-1 West European | latin1_swedish_ci | 1 | | latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 | | latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 | | latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 | +---------+-----------------------------+-------------------+--------+
The Maxlen
column shows the maximum number of bytes used to
store one character.
SHOW CHARACTER SET
is available as of MySQL 4.1.0.
SHOW COLLATION
SyntaxSHOW COLLATION [LIKE 'pattern']
The output from SHOW COLLATION
includes all available character
sets.
It takes an optional LIKE
clause that indicates which collation
names to match. For example:
mysql> SHOW COLLATION LIKE 'latin1%'; +-------------------+---------+----+---------+----------+---------+ | Collation | Charset | Id | Default | Compiled | Sortlen | +-------------------+---------+----+---------+----------+---------+ | latin1_german1_ci | latin1 | 5 | | | 0 | | latin1_swedish_ci | latin1 | 8 | Yes | Yes | 0 | | latin1_danish_ci | latin1 | 15 | | | 0 | | latin1_german2_ci | latin1 | 31 | | Yes | 2 | | latin1_bin | latin1 | 47 | | Yes | 0 | | latin1_general_ci | latin1 | 48 | | | 0 | | latin1_general_cs | latin1 | 49 | | | 0 | | latin1_spanish_ci | latin1 | 94 | | | 0 | +-------------------+---------+----+---------+----------+---------+
The Default
column indicates whether a collation is the
default for its character set.
Compiled
indicates whether the character set is
compiled into the server.
Sortlen
is related to the amount of memory required to sort strings
expressed in the character set.
SHOW COLLATION
is available as of MySQL 4.1.0.
SHOW COLUMNS
SyntaxSHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
SHOW COLUMNS
lists the columns in a given table. If the column types
differ from what you expect them to be based on your CREATE TABLE
statement, note that MySQL sometimes changes column types when you create or
alter a table. The conditions for which this occurs are described in
section 13.2.6.1 Silent Column Specification Changes.
The FULL
keyword can be used from MySQL 3.23.32 on. It causes the
output to include the privileges you have for each column. As of MySQL 4.1,
FULL
also causes any per-column comments to be displayed.
You can use db_name.tbl_name as an alternative to the tbl_name
FROM db_name
syntax. These two statements are equivalent:
mysql> SHOW COLUMNS FROM mytable FROM mydb; mysql> SHOW COLUMNS FROM mydb.mytable;
SHOW FIELDS
is a synonym for SHOW COLUMNS
. You can also
list a table's columns with the mysqlshow db_name tbl_name
command.
The DESCRIBE
statement provides information similar to
SHOW COLUMNS
.
See section 13.3.1 DESCRIBE
Syntax (Get Information About Columns).
SHOW CREATE DATABASE
SyntaxSHOW CREATE {DATABASE | SCHEMA} db_name
Shows a CREATE DATABASE
statement that will create the given
database. It was added in MySQL 4.1. SHOW CREATE SCHEMA
can be used
as of MySQL 5.0.2.
mysql> SHOW CREATE DATABASE test\G *************************** 1. row *************************** Database: test Create Database: CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */
SHOW CREATE TABLE
SyntaxSHOW CREATE TABLE tbl_name
Shows a CREATE TABLE
statement that will create the given table.
It was added in MySQL 3.23.20.
mysql> SHOW CREATE TABLE t\G *************************** 1. row *************************** Table: t Create Table: CREATE TABLE t ( id INT(11) default NULL auto_increment, s char(60) default NULL, PRIMARY KEY (id) ) TYPE=MyISAM
SHOW CREATE TABLE
quotes table and column names according to
the value of the SQL_QUOTE_SHOW_CREATE
option.
section 13.5.3 SET
Syntax.
SHOW CREATE VIEW
SyntaxSHOW CREATE VIEW view_name
This statement shows a CREATE VIEW
statement that will create
the given view.
mysql> SHOW CREATE VIEW v; +-------+----------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------+ | v | CREATE VIEW `test`.`v` AS select 1 AS `a`,2 AS `b` | +-------+----------------------------------------------------+
This statement was added in MySQL 5.0.1.
SHOW DATABASES
SyntaxSHOW {DATABASES | SCHEMAS} [LIKE 'pattern']
SHOW DATABASES
lists the databases on the MySQL server host.
You can also get this list using the mysqlshow
command.
As of MySQL 4.0.2, you will see only those databases for which you have some
kind of privilege, if you don't have the global SHOW DATABASES
privilege.
If the server was started with the --skip-show-database
option, you
cannot use this statement at all unless you have the SHOW DATABASES
privilege.
SHOW SCHEMAS
can be used as of MySQL 5.0.2
SHOW ENGINES
SyntaxSHOW [STORAGE] ENGINES
SHOW ENGINES
shows you status information about the storage engines.
This is particularly useful for checking whether a storage engine is
supported, or to see what the default engine is.
This statement is implemented in MySQL 4.1.2.
SHOW TABLE TYPES
is a deprecated synonym.
mysql> SHOW ENGINES\G *************************** 1. row *************************** Engine: MyISAM Support: DEFAULT Comment: Default engine as of MySQL 3.23 with great performance *************************** 2. row *************************** Engine: HEAP Support: YES Comment: Alias for MEMORY *************************** 3. row *************************** Engine: MEMORY Support: YES Comment: Hash based, stored in memory, useful for temporary tables *************************** 4. row *************************** Engine: MERGE Support: YES Comment: Collection of identical MyISAM tables *************************** 5. row *************************** Engine: MRG_MYISAM Support: YES Comment: Alias for MERGE *************************** 6. row *************************** Engine: ISAM Support: NO Comment: Obsolete storage engine, now replaced by MyISAM *************************** 7. row *************************** Engine: MRG_ISAM Support: NO Comment: Obsolete storage engine, now replaced by MERGE *************************** 8. row *************************** Engine: InnoDB Support: YES Comment: Supports transactions, row-level locking, and foreign keys *************************** 9. row *************************** Engine: INNOBASE Support: YES Comment: Alias for INNODB *************************** 10. row *************************** Engine: BDB Support: YES Comment: Supports transactions and page-level locking *************************** 11. row *************************** Engine: BERKELEYDB Support: YES Comment: Alias for BDB *************************** 12. row *************************** Engine: NDBCLUSTER Support: YES Comment: Clustered, fault-tolerant, memory-based tables *************************** 13. row *************************** Engine: NDB Support: YES Comment: Alias for NDBCLUSTER *************************** 14. row *************************** Engine: EXAMPLE Support: YES Comment: Example storage engine *************************** 15. row *************************** Engine: ARCHIVE Support: YES Comment: Archive storage engine *************************** 16. row *************************** Engine: CSV Support: YES Comment: CSV storage engine *************************** 17. row *************************** Engine: FEDERATED Support: YES Comment: Federated MySQL storage engine
A Support
value indicates whether the particular storage engine is
supported, and which is the default engine. For example, if the server
is started with the --default-table-type=InnoDB
option, then
the Support
value for the InnoDB
row will have the value
DEFAULT
.
SHOW ERRORS
SyntaxSHOW ERRORS [LIMIT [offset,] row_count] SHOW COUNT(*) ERRORS
This statement is similar to SHOW WARNINGS
, except that instead
of displaying errors, warnings, and notes, it displays only errors.
SHOW ERRORS
is available as of MySQL 4.1.0.
The LIMIT
clause has the same syntax as for the SELECT
statement.
See section 13.1.7 SELECT
Syntax.
The SHOW COUNT(*) ERRORS
statement displays the number of errors.
You can also retrieve this number from the error_count
variable:
SHOW COUNT(*) ERRORS; SELECT @@error_count;
For more information, see section 13.5.4.20 SHOW WARNINGS
Syntax.
SHOW GRANTS
SyntaxSHOW GRANTS FOR user
This statement lists the GRANT
statements that must be issued to
duplicate the privileges for a MySQL user account.
mysql> SHOW GRANTS FOR 'root'@'localhost'; +---------------------------------------------------------------------+ | Grants for root@localhost | +---------------------------------------------------------------------+ | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION | +---------------------------------------------------------------------+
As of MySQL 4.1.2, to list privileges for the current session, you can use any of the following statements:
SHOW GRANTS; SHOW GRANTS FOR CURRENT_USER; SHOW GRANTS FOR CURRENT_USER();
Before MySQL 4.1.2, you can find out what user the
session was authenticated as by selecting the value
of the CURRENT_USER()
function (new in MySQL 4.0.6).
Then use that value in the SHOW GRANTS
statement.
See section 12.8.3 Information Functions.
SHOW GRANTS
is available as of MySQL 3.23.4.
SHOW INDEX
SyntaxSHOW INDEX FROM tbl_name [FROM db_name]
SHOW INDEX
returns table index information in a format that
resembles the SQLStatistics
call in ODBC.
SHOW INDEX
returns the following fields:
Table
Non_unique
Key_name
Seq_in_index
Column_name
Collation
NULL
(Not sorted).
Cardinality
ANALYZE TABLE
or myisamchk -a
. Cardinality
is counted
based on statistics stored as integers, so it's not necessarily accurate for
small tables. The higher the cardinality, the greater the chance that MySQL
will use the index when doing joins.
Sub_part
NULL
if the entire column is indexed.
Packed
NULL
if it is not.
Null
YES
if the column may contain NULL
. If not, the column
contains NO
as of MySQL 5.0.3, and ''
before that.
Index_type
BTREE
, FULLTEXT
, HASH
,
RTREE
).
Comment
Index_type
column was
added, Comment
indicates whether an index is FULLTEXT
.
The Packed
and Comment
columns were added in MySQL 3.23.0.
The Null
and Index_type
columns were added in MySQL 4.0.2.
You can use db_name.tbl_name as an alternative to the tbl_name
FROM db_name
syntax. These two statements are equivalent:
mysql> SHOW INDEX FROM mytable FROM mydb; mysql> SHOW INDEX FROM mydb.mytable;
SHOW KEYS
is a synonym for SHOW INDEX
. You can also list
a table's indexes with the mysqlshow -k db_name tbl_name
command.
SHOW INNODB STATUS
SyntaxSHOW INNODB STATUS
This statement shows extensive information about the state of the
InnoDB
storage engine.
SHOW LOGS
SyntaxSHOW [BDB] LOGS
SHOW LOGS
displays status information about existing log files.
It was implemented in MySQL 3.23.29. Currently, it displays only information
about Berkeley DB log files, so an alias for it (available as of MySQL
4.1.1) is SHOW BDB LOGS
.
SHOW LOGS
returns the following fields:
File
Type
BDB
for Berkeley DB log files).
Status
FREE
if the file can be removed, or
IN USE
if the file is needed by the transaction subsystem)
SHOW PRIVILEGES
SyntaxSHOW PRIVILEGES
SHOW PRIVILEGES
shows the list of system privileges that the underlying
MySQL server supports.
This statement is implemented as of MySQL 4.1.0.
mysql> SHOW PRIVILEGES\G *************************** 1. row *************************** Privilege: Select Context: Tables Comment: To retrieve rows from table *************************** 2. row *************************** Privilege: Insert Context: Tables Comment: To insert data into tables *************************** 3. row *************************** Privilege: Update Context: Tables Comment: To update existing rows *************************** 4. row *************************** Privilege: Delete Context: Tables Comment: To delete existing rows *************************** 5. row *************************** Privilege: Index Context: Tables Comment: To create or drop indexes *************************** 6. row *************************** Privilege: Alter Context: Tables Comment: To alter the table *************************** 7. row *************************** Privilege: Create Context: Databases,Tables,Indexes Comment: To create new databases and tables *************************** 8. row *************************** Privilege: Drop Context: Databases,Tables Comment: To drop databases and tables *************************** 9. row *************************** Privilege: Grant Context: Databases,Tables Comment: To give to other users those privileges you possess *************************** 10. row *************************** Privilege: References Context: Databases,Tables Comment: To have references on tables *************************** 11. row *************************** Privilege: Reload Context: Server Admin Comment: To reload or refresh tables, logs and privileges *************************** 12. row *************************** Privilege: Shutdown Context: Server Admin Comment: To shutdown the server *************************** 13. row *************************** Privilege: Process Context: Server Admin Comment: To view the plain text of currently executing queries *************************** 14. row *************************** Privilege: File Context: File access on server Comment: To read and write files on the server
SHOW PROCESSLIST
SyntaxSHOW [FULL] PROCESSLIST
SHOW PROCESSLIST
shows you which threads are running.
You can also get this information using the mysqladmin processlist
statement. If you have the SUPER
privilege, you can see all
threads. Otherwise, you can see only your own threads (that is, threads
associated with the MySQL account that you are using).
See section 13.5.5.3 KILL
Syntax.
If you don't use the FULL
keyword, only the first 100
characters of each query are shown.
Starting from MySQL 4.0.12, the statement reports the hostname for TCP/IP
connections in host_name:client_port
format to make it easier to
determine which client is doing what.
This statement is very useful if you get the "too many connections" error
message and want to find out what is going on. MySQL reserves one extra
connection to be used by accounts that have the SUPER
privilege, to
ensure that administrators should always be able to connect and check the
system (assuming that you are not giving this privilege to all your users).
Some states commonly seen in the output from SHOW PROCESSLIST
:
Checking table
Closing tables
Connect Out
Copying to tmp table on disk
tmp_table_size
and the
thread is changing the temporary table from in-memory to disk-based
format to save memory.
Creating tmp table
deleting from main table
deleting from reference tables
Flushing tables
FLUSH TABLES
and is waiting for all
threads to close their tables.
Killed
Locked
Sending data
SELECT
statement and
also is sending data to the client.
Sorting for group
GROUP BY
.
Sorting for order
ORDER BY
.
Opening tables
ALTER TABLE
or a
LOCK TABLE
statement can prevent opening a table until the statement
is finished.
Removing duplicates
SELECT DISTINCT
in such a way that MySQL
couldn't optimize away the distinct operation at an early stage. Because of
this, MySQL requires an extra stage to remove all duplicated rows before
sending the result to the client.
Reopen table
Repair by sorting
Repair with keycache
Repair by sorting
.
Searching rows for update
UPDATE
is changing
the index that is used to find the involved rows.
Sleeping
System lock
mysqld
servers that are accessing
the same tables, you can disable system locks with the
--skip-external-locking
option.
Upgrading lock
INSERT DELAYED
handler is trying to get a lock for the table
to insert rows.
Updating
User Lock
GET_LOCK()
.
Waiting for tables
FLUSH TABLES
or one of the following statements on the table in question: FLUSH
TABLES tbl_name
, ALTER TABLE
, RENAME TABLE
,
REPAIR TABLE
, ANALYZE TABLE
, or OPTIMIZE TABLE
.
waiting for handler insert
INSERT DELAYED
handler has processed all pending inserts and is
waiting for new ones.
Most states correspond to very quick operations. If a thread stays in any of these states for many seconds, there might be a problem that needs to be investigated.
There are some other states that are not mentioned in the preceding list, but many of them are useful only for finding bugs in the server.
SHOW STATUS
SyntaxSHOW STATUS [LIKE 'pattern']
SHOW STATUS
provides server status information. This information
also can be obtained using the mysqladmin extended-status
command.
Partial output is shown here. The list of variables and their values may be different for your server. The meaning of each variable is given in See section 5.2.4 Server Status Variables.
mysql> SHOW STATUS; +--------------------------+------------+ | Variable_name | Value | +--------------------------+------------+ | Aborted_clients | 0 | | Aborted_connects | 0 | | Bytes_received | 155372598 | | Bytes_sent | 1176560426 | | Connections | 30023 | | Created_tmp_disk_tables | 0 | | Created_tmp_tables | 8340 | | Created_tmp_files | 60 | ... | Open_tables | 1 | | Open_files | 2 | | Open_streams | 0 | | Opened_tables | 44600 | | Questions | 2026873 | ... | Table_locks_immediate | 1920382 | | Table_locks_waited | 0 | | Threads_cached | 0 | | Threads_created | 30022 | | Threads_connected | 1 | | Threads_running | 1 | | Uptime | 80380 | +--------------------------+------------+
With a LIKE
clause, the statement displays only those variables that
match the pattern:
mysql> SHOW STATUS LIKE 'Key%'; +--------------------+----------+ | Variable_name | Value | +--------------------+----------+ | Key_blocks_used | 14955 | | Key_read_requests | 96854827 | | Key_reads | 162040 | | Key_write_requests | 7589728 | | Key_writes | 3813196 | +--------------------+----------+
SHOW TABLE STATUS
SyntaxSHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
SHOW TABLE STATUS
works likes SHOW TABLE
, but provides a lot
of information about each table. You can also get this list using the
mysqlshow --status db_name
command. This statement was
added in MySQL 3.23. As of MySQL 5.0.1, it also displays information about
views.
SHOW TABLE STATUS
returns the following fields:
Name
Engine
Type
.
See section 14 MySQL Storage Engines and Table Types.
Version
Row_format
Fixed
, Dynamic
, Compressed
,
Redundant
, Compact
). Starting with MySQL/InnoDB 5.0.3,
the format of InnoDB tables is reported as Redundant
or
Compact
. Before 5.0.3, InnoDB tables are always in the
Redundant
format.
Rows
MyISAM
and ISAM
, store the
exact count.
For other storage engines, such as InnoDB
, this value is an
approximation, and may vary from the actual value by as much as
40 to 50%. In such cases, use SELECT COUNT(*)
to obtain an
accurate count.
Avg_row_length
Data_length
Max_data_length
Index_length
Data_free
Auto_increment
AUTO_INCREMENT
value.
Create_time
Update_time
Check_time
Collation
Checksum
Create_options
CREATE TABLE
.
Comment
In the table comment, InnoDB
tables will report the free space of
the tablespace to which the table belongs. For a table located in the
shared tablespace, this is the free space of the shared tablespace. If
you are using multiple tablespaces and the table has its own tablespace,
the freespace is for just that table.
For MEMORY
(HEAP
) tables, the Data_length
,
Max_data_length
, and Index_length
values approximate the
actual amount of allocated memory. The allocation algorithm reserves memory
in large amounts to reduce the number of allocation operations.
For views, all the fields displayed by SHOW TABLE STATUS
are
NULL
except that Name
indicates the view name and Comment
says view
.
SHOW TABLES
SyntaxSHOW [FULL|OPEN] TABLES [FROM db_name] [LIKE 'pattern']
SHOW TABLES
lists the non-TEMPORARY
tables in a given
database. You can also get this list using the mysqlshow db_name
command.
Before MySQL 5.0.1, the output from SHOW TABLES
contains a single
column of table names. Beginning with MySQL 5.0.1, also lists the views in
the database. As of MySQL 5.0.2, the FULL
modifier is supported such
that SHOW FULL TABLES
displays a second output column. Values in the
second column are BASE TABLE
for a table and VIEW
for a view.
Note: If you have no privileges for a table, the table
will not show up in the output from SHOW TABLES
or mysqlshow
db_name
.
SHOW OPEN TABLES
lists the tables that are currently open in
the table cache. See section 7.4.8 How MySQL Opens and Closes Tables. The Comment
field in the output
tells how many times the table is cached
and in_use
.
OPEN
can be used from MySQL 3.23.33 on.
SHOW VARIABLES
SyntaxSHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
SHOW VARIABLES
shows the values of some MySQL system variables. This
information also can be obtained using the mysqladmin variables
command.
The GLOBAL
and SESSION
options are new in MySQL 4.0.3.
With GLOBAL
, you will get the values that will be used for new
connections to MySQL. With SESSION
, you will get the values that
are in effect for the current connection. If you use neither option, the
default SESSION
. LOCAL
is a synonym for SESSION
.
If the default values are unsuitable, you can set most of these variables
using command-line options when mysqld
starts or at runtime with
the SET
statement.
See section 5.2.1 mysqld
Command-Line Options and section 13.5.3 SET
Syntax.
Partial output is shown here. The list of variables and their values may be different for your server. The meaning of each variable is given in See section 5.2.3 Server System Variables. Information about tuning them is provided in section 7.5.2 Tuning Server Parameters.
mysql> SHOW VARIABLES; +---------------------------------+------------------------------+ | Variable_name | Value | +---------------------------------+------------------------------| | back_log | 50 | | basedir | /usr/local/mysql | | bdb_cache_size | 8388572 | | bdb_log_buffer_size | 32768 | | bdb_home | /usr/local/mysql | ... | max_connections | 100 | | max_connect_errors | 10 | | max_delayed_threads | 20 | | max_error_count | 64 | | max_heap_table_size | 16777216 | | max_join_size | 4294967295 | | max_relay_log_size | 0 | | max_sort_length | 1024 | ... | timezone | EEST | | tmp_table_size | 33554432 | | tmpdir | /tmp/:/mnt/hd2/tmp/ | | version | 4.0.4-beta | | wait_timeout | 28800 | +---------------------------------+------------------------------+
With a LIKE
clause, the statement displays only those variables that
match the pattern:
mysql> SHOW VARIABLES LIKE 'have%'; +--------------------+----------+ | Variable_name | Value | +--------------------+----------+ | have_bdb | YES | | have_innodb | YES | | have_isam | YES | | have_raid | NO | | have_symlink | DISABLED | | have_openssl | YES | | have_query_cache | YES | +--------------------+----------+
SHOW WARNINGS
SyntaxSHOW WARNINGS [LIMIT [offset,] row_count] SHOW COUNT(*) WARNINGS
SHOW WARNINGS
shows the error, warning, and note messages that
resulted from the last statement that generated messages, or nothing if the
last statement that used a table generated no messages.
This statement is implemented as of MySQL 4.1.0.
A related statement, SHOW ERRORS
, shows only the errors.
See section 13.5.4.9 SHOW ERRORS
Syntax.
The list of messages is reset for each new statement that uses a table.
The SHOW COUNT(*) WARNINGS
statement displays the total number of
errors, warnings, and notes. You can also retrieve this number from the
warning_count
variable:
SHOW COUNT(*) WARNINGS; SELECT @@warning_count;
The value of warning_count
might be greater than the number of
messages displayed by SHOW WARNINGS
if the max_error_count
system variable is set low enough that not all messages are stored. An
example shown later in this section demonstrates how this can happen.
The LIMIT
clause has the same syntax as for the SELECT
statement.
See section 13.1.7 SELECT
Syntax.
The MySQL server sends back the total number of errors, warnings, and
notes resulting from the last statement.
If you are using the C API, this value can be obtained by calling
mysql_warning_count()
.
See section 22.2.3.61 mysql_warning_count()
.
Note that the framework for warnings was added in MySQL 4.1.0, at which
point many statements did not generate warnings. In 4.1.1, the situation is
much improved, with warnings generated for statements such as LOAD
DATA INFILE
and DML statements such as INSERT
, UPDATE
,
CREATE TABLE
, and ALTER TABLE
.
The following DROP TABLE
statement results in a note:
mysql> DROP TABLE IF EXISTS no_such_table; mysql> SHOW WARNINGS; +-------+------+-------------------------------+ | Level | Code | Message | +-------+------+-------------------------------+ | Note | 1051 | Unknown table 'no_such_table' | +-------+------+-------------------------------+
Here is a simple example that shows a syntax warning for CREATE TABLE
and conversion warnings for INSERT
:
mysql> CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4)) TYPE=MyISAM; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> SHOW WARNINGS\G *************************** 1. row *************************** Level: Warning Code: 1287 Message: 'TYPE=storage_engine' is deprecated, use 'ENGINE=storage_engine' instead 1 row in set (0.00 sec) mysql> INSERT INTO t1 VALUES(10,'mysql'),(NULL,'test'), -> (300,'Open Source'); Query OK, 3 rows affected, 4 warnings (0.01 sec) Records: 3 Duplicates: 0 Warnings: 4 mysql> SHOW WARNINGS\G *************************** 1. row *************************** Level: Warning Code: 1265 Message: Data truncated for column 'b' at row 1 *************************** 2. row *************************** Level: Warning Code: 1263 Message: Data truncated, NULL supplied to NOT NULL column 'a' at row 2 *************************** 3. row *************************** Level: Warning Code: 1264 Message: Data truncated, out of range for column 'a' at row 3 *************************** 4. row *************************** Level: Warning Code: 1265 Message: Data truncated for column 'b' at row 3 4 rows in set (0.00 sec)
The maximum number of error, warning, and note messages to store is controlled
by the max_error_count
system variable. By default, its value is 64.
To change the number of messages you want stored, change the value of
max_error_count
.
In the following example, the ALTER TABLE
statement produces three
warning messages, but only one is stored because max_error_count
has been set to 1
:
mysql> SHOW VARIABLES LIKE 'max_error_count'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_error_count | 64 | +-----------------+-------+ 1 row in set (0.00 sec) mysql> SET max_error_count=1; Query OK, 0 rows affected (0.00 sec) mysql> ALTER TABLE t1 MODIFY b CHAR; Query OK, 3 rows affected, 3 warnings (0.00 sec) Records: 3 Duplicates: 0 Warnings: 3 mysql> SELECT @@warning_count; +-----------------+ | @@warning_count | +-----------------+ | 3 | +-----------------+ 1 row in set (0.01 sec) mysql> SHOW WARNINGS; +---------+------+----------------------------------------+ | Level | Code | Message | +---------+------+----------------------------------------+ | Warning | 1263 | Data truncated for column 'b' at row 1 | +---------+------+----------------------------------------+ 1 row in set (0.00 sec)
To disable warnings, set max_error_count
to 0
. In this case,
warning_count
still indicates how many warnings have occurred, but
none of the messages are stored.
CACHE INDEX
SyntaxCACHE INDEX tbl_index_list [, tbl_index_list] ... IN key_cache_name tbl_index_list: tbl_name [[INDEX|KEY] (index_name[, index_name] ...)]
The CACHE INDEX
statement assigns table indexes to a specific key
cache. It is used only for MyISAM
tables.
The following statement assigns indexes from the tables t1
,
t2
, and t3
to the key cache named hot_cache
:
mysql> CACHE INDEX t1, t2, t3 IN hot_cache; +---------+--------------------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------+--------------------+----------+----------+ | test.t1 | assign_to_keycache | status | OK | | test.t2 | assign_to_keycache | status | OK | | test.t3 | assign_to_keycache | status | OK | +---------+--------------------+----------+----------+
The syntax of CACHE INDEX
allows you to specify that only particular
indexes from a table should be assigned to the cache. However, the current
implementation assigns all the table's indexes to the cache, so there is no
reason to specify anything other than the table name.
The key cache referred to in a CACHE INDEX
statement can be created
by setting its size with a parameter setting statement or in the server
parameter settings. For example:
mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
Key cache parameters can be accessed as members of a structured system variable. See section 9.4.1 Structured System Variables.
A key cache must exist before you can assign indexes to it:
mysql> CACHE INDEX t1 IN non_existent_cache; ERROR 1284 (HY000): Unknown key cache 'non_existent_cache'
By default, table indexes are assigned to the main (default) key cache created at the server startup. When a key cache is destroyed, all indexes assigned to it become assigned to the default key cache again.
Index assignment affects the server globally: If one client assigns an index to a given cache, this cache is used for all queries involving the index, no matter what client issues the queries.
CACHE INDEX
was added in MySQL 4.1.1.
FLUSH
SyntaxFLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ...
You should use the FLUSH
statement if you want to clear some of the
internal caches MySQL uses. To execute FLUSH
, you must have
the RELOAD
privilege.
flush_option can be any of the following:
HOSTS
Host ... is blocked
. When more than
max_connect_errors
errors occur successively for a given host while
connecting to the MySQL server, MySQL assumes that
something is wrong and blocks the host from further connection requests.
Flushing the host tables allows the host to attempt to connect
again. See section A.2.5 Host 'host_name
' is blocked. You can start mysqld
with
--max_connect_errors=999999999
to avoid this error message.
DES_KEY_FILE
--des-key-file
option at server startup time.
LOGS
SIGHUP
signal to the mysqld
server (except on some Mac OS X 10.3 versions
where mysqld
will ignore SIGHUP
and SIGQUIT
).
PRIVILEGES
mysql
database.
QUERY CACHE
RESET QUERY CACHE
.
STATUS
{TABLE | TABLES} [tbl_name [, tbl_name] ...]
FLUSH TABLES
also removes all query results from the query cache, like
the RESET QUERY CACHE
statement.
TABLES WITH READ LOCK
UNLOCK
TABLES
. This is very convenient way to get backups if you have a filesystem
such as Veritas that can take snapshots in time.
USER_RESOURCES
FLUSH USER_RESOURCES
does not apply to the limit on maximum
simultaneous connections.
See section 13.5.1.3 GRANT
and REVOKE
Syntax.
Before MySQL 4.1.1, FLUSH
statements are not written to the binary
log. As of MySQL 4.1.1, they are written to the binary log unless the
optional NO_WRITE_TO_BINLOG
keyword (or its alias LOCAL
) is
used. Exceptions are that FLUSH LOGS
, FLUSH MASTER
,
FLUSH SLAVE
, and FLUSH TABLES WITH READ LOCK
are not logged in
any case because they would cause problems if replicated to a slave.
You can also access some of these statements with the mysqladmin
utility, using the flush-hosts
, flush-logs
, flush-privileges
,
flush-status
, or flush-tables
commands.
Take also a look at the RESET
statement used with replication.
See section 13.5.5.5 RESET
Syntax.
KILL
SyntaxKILL [CONNECTION | QUERY] thread_id
Each connection to mysqld
runs in a separate thread. You can see
which threads are running with the SHOW PROCESSLIST
statement and kill
a thread with the KILL thread_id
statement.
As of MySQL 5.0.0, KILL
allows the optional CONNECTION
or
QUERY
modifiers:
KILL CONNECTION
is the same as KILL
with no modifier:
It terminates the connection associated with the given thread_id.
KILL QUERY
terminates the statement that the connection currently
is executing, but leaves the connection intact.
If you have the PROCESS
privilege, you can see all threads.
If you have the SUPER
privilege, you can kill all threads and
statements. Otherwise, you can see and kill only your own threads and
statements.
You can also use the mysqladmin processlist
and mysqladmin kill
commands to examine and kill threads.
Note: You currently cannot use KILL
with the Embedded MySQL
Server library, because the embedded server merely runs inside the threads
of the host application, it does not create connection threads of its own.
When you do a KILL
, a thread-specific kill flag is set for
the thread.
In most cases, it might take some time for the thread to die, because the kill
flag is checked only at specific intervals:
SELECT
, ORDER BY
and GROUP BY
loops, the flag is
checked after reading a block of rows. If the kill flag is set, the
statement is aborted.
ALTER TABLE
, the kill flag is checked before each block of
rows are read from the original table. If the kill flag was set, the statement
is aborted and the temporary table is deleted.
UPDATE
or DELETE
, the kill flag
is checked after each block read and after each updated or deleted
row. If the kill flag is set, the statement is aborted. Note that if you
are not using transactions, the changes will not be rolled back!
GET_LOCK()
will abort and return NULL
.
INSERT DELAYED
thread will quickly flush (insert) all rows it has in
memory and terminate.
Locked
),
the table lock will be quickly aborted.
REPAIR TABLE
,
CHECK TABLE
, and OPTIMIZE TABLE
cannot be killed before
MySQL 4.1 and run to completion. This is changed: REPAIR TABLE
and OPTIMIZE TABLE
can be killed as of MySQL 4.1.0, as can CHECK TABLE
as of MySQL 4.1.3.
However, killing a REPAIR TABLE
or OPTIMIZE TABLE
operation
on a MyISAM
table results in a table that IS corrupted and will be
unusable (reads and writes to it will fail) until you optimize or repair it
again.
LOAD INDEX INTO CACHE
SyntaxLOAD INDEX INTO CACHE tbl_index_list [, tbl_index_list] ... tbl_index_list: tbl_name [[INDEX|KEY] (index_name[, index_name] ...)] [IGNORE LEAVES]
The LOAD INDEX INTO CACHE
statement preloads a table index into the
key cache to which it has been assigned by an explicit CACHE INDEX
statement, or into the default key cache otherwise. LOAD INDEX INTO
CACHE
is used only for MyISAM
tables.
The IGNORE LEAVES
modifier causes only blocks for the non-leaf
nodes of the index to be preloaded.
The following statement preloads nodes (index blocks) of indexes of the
tables t1
and t2
:
mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES; +---------+--------------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------+--------------+----------+----------+ | test.t1 | preload_keys | status | OK | | test.t2 | preload_keys | status | OK | +---------+--------------+----------+----------+
This statement preloads all index blocks from t1
. It preloads only
blocks for the non-leaf nodes from t2
.
The syntax of LOAD INDEX INTO CACHE
allows you to specify that only
particular indexes from a table should be preloaded. However, the current
implementation preloads all the table's indexes into the cache, so there is
no reason to specify anything other than the table name.
LOAD INDEX INTO CACHE
was added in MySQL 4.1.1.
RESET
SyntaxRESET reset_option [, reset_option] ...
The RESET
statement is used to clear the state of various server
operations. It also acts as a stronger
version of the FLUSH
statement. See section 13.5.5.2 FLUSH
Syntax.
To execute RESET
, you must have the RELOAD
privilege.
reset_option can be any of the following:
MASTER
FLUSH MASTER
.
See section 13.6.1 SQL Statements for Controlling Master Servers.
QUERY CACHE
SLAVE
FLUSH SLAVE
.
See section 13.6.2 SQL Statements for Controlling Slave Servers.
This section describes replication-related SQL statements. One group of statements is used for controlling master servers. The other is used for controlling slave servers.
Replication can be controlled through the SQL interface. This section discusses statements for managing master replication servers. section 13.6.2 SQL Statements for Controlling Slave Servers discusses statements for managing slave servers.
PURGE MASTER LOGS
SyntaxPURGE {MASTER | BINARY} LOGS TO 'log_name' PURGE {MASTER | BINARY} LOGS BEFORE 'date'
Deletes all the binary logs listed in the log index that are strictly prior to the specified log or date. The logs also are removed from the list recorded in the log index file, so that the given log becomes the first.
Example:
PURGE MASTER LOGS TO 'mysql-bin.010'; PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';
The BEFORE
variant is available as of MySQL 4.1. Its date argument
can be in 'YYYY-MM-DD hh:mm:ss'
format.
MASTER
and BINARY
are synonyms, but BINARY
can be used
only as of MySQL 4.1.1.
If you have an active slave that currently is reading one of the logs you are trying to delete, this statement does nothing and fails with an error. However, if a slave is dormant and you happen to purge one of the logs it wants to read, the slave will be unable to replicate once it comes up. The statement is safe to run while slaves are replicating. You do not need to stop them.
To purge logs, follow this procedure:
SHOW SLAVE STATUS
to check which log it is
reading.
SHOW MASTER LOGS
.
RESET MASTER
SyntaxRESET MASTER
Deletes all binary logs listed in the index file, resets the binary log index file to be empty, and creates a new binary log file.
This statement was named FLUSH MASTER
before MySQL 3.23.26.
SET SQL_LOG_BIN
SyntaxSET SQL_LOG_BIN = {0|1}
Disables or enables binary logging for the current connection
(SQL_LOG_BIN
is a session variable)
if the client connects using an account that has the SUPER
privilege.
The statement is refused with an error if the client does not have that
privilege. (Before MySQL 4.1.2, the statement was simply ignored in that case.)
SHOW BINLOG EVENTS
SyntaxSHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
Shows the events in the binary log.
If you do not specify 'log_name'
, the first binary log will be displayed.
The LIMIT
clause has the same syntax as for the SELECT
statement.
See section 13.1.7 SELECT
Syntax.
This statement is available as of MySQL 4.0.
SHOW MASTER LOGS
SyntaxSHOW MASTER LOGS SHOW BINARY LOGS
Lists the binary log files on the server. This statement is used as part of
the procedure described in section 13.6.1.1 PURGE MASTER LOGS
Syntax
for determining which logs can be purged.
SHOW MASTER LOGS
was added in MySQL 3.23.38. As of MySQL 4.1.1,
you can also use SHOW BINARY LOGS
, which is equivalent.
SHOW MASTER STATUS
SyntaxSHOW MASTER STATUS
Provides status information on the binary log files of the master.
SHOW SLAVE HOSTS
SyntaxSHOW SLAVE HOSTS
Displays a list of slaves currently registered with the master.
Any slave not started with the --report-host=slave_name
option will not be visible in that list.
Replication can be controlled through the SQL interface. This section discusses statements for managing slave replication servers. section 13.6.1 SQL Statements for Controlling Master Servers discusses statements for managing master servers.
CHANGE MASTER TO
SyntaxCHANGE MASTER TO master_def [, master_def] ... master_def: MASTER_HOST = 'host_name' | MASTER_USER = 'user_name' | MASTER_PASSWORD = 'password' | MASTER_PORT = port_num | MASTER_CONNECT_RETRY = count | MASTER_LOG_FILE = 'master_log_name' | MASTER_LOG_POS = master_log_pos | RELAY_LOG_FILE = 'relay_log_name' | RELAY_LOG_POS = relay_log_pos | MASTER_SSL = {0|1} | MASTER_SSL_CA = 'ca_file_name' | MASTER_SSL_CAPATH = 'ca_directory_name' | MASTER_SSL_CERT = 'cert_file_name' | MASTER_SSL_KEY = 'key_file_name' | MASTER_SSL_CIPHER = 'cipher_list'
Changes the parameters that the slave server uses for connecting to and communicating with the master server.
MASTER_USER
, MASTER_PASSWORD
, MASTER_SSL
,
MASTER_SSL_CA
, MASTER_SSL_CAPATH
, MASTER_SSL_CERT
,
MASTER_SSL_KEY
, and MASTER_SSL_CIPHER
provide information for
the slave about how to connect to its master.
The relay log options (RELAY_LOG_FILE
and RELAY_LOG_POS
) are
available beginning with MySQL 4.0.
The SSL options
(MASTER_SSL
,
MASTER_SSL_CA
,
MASTER_SSL_CAPATH
,
MASTER_SSL_CERT
,
MASTER_SSL_KEY
,
and
MASTER_SSL_CIPHER
)
are available beginning with MySQL 4.1.1.
You can change these options even on slaves that are compiled without SSL
support. They are saved to the `master.info' file, but are ignored
until you use a server that has SSL support enabled.
If you don't specify a given parameter, it keeps its old value, except as indicated in the following discussion. For example, if the password to connect to your MySQL master has changed, you just need to issue these statements to tell the slave about the new password:
mysql> STOP SLAVE; -- if replication was running mysql> CHANGE MASTER TO MASTER_PASSWORD='new3cret'; mysql> START SLAVE; -- if you want to restart replication
There is no need to specify the parameters that do not change (host, port, user, and so forth).
MASTER_HOST
and MASTER_PORT
are the hostname (or IP address) of
the master host and its TCP/IP port. Note that if MASTER_HOST
is
equal to localhost
, then, like in other parts of MySQL, the port
may be ignored (if Unix socket files can be used, for example).
If you specify MASTER_HOST
or MASTER_PORT
,
the slave assumes that the master server is different than
before (even if you specify a host or port value that is
the same as the current value.) In this case, the old values for the master
binary log name and position are considered no longer applicable, so if you
do not specify MASTER_LOG_FILE
and MASTER_LOG_POS
in the
statement, MASTER_LOG_FILE=''
and MASTER_LOG_POS=4
are
silently appended to it.
MASTER_LOG_FILE
and MASTER_LOG_POS
are the coordinates
at which the slave I/O thread should begin reading from the master the
next time the thread starts.
If you specify either of them, you can't specify RELAY_LOG_FILE
or
RELAY_LOG_POS
.
If neither of MASTER_LOG_FILE
or MASTER_LOG_POS
are
specified, the slave uses the last coordinates of the slave SQL thread
before CHANGE MASTER
was issued. This ensures that
replication has no discontinuity, even if the slave SQL thread was late
compared to the slave I/O thread, when you just want to change, say, the
password to use. This safe behavior was introduced starting from MySQL
4.0.17 and 4.1.1. (Before these versions, the coordinates used were
the last coordinates of the slave I/O thread before CHANGE MASTER
was issued. This caused the SQL thread to possibly lose some events
from the master, thus breaking replication.)
CHANGE MASTER
deletes all relay log files and starts
a new one, unless you specify RELAY_LOG_FILE
or
RELAY_LOG_POS
. In that case, relay logs are kept;
as of MySQL 4.1.1 the relay_log_purge
global variable
is set silently to 0.
CHANGE MASTER TO
updates the contents of the `master.info' and
`relay-log.info' files.
CHANGE MASTER
is useful for setting up a slave when you have
the snapshot of the master and have recorded the log and the offset
corresponding to it. After loading the snapshot into the slave, you
can run CHANGE MASTER TO MASTER_LOG_FILE='log_name_on_master',
MASTER_LOG_POS=log_offset_on_master
on the slave.
Examples:
mysql> CHANGE MASTER TO -> MASTER_HOST='master2.mycompany.com', -> MASTER_USER='replication', -> MASTER_PASSWORD='bigs3cret', -> MASTER_PORT=3306, -> MASTER_LOG_FILE='master2-bin.001', -> MASTER_LOG_POS=4, -> MASTER_CONNECT_RETRY=10; mysql> CHANGE MASTER TO -> RELAY_LOG_FILE='slave-relay-bin.006', -> RELAY_LOG_POS=4025;
The first example changes the master and master's binary log coordinates. This is used when you want to set up the slave to replicate the master.
The second example shows an operation that is less frequently used. It
is done when the slave has relay logs that you want it to execute again
for some reason. To do this, the master need not be reachable. You just
have to use CHANGE MASTER TO
and start the SQL thread (START
SLAVE SQL_THREAD
).
You can even use the second operation in a non-replication setup with a
standalone, non-slave server, to recover after a crash. Suppose that your
server has crashed and you have restored a backup. You want to replay
the server's own binary logs (not relay logs, but regular binary logs),
supposedly named `myhost-bin.*'. First, make a backup copy of these
binary logs in some safe place, in case you don't exactly follow the
procedure below and accidentally have the server purge the binary logs.
If using MySQL 4.1.1 or newer, use SET GLOBAL relay_log_purge=0
for
additional safety. Then start the server without the --log-bin
option. Before MySQL 4.0.19, start it with a new (different from before) server
id; in newer versions there is no need, just use the
--replicate-same-server-id
option. Start it with
--relay-log=myhost-bin
(to make the server believe that these
regular binary logs are relay logs) and with --skip-slave-start
. After
the server starts, issue these statements:
mysql> CHANGE MASTER TO -> RELAY_LOG_FILE='myhost-bin.153', -> RELAY_LOG_POS=410, -> MASTER_HOST='some_dummy_string'; mysql> START SLAVE SQL_THREAD;
The server will read and execute its own binary logs, thus achieving
crash recovery. Once the recovery is finished, run STOP SLAVE
,
shut down the server, delete `master.info' and `relay-log.info',
and restart the server with its original options.
For the moment, specifying MASTER_HOST
(even with a dummy value) is
required to make the server think it is a slave. In the future, we plan to add
options to get rid of these small constraints.
LOAD DATA FROM MASTER
SyntaxLOAD DATA FROM MASTER
Takes a snapshot of the master and copies it to the slave. It updates the
values of MASTER_LOG_FILE
and MASTER_LOG_POS
so that the slave
will start replicating from the correct position. Any table and database
exclusion rules specified with the --replicate-*-do-*
and
--replicate-*-ignore-*
options are honored.
--replicate-rewrite-db
is not taken into account (because one user
could, with this option, set up a non-unique mapping such as
--replicate-rewrite-db=db1->db3
and
--replicate-rewrite-db=db2->db3
, which would confuse the slave when
it loads the master's tables).
Use of this statement is subject to the following conditions:
MyISAM
tables.
In the future, it is planned to make this statement work with
InnoDB
tables and to remove the need for a global read lock by using
non-blocking online backup.
If you are loading big tables, you might have to increase the values
of net_read_timeout
and net_write_timeout
on both your master and slave servers.
See section 5.2.3 Server System Variables.
Note that LOAD DATA FROM MASTER
does not copy any
tables from the mysql
database. This makes it easy to have
different users and privileges on the master and the slave.
The LOAD DATA FROM MASTER
statement
requires the replication account that is used to connect to the master
to have the RELOAD
and SUPER
privileges on the master and the
SELECT
privilege for all master tables you want to load. All
master tables for which the user does not have the SELECT
privilege are
ignored by LOAD DATA FROM MASTER
. This is because the
master will hide them from the user: LOAD DATA FROM MASTER
calls
SHOW DATABASES
to know the master databases to load, but
SHOW DATABASES
returns only databases for which the user has
some privilege.
See section 13.5.4.7 SHOW DATABASES
Syntax.
On the slave's side, the user that issues LOAD DATA FROM MASTER
should
have grants to drop and create the databases and tables that are copied.
LOAD TABLE tbl_name FROM MASTER
SyntaxLOAD TABLE tbl_name FROM MASTER
Transfers a copy of the table from master to the slave. This statement is
implemented mainly for debugging of LOAD DATA FROM MASTER
.
It requires that the account used for connecting to the master server has the
RELOAD
and SUPER
privileges on the master and the
SELECT
privilege on the master table to load.
On the slave side, the user that issues LOAD TABLE FROM MASTER
should
have privileges to drop and create the table.
The conditions for LOAD DATA FROM MASTER
apply here, too. For
example, LOAD TABLE FROM MASTER
works only for MyISAM
tables.
The timeout notes for LOAD DATA FROM MASTER
apply as well.
MASTER_POS_WAIT()
SyntaxSELECT MASTER_POS_WAIT('master_log_file', master_log_pos)
This is a function, not a statement. It is used to ensure that the slave has read and executed events up to a given position in the master's binary log. See section 12.8.4 Miscellaneous Functions for a full description.
RESET SLAVE
SyntaxRESET SLAVE
Makes the slave forget its replication position in the master's binary logs. This statement is meant to be used for a clean start: It deletes the `master.info' and `relay-log.info' files, all the relay logs, and starts a new relay log.
Note: All relay logs are deleted, even if they have not been
totally executed by the slave SQL thread. (This is a condition likely to
exist on a replication slave if you have issued a STOP SLAVE
statement or if the slave is highly loaded.)
Connection information stored in the `master.info' file is immediately
reset using any values specified in the corresponding startup options.
This information includes values such as master host, master port, master
user, and master password. If the slave SQL thread was in the middle of
replicating temporary tables when it was stopped, and RESET SLAVE
is issued, these replicated temporary tables are deleted on the slave.
This statement was named FLUSH SLAVE
before MySQL 3.23.26.
SET GLOBAL SQL_SLAVE_SKIP_COUNTER
SyntaxSET GLOBAL SQL_SLAVE_SKIP_COUNTER = n
Skip the next n events from the master. This is useful for recovering from replication stops caused by a statement.
This statement is valid only when the slave thread is not running. Otherwise, it produces an error.
Before MySQL 4.0, omit the GLOBAL
keyword from the statement.
SHOW SLAVE STATUS
SyntaxSHOW SLAVE STATUS
Provides status information on
essential parameters of the slave threads. If you issue this statement using
the
mysql
client, you can use a \G
statement terminator rather than
semicolon to get a more readable vertical layout:
mysql> SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: localhost Master_User: root Master_Port: 3306 Connect_Retry: 3 Master_Log_File: gbichot-bin.005 Read_Master_Log_Pos: 79 Relay_Log_File: gbichot-relay-bin.005 Relay_Log_Pos: 548 Relay_Master_Log_File: gbichot-bin.005 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 79 Relay_Log_Space: 552 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 8
Depending on your version of MySQL, you may not see all the fields just shown. In particular, several fields are present only as of MySQL 4.1.1.
SHOW SLAVE STATUS
returns the following fields:
Slave_IO_State
State
field of
the output of SHOW PROCESSLIST
for the slave I/O thread. This
tells you if the thread is trying to connect to the master, waiting
for events from the master, reconnecting to the master, and so on. Possible
states are listed in section 6.3 Replication Implementation Details. Looking at
this field is necessary because, for example, the thread can be running
but unsuccessfully trying to connect to the master; only this field
will make you aware of the connection problem.
The state of the SQL thread is not copied because it is simpler.
If it is running, there is no
problem; if it is not, you will find the error in the
Last_Error
field (described below).
This field is present beginning with MySQL 4.1.1.
Master_Host
Master_User
Master_Port
Connect_Retry
--master-connect-retry
option.
Master_Log_File
Read_Master_Log_Pos
Relay_Log_File
Relay_Log_Pos
Relay_Master_Log_File
Slave_IO_Running
Slave_SQL_Running
Replicate_Do_DB, Replicate_Ignore_DB
--replicate-do-db
and --replicate-ignore-db
options, if any.
These fields are present beginning with MySQL 4.1.1.
Replicate_Do_Table, Replicate_Ignore_Table, Replicate_Wild_Do_Table, Replicate_Wild_Ignore_Table
--replicate-do-table
,
--replicate-ignore-table
,
--replicate-wild-do-table
,
and
--replicate-wild-ignore_table
options, if any.
These fields are present beginning with MySQL 4.1.1.
Last_Errno, Last_Error
Last_Error
value is not empty, it will also appear as a
message in the slave's error log.
For example:
Last_Errno: 1051 Last_Error: error 'Unknown table 'z'' on query 'drop table z'The message indicates that the table
z
existed on the master and was dropped there, but it
did not exist on the slave, so DROP TABLE
failed on the slave.
(This might occur, for example, if you forget to copy the table to the
slave when setting up replication.)
Skip_Counter
SQL_SLAVE_SKIP_COUNTER
.
Exec_Master_Log_Pos
Relay_Master_Log_File
).
(Relay_Master_Log_File
, Exec_Master_Log_Pos
) in the
master's binary log corresponds to
(Relay_Log_File
, Relay_Log_Pos
)
in the relay log.
Relay_Log_Space
Until_Condition, Until_Log_File, Until_Log_Pos
UNTIL
clause of the START SLAVE
statement.
Until_Condition
has these values:
None
if no UNTIL
clause was specified
Master
if the slave is reading until a given position in the master's
binary logs
Relay
if the slave is reading until a given position in its relay logs
Until_Log_File
and Until_Log_Pos
indicate the log filename and
position values that define the point at which the SQL thread will stop
executing.
These fields are present beginning with MySQL 4.1.1.
Master_SSL_Allowed, Master_SSL_CA_File, Master_SSL_CA_Path, Master_SSL_Cert, Master_SSL_Cipher, Master_SSL_Key
Master_SSL_Allowed
has these values:
Yes
if an SSL connection to the master is allowed
No
if an SSL connection to the master is not allowed
Ignored
if an SSL connection is allowed but the slave server does not
have SSL support enabled
--master-ca
,
--master-capath
,
--master-cert
,
--master-cipher
,
and
--master-key
options.
These fields are present beginning with MySQL 4.1.1.
Seconds_Behind_Master
Seconds_Behind_Master
will often show a value of 0, even if I/O
thread is late compared to master. In other words, this column is
useful only for fast networks.
This time difference computation will work even though your master and slave
don't have identical clocks (the clock difference is computed when the slave
I/O thread starts, and assumed to remain constant from then on).
Seconds_Behind_Master
will be NULL
(which means ``unknown'') if
the slave SQL thread is not running, or if the slave I/O thread is not running
or not connected to master. For example if the slave I/O thread is sleeping for
master-connect-retry
seconds before reconnecting, NULL
will be
shown, as the slave cannot know what the master is doing, so cannot
reliably say how late it is.
This field has one limitation. Indeed the timestamp is preserved through
replication, which means that if your master M1 is itself a slave of M0, any
event from M1's binlog which has its origin in replication of an event of M0's
binlog, has the timestamp of that last event. This enables MySQL to replicate
TIMESTAMP
successfully. But the drawback for
Seconds_Behind_Master
is that if M1 also receives direct updates from
clients, then the value will randomly go up and down, because sometimes the
last M1's event will be from M0 and sometimes it will be from a direct update,
and so will be the last timestamp.
START SLAVE
SyntaxSTART SLAVE [thread_type [, thread_type] ... ] START SLAVE [SQL_THREAD] UNTIL MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos START SLAVE [SQL_THREAD] UNTIL RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos thread_type: IO_THREAD | SQL_THREAD
START SLAVE
with no options starts both of the slave threads.
The I/O thread reads queries from the master server and stores them in the
relay log. The SQL thread reads the relay log and executes the
queries.
START SLAVE
requires the SUPER
privilege.
If START SLAVE
succeeds in starting the slave threads, it
returns without any error. However, even in that case, it might be that the slave
threads start and then later stop (for example, because they don't manage to
connect to the master or read its binary logs, or some other
problem). START SLAVE
will not warn you about this. You must
check your slave's error log for error messages generated by
the slave threads, or check that they are running fine with SHOW
SLAVE STATUS
.
As of MySQL 4.0.2, you can add IO_THREAD
and SQL_THREAD
options to the statement to name which of the threads to start.
As of MySQL 4.1.1, an UNTIL
clause may be added to specify that
the slave should start and run until the SQL thread reaches a given point in
the master binary logs or in the slave relay logs. When the SQL thread reaches
that point, it stops. If the SQL_THREAD
option is specified in the
statement, it starts only the SQL thread. Otherwise, it starts both slave
threads. If the SQL thread is running, the UNTIL
clause is
ignored and a warning is issued.
With an UNTIL
clause, you must specify both a log filename and
position. Do not mix master and relay log options.
Any UNTIL
condition is reset by a subsequent STOP SLAVE
statement, a START SLAVE
statement that includes no UNTIL
clause, or a server restart.
The UNTIL
clause can be useful for debugging replication, or to
cause replication to proceed until just before the point where you want
to avoid having the slave replicate a statement. For example, if an unwise
DROP TABLE
statement was executed on the master, you can use
UNTIL
to tell the slave to execute up to that point but no farther.
To find what the event is, use mysqlbinlog
with the master logs or
slave relay logs, or by using a SHOW BINLOG EVENTS
statement.
If you are using UNTIL
to have the slave process replicated queries in
sections, it is recommended that you start the slave with the
--skip-slave-start
option to prevent the SQL thread from running
when the slave server starts. It is probably best to use this option in an
option file rather than on the command line, so that an unexpected server
restart does not cause it to be forgotten.
The SHOW SLAVE STATUS
statement includes output fields that display
the current values of the UNTIL
condition.
This statement is called SLAVE START
before MySQL 4.0.5.
For the moment, SLAVE START
is still accepted for backward
compatibility, but is deprecated.
STOP SLAVE
SyntaxSTOP SLAVE [thread_type [, thread_type] ... ] thread_type: IO_THREAD | SQL_THREAD
Stops the slave threads.
STOP SLAVE
requires the SUPER
privilege.
Like START SLAVE
, as of MySQL 4.0.2, this statement
may be used with the IO_THREAD
and SQL_THREAD
options to name
the thread or threads to stop.
This statement is called SLAVE STOP
before MySQL 4.0.5.
For the moment, SLAVE STOP
is still accepted for backward
compatibility, but is deprecated.
Support for server-side prepared statements was added in MySQL 4.1. This support takes advantage of the efficient client/server binary protocol, provided that you use an appropriate client programming interface. Candidate interfaces include the MySQL C API client library (for C programs) or MySQL Connector/J (for Java programs). For example, the C API provides a set of function calls that make up its prepared statement API. See section 22.2.4 C API Prepared Statements. Other language interfaces can provide support for prepared statements that use the binary protocol by linking in the C client library. (The mysqli extension in PHP 5.0 does this, for example.)
Beginning with MySQL 4.1.3, an alternative interface to prepared statements is available: SQL syntax for prepared statements. This interface is not as efficient as using the binary protocol through a prepared statement API, but requires no programming because it is available directly at the SQL level:
mysql
client program.
SQL syntax for prepared statements is intended to be used for situations such as these:
SQL syntax for prepared statements is based on three SQL statements:
PREPARE stmt_name FROM preparable_stmt; EXECUTE stmt_name [USING @var_name [, @var_name] ...]; {DEALLOCATE | DROP} PREPARE stmt_name;
The PREPARE
statement prepares a statement and assigns it
a name, stmt_name, by which to refer to the statement later.
Statement names are not case sensitive.
preparable_stmt is either a string literal or a user variable that
contains the text of the statement. The text must represent a single SQL
statement, not multiple statements. Within the statement, `?'
characters can be used as parameter markers to indicate where data values
are to be bound to the query later when you execute it. The `?'
characters should not be enclosed within quotes, even if you intend to bind
them to string values.
If a prepared statement exists with the same name, it is deallocated implicitly before the new statement is prepared. This means that if the new statement contains an error and cannot be prepared, an error is returned and no statement with the given name will exist.
The scope of a prepared statement is the client session within which it is created. Other clients cannot see it.
After preparing a statement, you execute it with an EXECUTE
statement that refers to the prepared statement name. If the prepared
statement contains any parameter markers, you must supply a USING
clause that lists user variables containing the values to be bound to
the parameters.
Parameter values can be supplied only by user variables, and the USING
clause must name exactly as many variables as the number of parameter markers
in the statement.
You can execute a given prepared statement multiple times, passing it different variables or setting the variables to different values before each execution.
To deallocate a prepared statement, use the DEALLOCATE PREPARE
statement. Attempting to execute a prepared statement after deallocating
it results in an error.
If you terminate a client session without deallocating a previously prepared statement, the server deallocates it automatically.
The following statements can be used as prepared statements:
CREATE TABLE
,
DELETE
,
DO
,
INSERT
,
REPLACE
,
SELECT
,
SET
,
UPDATE
,
and most
SHOW
,
statements.
Other statements are not yet supported.
The following examples show two equivalent ways of preparing a statement that computes the hypotenuse of a triangle given the lengths of the two sides.
The first example shows how to create a prepared statement by using a string literal to supply the text of the statement:
mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; mysql> SET @a = 3; mysql> SET @b = 4; mysql> EXECUTE stmt1 USING @a, @b; +------------+ | hypotenuse | +------------+ | 5 | +------------+ mysql> DEALLOCATE PREPARE stmt1;
The second example is similar, but supplies the text of the statement with a user variable:
mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; mysql> PREPARE stmt2 FROM @s; mysql> SET @a = 6; mysql> SET @b = 8; mysql> EXECUTE stmt2 USING @a, @b; +------------+ | hypotenuse | +------------+ | 10 | +------------+ mysql> DEALLOCATE PREPARE stmt2;
SQL syntax for prepared statements cannot be used in nested fashion.
That is, a statement passed to PREPARE
cannot itself be a
PREPARE
, EXECUTE
, or DEALLOCATE PREPARE
statement.
Also, SQL syntax for prepared statements is distinct from using
prepared statement API calls. For example, you cannot use the
mysql_stmt_prepare()
C API function to prepare a PREPARE
,
EXECUTE
, or DEALLOCATE PREPARE
statement.
MySQL supports several storage engines that act as handlers for different table types. MySQL storage engines include both those that handle transaction-safe tables and those that handle non-transaction-safe tables:
ISAM
, which managed non-transactional
tables. This engine has been replaced by MyISAM
and should no longer
be used. It is deprecated in MySQL 4.1, and will be removed in MySQL 5.0.
MyISAM
and HEAP
storage engines were
introduced. MyISAM
is an improved replacement for ISAM
.
The HEAP
storage engine provides in-memory tables.
The MERGE
storage engine was
added in MySQL 3.23.25. It allows a collection of identical MyISAM
tables to be handled as a single table. All three of these storage engines
handle non-transactional tables, and all are included in MySQL by default.
Note that the
HEAP
storage engine has been renamed the MEMORY
engine.
InnoDB
and BDB
storage engines that handle transaction-safe tables were introduced in later
versions of MySQL 3.23.
Both are available in source distributions as of MySQL 3.23.34a.
BDB
is included in MySQL-Max binary distributions on those operating
systems that support it. InnoDB
also is included in MySQL-Max binary
distributions for MySQL 3.23. Beginning with MySQL 4.0, InnoDB
is included by default in all MySQL binary distributions. In source
distributions, you can enable or disable either engine by configuring MySQL
as you like.
EXAMPLE
storage engine was added in MySQL 4.1.3. It is a
``stub'' engine that does nothing. You can create tables with this engine,
but no data can be stored into them or retrieved from them. The purpose of
this engine is to serve as an example in the MySQL source code that
illustrates how to begin writing new storage engines. As such, it is
primarily of interest to developers.
NDB Cluster
is the storage engine used by MySQL Cluster to implement
tables that are partitioned over many computers. It is available in source
code distributions as of MySQL 4.1.2 and binary distributions as of
MySQL-Max 4.1.3.
ARCHIVE
storage engine was added in MySQL 4.1.3. It is used
for storing large amounts of data without indexes in a very small footprint.
CSV
storage engine was added in MySQL 4.1.4. This engine stores
data in text files using comma-separated-values format.
FEDERATED
storage engine was added in MySQL 5.0.3. This engine
stores data in a remote database. In this release, it works with MySQL only,
using the MySQL C Client API. Future releases will be able to connect to
other data sources using other driver or client connection methods.
This chapter describes each of the MySQL storage engines except for
InnoDB
and NDB Cluster
, which are covered in section 15 The InnoDB
Storage Engine
and section 16 MySQL Cluster.
When you create a new table, you can tell MySQL what type of table to create
by adding an ENGINE
or TYPE
table option to the CREATE
TABLE
statement:
CREATE TABLE t (i INT) ENGINE = INNODB; CREATE TABLE t (i INT) TYPE = MEMORY;
ENGINE
is the preferred term, but cannot be used before MySQL 4.0.18.
TYPE
is available beginning with MySQL 3.23.0, the first
version of MySQL for which multiple storage engines were available.
If you omit the ENGINE
or TYPE
option, the default storage
engine is used. By default this is MyISAM
. You can change it by
using the --default-storage-engine
or --default-table-type
server startup option, or by setting the storage_engine
or
table_type
system variable.
When MySQL is installed on Windows using the MySQL Configuration Wizard,
the InnoDB
storage engine will be the default instead of MyISAM
.
See section 2.3.5.1 Introduction.
To convert a table from one type to another, use an ALTER TABLE
statement that indicates the new type:
ALTER TABLE t ENGINE = MYISAM; ALTER TABLE t TYPE = BDB;
See section 13.2.6 CREATE TABLE
Syntax and
section 13.2.2 ALTER TABLE
Syntax.
If you try to use a storage engine that is not compiled in or that is
compiled in but deactivated, MySQL instead creates a table of type
MyISAM
. This behavior is convenient when you want to copy tables
between MySQL servers that support different storage engines. (For example, in
a replication setup, perhaps your
master server supports transactional storage engines for increased safety,
but the slave servers use only non-transactional storage engines for greater
speed.)
This automatic substitution of the MyISAM
table type when an
unavailable type is specified can be confusing for new MySQL
users. In MySQL 4.1 and up, a warning is generated when a table type is
automatically changed.
MySQL always creates an `.frm' file to hold the table and column definitions. The table's index and data may be stored in one or more other files, depending on the table type. The server creates the `.frm' file above the storage engine level. Individual storage engines create any additional files required for the tables that they manage.
A database may contain tables of different types.
Transaction-safe tables (TSTs) have several advantages over non-transaction-safe tables (NTSTs):
COMMIT
statement (if autocommit is disabled).
ROLLBACK
to ignore your changes (if
autocommit is disabled).
Note that to use the InnoDB
storage engine in MySQL 3.23, you
must configure at least the innodb_data_file_path
startup option.
In 4.0 and up, InnoDB
uses default configuration values if you specify
none.
See section 15.4 InnoDB
Configuration.
Non-transaction-safe tables have several advantages of their own, all of which occur because there is no transaction overhead:
You can combine transaction-safe and non-transaction-safe tables in the same statements to get the best of both worlds. However, within a transaction with autocommit disabled, changes to non-transaction-safe tables still are committed immediately and cannot be rolled back.
MyISAM
Storage Engine
MyISAM
is the default storage engine as of MySQL 3.23. It is
based on the ISAM
code but has many useful extensions.
Each MyISAM
table is stored on disk in three files. The files have
names that begin with the table name and have an extension to indicate the
file type. An `.frm' file stores the table definition. The data file
has an `.MYD' (MYData) extension. The index file has an `.MYI'
(MYIndex) extension,
To specify explicitly that you want a MyISAM
table, indicate that with
an ENGINE
or TYPE
table option:
CREATE TABLE t (i INT) ENGINE = MYISAM; CREATE TABLE t (i INT) TYPE = MYISAM;
Normally, the ENGINE
or TYPE
option is unnecessary;
MyISAM
is the default storage engine unless the default has been
changed.
You can check or repair MyISAM
tables with the myisamchk
utility. See section 5.7.3.7 Using myisamchk
for Crash Recovery. You can compress MyISAM
tables with
myisampack
to take up much less space.
See section 8.2 myisampack
, the MySQL Compressed Read-only Table Generator.
The following characteristics of the MyISAM
storage engine are
improvements over the older ISAM
engine:
BLOB
and TEXT
columns can be indexed.
NULL
values are allowed in indexed columns. This takes 0-1
bytes per key.
MyISAM
than with
ISAM
. This means that MyISAM
normally will use less
system resources than ISAM
, but will need more CPU time when inserting
data into a compressed index.
AUTO_INCREMENT
column), the index tree is split so that the high
node only contains one key. This improves space utilization in the index
tree.
AUTO_INCREMENT
column per table.
MyISAM
automatically updates this column for INSERT/UPDATE
. This
makes AUTO_INCREMENT
columns faster (at least 10%).
Values at the top of the sequence are not reused after being deleted as they
are with ISAM
. (When an AUTO_INCREMENT
column is
defined as the last column of a multiple-column index, reuse of deleted
values does occur.) The AUTO_INCREMENT
value can be reset with
ALTER TABLE
or myisamchk
.
INSERT
new rows into it at the same time that other threads are
reading from the table. (These are known as concurrent inserts.) A free block can
occur as a result of deleting rows or an update of a dynamic length row with
more data than its current contents. When all free blocks are used up
(filled in), future inserts become concurrent again.
DATA DIRECTORY
and INDEX DIRECTORY
table options to
CREATE TABLE
. See section 13.2.6 CREATE TABLE
Syntax.
MyISAM
index file that indicates whether the
table was closed correctly. If mysqld
is started with the
--myisam-recover
option, MyISAM
tables are automatically
checked when opened and repaired if the table wasn't closed
properly.
myisamchk
marks tables as checked if you run it with the
--update-state
option. myisamchk --fast
checks only those
tables that don't have this mark.
myisamchk --analyze
stores statistics for key parts, not only for
whole keys as in ISAM
.
myisampack
can pack BLOB
and VARCHAR
columns;
pack_isam
cannot.
MyISAM
also supports the following features, which MySQL
will be able to use in the near future:
VARCHAR
type; a VARCHAR
column starts
with a length stored in two bytes.
VARCHAR
may have fixed or dynamic record length.
VARCHAR
and CHAR
columns may be up to 64KB.
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.)
MyISAM
Startup Options
The following options to mysqld
can be used to change the behavior of
MyISAM
tables:
--myisam-recover=mode
MyISAM
tables.
--delay-key-write=ALL
MyISAM
table.
Note: If you do this, you should not use MyISAM
tables from
another program (such as from another MySQL server or with myisamchk
) when
the table is in use. Doing so will lead to index corruption.
Using --external-locking
will not help for tables that use
--delay-key-write
.
See section 5.2.1 mysqld
Command-Line Options.
The following system variables affect the behavior of
MyISAM
tables:
bulk_insert_buffer_size
myisam_max_extra_sort_file_size
myisam_max_sort_file_size
myisam_sort_buffer_size
See section 5.2.3 Server System Variables.
Automatic recovery is activated if you start mysqld
with the
--myisam-recover
option. In this case, when the server opens a
MyISAM
table, it checks whether the table
is marked as crashed or whether the open count variable for the
table is not 0 and you are running the server with
--skip-external-locking
. If either of these conditions is true, the
following happens:
If the recovery wouldn't be able to recover all rows from a previous
completed statement and you didn't specify FORCE
in the value of the
--myisam-recover
option, automatic repair aborts with an error
message in the error log:
Error: Couldn't repair table: test.g00pages
If you specify FORCE
, a warning like this is written instead:
Warning: Found 344 of 354 rows when repairing ./test/g00pages
Note that if the automatic recovery value includes BACKUP
, the
recovery process creates files with names of the form
`tbl_name-datetime.BAK'. You should have a cron
script that
automatically moves these files from the database directories to backup
media.
MyISAM
tables use B-tree indexes. 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 the table doesn'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 worst-case figure 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 Storage Formats
MyISAM
supports three different storage formats. Two of them (fixed
and dynamic format) are chosen automatically depending on the type of
columns you are using. The third, compressed format, can be created only
with the myisampack
utility.
When you CREATE
or ALTER
a table that has no BLOB
or TEXT
columns, you can force the table format to FIXED
or
DYNAMIC
with the ROW_FORMAT
table option. This causes
CHAR
and VARCHAR
columns to become CHAR
for
FIXED
format or VARCHAR
for DYNAMIC
format.
In the future, you will be able to compress or decompress tables by specifying
ROW_FORMAT={COMPRESSED | DEFAULT}
to ALTER TABLE
.
See section 13.2.6 CREATE TABLE
Syntax.
Static format is the default for MyISAM
tables. It is used when the
table contains no variable-length columns (VARCHAR
, BLOB
, or
TEXT
). Each row is stored using a fixed number of bytes.
Of the three MyISAM
storage formats, static format is the simplest
and most secure (least subject to corruption). It is also the fastest of the
on-disk formats. The speed comes from the easy way that rows in the data file
can be found on disk: When looking up a row based on a row number in the
index, 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 operation.
The security is evidenced if your computer crashes while the MySQL server is
writing to a fixed-format MyISAM
file. In this case, myisamchk
can easily determine where each row starts and ends, so it can usually
reclaim all records except the partially written one. Note that MyISAM
table
indexes can always be reconstructed based on the data rows.
General characteristics of static format tables:
CHAR
, NUMERIC
, and DECIMAL
columns are space-padded
to the column width.
OPTIMIZE TABLE
or myisamchk -r
.
Dynamic storage format is used if a MyISAM
table contains any
variable-length columns (VARCHAR
, BLOB
, or TEXT
), or if
the table was created with the ROW_FORMAT=DYNAMIC
option.
This format is a little more complex because each row has a header that indicates how long it is. One record can also end up at more than one location when it is made longer as a result of an update.
You can use OPTIMIZE TABLE
or myisamchk
to defragment a
table. If you have fixed-length columns that you access or change frequently
in a table that also contains some variable-length columns, it might be
a good idea to move the variable-length columns to other tables just to
avoid fragmentation.
General characteristics of dynamic-format tables:
NULL
values. If a string
column has a length of zero after trailing space removal, or a numeric
column has a value of zero, it is marked in the bitmap and not saved to
disk. Non-empty strings are saved as a length byte plus the string
contents.
OPTIMIZE TABLE
or myisamchk -r
from time to time to get better
performance. Use myisamchk -ei
to obtain table 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
.
Compressed storage format is a read-only format that is generated with the
myisampack
tool.
All MySQL distributions as of version 3.23.19 include myisampack
by
default. (This version is when MySQL was placed under the GPL.) For earlier
versions, myisampack
was included only with licenses or support
agreements, but the server still can read tables that were compressed
with myisampack
. Compressed tables can be uncompressed with
myisamchk
. (For the ISAM
storage engine, compressed tables
can be created with pack_isam
and uncompressed with isamchk
.)
Compressed tables have the following characteristics:
BIGINT
column
(eight bytes) can be stored as a TINYINT
column (one byte) if all
its values are in the range from -128
to 127
.
ENUM
.
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
Tables
Even though the MyISAM
table format is very reliable (all changes to
a table made by an SQL statement are written before the statement returns),
you can still get corrupted tables if some of the following things happen:
mysqld
process is killed in the middle of a write.
myisamchk
) on a table that
is being modified by the server at the same time.
MyISAM
code.
Typical symptoms for a corrupt table are:
Incorrect key file for table: '...'. Try to repair it
You can check whether a MyISAM
table is okay with the CHECK
TABLE
statement. You can repair a corrupted MyISAM
table with
REPAIR TABLE
. When mysqld
is not running, you can also
check or repair a table with the myisamchk
command.
See section 13.5.2.3 CHECK TABLE
Syntax,
section 13.5.2.6 REPAIR TABLE
Syntax, and section 5.7.3.1 myisamchk
Invocation Syntax.
If your tables become corrupted frequently, you should try to determine why
this is happening. The most important thing to know is whether the table
became corrupted as a result of a server crash. You can verify this easily
by looking for a recent restarted mysqld
message in the error log.
If there is such a message, it is likely that table corruption is a
result of the server dying. Otherwise, corruption may have occurred during
normal operation, which is a bug. You should try to create a reproducible
test case that demonstrates the problem.
See section A.4.2 What to Do If MySQL Keeps Crashing and section E.1.6 Making a Test Case If You Experience Table Corruption.
Each MyISAM
index (`.MYI') file has a counter in the header
that can be used to check whether a table has been closed properly.
If you get the following warning from CHECK TABLE
or myisamchk
,
it means that this counter has gone out of sync:
clients are using or haven't closed the table properly
This warning doesn't necessarily mean that the table is corrupted, but you should at least check the table to verify that it's okay.
The counter works as follows:
FLUSH
TABLES
operation 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 counter can go out of sync only under these conditions:
MyISAM
tables are copied without a preceding LOCK TABLES
and
FLUSH TABLES
.
myisamchk --recover
or myisamchk
--update-state
at the same time that it was in use by mysqld
.
mysqld
servers are using the table and one server performed a
REPAIR TABLE
or CHECK TABLE
on the table while it was in use by
another server. In this setup, it is safe to use CHECK TABLE
,
although you might get the warning from other servers. However, REPAIR
TABLE
should be avoided because when one server replaces the data file
with a new one, this is not signaled to the other servers.
In general, it is a bad idea to share a data directory among multiple servers.
See section 5.10 Running Multiple MySQL Servers on the Same Machine for additional discussion.
MERGE
Storage Engine
The MERGE
storage engine was introduced in MySQL 3.23.25. It
is also known as the MRG_MyISAM
engine.
A MERGE
table is a collection of identical MyISAM
tables that
can be used as one. ``Identical'' means that all tables have
identical column and index information. You can't merge tables in which the
columns are listed in a different order, don't have exactly the same columns, or
have the indexes in different order. However, any or all of the tables can be
compressed with myisampack
.
See section 8.2 myisampack
, the MySQL Compressed Read-only Table Generator.
Differences in table options such as AVG_ROW_LENGTH
, MAX_ROWS
,
or PACK_KEYS
do not matter.
When you create a MERGE
table, MySQL creates two files on disk.
The files have names that begin with the table name and have an extension
to indicate the file type. An `.frm' file stores the table definition,
and an `.MRG' file contains the names of the tables that should be
used as one. (Originally, all used tables had to be in the same database
as the MERGE
table itself. This restriction has been lifted as of
MySQL 4.1.1.)
You can use SELECT
, DELETE
, UPDATE
, and (as of MySQL
4.0) INSERT
on the collection of tables. For the moment, you must
have SELECT
, UPDATE
, and DELETE
privileges on the
tables that you map to a MERGE
table.
If you DROP
the MERGE
table, you are dropping only the
MERGE
specification. The underlying tables are not affected.
When you create a MERGE
table, you must specify a
UNION=(list-of-tables)
clause that indicates which tables you want to
use as one. You can optionally specify an INSERT_METHOD
option if you
want inserts for the MERGE
table to happen in the first or last table
of the UNION
list. If you don't specify any INSERT_METHOD
option or specify it with a value of NO
, attempts to insert records
into the MERGE
table result in an error.
The following example shows how to create a MERGE
table:
mysql> CREATE TABLE t1 ( -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -> message CHAR(20)); mysql> CREATE TABLE t2 ( -> a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -> message CHAR(20)); mysql> INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1'); mysql> INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2'); mysql> CREATE TABLE total ( -> a INT NOT NULL AUTO_INCREMENT, -> message CHAR(20), INDEX(a)) -> TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
Note that the a
column is indexed in the MERGE
table, but is
not declared as a PRIMARY KEY
as it is in the underlying
MyISAM
tables. This is necessary because a MERGE
table cannot
enforce uniqueness over the set of underlying tables.
After creating the MERGE
table, you can do things like this:
mysql> SELECT * FROM total; +---+---------+ | a | message | +---+---------+ | 1 | Testing | | 2 | table | | 3 | t1 | | 1 | Testing | | 2 | table | | 3 | t2 | +---+---------+
Note that you can also manipulate the `.MRG' file directly from outside of the MySQL server:
shell> cd /mysql-data-directory/current-database shell> ls -1 t1 t2 > total.MRG shell> mysqladmin flush-tables
To remap a MERGE
table to a different collection of MyISAM
tables, you can do one of the following:
DROP
the table and re-create it.
ALTER TABLE tbl_name UNION=(...)
to change the list of underlying
tables.
FLUSH TABLE
statement for the
MERGE
table and all underlying tables to force the storage engine to
read the new definition file.
MERGE
tables can help you solve the following problems:
myisampack
, and then create a MERGE
table to use them as one.
MERGE
table on this could be much faster than using
the big table. (You can also use a RAID table to get the same
kind of benefits.)
MERGE
table for others. You can even have many
different MERGE
tables that use overlapping sets of tables.
MERGE
table than to repair a single really big table.
MERGE
table need not maintain
an index of its own because it uses the indexes of the individual tables.
As a result, MERGE
table collections are very fast to create
or remap. (Note that you must still specify the index definitions when
you create a MERGE
table, even though no indexes are created.)
MERGE
table on them on demand.
This is much faster and will save a lot of disk space.
MyISAM
table
is bound by this limit, but a collection of MyISAM
tables is not.
MyISAM
table by defining a
MERGE
table that maps to that single table. There should be no
really notable performance impact of doing this (only a couple of indirect
calls and memcpy()
calls for each read).
The disadvantages of MERGE
tables are:
MyISAM
tables for a MERGE
table.
MERGE
tables use more file descriptors. If 10 clients are using a
MERGE
table that maps to 10 tables, the server uses
(10*10) + 10 file descriptors. (10 data file descriptors for each of the 10
clients, and 10 index file descriptors shared among the clients.)
MERGE
storage engine needs 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,''
the MERGE
storage engine needs 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 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
) for more information about eq_ref
and ref
.
MERGE
Table Problems
The following are the known problems with MERGE
tables:
ALTER TABLE
to change a MERGE
table to another
table type, the mapping to the underlying tables is lost. Instead, the rows
from the underlying MyISAM
tables are copied into the altered table,
which then is assigned the new type.
MERGE
table itself
had to be in the same database.
REPLACE
doesn't work.
DROP TABLE
,
ALTER TABLE
,
DELETE FROM
without a WHERE
clause,
REPAIR TABLE
,
TRUNCATE TABLE
,
OPTIMIZE TABLE
, or
ANALYZE TABLE
on any of the tables that are
mapped into 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 work around this deficiency
is to issue a FLUSH TABLES
statement to ensure that no MERGE
tables remain ``open.''
MERGE
table cannot maintain UNIQUE
constraints over the
whole table. When you perform an INSERT
, the data goes into the
first or last MyISAM
table (depending on the value of the
INSERT_METHOD
option). MySQL ensures that unique key values remain
unique within that MyISAM
table, but not across all the tables in the
collection.
DELETE FROM merge_table
used without a
WHERE
clause only clears the mapping for the table. That is, it
incorrectly empties the `.MRG' file rather than deleting records from
the mapped tables.
RENAME TABLE
on an active MERGE
table may corrupt the
table. This will be fixed in MySQL 4.1.x.
MERGE
table, there is no check whether the
underlying tables exist and have identical structure. When the MERGE
table is used, MySQL does a quick check that the record length for all
mapped tables is equal, but this is not foolproof. If you create a
MERGE
table from dissimilar MyISAM
tables, you are very likely
to run into strange problems.
MERGE
table and its underlying tables should be
the same. If you use ALTER TABLE
to add a UNIQUE
index
to a table used in a MERGE
table, and then use ALTER TABLE
to
add a non-unique index on the MERGE
table, the index order will be
different for the tables if there was an old non-unique index in the
underlying table. (This is because ALTER TABLE
puts UNIQUE
indexes before non-unique indexes to be able to detect duplicate keys as early
as possible.) Consequently, queries may return unexpected results.
DROP TABLE
on a table that is in use by a MERGE
table does
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 delete files that are open, you first must flush all MERGE
tables (with FLUSH TABLES
) or drop the MERGE
table before
dropping the table.
MEMORY
(HEAP
) Storage Engine
The MEMORY
storage engine creates tables with contents that are stored
in memory. Before MySQL 4.1, MEMORY
tables are called HEAP
tables. As of 4.1, HEAP
is a synonym for MEMORY
, and
MEMORY
is the preferred term.
Each MEMORY
table is associated with one disk file. The filename
begins with the table name and has an extension of `.frm' to indicate
that it stores the table definition.
To specify explicitly that you want a MEMORY
table, indicate that with
an ENGINE
or TYPE
table option:
CREATE TABLE t (i INT) ENGINE = MEMORY; CREATE TABLE t (i INT) TYPE = HEAP;
MEMORY
tables are stored in memory and use hash indexes by default.
This makes them very fast, and very useful for creating temporary tables.
However, when the server shuts down, all data stored in MEMORY
tables is lost. The tables continue to exist because their definitions
are stored in the `.frm' files on disk, but their contents will be
empty when the server restarts.
Here is an example that shows how you might create, use, and remove a
MEMORY
table:
mysql> CREATE TABLE test TYPE=MEMORY -> SELECT ip,SUM(downloads) AS down -> FROM log_table GROUP BY ip; mysql> SELECT COUNT(ip),AVG(down) FROM test; mysql> DROP TABLE test;
MEMORY
tables have the following characteristics:
MEMORY
tables is allocated in small blocks. The tables use
100% dynamic hashing (on inserting). No overflow areas and no extra key
space are needed. There is no extra space needed for free lists. Deleted
rows are put in a linked list and are reused when you insert new data into
the table. MEMORY
tables also don't have problems with deletes plus
inserts, which is common with hashed tables.
MEMORY
tables allow up to 32 indexes per table, 16 columns per index,
and a maximum key length of 500 bytes.
MEMORY
storage engine implements only hash
indexes. From MySQL 4.1 on,
hash indexes are still the default, but
you can specify explicitly that a MEMORY
table index should be HASH
or BTREE
by adding a USING
clause:
CREATE TABLE lookup (id INT, INDEX USING HASH (id)) ENGINE = MEMORY; CREATE TABLE lookup (id INT, INDEX USING BTREE (id)) ENGINE = MEMORY;General characteristics of B-tree and hash indexes are described in section 7.4.5 How MySQL Uses Indexes.
MEMORY
table.
(This is an uncommon feature for implementations of hash indexes.)
MEMORY
table that has a high degree of
key duplication (many index entries containing the same value), updates to
the table that affect key values and all deletes will be significantly
slower. The degree of slowdown is proportional to the degree of duplication
(or, inversely proportional to the index cardinality). You can use a
BTREE
index to avoid this problem.
MEMORY
tables use a fixed record length format.
MEMORY
doesn't support BLOB
or TEXT
columns.
MEMORY
doesn't support AUTO_INCREMENT
columns before MySQL
4.1.0.
MEMORY
doesn't support indexes on columns that
can contain NULL
values.
MEMORY
tables are shared between all clients (just like any other
non-TEMPORARY
table).
MEMORY
table contents are stored in memory, which is a property that
MEMORY
tables share with internal tables that the server creates on
the fly while processing queries. However, the two types of tables differ in
that MEMORY
tables are not subject to storage conversion, whereas
internal tables are:
tmp_table_size
system variable.
MEMORY
tables are never converted to disk tables. To ensure that you
don't accidentally do anything foolish, you can set the
max_heap_table_size
system variable to impose a maximum size on
MEMORY
tables. For individual tables, you can also specify a
MAX_ROWS
table option in the CREATE TABLE
statement.
MEMORY
tables
that are in use at the same time.
MEMORY
table if you no longer require its
contents, you should execute DELETE
or
TRUNCATE TABLE
, or else remove the table with DROP TABLE
.
MEMORY
table when the MySQL server starts,
you can use the --init-file
option. For example, you can put
statements such as INSERT INTO ... SELECT
or LOAD DATA INFILE
into the file to load the table from some persistent data source.
See section 5.2.1 mysqld
Command-Line Options.
MEMORY
tables
become empty when it is shut down and restarted. However, a slave is not
aware that these tables have become empty, so it will return out-of-date
content if you select data from them. Beginning with MySQL 4.0.18, when a
MEMORY
table is used on the master for the first time since the master's
startup, a DELETE FROM
statement is written to the master's binary
log automatically, thus synchronizing the slave to the master again. Note
that even with this strategy, the slave still has out-of-date data in the
table during the interval between the master's restart and its first use of
the table. But if you use the --init-file
option to populate the
MEMORY
table on the master at startup, it ensures that the failing
time interval is zero.
MEMORY
table is calculated using the
following expression:
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4) + SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2) + ALIGN(length_of_row+1, sizeof(char*))
ALIGN()
represents a round-up factor to cause the row length to be an
exact multiple of the char
pointer size.
sizeof(char*)
is 4 on 32-bit machines and 8 on 64-bit machines.
BDB
(BerkeleyDB
) Storage Engine
Sleepycat Software has provided MySQL with the Berkeley DB transactional
storage engine. This storage engine typically is called BDB
for short.
Support for the BDB
storage engine is included in MySQL source
distributions starting from version 3.23.34a and is activated in MySQL-Max
binary distributions.
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. (Even though Berkeley DB is in itself very tested and reliable, the MySQL interface is still considered gamma quality. We are improving and optimizing it.)
When it comes to support for any problems involving BDB
tables, we
are committed to helping our users locate the problem and create a
reproducible test case. Any such test case will be forwarded to Sleepycat,
which 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, we anticipate no
significant difficulties with this procedure because the Berkeley DB code
itself is used in many applications other than MySQL.
For general information about Berkeley DB, please visit the Sleepycat Web site, http://www.sleepycat.com/.
BDB
Currently, we know that the BDB
storage engine works with the following
operating systems:
BDB
does not work with the following operating systems:
Note: The preceding lists are not complete. We will update them as we receive more information.
If you build MySQL from source with support for BDB
tables, but the
following error occurs when you start mysqld
, it means BDB
is not supported for your architecture:
bdb: architecture lacks fast mutexes: applications cannot be threaded Can't init databases
In this case, you must rebuild MySQL without BDB
table support or
start the server with the --skip-bdb
option.
BDB
If you have downloaded a binary version of MySQL that includes support for
Berkeley DB, simply follow the usual binary distribution installation
instructions. (MySQL-Max distributions include BDB
support.)
If you build MySQL from source, you can enable BDB
support by running
configure
with the --with-berkeley-db
option in addition
to any other options that you normally use. Download a distribution for
MySQL 3.23.34 or newer, change location into its top-level directory,
and run this command:
shell> ./configure --with-berkeley-db [other-options]
For more information, see
section 2.7 Installing MySQL on Other Unix-Like Systems,
section 5.1.2 The mysqld-max
Extended MySQL Server, and
See section 2.8 MySQL Installation Using a Source Distribution.
BDB
Startup Options
The following options to mysqld
can be used to change the behavior of
the BDB
storage engine:
--bdb-home=path
BDB
tables. This should be the same directory
you
use for --datadir
.
--bdb-lock-detect=method
BDB
lock detection method. The option value should be
DEFAULT
, OLDEST
, RANDOM
, or YOUNGEST
.
--bdb-logdir=path
BDB
log file directory.
--bdb-no-recover
--bdb-no-sync
BDB
logs.
--bdb-shared-data
DB_PRIVATE
when
initializing Berkeley DB.)
--bdb-tmpdir=path
BDB
temporary file directory.
--skip-bdb
BDB
storage engine.
See section 5.2.1 mysqld
Command-Line Options.
The following system variable affects the behavior of
BDB
tables:
bdb_max_lock
BDB
table.
See section 5.2.3 Server System Variables.
If you use the --skip-bdb
option, MySQL will not initialize the Berkeley DB
library and this will save a lot of memory. However, if you use this
option, you cannot use BDB
tables. If you try to create a BDB
table, MySQL will create a MyISAM
table instead.
Normally, you should start mysqld
without the --bdb-no-recover
option if you intend to use BDB
tables. However, this may give you
problems when you try to start mysqld
if the BDB
log files are
corrupted.
See section 2.9.2.3 Starting and Troubleshooting the MySQL Server.
With the bdb_max_lock
variable, you can specify the maximum number of
locks that can be active on a BDB
table. The default is
10,000. You should increase this if errors such as the following occur
when you perform long transactions or when mysqld
has to examine
many rows to execute a query:
bdb: Lock table is out of available locks Got error 12 from ...
You may also want to change the binlog_cache_size
and
max_binlog_cache_size
variables if you are using large
multiple-statement transactions.
See section 5.9.4 The Binary Log.
BDB
Tables
Each BDB
table is stored on disk in two files. The files have
names that begin with the table name and have an extension to indicate the
file type. An `.frm' file stores the table definition, and a `.db'
file contains the table data and indexes.
To specify explicitly that you want a BDB
table, indicate that with
an ENGINE
or TYPE
table option:
CREATE TABLE t (i INT) ENGINE = BDB; CREATE TABLE t (i INT) TYPE = BDB;
BerkeleyDB
is a synonym for BDB
in the ENGINE
or
TYPE
option.
The BDB
storage engine provides transactional tables. The way you use
these tables depends on the autocommit mode:
BDB
tables are committed immediately and cannot be rolled
back.
COMMIT
statement. Instead of
committing, you can execute ROLLBACK
to forget the changes.
You can start a transaction with
the BEGIN WORK
statement to suspend autocommit, or with
SET AUTOCOMMIT=0
to disable autocommit explicitly.
See section 13.4.1 START TRANSACTION
, COMMIT
, and ROLLBACK
Syntax.
The BDB
storage engine has the following characteristics:
BDB
tables can have up to 31 indexes per table, 16 columns per index,
and a maximum key size of 1024 bytes (500 bytes before MySQL 4.0).
PRIMARY KEY
in each BDB
table so that each row
can be uniquely identified. If you don't create one explicitly,
MySQL creates and maintains a hidden PRIMARY KEY
for
you. The hidden key has a length of five bytes and is incremented for each
insert attempt.
PRIMARY KEY
will be faster than any other index, because the
PRIMARY KEY
is stored together with the row data. The other indexes
are stored as the key data + the PRIMARY KEY
, so it's important to
keep the PRIMARY KEY
as short as possible to save disk space and get
better speed.
This behavior is similar to that of InnoDB
, where shorter primary
keys save space not only in the primary index but in secondary indexes as
well.
BDB
table are part of the same index or
part of the primary key, MySQL can execute the query
without having to access the actual row. In a MyISAM
table, this can
be done only if the columns are part of the same index.
MyISAM
tables because the data
in BDB
tables is stored in B-trees and not in a separate data file.
MyISAM
tables. In other words, key information takes 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 index tree. This makes BDB
tables
somewhat larger than MyISAM
tables.
SELECT COUNT(*) FROM tbl_name
is slow for BDB
tables, because
no row count is maintained in the table.
BDB
table. If you don't issue a lot of DELETE
or ROLLBACK
statements, this number should be accurate enough for
the MySQL optimizer. However, MySQL stores the number only on close, so
it may be incorrect if the server terminates unexpectedly. It should not
be fatal even if this number is not 100% correct. You can update the row
count by using ANALYZE TABLE
or OPTIMIZE TABLE
.
See section 13.5.2.1 ANALYZE TABLE
Syntax and
section 13.5.2.5 OPTIMIZE TABLE
Syntax.
BDB
tables is done at the page level.
LOCK TABLES
works on BDB
tables as with other tables. If you
don't use LOCK TABLE
, MySQL issues an internal multiple-write lock on
the table (a lock that doesn't block other writers) to ensure that the
table will be properly locked if another thread issues a table lock.
BDB
storage engine
maintains log files. For maximum performance, you can use the
--bdb-logdir
option to place the BDB
logs on a different disk
than the one where your databases are located.
BDB
log file is started,
and removes any BDB
log files that are not needed for current
transactions. You can also use FLUSH LOGS
at any time to checkpoint
the Berkeley DB tables.
For disaster recovery, you should use table backups plus MySQL's binary log.
See section 5.7.1 Database Backups.
Warning: If you delete old log files that are still in use,
BDB
will not be able to do recovery at all and you may lose data if
something goes wrong.
BDB
table may cause an automatic rollback and any
read may fail with a deadlock error.
BDB
table, you will get an error
(probably error 28) and the transaction should roll back. This contrasts
with MyISAM
and ISAM
tables, for which mysqld
will wait
for enough free disk before continuing.
BDB
BDB
tables at the same time. If you are
going to use BDB
tables, you should not have a very large table cache
(for example, with a size larger than 256) and you should use the
--no-auto-rehash
option when you use the mysql
client. We
plan to partly fix this in 4.0.
SHOW TABLE STATUS
doesn't yet provide very much information for
BDB
tables.
BDB
Tables
The following list indicates restrictions that you must observe when using
BDB
tables:
BDB
table stores 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. However, the consequence is that
BDB
table files cannot be moved from one database directory to
another.
BDB
tables, you must either use
mysqldump
or else make a backup that includes the files for each
BDB
table (the `.frm' and `.db' files) as well as the
BDB
log files. The BDB
storage engine stores unfinished
transactions in its log files and requires them to be present when
mysqld
starts. The BDB
logs are the files in the data
directory with names of the form `log.XXXXXXXXXX' (ten digits).
NULL
values has a unique index, only a single
NULL
value is allowed. This differs from other storage engines.
BDB
Tablesmysqld
, it means that
the new BDB
version doesn't support the old log file format:
bdb: Ignoring log file: .../log.XXXXXXXXXX: unsupported log version #In this case, you must delete all
BDB
logs from your data directory
(the files with names that have the format `log.XXXXXXXXXX') and
restart mysqld
. We also recommend that you then use mysqldump
--opt
to dump your BDB
tables, drop the tables, and restore them
from the dump file.
BDB
table that
is referenced in another transaction, you may get error messages of the
following form in your MySQL error log:
001119 23:43:56 bdb: Missing log fileid entry 001119 23:43:56 bdb: txn_abort: Log undo failed for LSN: 1 3644744: InvalidThis is not fatal, but until the problem is fixed, we recommend that you not drop
BDB
tables except while autocommit mode is enabled. (The
fix is not trivial.)
EXAMPLE
Storage Engine
The EXAMPLE
storage engine was added in MySQL 4.1.3. It is a
``stub'' engine that does nothing. Its purpose is to serve as an example in
the MySQL source code that illustrates how to begin writing new storage
engines. As such, it is primarily of interest to developers.
To examine the source for the EXAMPLE
engine, look in the
`sql/examples' directory of a source distribution for MySQL 4.1.3 or
newer.
To enable this storage engine, use the --with-example-storage-engine
option to configure
when you build MySQL.
When you create an EXAMPLE
table, the server creates a table
definition file in the database directory. The file begins with the table
name and has an `.frm' extension. No other files are created. No data
can be stored into the table or retrieved from it.
mysql> CREATE TABLE test (i INT) ENGINE = EXAMPLE; Query OK, 0 rows affected (0.78 sec) mysql> INSERT INTO test VALUES(1),(2),(3); ERROR 1031 (HY000): Table storage engine for 'test' doesn't have this option mysql> SELECT * FROM test; Empty set (0.31 sec)
The EXAMPLE
storage engine does not support indexing.
FEDERATED
Storage Engine
The FEDERATED
storage engine was added in MySQL 5.0.3. It is a
storage engine that accesses data in tables of remote databases rather than in
local tables.
To examine the source for the FEDERATED
engine, look in the
`sql' directory of a source distribution for MySQL 5.0.3 or
newer.
FEDERATED
Storage Engine
To enable this storage engine, use the --with-federated-storage-engine
option to configure
when you build MySQL.
FEDERATED
Storage Engine
When you create a FEDERATED
table, the server creates a table
definition file in the database directory. The file begins with the table
name and has an `.frm' extension. No other files are created, because
the actual data is in a remote database. This differs from the way that
storage engines for local tables work.
For local database tables, data files are local. For example, if you create
a MyISAM
table named users
, the MyISAM
handler creates a
data file named users.MYD
. A handler for local tables reads, inserts,
deletes, and updates data in local data files, and records are stored in a
format particular to the handler. To read records, the handler must parse
data into columns. To write records, column values must be converted to
the row format used by the handler and written to the local data file.
With the MySQL FEDERATED
storage engine, there are no local data
files for a table (for example, there is no `.MYD' file). Instead, a
remote database stores the data that normally would be in the table. This
necessitates the use of the MySQL client API to read, delete, update,
and insert data. Data retrieval is initiated via a SELECT * FROM
tbl_name
SQL statement. To read the result, rows are fetched one
at a time by using the mysql_fetch_row()
C API function, and then
converted from the columns in the SELECT
result set to the format
that the FEDERATED
handler expects.
The basic flow is as follows:
FEDERATED
Tables
The procedure for using FEDERATED
tables is very simple. Normally, you
have two servers running, either both on the same host or on different hosts.
(It is also possible for a FEDERATED
table to use another table that
is managed by the same server, though there is little point in doing so.)
First, you must have a table on the remote server that you want to access with
the FEDERATED
table. Suppose that the remote table is in the
federated
database and is defined like this:
CREATE TABLE test_table ( id int(20) NOT NULL auto_increment, name varchar(32) NOT NULL default '', other int(20) NOT NULL default '0', PRIMARY KEY (id), KEY name (name), KEY other_key (other) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
The ENGINE
table option could name any storage engine; the table
need not be a MyISAM
table.
Next, create a FEDERATED
table for accessing the remote table.
The server where you will create the FEDERATED
table is the ``client
server.'' On this server, create the table as follows:
CREATE TABLE federated_table ( id int(20) NOT NULL auto_increment, name varchar(32) NOT NULL default '', other int(20) NOT NULL default '0', PRIMARY KEY (id), KEY name (name), KEY other_key (other) ) ENGINE=FEDERATED DEFAULT CHARSET=latin1 COMMENT='mysql://root@remote_host:9306/federated/test_table';
The structure of this table must be exactly the same as the remote table,
except that the ENGINE
table option should be FEDERATED
and
the COMMENT
table option is a connection string that indicates to
the FEDERATED
engine how to connect to the remote server.
The FEDERATED
engine will create only the `test_table.frm' file in
the federated
database.
The remote host information indicates the remote server to which your
``client'' server will connect, and the database and table information
indicates which remote table to use as the ``data file.'' In the example,
the remote server is indicated to be running as remote_host
on port
9306, so you want to start that server so that it is indeed listening to
port 9306.
The general form of the connection string in the COMMENT
option is as
follows:
scheme://user_name[:password]@host_name[:port_num]:/db_name/tbl_name
Only mysql
is supported as the scheme at this point, and the
password and port number are optional.
Here are some example connection strings:
COMMENT='mysql://username:password@hostname:port/database/tablename' COMMENT='mysql://username@hostname/database/tablename' COMMENT='mysql://username:password@hostname/database/tablename'
The use of COMMENT
for specifying the connection string is non-optimal
and likely will change in MySQL 5.1. Keep this in mind when you use
FEDERATED
tables, because it means you'll need to make some
modifications when that happens.
Also, because a password is stored in the connection string as plain text,
it can be seen by any user who can use SHOW CREATE TABLE
or SHOW TABLE STATUS
for the FEDERATED
table.
FEDERATED
Storage Engine
What the FEDERATED
storage engine does and doesn't support:
FEDERATED
for other database engines may be be added in the future.
FEDERATED
table points to must exist
before you try to access the table through the FEDERATED
table.
FEDERATED
table to point to another, but
you must be careful not to create a loop. You know and have heard the
screeching of audio feedback? You know what you see visually when you
place two mirrors in front of each other, how the reflection continues
for eternity? Well, need we say more?!
FEDERATED
engine to know if the remote table
has changed. The reason for this is that this table has to work like a
data file that would never be written to by anything other than the
database. The integrity of the data in the local table could be breached
if there was any change to the remote database.
FEDERATED
storage engine supports SELECT
, INSERT
,
UPDATE
, DELETE
, and indexes. It does not support ALTER
TABLE
, DROP TABLE
, or any other Data Definition Language statements.
The first implementation does not use Prepared statements. It remains
to be seen whether the limited subset of the client API for the server
supports this capability.
SELECT
, INSERT
, UPDATE
,
DELETE
and not HANDLER
.
FEDERATED
tables do not work with the query cache.
Some of these limitations may be lifted in future versions of the
FEDERATED
handler.
ARCHIVE
Storage Engine
The ARCHIVE
storage engine was added in MySQL 4.1.3.
It is used for storing large amounts of data without indexes in a very
small footprint.
To enable this storage engine, use the --with-archive-storage-engine
option to configure
when you build MySQL.
When you create an ARCHIVE
table, the server creates a table definition
file in the database directory. The file begins with the table name and has
an `.frm' extension. The storage engine creates other files, all having
names beginning with the table name. The data and metadata files have
extensions of `.ARZ' and `.ARM'. An `.ARN' file may appear
during optimization operations.
The ARCHIVE
engine supports only INSERT
and SELECT
. (No
deletes, replaces, or updates.) A SELECT
performs a complete table
scan. Records are compressed as they are inserted. Use of OPTIMIZE
TABLE
can analyze the table and pack it into a smaller format.
The ARCHIVE
engine uses row-level locking.
CSV
Storage Engine
The CSV
storage engine was added in MySQL 4.1.4. This engine stores
data in text files using comma-separated-values format.
To enable this storage engine, use the --with-csv-storage-engine
option to configure
when you build MySQL.
When you create a CSV
table, the server creates a table definition
file in the database directory. The file begins with the table name and has
an `.frm' extension. The storage engine also creates a data file. Its
name begins with the table name and has a `.CSV' extension. The data
file is a plain text file. When you store data into the table, the storage
engine saves it into the data file in CSV format.
mysql> CREATE TABLE test(i INT, c CHAR(10)) ENGINE = CSV; Query OK, 0 rows affected (0.12 sec) mysql> INSERT INTO test VALUES(1,'record one'),(2,'record two'); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM test; +------+------------+ | i | c | +------+------------+ | 1 | record one | | 2 | record two | +------+------------+ 2 rows in set (0.00 sec)
If you examine the `test.CSV' file in the database directory after executing the preceding statements, its contents look like this:
"1","record one" "2","record two"
The CSV
storage engine does not support indexing.
ISAM
Storage Engine
The original storage engine in MySQL was the ISAM
engine. It was the
only storage engine available until MySQL 3.23, when the improved
MyISAM
engine was introduced as the default. ISAM
is
deprecated. As of MySQL 4.1, it's included in the source but not enabled in
binary distributions. It is not available in MySQL 5.0.
Embedded MySQL server versions do not support ISAM
tables by default.
Due to the deprecated status of ISAM
, and because MyISAM
is
an improvement over ISAM
, you are advised to convert any remaining
ISAM
tables to MyISAM
as soon as possible. To convert an
ISAM
table to a MyISAM
table, use an ALTER TABLE
statement:
mysql> ALTER TABLE tbl_name TYPE = MYISAM;
For more information about MyISAM
, see
section 14.1 The MyISAM
Storage Engine.
Each ISAM
table is stored on disk in three files. The files have
names that begin with the table name and have an extension to indicate the
file type. An `.frm' file stores the table definition. The data file
has an `.ISD' extension. The index file has an `.ISM'
extension.
ISAM
uses B-tree indexes.
You can check or repair ISAM
tables with the isamchk
utility.
See section 5.7.3.7 Using myisamchk
for Crash Recovery.
ISAM
has the following properties:
Many of the properties of MyISAM
tables are also true for ISAM
tables. However, there are also many differences. The following list
describes some of the ways that ISAM
is distinct from MyISAM
:
MERGE
tables.
isamchk
rather than with
myisamchk
.
pack_isam
rather than with myisampack
.
BACKUP TABLE
or RESTORE TABLE
backup-related statements.
CHECK TABLE
, REPAIR TABLE
, OPTIMIZE
TABLE
, or ANALYZE TABLE
table-maintenance statements.
InnoDB
Storage EngineInnoDB
Overview
InnoDB
provides MySQL with a transaction-safe (ACID
compliant)
storage engine with commit, rollback, and crash recovery capabilities.
InnoDB
does locking on the row level and also provides an Oracle-style
consistent
non-locking read in SELECT
statements. These features increase
multi-user concurrency and performance. There is no need for
lock escalation in InnoDB
because row-level locks in InnoDB
fit in very little space.
InnoDB
also supports FOREIGN KEY
constraints.
In SQL queries you can freely mix InnoDB
type tables with other
table types of MySQL, even within the same query.
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.
Fully integrated with MySQL Server, the InnoDB
storage engine maintains
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 (or raw disk partitions).
This is different from, for example,
MyISAM
tables where each table is stored using separate files.
InnoDB
tables can be of any size even on operating
systems where file size is limited to 2GB.
InnoDB
is included in binary distributions by default as of MySQL 4.0.
For information about InnoDB
support in MySQL 3.23, see
section 15.3 InnoDB
in MySQL 3.23. Starting from MySQL 4.1.5, the new
Windows installer makes InnoDB
the MySQL default table type on
Windows.
InnoDB
is used in production at numerous
large database sites requiring high performance.
The famous Internet news site Slashdot.org runs on InnoDB
.
Mytrix, Inc. stores over 1TB of data in InnoDB
,
and another site handles an average
load of 800 inserts/updates per second in InnoDB
.
InnoDB
is published under the same GNU GPL License Version 2
(of June 1991) as MySQL. For more information on MySQL licensing,
see http://www.mysql.com/company/legal/licensing/.
InnoDB
Contact Information
Contact information for Innobase Oy, producer of the InnoDB
engine:
Web site: http://www.innodb.com/ Email: sales@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
InnoDB
in MySQL 3.23
Beginning with MySQL 4.0, InnoDB
is enabled by default, so
the following information applies only to MySQL 3.23.
InnoDB
tables are included in the MySQL source distribution
starting from 3.23.34a and are activated in the MySQL-Max
binaries of the 3.23 series.
For Windows, the MySQL-Max binaries are included 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 have MySQL 3.23
installed, the simplest way to install MySQL-Max is to replace the
executable mysqld
server with the corresponding executable from the
MySQL-Max distribution. MySQL and MySQL-Max differ only in the server
executable.
See section 2.7 Installing MySQL on Other Unix-Like Systems and
section 5.1.2 The mysqld-max
Extended MySQL Server.
To compile the MySQL source code with InnoDB
support,
download MySQL 3.23.34a or newer from
http://www.mysql.com/
and configure MySQL with the
--with-innodb
option.
See section 2.8 MySQL Installation Using a Source Distribution.
To use InnoDB
tables with MySQL 3.23, you must specify configuration
parameters in the [mysqld]
section of the `my.cnf' option file.
On Windows, you can use `my.ini' instead. If you do not configure
InnoDB
in the option file, InnoDB
will not start. (From MySQL
4.0 on, InnoDB
uses default parameters if you do not specify any.
However, to get best performance, it is still recommended that
you use
parameters appropriate for your system, as discussed in
section 15.4 InnoDB
Configuration.)
In MySQL 3.23, you must specify at the minimum an innodb_data_file_path
value to configure the InnoDB
data files. For example, to configure
InnoDB
to use a single 500MB data file, place the
following setting in the [mysqld]
section of your option file:
[mysqld] innodb_data_file_path=ibdata1:500M
InnoDB
will create the `ibdata1' file in the MySQL data directory
by default. To specify the location explicitly, specify an
innodb_data_home_dir
setting.
See section 15.4 InnoDB
Configuration.
InnoDB
Configuration
To enable InnoDB
tables in MySQL 3.23, see
section 15.3 InnoDB
in MySQL 3.23.
From MySQL 4.0 on, the InnoDB
storage engine is enabled
by default. If you don't want to use InnoDB
tables, you can
add the skip-innodb
option to your MySQL option file.
Two important disk-based resources managed by the InnoDB
storage
engine are its tablespace data files and its log files.
If you specify no InnoDB
configuration options, MySQL 4.0 and
above creates an auto-extending 10MB data file named `ibdata1' and
two 5MB log files named `ib_logfile0' and `ib_logfile1' in the MySQL data directory.
(In MySQL 4.0.0 and 4.0.1, the data file is 64MB and not auto-extending.)
In MySQL 3.23, InnoDB
will not start if you provide no configuration
options.
Note: To get good performance, you should explicitly provide
InnoDB
parameters as discussed in the following examples. Naturally,
you should edit the settings to suit your hardware and requirements.
To set up the InnoDB
tablespace files, use the
innodb_data_file_path
option in the [mysqld]
section of the
`my.cnf' option file. On Windows, you can use `my.ini' instead.
The value of innodb_data_file_path
should be a list of one or more
data file specifications. If you name more than one data file, separate them
by semicolon (`;') characters:
innodb_data_file_path=datafile_spec1[;datafile_spec2]...
For example, a setting that explicitly creates a tablespace having the same characteristics as the MySQL 4.0 default is as follows:
[mysqld] innodb_data_file_path=ibdata1:10M:autoextend
This setting configures a single 10MB data file named `ibdata1' that is auto-extending. No location for the file is given, so the default is the MySQL data directory.
Sizes are specified using M
or G
suffix letters to indicate
units of MB or GB.
A tablespace containing a fixed-size 50MB data file named `ibdata1' and
a 50MB auto-extending file named ibdata2
in the data directory can be
configured like this:
[mysqld] innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
The full syntax for a data file specification includes the filename, its size, and several optional attributes:
file_name:file_size[:autoextend[:max:max_file_size]]
The autoextend
attribute and those following can be used only for the
last data file in the innodb_data_file_path
line. autoextend
is available starting from MySQL 3.23.50 and 4.0.2.
If you specify the autoextend
option for the last data file,
InnoDB
extends the data file if it runs out of free space in the
tablespace. The increment is 8MB at a time.
If the disk becomes full, you might want to add another data file on
another disk. Instructions for reconfiguring an existing tablespace are
given in section 15.8 Adding and Removing InnoDB
Data and Log Files.
InnoDB
is not aware of the maximum file size, so
be cautious on filesystems where the maximum file size is 2GB.
To specify a maximum size for an auto-extending data file, use the max
attribute. The following configuration allows `ibdata1' to grow up to a
limit of 500MB:
[mysqld] innodb_data_file_path=ibdata1:10M:autoextend:max:500M
InnoDB
creates tablespace files in the MySQL data directory by default.
To specify a location explicitly, use the innodb_data_home_dir
option.
For example, to use two files named `ibdata1' and `ibdata2' but
create them in the `/ibdata' directory, configure InnoDB
like this:
[mysqld] innodb_data_home_dir = /ibdata innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
Note: InnoDB
does not create directories, so make sure that
the `/ibdata' directory exists before you start the server. This is
also true of any log file directories that you configure. Use the Unix or
DOS mkdir
command to create any necessary directories.
InnoDB
forms the directory path for each data file by textually
concatenating the value of innodb_data_home_dir
to the data file name,
adding a slash or backslash between if needed. If the
innodb_data_home_dir
option is not mentioned in `my.cnf' at all,
the default value is the ``dot'' directory `./', which means the MySQL
data directory.
If you specify innodb_data_home_dir
as an empty string, you can
specify absolute paths for the data files listed in the
innodb_data_file_path
value. The following example is equivalent to
the preceding one:
[mysqld] innodb_data_home_dir = innodb_data_file_path=/ibdata/ibdata1:50M;/ibdata/ibdata2:50M:autoextend
A simple `my.cnf' example.
Suppose that you have a computer
with 128MB RAM and one hard disk. The following example shows
possible configuration parameters in `my.cnf' or
`my.ini' for InnoDB
. The example assumes the use of
MySQL-Max 3.23.50 or later or MySQL 4.0.2 or later because it uses the
autoextend
attribute.
This example suits most users, both on Unix and Windows,
who do not want to distribute InnoDB
data files and
log files on several disks. It creates an
auto-extending data file `ibdata1' and two InnoDB
log files
`ib_logfile0' and `ib_logfile1' in the
MySQL data directory. Also, the small archived InnoDB
log file
`ib_arch_log_0000000000' that InnoDB
creates automatically ends
up in the data directory.
[mysqld] # You can write your other MySQL server options here # ... # Data files must be able to hold your data and indexes. # Make sure that 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 # innodb_flush_log_at_trx_commit=1
Make sure that the MySQL server has the proper access rights to create files in the data directory. More generally, the server must have access rights in any directory where it needs to create data files or log files.
Note that data files must be less than 2GB in some filesystems. The combined size of the log files must be less than 4GB. The combined size of data files must be at least 10MB.
When you create an InnoDB
tablespace for the first time, it is
best that you start the MySQL server from the command prompt.
InnoDB
will then print the information about the database
creation to the screen, so you can see what is happening.
For example, on Windows, if mysqld-max
is located in
`C:\mysql\bin', you can start it like this:
C:\> C:\mysql\bin\mysqld-max --console
If you do not send server output to the screen, check the server's error log
to see what InnoDB
prints during the startup process.
See section 15.6 Creating the InnoDB
Tablespace for an example of what the
information displayed by InnoDB
should look like.
Where to specify options on Windows? The rules for option files on Windows are as follows:
WINDIR
directory; for
example, `C:\WINDOWS' or `C:\WINNT'. You can use the SET
command at the command prompt in a console window to print the value of
WINDIR
:
C:\> SET WINDIR windir=C:\WINNT
Where to specify options on Unix?
On Unix, mysqld
reads options from the following files, if they exist,
in the following order:
--defaults-extra-file
option.
DATADIR represents the MySQL data directory that 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 want to make sure that mysqld
reads options only from a
specific file, you can use the --defaults-option
as the first option
on the command line when starting the server:
mysqld --defaults-file=your_path_to_my_cnf
An advanced `my.cnf' example.
Suppose that you have a Linux computer
with 2GB RAM and three 60GB hard disks
(at directory paths `/', `/dr2' and
`/dr3'). The following example shows possible
configuration parameters in `my.cnf' for InnoDB
.
[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 < 2GB set-variable = innodb_buffer_pool_size=1G set-variable = innodb_additional_mem_pool_size=20M innodb_log_group_home_dir = /dr3/iblogs # # innodb_log_arch_dir must be the same as innodb_log_group_home_dir # (starting from 4.0.6, you can omit it) innodb_log_arch_dir = /dr3/iblogs set-variable = innodb_log_files_in_group=2 # # Set the log file size to about 25% of the buffer pool size set-variable = innodb_log_file_size=250M set-variable = innodb_log_buffer_size=8M # innodb_flush_log_at_trx_commit=1 set-variable = innodb_lock_wait_timeout=50 # # Uncomment the next lines if you want to use them #innodb_flush_method=fdatasync #set-variable = innodb_thread_concurrency=5
Note that the example places the two data files on different disks.
InnoDB
will fill the tablespace beginning with the first data file.
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 InnoDB
data files, which may speed up I/O. See section 15.15.2 Using Raw Devices for the Tablespace.
Warning: On 32-bit GNU/Linux x86, you must be careful not to set
memory usage too high. glibc
may allow the process heap to grow over
thread stacks, which will crash your server. It is a risk if the value of
the following expression is close to or exceeds 2GB:
innodb_buffer_pool_size + key_buffer_size + max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size) + max_connections*2MB
Each thread will use a stack (often 2MB, but only 256KB in MySQL AB binaries)
and in the worst case also uses sort_buffer_size + read_buffer_size
additional memory.
Starting from MySQL 4.1, by compiling MySQL yourself,
you can use up to 64GB of physical memory in 32-bit
Windows. See the description for innodb_buffer_pool_awe_mem_mb
in
section 15.5 InnoDB
Startup Options.
How to tune other mysqld
server parameters?
The following values are typical and suit most users:
[mysqld] skip-external-locking set-variable = max_connections=200 set-variable = read_buffer_size=1M set-variable = sort_buffer_size=1M # # Set key_buffer to 5 - 50% of your RAM depending on how much # you use MyISAM tables, but keep key_buffer_size + InnoDB # buffer pool size < 80% of your RAM set-variable = key_buffer_size=...
InnoDB
Startup Options
This section describes the InnoDB
-related server options. In MySQL
4.0 and up, all of them can be specified in --opt_name=value
form on
the command line or in option files. Before MySQL 4.0, numeric options
should be specified using --set-variable=opt_name=value
or -O
opt_name=value
syntax.
innodb_additional_mem_pool_size
InnoDB
uses to store data dictionary
information and other internal data structures. The more tables you have in
your application, the more memory 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. The default value is 1MB.
innodb_autoextend_increment
innodb_buffer_pool_awe_mem_mb
InnoDB
buffer pool into the
AWE physical memory using this parameter. The maximum possible value for this
is 64000. If this parameter is specified, innodb_buffer_pool_size
is the window in the 32-bit address space of mysqld
where InnoDB
maps that AWE memory. A good value for innodb_buffer_pool_size
is 500MB.
innodb_buffer_pool_size
InnoDB
uses to cache data and indexes
of its tables. The larger you set this value, the less disk I/O is needed
to access data in tables. On a dedicated database server, you may set this
to up to 80% of the machine physical memory size. However, do not set it
too large because competition for the physical memory might cause paging
in the operating system.
innodb_checksums
InnoDB
uses checksum validation on all pages read from the disk to
ensure extra fault tolerance against broken hardware or data files. However,
under some rare circumstances (such as when running benchmarks) this ``extra
safety'' feature is unneeded. In such cases, this option (which is enabled
by default) can be turned off with --skip-innodb-checksums
. This
option was added in MySQL 5.0.3.
innodb_data_file_path
innodb_data_home_dir
to each path specified here. The file sizes are specified in megabytes
or gigabytes (1024MB) by appending M
or G
to the size
value. The sum of the sizes of the files must be at least 10MB. On some
operating systems, files must be less than 2GB. If you do not specify
innodb_data_file_path
, the default behavior starting from 4.0 is to
create a single 10MB auto-extending data file named `ibdata1'. Starting
from 3.23.44, you can set the file size bigger than 4GB on those operating
systems that support big files. You can also use raw disk partitions as
data files. See section 15.15.2 Using Raw Devices for the Tablespace.
innodb_data_home_dir
InnoDB
data files. If
you do not set this value, the default is the MySQL data directory. You can
specify this also as an empty string, in which case you can use absolute
file paths in innodb_data_file_path
.
innodb_doublewrite
InnoDB
stores all data twice, first to the doublewrite
buffer, and then to the actual data files. This option can be used to
disable this functionality. Like innodb_checksums
, this option is
enabled by default; it can be turned off with
--skip-innodb-doublewrite
for benchmarks or cases when top
performance is needed rather than concern for data integrity or possible
failures. This option was added in MySQL 5.0.3.
innodb_fast_shutdown
InnoDB
does a full purge and an insert buffer merge
before a shutdown. These operations can take minutes, or even hours in extreme
cases. If you set this parameter to 1, InnoDB
skips these operations at shutdown. This option is available starting from
MySQL 3.23.44 and 4.0.1. Its default value is 1 starting from 3.23.50.
innodb_file_io_threads
InnoDB
. Normally this should be
left at the default value of 4, but disk I/O on Windows may benefit from
a larger number. On Unix, increasing the number has no effect; InnoDB
always uses the default value.
This option is available as of MySQL 3.23.37.
innodb_file_per_table
innodb_file_per_table
in `my.cnf'! If you shut down mysqld
, then records may
disappear from the secondary indexes of a table.
See (Bug #7496) for more information and workarounds. This is fixed in
4.1.9, but another bug (Bug #8021) bit the Windows version in 4.1.9, and
in the Windows version of 4.1.9 you must put the line
innodb_flush_method=unbuffered
to your `my.cnf' or
`my.ini' to get mysqld
to work.
This option causes InnoDB
to create each new table
using its own `.ibd' file for storing data and indexes, rather than in
the shared tablespace. See section 15.7.6 Using Per-Table Tablespaces.
This option is available as of MySQL 4.1.1.
innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit
is set to 0, once per second
the log buffer is written out to the log file, and the flush to disk
operation is performed on the log file, but nothing is done at a transaction
commit. When this value is 1 (the default), at each transaction commit
the log buffer is written out to the log file, and the flush to disk
operation is performed on the log file. When set to 2, at each commit
the log buffer is written out to the file, but the flush to disk operation
is not performed on it. However, the flushing on the log file
takes place once per second also in the case of 2.
We must note that the once-per-second flushing is not 100% guaranteed to happen every second, due to process scheduling issues.
You can achieve better performance by setting the value different from
1, but then you can lose at most one second worth of transactions in
a crash. If you set the value to 0, then any mysqld
process
crash can erase the last second of transactions. If you set the value
to 2, then only an operating system crash or a power outage can erase
the last second of transactions.
Note that many operating systems and some disk hardware fool in the
flush-to-disk operation. They may tell to mysqld
that the flush
has taken place, though it has not. Then the durability of transactions
is not guaranteed even with the setting 1, and in the worst case a
power outage can even corrupt the InnoDB database. Using a battery-backed
disk cache in the SCSI disk controller or in the disk itself speeds up
file flushes, and makes the operation safer. You can also try
using the Unix command hdparm
to disable the caching of disk writes
in hardware caches, or use some other command specific to the hardware
vendor.
The default value of this option is 1 (prior to MySQL 4.0.13, the default is 0).
innodb_flush_method
fdatasync
,
InnoDB
uses fsync()
to flush both the data and log
files. If set to O_DSYNC
, InnoDB
uses O_SYNC
to open and flush the log files, but uses fsync()
to flush the
data files. If O_DIRECT
is specified (available on some GNU/Linux
versions starting from MySQL 4.0.14), InnoDB
uses O_DIRECT
to open the data files, and uses fsync()
to flush both the data
and log files. Note that InnoDB
does not use fdatasync
or
O_DSYNC
by default because there have been problems with them on
many Unix flavors. This option is available as of MySQL 3.23.40.
innodb_force_recovery
InnoDB
prevents a user from modifying
data when this option is greater than 0. This option is available starting
from MySQL 3.23.44.
innodb_lock_wait_timeout
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. Beginning
with MySQL 4.0.20 and 4.1.2, InnoDB notices locks set using the LOCK
TABLES
statement. Before that, if you
use the LOCK TABLES
statement, or other transaction-safe storage
engines than InnoDB
in the same transaction, a deadlock may arise
that InnoDB
cannot notice. In cases like this, the timeout is useful
to resolve the situation. The default is 50 seconds.
innodb_locks_unsafe_for_binlog
InnoDB
searches
and index scans. Default value for this option is false.
Normally InnoDB
uses an algorithm called ``next-key locking.''
InnoDB
does the row-level locking in such a way that when it
searches or scans an index of a table, it sets shared or exclusive
locks on the index records it encounters. Thus the row-level locks
are actually 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,
another user cannot insert a new index record immediately before
R in the index order. This option causes InnoDB
not to
use next-key locking in searches or index scans. Next-key locking is
still used to ensure foreign key constraints and duplicate key checking.
Note that using this option may cause phantom problems: Suppose that you
want to read and lock all children from the child
table with an
identifier value larger than 100, with the intent of updating
some column in the selected rows later:
SELECT * FROM child WHERE id > 100 FOR UPDATE;Suppose that there is an index on the
id
column. The query will scan
that index starting from the first record where id is bigger than 100.
If the locks set on the index records do not lock out inserts
made in the gaps, a new row will meanwhile be inserted to the table.
If you execute the same SELECT
within the same transaction,
you will see a new row in the result set returned by the query.
This also means, that if new items are added to the database,
InnoDB does not guarantee serializability instead conflict
serializability is still guaranteed. Therefore, if this option is
used InnoDB guarantees at most isolation level READ COMMITTED
.
This option is available as of MySQL 4.1.4.
Starting from MySQL 5.0.2 this option is even more unsafe. InnoDB in
an UPDATE
or a DELETE
only locks rows that it updates or
deletes. This greatly reduces the probability of deadlocks but they
can happen. Note that this option still does not allow
e.g. UPDATE
to overtake other UPDATE
even the case
when both updates different rows. Consider following example:
CREATE TABLE A(A INT NOT NULL, B INT); INSERT INTO A VALUES (1,2),(2,3),(3,2),(4,3),(5,2); COMMIT;If one connection executes a query:
SET AUTOCOMMIT = 0; UPDATE A SET B = 5 WHERE B = 3;and the other connection executes after the first one a query:
SET AUTOCOMMIT = 0; UPDATE A SET B = 4 WHERE B = 2;Then query two has to wait for a commit or rollback of query one, because query one has an exclusive lock to a row (2,3), and query two while scanning rows also tries to take an exclusive lock to the row (2,3) which it cannot have. This is because query two first takes an exclusive lock to a row and then checks does this row belong to the result set and if not then releases the unnecessary lock when option
innodb_locks_unsafe_for_binlog
is used.
Therefore, query one is executed as follows:
x-lock(1,2) unlock(1,2) x-lock(2,3) update(2,3) to (2,5) x-lock(3,2) unlock(3,2) x-lock(4,3) update(4,3) to (4,5) x-lock(5,2) unlock(5,2)and then query two is executed as follows:
x-lock(1,2) update(1,2) to (1,4) x-lock(2,3) - wait for query one to commit or rollback
innodb_log_arch_dir
innodb_log_group_home_dir
. Starting from MySQL 4.0.6, you may omit
this option.
innodb_log_archive
InnoDB
log files. The default for this option is 0.
innodb_log_buffer_size
InnoDB
uses to write to the log files
on disk. Sensible values range from 1MB to 8MB. The default is 1MB. A large
log buffer allows large transactions to run without a need to write the log
to disk before the transactions commit. Thus, if you have big transactions,
making the log buffer larger will save disk I/O.
innodb_log_file_size
innodb_log_files_in_group
InnoDB
writes to the
files in a circular fashion. The default is 2 (recommended).
innodb_log_group_home_dir
InnoDB
log files. It must have the same
value as innodb_log_arch_dir
. If you do not specify any InnoDB
log parameters, the default is to create two 5MB files names `ib_logfile0'
and `ib_logfile1' in the MySQL data directory.
innodb_max_dirty_pages_pct
InnoDB
tries to flush pages from the buffer pool so that
at most this many percent of pages may not yet flushed been flushed at
any particular time. Available starting from 4.0.13 and 4.1.1. If you have the
SUPER
privilege, this percentage can be changed while the server is
running:
SET GLOBAL innodb_max_dirty_pages_pct = value;
innodb_max_purge_lag
INSERT
, UPDATE
and DELETE
operations when the purge operations are lagging.
The default value of this parameter is zero, meaning that there will
not be any delays. When the value is greater than zero, InnoDB
may delay new row operations, as described in section 15.13 Implementation of Multi-Versioning.
This option can be changed at runtime as a global system variable.
innodb_max_purge_lag
is available as of MySQL 4.0.22 and 4.1.6.
innodb_mirrored_log_groups
innodb_open_files
InnoDB
. It specifies the maximum number of `.ibd' files that
InnoDB
can keep open at one time. The minimum value is 10. The
default is 300. This option is available as of MySQL 4.1.1.
The file descriptors used for `.ibd' files are for InnoDB
only.
They are independent of those specified by the --open-files-limit
server option, and do not affect the operation of the table cache.
innodb_table_locks
InnoDB
honors LOCK TABLES
;
MySQL will not return from LOCK TABLE .. WRITE
until all other
threads have released all their locks to the table. In MySQL 4.0.19
and before, InnoDB ignored table locks, which allowed one to more easily
simulate transactions with a combination of MyISAM and InnoDB tables.
The default value is 1, which means that
LOCK TABLES
causes also InnoDB internally to take a table lock.
In applications using AUTOCOMMIT=1
, InnoDB's
internal table locks can cause deadlocks. You can set
innodb_table_locks=0
in `my.cnf' to remove that problem.
innodb_thread_concurrency
InnoDB
tries to keep the number of operating system threads
concurrently inside InnoDB
less than or equal to the limit given
by this parameter. The default value is 8. If you have low performance
and SHOW INNODB STATUS
reveals many threads waiting for semaphores,
you may have thread thrashing and should try setting this parameter lower
or higher. If you have a computer with many processors and disks, you
can try setting the value higher to better utilize the resources of you
computer. A recommended value is the sum of the number of processors and
disks your system has. A value of 500 or greater disables the concurrency
checking. This option is available starting from MySQL 3.23.44 and 4.0.1.
innodb_status_file
InnoDB
to create a file
`<datadir>/innodb_status.<pid>' for periodical
SHOW INNODB STATUS
output. This option is available as of MySQL 4.0.21.
InnoDB
Tablespace
Suppose that you have installed MySQL and have edited your option file so
that it contains the necessary InnoDB
configuration parameters.
Before starting MySQL, you should verify that the directories you have
specified for InnoDB
data files and log files exist and that the
MySQL server has access rights to those directories. InnoDB
cannot
create directories, only files. Check also that you have enough disk space
for the data and log files.
It is best to run the MySQL server mysqld
from the command prompt
when you create an InnoDB
database, not from the mysqld_safe
wrapper or as a Windows service. When you run from a command prompt you
see what mysqld
prints and what is happening. On Unix, just invoke
mysqld
. On Windows, use the --console
option.
When you start the MySQL server after initially configuring InnoDB
in
your option file, InnoDB
creates your
data files and log files. InnoDB
will print something like the following:
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: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: Creating foreign key constraint system tables InnoDB: Foreign key constraint system tables created InnoDB: Started mysqld: ready for connections
A new InnoDB
database has 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
,
the 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 look at the data file and log 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 started again, the data files and log files will have
been created, so the output will be much briefer:
InnoDB: Started mysqld: ready for connections
Starting from MySQL 4.1.1, you can add the option innodb_file_per_table
to `my.cnf', and make InnoDB to store each table into its own
`.ibd' file in a database directory of MySQL.
See section 15.7.6 Using Per-Table Tablespaces.
InnoDB
Initialization Problems
If InnoDB
prints an operating system error in a file operation,
usually the problem is one of the following:
InnoDB
data file directory
or the InnoDB log directory.
mysqld
does not have access rights to create files in those
directories.
mysqld
does not read the proper `my.cnf' or `my.ini'
option file, and consequently does not see the options you specified.
innodb_data_home_dir
or innodb_data_file_path
.
If something goes wrong when InnoDB
attempts to initialize
its tablespace or its log files, you should delete all files created
by InnoDB
. This means all `ibdata' files and all
`ib_logfile's. In case you created some InnoDB
tables,
delete the corresponding `.frm' files for these tables (and any
`.ibd' files if you are using multiple tablespaces) from the
MySQL database directories as well. Then you can try the InnoDB
database creation again. It is best to start the MySQL server from a
command prompt so that you see what is happening.
InnoDB
Tables
Suppose that you have started the MySQL client with the command mysql test
.
To create an InnoDB
table, you must specify and ENGINE = InnoDB
or TYPE = InnoDB
option in the table creation SQL statement:
CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) ENGINE=InnoDB; CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) TYPE=InnoDB;
The SQL statement creates a table and an index on column a
in the
InnoDB
tablespace that consists of the data files you specified in
`my.cnf'. In addition, MySQL creates a file `customers.frm'
in the `test' directory under the MySQL database directory.
Internally, InnoDB
adds to its own data dictionary an entry for
table 'test/customers'
. This means you can create a table of the same
name customers
in some other database, and the table names will
not collide inside InnoDB
.
You can query the amount of free space in the InnoDB
tablespace
by issuing a SHOW TABLE STATUS
statement for any InnoDB
table.
The amount of free
space in the tablespace appears in the Comment
section in the
output of SHOW TABLE STATUS
. An example:
SHOW TABLE STATUS FROM test LIKE 'customers'
Note that the statistics SHOW
gives about InnoDB
tables
are only approximate. They are used in SQL optimization. Table and index
reserved sizes in bytes are accurate, though.
InnoDB
with Different APIs
By default, each client that connects to the MySQL server begins with autocommit
mode enabled, which automatically commits every SQL statement you run.
To use multiple-statement transactions, you can switch autocommit off
with the SQL statement SET AUTOCOMMIT = 0
and use COMMIT
and ROLLBACK
to commit or roll back your transaction.
If you want to leave autocommit on, you can enclose your transactions
between START TRANSACTION
and COMMIT
or ROLLBACK
.
Before MySQL 4.0.11, you have to use the keyword BEGIN
instead of START TRANSACTION
. The following example shows two
transactions. The first is committed and the second is rolled back.
shell> mysql test Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5 to server version: 3.23.50-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A)) -> TYPE=InnoDB; Query OK, 0 rows affected (0.00 sec) mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO CUSTOMER VALUES (10, 'Heikki'); Query OK, 1 row affected (0.00 sec) mysql> COMMIT; Query OK, 0 rows affected (0.00 sec) mysql> SET AUTOCOMMIT=0; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO CUSTOMER VALUES (15, 'John'); Query OK, 1 row affected (0.00 sec) mysql> ROLLBACK; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM CUSTOMER; +------+--------+ | A | B | +------+--------+ | 10 | Heikki | +------+--------+ 1 row in set (0.00 sec) mysql>
In APIs like PHP, Perl DBI/DBD, JDBC, ODBC, or the standard C call
interface of MySQL, you can send transaction control statements such as
COMMIT
to the MySQL server as strings just like any other
SQL statements such as SELECT
or INSERT
.
Some APIs also offer separate special transaction commit and rollback functions
or methods.
MyISAM
Tables to InnoDB
Important: You should not convert MySQL system tables in the mysql
database (such as user
or host
) to the InnoDB
type. The
system tables must always be of the MyISAM
type.
If you want all your (non-system) tables to be created as InnoDB
tables, you can, starting from the MySQL 3.23.43, add the line
default-table-type=innodb
to the [mysqld]
section of
your `my.cnf' or `my.ini' file.
InnoDB
does not have a special optimization for separate index
creation the way the MyISAM
storage engine does. Therefore, it does
not pay to export and import the table and create indexes afterward.
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 ...
.
If you have UNIQUE
constraints on secondary keys, starting from
MySQL 3.23.52, you can speed up a table import by turning off the uniqueness
checks temporarily during the import session: SET UNIQUE_CHECKS=0;
For big tables, this saves a lot of disk I/O because InnoDB
can then
use its insert buffer to write secondary index records in a batch.
To get better control over the insertion process, it might be good to insert big tables in pieces:
INSERT INTO newtable SELECT * FROM oldtable WHERE yourkey > something AND yourkey <= somethingelse;
After all records have been inserted, you can rename the tables.
During the conversion of big tables, you should increase the size of the
InnoDB
buffer pool to reduce disk I/O. Do not use more than 80% of the
physical memory, though. You can also increase the sizes of the InnoDB
log files and the log files.
Make sure that you do not fill up the tablespace: InnoDB
tables require
a lot more disk 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. For 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 may be advisable to kill the database process rather than wait for millions of disk I/O operations to complete. For the complete procedure, see section 15.9.1 Forcing Recovery.
AUTO_INCREMENT
Column Works in InnoDB
If you specify an AUTO_INCREMENT
column for a table, the InnoDB
table handle in the data dictionary will contain a special counter called
the auto-increment counter that is used in assigning new values for the
column. The auto-increment counter is stored only in main memory, not
on disk.
InnoDB
uses the following algorithm to initialize the auto-increment
counter for a table T
that contains an AUTO_INCREMENT
column
named ai_col
: After a server startup, when a user first does an insert
to a table T
, InnoDB
executes the equivalent of this statement:
SELECT MAX(ai_col) FROM T FOR UPDATE;
The value retrieved by the statement is incremented by one and assigned to
the column and the auto-increment counter of the table. If the table is
empty, the value 1
is assigned. If the auto-increment counter is not
initialized and the user invokes a SHOW TABLE STATUS
statement that
displays output for the table T
, the counter is initialized (but not
incremented) and stored for use by later inserts.
Note that in this initialization
we do a normal exclusive-locking read on the table and the lock lasts to the end
of the transaction.
InnoDB
follows the same procedure for initializing the auto-increment
counter for a freshly created table.
Note that if the user specifies NULL
or 0
for the
AUTO_INCREMENT
column in an INSERT
, InnoDB
treats the
row as if the value had not been specified and generates a new value for it.
After the auto-increment counter has been initialized, if a user inserts
a row that explicitly specifies the column value, and the value is
bigger than the current counter value, the counter is set to the specified
column value. If the user does not explicitly specify a value, InnoDB
increments the counter by one and assigns the new value to the column.
When accessing the auto-increment counter, InnoDB
uses a special table
level AUTO-INC
lock that it keeps to the end of the current SQL
statement, not to the end of the transaction.
The special lock release strategy was introduced to improve concurrency
for inserts into a table containing an AUTO_INCREMENT
column. Two
transactions cannot have the AUTO-INC
lock on the same table
simultaneously.
Note that you may see gaps in the sequence of values assigned to the
AUTO_INCREMENT
column if you roll back transactions that have gotten
numbers from the counter.
The behavior of the auto-increment mechanism is not defined if a user assigns 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.
FOREIGN KEY
Constraints
Starting from MySQL 3.23.44, InnoDB
features foreign key constraints.
The syntax of a foreign key constraint definition in InnoDB
looks like
this:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...) REFERENCES tbl_name (index_col_name, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
Both tables must be InnoDB
type. In the referencing table, there must
be an index where the foreign key columns are listed as the first
columns in the same order. In the referenced table, there must be an index
where the referenced columns are listed as the first columns in
the same order. Index prefixes on foreign key columns are not supported.
InnoDB
needs indexes on foreign keys and referenced keys so that
foreign key checks can be fast and not require a table scan. Starting with
MySQL 4.1.2, these indexes are created automatically. In older versions,
the indexes must be created explicitly or the creation of foreign key
constraints will fail.
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 that you
have not declared the columns in the child table as
NOT NULL
.
If MySQL reports an error number 1005 from a CREATE TABLE
statement,
and the error message string refers to errno 150, this means that 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 MySQL 4.0.13, you can use SHOW INNODB
STATUS
to display a detailed explanation of the latest InnoDB
foreign key error in the server.
Starting from MySQL 3.23.50, InnoDB
does not check foreign key
constraints on those foreign key or referenced key values
that contain a NULL
column.
A deviation from SQL standards: If in the parent table
there are several rows that have the same referenced key value,
then InnoDB
acts in foreign key checks as if the other parent
rows with the same key value do not exist. For example,
if you have defined a RESTRICT
type constraint, and there
is a child row with several parent rows, InnoDB
does not allow
the deletion of any of those parent rows.
Starting from MySQL 3.23.50, you can also associate the
ON DELETE CASCADE
or ON DELETE SET NULL
clause with
the foreign key constraint. Corresponding ON UPDATE
options
are available starting from 4.0.8. If ON DELETE CASCADE
is
specified, and a row in the parent table is deleted, 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.
SET DEFAULT
is parsed but ignored by MySQL. InnoDB
will reject table definitions containing ON DELETE SET DEFAULT
clauses.
InnoDB
performs cascading operations through a depth-first algorithm,
based on records in the indexes corresponding to the foreign key
constraints.
A deviation from SQL standards: If
ON UPDATE CASCADE
or ON UPDATE SET NULL
recurses to
update the same table it has previously updated during the cascade,
it acts like RESTRICT
. This means that you cannot use
self-referential ON UPDATE CASCADE
or
ON UPDATE SET NULL
operations.
This is to prevent infinite loops resulting from cascaded updates.
A self-referential ON DELETE SET NULL
, on the other hand,
is possible from 4.0.13.
A self-referential ON DELETE CASCADE
has been possible since ON
DELETE
was implemented. Since 4.0.21, cascading operations may not be nested
more than 15 levels.
A deviation from SQL standards:
Like MySQL in general, in an SQL statement that inserts, deletes, or
updates many rows, InnoDB checks UNIQUE
and FOREIGN KEY
constraints row-by-row. According to the SQL standard, the default behavior
should be that constraints are only checked after the WHOLE SQL statement
has been processed.
A simple example that relates parent
and child
tables through a
single-column foreign key:
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 CASCADE ) TYPE=INNODB;
A more complex example in which a product_order
table has foreign keys
for two other tables. One foreign key references a two-column index in the
product
table. The other references a single-column index in the
customer
table:
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, price DECIMAL, PRIMARY KEY(category, id)) TYPE=INNODB; CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB; CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, PRIMARY KEY(no), INDEX (product_category, product_id), FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT, INDEX (customer_id), FOREIGN KEY (customer_id) REFERENCES customer(id)) TYPE=INNODB;
Starting from MySQL 3.23.50, InnoDB
allows you to add a new
foreign key constraint to a table by using ALTER TABLE
:
ALTER TABLE yourtablename ADD [CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...) REFERENCES tbl_name (index_col_name, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
Remember to create the required indexes first.
You can also add a self-referential foreign key constraint to a
table using ALTER TABLE
.
Starting from MySQL 4.0.13, InnoDB
supports the use of ALTER
TABLE
to drop foreign keys:
ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol;
If the FOREIGN KEY
clause included a CONSTRAINT
name when you
created the foreign key, you can refer to that name to drop the foreign key.
(A constraint name can be given as of MySQL 4.0.18.) Otherwise, the
fk_symbol
value is internally generated by InnoDB
when the
foreign key is created. To find out the symbol when you want to drop a foreign
key, use the SHOW CREATE TABLE
statement.
An example:
mysql> SHOW CREATE TABLE ibtest11c\G *************************** 1. row *************************** Table: ibtest11c Create Table: CREATE TABLE `ibtest11c` ( `A` int(11) NOT NULL auto_increment, `D` int(11) NOT NULL default '0', `B` varchar(200) NOT NULL default '', `C` varchar(175) default NULL, PRIMARY KEY (`A`,`D`,`B`), KEY `B` (`B`,`C`), KEY `C` (`C`), CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11a` (`A`, `D`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`) REFERENCES `ibtest11a` (`B`, `C`) ON DELETE CASCADE ON UPDATE CASCADE ) TYPE=InnoDB CHARSET=latin1 1 row in set (0.01 sec) mysql> ALTER TABLE ibtest11c DROP FOREIGN KEY 0_38775;
Starting from MySQL 3.23.50, the InnoDB
parser allows you to use
backticks around table and column names in a
FOREIGN KEY ... REFERENCES ...
clause.
Starting from MySQL 4.0.5, the InnoDB
parser also takes into account
the lower_case_table_names
system variable setting.
Before MySQL 3.23.50, ALTER TABLE
or CREATE INDEX
should not be used in connection with tables that have foreign
key constraints or that are referenced in foreign key constraints:
Any ALTER TABLE
removes all foreign key
constraints defined for the table. You should not use
ALTER TABLE
with the referenced table, either. Instead,
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 constraints that refer to the table.
In MySQL, a CREATE INDEX
statement is processed as an
ALTER TABLE
, so the same considerations apply.
Starting from MySQL 3.23.50, InnoDB
returns the foreign key
definitions of a table as part of the output of the SHOW CREATE TABLE
statement:
SHOW CREATE TABLE tbl_name;
From this version, mysqldump
also produces correct definitions
of tables to the dump file, and does not forget about the foreign keys.
You can display the foreign key constraints for a table like this:
SHOW TABLE STATUS FROM db_name LIKE 'tbl_name'
The foreign key constraints are listed in the Comment
column of
the output.
When performing 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.
To make it easier to reload dump files for tables that have foreign key
relationships, mysqldump
automatically includes a statement in the
dump output to set FOREIGN_KEY_CHECKS
to 0 as of MySQL 4.1.1. This
avoids problems with tables having to be reloaded in a particular order
when the dump is reloaded. For earlier versions, you can disable the
variable manually within mysql
when loading the dump file like this:
mysql> SET FOREIGN_KEY_CHECKS = 0; mysql> SOURCE dump_file_name mysql> SET FOREIGN_KEY_CHECKS = 1;
This allows you to import the tables in any order if the dump file contains
tables that are not correctly ordered for foreign keys. It also speeds
up the import operation. FOREIGN_KEY_CHECKS
is available starting
from MySQL 3.23.52 and 4.0.3.
Setting FOREIGN_KEY_CHECKS
to 0 can also be useful for ignoring
foreign key constraints during LOAD DATA
operations.
InnoDB
does not allow you to drop a table that is
referenced by a FOREIGN KEY
constraint, unless
you do SET FOREIGN_KEY_CHECKS=0
.
When you drop a table, the constraints that
were defined in its create statement are also dropped.
If you re-create a table that was dropped, it must have a definition that 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 earlier. If these are not satisfied, MySQL returns error number 1005 and refers to errno 150 in the error message string.
InnoDB
and MySQL Replication
MySQL replication works for InnoDB
tables as it does
for MyISAM
tables. It is also possible to use replication in
a way where the table type on the slave is not the same as the original
table type on the master. For example, you can replicate modifications to
an InnoDB
table on the master to a MyISAM
table on the slave.
To set up a new slave for a master, you have to make a copy of the
InnoDB
tablespace and the log files, as well as the `.frm' files
of the InnoDB
tables, and move the copies to the slave.
For the proper procedure to do this, see section 15.10 Moving an InnoDB
Database to Another Machine.
If you can shut down the master or an existing slave, you can take a
cold backup of the InnoDB
tablespace and log files and use that to
set up a slave.
To make a new slave without taking down any server you can also use
the non-free (commercial) InnoDB Hot Backup
tool.
There are minor limitations in InnoDB
replication:
LOAD TABLE FROM MASTER
does not work for InnoDB
type
tables. There are workarounds: 1) dump the table on the master and import the
dump file into the slave, or 2) use ALTER TABLE tbl_name TYPE=MyISAM
on the master before setting up replication with LOAD TABLE tbl_name
FROM MASTER
, and then use ALTER TABLE
to alter the master table
back to the InnoDB
type afterward.
SLAVE STOP
did not
respect the boundary of a multiple-statement transaction.
An incomplete transaction would be rolled back, and the next
SLAVE START
would only execute the remaining part of the half
transaction. That would cause replication to fail.
SLAVE STOP
.
SET FOREIGN_KEY_CHECKS=0
statement does not work properly.
Most of these limitations can be eliminated by using more recent server versions for which the limitations do not apply.
Transactions that fail on the master do not affect replication at all. MySQL replication is based on the binary log where MySQL writes SQL statements that modify data. A slave reads the binary log of the master and executes the same SQL statements. However, statements that occur within a transaction are not written to the binary log until the transaction commits, at which point all statements in the transaction are written at once. If a statement fails, for example, because of a foreign key violation, or if a transaction is rolled back, no SQL statements are written to the binary log, and the transaction is not executed on the slave at all.
NOTE: CRITICAL BUG in 4.1 if you specify innodb_file_per_table
in `my.cnf'! If you shut down mysqld
, then records may
disappear from the secondary indexes of a table. See (Bug #7496) for
more information and workarounds. This is fixed in 4.1.9,
but another bug (Bug #8021) bit the Windows version in 4.1.9, and
in the Windows version of 4.1.9 you must put the line
innodb_flush_method=unbuffered
to your `my.cnf' or
`my.ini' to get mysqld
to work.
Starting from MySQL 4.1.1, you can store each InnoDB
table and its
indexes into its own file. This feature is called ``multiple tablespaces''
because in effect each table has its own tablespace.
Using multiple tablespaces can be beneficial to users who want to move specific tables to separate physical disks or who wish to restore backups of single tables quickly without interrupting the use of the remaining InnoDB tables.
If you need to downgrade to 4.0, you have to take table dumps and
re-create the whole InnoDB
tablespace. If you have not created new
InnoDB
tables under MySQL 4.1.1 or later, and need to downgrade
quickly, you can also do a direct downgrade to the MySQL
4.0.18 or later in the 4.0 series.
Before doing the direct downgrade to 4.0.x, you have to end all client
connections to the mysqld
server that is to be downgraded, and let it
run the purge and insert buffer merge operations to completion, so that
SHOW INNODB STATUS
shows the main thread in the state
waiting for server activity
. Then you can shut down
mysqld
and start 4.0.18 or later in the 4.0 series.
You can enable multiple tablespaces by adding a line to the
[mysqld]
section of `my.cnf':
[mysqld] innodb_file_per_table
After restarting the server, InnoDB
will store each newly created
table into its own file `tbl_name.ibd' in the database directory
where the table belongs. This is similar to what the MyISAM
storage engine does, but MyISAM
divides the table into a data
file `tbl_name.MYD' and the index file `tbl_name.MYI'.
For InnoDB
, the data and the indexes are stored together in the
`.ibd' file. The `tbl_name.frm' file is still created as usual.
If you remove the innodb_file_per_table
line from `my.cnf' and
restart the server, InnoDB
creates tables inside the shared tablespace
files again.
innodb_file_per_table
affects only table creation. If you start the
server with this option, new tables are created using `.ibd' files, but you can still access tables that exist in the shared
tablespace. If you remove the option, new tables are created in the shared
tablespace, but you can still access any tables that
were created using multiple tablespaces.
InnoDB
always needs the shared tablespace. The `.ibd'
files are not sufficient for InnoDB
to operate. The shared tablespace
consists of the familiar `ibdata' files where InnoDB
puts its
internal data dictionary and undo logs.
You cannot freely move `.ibd' files around between database
directories the way you can with
MyISAM
table files. This is because the table definition is stored
in the InnoDB
shared tablespace, and also because InnoDB
must preserve the consistency of transaction IDs and log sequence numbers.
Within a given MySQL installation, you can move an `.ibd' file and the
associated table from one database to another with the familiar RENAME
TABLE
statement:
RENAME TABLE old_db_name.tbl_name TO new_db_name.tbl_name;
If you have a ``clean'' backup of an `.ibd' file, you can restore it to the MySQL installation from which it originated as follows:
ALTER TABLE
statement:
ALTER TABLE tbl_name DISCARD TABLESPACE;Caution: This deletes the current `.ibd' file.
ALTER TABLE
statement:
ALTER TABLE tbl_name IMPORT TABLESPACE;
In this context, a ``clean'' `.ibd' file backup means:
mysqld
has flushed all modified pages of the `.ibd' file from
the buffer pool to the file.
You can make such a clean backup `.ibd' file with the following method:
mysqld
server and commit all transactions.
SHOW INNODB STATUS
shows that there are no active
transactions in the database, and the main thread status of InnoDB
is
Waiting for server activity
. Then you can make a copy of the
`.ibd' file.
Another method for making a clean copy of an `.ibd' file is to
use the commercial InnoDB Hot Backup
tool:
InnoDB Hot Backup
to back up the InnoDB
installation.
mysqld
server on the backup and let it clean up
the `.ibd' files in the backup.
It is in the TODO to also allow moving clean `.ibd' files to another MySQL installation. This requires resetting of transaction IDs and log sequence numbers in the `.ibd' file.
InnoDB
Data and Log Files
This section describes what you can do when your InnoDB
tablespace runs
out of room or when you want to change the size of the log files.
From MySQL 3.23.50 and 4.0.2, the easiest way to increase the size of the
InnoDB
tablespace is to configure it from the beginning to be
auto-extending. Specify the autoextend
attribute for the last
data file in the tablespace definition. Then InnoDB
will increase the
size of that file automatically in 8MB increments when it runs out of space.
Starting with MySQL 4.0.24 and 4.1.5, the increment size can be
configured with the option innodb_autoextend_increment
, in megabytes.
The default value is 8.
Alternatively, you can increase the size of your tablespace by adding another
data file. To do this, you have to shut down the MySQL server,
edit the `my.cnf' file to add a new data file to the end of
innodb_data_file_path
, and start the server again.
If your last data file was defined with the keyword autoextend
,
the procedure to edit `my.cnf' must take into account the size to
which the last data file has grown. You have to
look at the size of the data file, round the size downward to the
closest multiple of 1024 * 1024 bytes (= 1MB), and specify the rounded
size explicitly in innodb_data_file_path
. Then you can add
another data file. Remember that only the last data file in the
innodb_data_file_path
can be specified as auto-extending.
As an example, assume that the tablespace has just one auto-extending data file `ibdata1':
innodb_data_home_dir = innodb_data_file_path = /ibdata/ibdata1:10M:autoextend
Suppose that this data file, over time, has grown to 988MB. Below is the configuration line after adding another auto-extending data file.
innodb_data_home_dir = innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend
When you add a new file to the tablespace, make sure that it does not
exist. InnoDB
will create and initialize it when you restart
the server.
Currently, you cannot remove a data file from the tablespace. To decrease the size of your tablespace, use this procedure:
mysqldump
to dump all your InnoDB
tables.
If you want to change the number or the size of your InnoDB
log
files, you have to stop the MySQL server 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
tablespace. Delete the old log files from the log file directory, edit
`my.cnf' to change the log file configuration, and start the MySQL
server again. mysqld
will see that the no log files exist at startup
and tell you that it is creating new ones.
InnoDB
DatabaseThe 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 (commercial) additional tool whose annual license fee is
390 euros per computer where the MySQL server is run.
See the InnoDB Hot Backup
home page
for detailed information and screenshots.
If you are able to shut down your MySQL server, you can make
a ``binary'' backup that consists of all files used by InnoDB
to manage
its tables. Use the following procedure:
InnoDB
tables to a safe place.
Replication works with InnoDB
type tables, so you can use MySQL
replication capabilities to keep a copy of your database at database sites
requiring high availability.
In addition to taking binary backups as just described,
you should also regularly take dumps of your tables with
mysqldump
. The reason for this is that a binary file
might be corrupted without you noticing it. Dumped tables are stored
into text files that are human-readable, so spotting table corruption
becomes easier. Also, since the format is simpler, the chance for
serious data corruption is smaller.
mysqldump
also has a --single-transaction
option that
you can use to take a consistent snapshot without locking out other
clients.
To be able to recover your InnoDB
database to the present from the
binary backup described above, you have to run your MySQL server
with binary logging turned on. Then you can apply the binary log to the
backup database to achieve point-in-time recovery:
mysqlbinlog yourhostname-bin.123 | mysql
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 that were
present at the time of the crash. During recovery, mysqld
will
display output something like this:
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 that is not corrupted. After restoring the base backup, do the recovery from the binary log files.
In some cases of database corruption it is enough just to dump, drop,
and re-create one or a few corrupt tables. You can use the
CHECK TABLE
SQL statement to check whether a table is corrupt, although
CHECK TABLE
naturally cannot detect every possible kind of corruption.
You can use innodb_tablespace_monitor
to check the integrity of
the file space management inside the tablespace files.
In some cases, apparent database page corruption is actually due to the operating system corrupting its own file cache, and the data on disk may be okay. It is best first to try restarting your computer. It may eliminate errors that appeared to be database page corruption.
If there is database page corruption, you may want to dump
your tables from the database with SELECT INTO OUTFILE
,
and usually most of the data
is intact and correct. But the corruption may cause
SELECT * FROM tbl_name
or InnoDB
background operations to crash or assert, or even the InnoDB
roll-forward recovery to crash. Starting from MySQL
3.23.44, there is an InnoDB
variable that you can use to
force the InnoDB
storage engine to start up, and you can also
prevent background operations from running, so that
you will be able to dump your tables. For example, you can add the following
line to the [mysqld]
section of your option file before restarting the
server:
[mysqld] innodb_force_recovery = 4
Before MySQL 4.0, use this syntax instead:
[mysqld] set-variable = innodb_force_recovery=4
The allowable non-zero values for innodb_force_recovery
follow.
A larger number includes all precautions of lower numbers. If you are
able to dump your tables with an option value of at most 4, then you are
relatively safe that only some data on corrupt individual pages
is lost. A value of 6 is more dramatic, because database pages are left
in an obsolete state, which in turn may introduce more corruption
into B-trees and other database structures.
1
(SRV_FORCE_IGNORE_CORRUPT
)
Let the server run even if it detects a corrupt page; try to make
SELECT * FROM tbl_name
jump over corrupt index records and pages,
which helps in dumping tables.
2
(SRV_FORCE_NO_BACKGROUND
)
Prevent the main thread from running. If a crash would occur
in the purge operation, this prevents it.
3
(SRV_FORCE_NO_TRX_UNDO
)
Do not run transaction rollbacks after recovery.
4
(SRV_FORCE_NO_IBUF_MERGE
)
Prevent also insert buffer merge operations. If they would cause a
crash, better not do them; do not calculate table statistics.
5
(SRV_FORCE_NO_UNDO_LOG_SCAN
)
Do not look at undo logs when starting the database: InnoDB
will
treat even incomplete transactions as committed.
6
(SRV_FORCE_NO_LOG_REDO
)
Do not do the log roll-forward in connection with recovery.
The database must not otherwise be used with any of these options enabled! As a safety
measure, InnoDB
prevents users from doing INSERT
,
UPDATE
, or DELETE
when innodb_force_recovery
is set to
a value greater than 0.
Starting from MySQL 3.23.53 and 4.0.4, you are allowed to DROP
or
CREATE
a table even if forced recovery is used. If you know that a
certain table is causing a crash in rollback, you can drop it. You can use
this also to stop a runaway rollback caused by a failing mass import or
ALTER TABLE
. You can kill the mysqld
process and set
innodb_force_recovery
to 3
to bring your database up without
the rollback. Then DROP
the table that is causing the runaway
rollback.
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 present in 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 that 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 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 preceding description 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 of big log files is that crash recovery can take longer because there will be more logged information to apply to the database.
InnoDB
Database to Another Machine
On Windows, InnoDB
internally always stores database and
table names in lowercase. To move databases in a binary format
from Unix to Windows or from Windows to Unix, you should have all table
and database names in lowercase. A convenient way to accomplish this
on Unix is to add the following line to the [mysqld]
section of
your `my.cnf' before you start creating your databases and tables:
[mysqld] set-variable = lower_case_table_names=1
On Windows, lower_case_table_names
is set to 1
by default.
Like MyISAM
data files, 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 were listed in section 15.9 Backing Up and Recovering an InnoDB
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
to dump your tables on one machine and then import the dump
files on the other machine.
A performance tip is to switch off autocommit mode when you import data into your database, assuming that 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.
InnoDB
Transaction Model and Locking
In the InnoDB
transaction model, the goal has been to combine the
best properties of a multi-versioning database with traditional two-phase
locking. InnoDB
does locking on the row level and runs queries as
non-locking consistent reads by default, 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.
InnoDB
and AUTOCOMMIT
In InnoDB
, all user activity occurs inside a transaction. If the
autocommit mode is enabled, each SQL statement forms a
single transaction on its own. MySQL always starts a new connection
with autocommit enabled.
If the autocommit mode is switched off with SET AUTOCOMMIT = 0
,
then we can consider that a user always has a transaction open. An
SQL COMMIT
or ROLLBACK
statement ends the
current transaction and a new one 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
statement, on the other hand, cancels all
modifications made by the current transaction.
If the connection has autocommit enabled, the user can still
perform a multiple-statement transaction by starting it with an
explicit START TRANSACTION
or BEGIN
statement and ending it with
COMMIT
or ROLLBACK
.
InnoDB
and TRANSACTION ISOLATION LEVEL
In terms of the SQL:1992 transaction isolation levels,
the InnoDB
default is REPEATABLE READ
.
Starting from MySQL 4.0.5, InnoDB
offers all four different
transaction isolation levels described by the SQL standard.
You can set the default isolation level for all connections by using the
--transaction-isolation
option on the command line or in option files.
For example, you can set the option
in the [mysqld]
section of `my.cnf' like this:
[mysqld] 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 TRANSACTION
statement. Its syntax is as follows:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
Note that there are hyphens in the level names for the
--transaction-isolation
option, but not for the SET
TRANSACTION
statement.
The default behavior is to set the isolation level for the next (not
started) transaction. If you use the GLOBAL
keyword, the statement
sets the default transaction level globally for all new connections
created from that point on (but not existing connections).
You need the SUPER
privilege to do this. Using the SESSION
keyword sets the default transaction level for all future transactions
performed on the current connection.
Any client is free to change the session isolation level (even in the middle of a transaction), or the isolation level for the next transaction.
Before MySQL 3.23.50, SET TRANSACTION
had no effect
on InnoDB
tables. Before 4.0.5, only REPEATABLE READ
and SERIALIZABLE
were available.
You can query the global and session transaction isolation levels with these statements:
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 refers to
a lock that locks an index record and the gap before it.
A gap lock refers to a lock that only locks a gap before some
index record.
A detailed description of each isolation level in InnoDB
:
READ UNCOMMITTED
SELECT
statements are performed in a non-locking fashion, but a
possible earlier version of a record might be used. Thus, using this
isolation level, such reads are not ``consistent.'' This is also called
``dirty read.'' Other than that, this isolation level works like READ
COMMITTED
.
READ COMMITTED
A somewhat Oracle-like isolation level. All SELECT ... FOR UPDATE
and SELECT ... LOCK IN SHARE MODE
statements lock only the index
records, not the gaps before them, and thus allow free inserting of new
records next to locked records. UPDATE
and DELETE
statements
that use a unique index with a unique search condition lock only the index
record found, not the gap before it. In range-type UPDATE
and DELETE
statements, InnoDB
must set next-key or gap locks
and block insertions by other users to the gaps covered by the range. This
is necessary because ``phantom rows'' must be blocked for MySQL replication
and recovery to work.
Consistent reads behave as in Oracle: Each consistent read,
even within the same transaction, sets and reads its own fresh
snapshot.
See section 15.11.3 Consistent Non-Locking Read.
REPEATABLE READ
This is the default isolation level of InnoDB
.
SELECT ... FOR UPDATE
, SELECT ... LOCK IN SHARE MODE
,
UPDATE
, and DELETE
statements that use a unique index with a
unique search condition lock only the index record found, not the gap
before it.
With other search conditions, 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
SELECT
statements within the same transaction, these
SELECT
statements are consistent also with respect to each
other.
See section 15.11.3 Consistent Non-Locking Read.
SERIALIZABLE
This level is like REPEATABLE READ
, but all plain
SELECT
statements 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 that 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.
SELECT ... FOR UPDATE
and SELECT ... LOCK IN SHARE MODE
In some circumstances, a consistent read is not convenient.
For example, you might want to add a new row into your table child
,
and make sure that the child has a parent in table
parent
. The following example shows how to implement referential
integrity in your application code.
Suppose that you use a consistent read to read the table parent
and indeed see the parent of the child in the table. Can you safely
add the child row to table child
? No, because it may
happen that meanwhile some other user deletes the parent row
from the table parent
, without you being aware of it.
The solution is to perform the SELECT
in a locking
mode using 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.
A shared mode lock prevents others from updating or deleting
the row we have read. Also,
if the latest data belongs to a yet uncommitted transaction of another
client connection, we will wait until that transaction commits.
After we see that the preceding query returns
the parent 'Jones'
, we can safely add the child record
to the child
table and commit our transaction.
Let us look at another example: We have an integer counter field in
a table child_codes
that we use to assign
a unique identifier to each child added 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
two users of the database may then see the same value for the
counter, and a duplicate-key error will occur if two users attempt to add
children with the same identifier to the table.
Here, LOCK IN SHARE MODE
is not a good solution because if two
users read the counter at the same time, at least one of them
will end up in deadlock when attempting to update the counter.
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. The latter approach can be implemented as follows:
SELECT counter_field FROM child_codes FOR UPDATE; UPDATE child_codes SET counter_field = counter_field + 1;
A SELECT ... FOR UPDATE
reads 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.
Please note that the above is merely an example of how SELECT ... FOR
UPDATE
works. In MySQL, the specific task of generating a unique identifier
actually can be accomplished using only a single access to the table:
UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1); SELECT LAST_INSERT_ID();
The SELECT
statement merely retrieves the identifier information
(specific to the current connection). It does not access any table.
In row-level locking, InnoDB
uses an algorithm called ``next-key locking.''
InnoDB
does the row-level locking in such a way that when it searches
or scans an index of a table, it sets shared or exclusive locks
on the index records it encounters. Thus the row-level locks are
actually 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, 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 that you want to read and
lock all children from the child
table with an identifier value
larger than 100, with the intent of updating some column in the selected
rows later:
SELECT * FROM child WHERE id > 100 FOR UPDATE;
Suppose that there is an index on the id
column. The query will scan that
index starting from the first record where id
is bigger than 100.
If the locks set on the index records would not lock out inserts made
in the gaps, a new row might meanwhile be inserted to the table. If you
execute the same SELECT
within the same transaction, you would see a
new row in the result set returned by the query. This is contrary 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, the new ``phantom'' child would violate
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
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.
InnoDB
Suppose that you are running in 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. If another transaction deletes
a row and commits after your timepoint was assigned, you will
not see the row as having been deleted. Inserts and updates are treated
similarly.
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 | --------------------- 1 row in set
In this example, user A sees the row inserted by B only when B has committed the insert and A has committed as well, 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 either the READ COMMITTED
isolation level or a locking read:
SELECT * FROM t LOCK IN SHARE MODE;
InnoDB
A locking read, an UPDATE
, or a DELETE
generally set record locks on every index record that is scanned in
the processing of the SQL query. It does not matter if there are
WHERE
conditions in the query that would exclude the row
from the result set of the query. InnoDB
does not remember the exact
WHERE
condition, but only knows which index ranges were
scanned. The record locks are normally next-key locks that also block
inserts to the ``gap'' immediately before the record.
If the locks to be set are exclusive,
then InnoDB
always retrieves also the clustered index record and sets
a lock on it.
If you do not have indexes suitable for your query and MySQL has to scan the whole table to process the query, every row of the table will become locked, which in turn blocks all inserts by other users to the table. It is important to create good indexes so that your queries do not unnecessarily need to scan many rows.
SELECT ... FROM
is a consistent read, reading a snapshot of the
database and setting no locks unless the transaction isolation level is set
to SERIALIZABLE
. For SERIALIZABLE
level, this sets shared
next-key locks on the index records it encounters.
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, a shared
lock on the duplicate index record is set.
AUTO_INCREMENT
column
on a table, InnoDB
sets an exclusive lock on the end of the index
associated with the AUTO_INCREMENT
column.
In accessing the auto-increment counter, InnoDB
uses a specific table
lock mode AUTO-INC
where the lock lasts only to the end of the
current SQL statement, instead of to the end of the whole transaction.
See section 15.11.1 InnoDB
and AUTOCOMMIT
.
Before MySQL 3.23.50, SHOW TABLE STATUS
applied to a table
with an AUTO_INCREMENT
column sets an exclusive row-level lock
to the high end of the AUTO_INCREMENT
index. This means
also that SHOW TABLE STATUS
could cause a deadlock of transactions,
something that may surprise users. Starting from MySQL 3.23.50,
InnoDB
fetches the value of a previously initialized
AUTO_INCREMENT
column without setting any locks.
INSERT INTO T SELECT ... FROM S WHERE ...
sets an exclusive (non-next-key) lock on each row inserted into
T
. It does the search on S
as a consistent read, but
sets shared next-key locks on S
if MySQL binary logging is turned
on. InnoDB
has to set locks in the latter case: In
roll-forward recovery from a backup, every SQL statement has to be
executed in exactly the same way it was done originally.
CREATE TABLE ... SELECT ...
performs the SELECT
as a consistent read or with shared locks,
as 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 that has
to be updated.
UPDATE ... 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 that requires checking of the constraint condition
sets shared record-level locks on the records it looks at to check the
constraint. InnoDB
also sets these locks
in the case where the constraint fails.
LOCK TABLES
sets table locks, but it is the higher MySQL layer
above the InnoDB
layer that sets these locks. Beginning with MySQL
4.0.20 and 4.1.2, InnoDB
is aware of table locks if
innodb_table_locks=1
and AUTOCOMMIT=0
, and the MySQL
layer above InnoDB
knows about row-level locks. Before that,
the automatic deadlock detection of InnoDB
cannot detect deadlocks
where such table locks are involved. Also, since the higher MySQL layer
does not know about row-level locks, it is possible to get a table lock
on a table where another user currently has row-level locks. But that does
not put transaction integrity in danger.
See section 15.11.9 Deadlock Detection and Rollback.
See section 15.17 Restrictions on InnoDB
Tables.
MySQL begins each client connection with autocommit mode enabled by default. When autocommit is enabled, MySQL does a commit after each SQL statement if that statement did not return an error.
If you have the autocommit mode off and close a connection without calling an explicit commit of your transaction, then MySQL will roll back your transaction.
If an SQL statement returns an error, the commit/rollback behavior depends on the error. See section 15.16 Error Handling.
The following SQL statements (and any synonyms for them) cause an implicit commit of the current transaction in MySQL:
ALTER TABLE
, BEGIN
, CREATE INDEX
, DROP DATABASE
,
DROP INDEX
, DROP TABLE
, LOAD MASTER DATA
, LOCK
TABLES
, RENAME TABLE
, SET AUTOCOMMIT=1
, START
TRANSACTION
, TRUNCATE
, UNLOCK TABLES
.
CREATE TABLE
(this commits only if before MySQL 4.0.13 and MySQL
binary logging is used).
CREATE TABLE
statement in InnoDB
is processed as a single
transaction. This means that a ROLLBACK
from the user does not
undo CREATE TABLE
statements the user made during that
transaction.
InnoDB
automatically detects a deadlock of transactions and rolls back a
transaction or transactions to prevent the deadlock. Starting from
MySQL 4.0.5, InnoDB
tries 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. Prior 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.
Beginning with MySQL 4.0.20 and 4.1.2, InnoDB
is aware of
table locks if innodb_table_locks=1
(1 is the default), and the MySQL
layer above InnoDB
knows about row-level locks. Before that,
InnoDB
cannot detect deadlocks where a table lock set by a MySQL
LOCK TABLES
statement is involved, or if a lock set
by another storage engine than InnoDB
is involved. You have to resolve
these situations by setting the value of the innodb_lock_wait_timeout
system variable.
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 such it cannot know afterward which lock was
set by which SQL statement.
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 must 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 that 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 or deleted.
You can cope with deadlocks and reduce the likelihood of their occurrence with the following techniques:
SHOW INNODB STATUS
to determine the cause of the latest deadlock.
That can help you to tune your application to avoid deadlocks. This
strategy can be used as of MySQL 3.23.52 and 4.0.3, depending on your MySQL
series.
SELECT ... FOR UPDATE
or ... LOCK IN SHARE MODE
), try using a lower isolation
level such as READ COMMITTED
.
EXPLAIN SELECT
to determine which indexes the MySQL
server regards as the most appropriate 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
with transactional
tables, like InnoDB, is to set AUTOCOMMIT = 0
and not to call
UNLOCK TABLES
until you commit the transaction explicitly.
For example, if you need to write table t1
and read table t2
,
you can do this:
SET AUTOCOMMIT=0; LOCK TABLES t1 WRITE, t2 READ, ...; [do something with tables t1 and t2 here]; COMMIT; UNLOCK TABLES;Table-level locks make your transactions queue nicely, and deadlocks are avoided.
InnoDB
instant
deadlock detection algorithm also works in this case,
because the serializing lock is a row-level lock.
With MySQL table-level locks, the timeout method must be used to
resolve deadlocks.
AUTOCOMMIT=1
and MySQL's LOCK TABLES
command, InnoDB's internal table locks that were present from 4.0.20
to 4.0.23 can cause deadlocks. Starting from 4.0.22, you can set
innodb_table_locks=0
in `my.cnf' to fall back to the
old behavior and remove the problem.
4.0.24 does not set InnoDB table locks if AUTOCOMMIT=1
.
InnoDB
Performance Tuning TipsInnoDB
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 167th/second if the disk does not fool the operating system.
innodb_flush_log_at_trx_commit
to 0. InnoDB
tries to flush the log once per second anyway,
although the flush is not guaranteed.
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 of big log files is that recovery
time will be longer.
VARCHAR
column type instead of CHAR
if you are
storing variable-length strings or if the column may contain many
NULL
values. A CHAR(N)
column always takes N bytes to
store data, even if the string is shorter or its value is
NULL
. Smaller tables fit better in the buffer pool and reduce
disk I/O.
fsync()
and other similar methods is surprisingly slow.
The default method InnoDB
uses is the fsync()
function.
If you are not satisfied with the database write performance, you might
try setting innodb_flush_method
in `my.cnf' to
O_DSYNC
, although O_DSYNC
seems to be slower on most
systems.
InnoDB
, make sure that MySQL does not have
autocommit mode enabled because that would require a log flush to disk for
every insert.
To disable autocommit during your import operation, surround it with SET
AUTOCOMMIT
and COMMIT
statements:
SET AUTOCOMMIT=0; /* SQL import statements ... */ COMMIT;If you use the
mysqldump
option --opt
, you will get dump
files that are fast to import into an InnoDB
table, even without
wrapping them with the SET AUTOCOMMIT
and COMMIT
statements.
InnoDB
uses the insert
buffer to save disk I/O in inserts, but no such mechanism is used in a
corresponding rollback. 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 server 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 to use a special procedure.
See section 15.9.1 Forcing Recovery.
DROP TABLE + CREATE TABLE
to empty a
table, not DELETE FROM tbl_name
.
INSERT
syntax 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 valid for inserts into any table type, not just
InnoDB
.
UNIQUE
constraints on
secondary keys, starting from MySQL 3.23.52 and 4.0.3, you
can speed up table imports by temporarily turning off the uniqueness
checks during the import session:
SET UNIQUE_CHECKS=0;For big tables, this saves a lot of disk I/O because
InnoDB
can
use its insert buffer to write secondary index records in a batch.
FOREIGN KEY
constraints in your tables, starting
from MySQL 3.23.52 and 4.0.3, you can speed up table imports by turning the
foreign key checks off for a while in the import session:
SET FOREIGN_KEY_CHECKS=0;For big tables, this can save a lot of disk I/O.
[mysqld] query_cache_type = ON query_cache_size = 10MIn MySQL 4.0, the query cache works only with autocommit enabled. This restriction is removed in MySQL 4.1.1 and up.
SHOW INNODB STATUS
and the InnoDB
Monitors
Starting from MySQL 3.23.42, InnoDB
includes InnoDB
Monitors
that print information about the InnoDB
internal state. Starting from
MySQL 3.23.52 and 4.0.3, you can use the SQL statement SHOW INNODB
STATUS
to fetch the output of the standard InnoDB
Monitor to your
SQL client. The information is useful in performance tuning. If you are
using the mysql
interactive SQL client, the output is more readable
if you replace the usual semicolon statement terminator by \G
:
mysql> SHOW INNODB STATUS\G
Another way to use InnoDB
Monitors is to let them continuously write
data to the standard output of the server mysqld
. In this case,
no output is sent to clients. When switched on, InnoDB
Monitors
print data about every 15 seconds. Server output usually is directed
to the `.err' log in the MySQL data directory. This data is useful in
performance tuning. On Windows, you must start the server from a command
prompt in a console window with the --console
option if you want
to direct the output to the window rather than to the error log.
Monitor output includes information of the following types:
InnoDB
thread
To cause the standard InnoDB
Monitor to write to the standard
output of mysqld
, use the following SQL statement:
CREATE TABLE innodb_monitor(a INT) TYPE=InnoDB;
The monitor can be stopped by issuing the following statement:
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 only things
that matter are the table name innodb_monitor
and that it be an
InnoDB
table. The structure of the
table is not relevant at all for the InnoDB
Monitor. If you shut down
the server 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
statement to start the monitor.
This syntax may change in a future release.
In a similar way, you can start innodb_lock_monitor
, which is
otherwise the same as innodb_monitor
but also prints a
lot of lock information. A separate innodb_tablespace_monitor
prints a list of created file segments existing in the tablespace
and also validates the tablespace allocation data structures.
Starting from 3.23.44, there is innodb_table_monitor
with which
you can print the contents of the InnoDB
internal data dictionary.
A sample of InnoDB
Monitor output:
mysql> SHOW INNODB STATUS\G *************************** 1. row *************************** Status: ===================================== 030709 13:00:59 INNODB MONITOR OUTPUT ===================================== Per second averages calculated from the last 18 seconds ---------- SEMAPHORES ---------- OS WAIT ARRAY INFO: reservation count 413452, signal count 378357 --Thread 32782 has waited at btr0sea.c line 1477 for 0.00 seconds the semaphore: X-lock on RW-latch at 41a28668 created in file btr0sea.c line 135 a writer (thread id 32782) has reserved it in mode wait exclusive number of readers 1, waiters flag 1 Last time read locked in file btr0sea.c line 731 Last time write locked in file btr0sea.c line 1347 Mutex spin waits 0, rounds 0, OS waits 0 RW-shared spins 108462, OS waits 37964; RW-excl spins 681824, OS waits 375485 ------------------------ LATEST FOREIGN KEY ERROR ------------------------ 030709 13:00:59 Transaction: TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id 34831 inser ting 15 lock struct(s), heap size 2496, undo log entries 9 MySQL thread id 25, query id 4668733 localhost heikki update insert into ibtest11a (D, B, C) values (5, 'khDk' ,'khDk') Foreign key constraint fails for table test/ibtest11a: , CONSTRAINT `0_219242` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11b` (`A`, `D`) ON DELETE CASCADE ON UPDATE CASCADE Trying to add in child table, in index PRIMARY tuple: 0: len 4; hex 80000101; asc ....;; 1: len 4; hex 80000005; asc ....;; 2: len 4; hex 6b68446b; asc khDk;; 3: len 6; hex 0000114e0edc; asc ...N..;; 4: len 7; hex 00000000c3e0a7; asc .......;; 5: len 4; hex 6b68446b; asc khDk;; But in parent table test/ibtest11b, in index PRIMARY, the closest match we can find is record: RECORD: info bits 0 0: len 4; hex 8000015b; asc ...[;; 1: len 4; hex 80000005; a sc ....;; 2: len 3; hex 6b6864; asc khd;; 3: len 6; hex 0000111ef3eb; asc ...... ;; 4: len 7; hex 800001001e0084; asc .......;; 5: len 3; hex 6b6864; asc khd;; ------------------------ LATEST DETECTED DEADLOCK ------------------------ 030709 12:59:58 *** (1) TRANSACTION: TRANSACTION 0 290252780, ACTIVE 1 sec, process no 3185, OS thread id 30733 inser ting LOCK WAIT 3 lock struct(s), heap size 320, undo log entries 146 MySQL thread id 21, query id 4553379 localhost heikki update INSERT INTO alex1 VALUES(86, 86, 794,'aA35818','bb','c79166','d4766t','e187358f' ,'g84586','h794',date_format('2001-04-03 12:54:22','%Y-%m-%d %H:%i'),7 *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index symbole trx id 0 290252780 lock mode S waiting Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138; asc a a35818;; 1: *** (2) TRANSACTION: TRANSACTION 0 290251546, ACTIVE 2 sec, process no 3190, OS thread id 32782 inser ting 130 lock struct(s), heap size 11584, undo log entries 437 MySQL thread id 23, query id 4554396 localhost heikki update REPLACE INTO alex1 VALUES(NULL, 32, NULL,'aa3572','','c3572','d6012t','', NULL,' h396', NULL, NULL, 7.31,7.31,7.31,200) *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index symbole trx id 0 290251546 lock_mode X locks rec but not gap Record lock, heap no 324 RECORD: info bits 0 0: len 7; hex 61613335383138; asc a a35818;; 1: *** (2) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 0 page no 48310 n bits 568 table test/alex1 index symbole trx id 0 290251546 lock_mode X locks gap before rec insert intention waiting Record lock, heap no 82 RECORD: info bits 0 0: len 7; hex 61613335373230; asc aa 35720;; 1: *** WE ROLL BACK TRANSACTION (1) ------------ TRANSACTIONS ------------ Trx id counter 0 290328385 Purge done for trx's n:o < 0 290315608 undo n:o < 0 17 Total number of lock structs in row lock hash table 70 LIST OF TRANSACTIONS FOR EACH SESSION: ---TRANSACTION 0 0, not started, process no 3491, OS thread id 42002 MySQL thread id 32, query id 4668737 localhost heikki show innodb status ---TRANSACTION 0 290328384, ACTIVE 0 sec, process no 3205, OS thread id 38929 in serting 1 lock struct(s), heap size 320 MySQL thread id 29, query id 4668736 localhost heikki update insert into speedc values (1519229,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgjgjlhh gghggggghhjhghgggggghjhghghghghghhhhghghghjhhjghjghjkghjghjghjghjfhjfh ---TRANSACTION 0 290328383, ACTIVE 0 sec, process no 3180, OS thread id 28684 co mmitting 1 lock struct(s), heap size 320, undo log entries 1 MySQL thread id 19, query id 4668734 localhost heikki update insert into speedcm values (1603393,1, 'hgjhjgghggjgjgjgjgjggjgjgjgjgjgggjgjgjlh hgghggggghhjhghgggggghjhghghghghghhhhghghghjhhjghjghjkghjghjghjghjfhjf ---TRANSACTION 0 290328327, ACTIVE 0 sec, process no 3200, OS thread id 36880 st arting index read LOCK WAIT 2 lock struct(s), heap size 320 MySQL thread id 27, query id 4668644 localhost heikki Searching rows for update update ibtest11a set B = 'kHdkkkk' where A = 89572 ------- TRX HAS BEEN WAITING 0 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 0 page no 65556 n bits 232 table test/ibtest11a index PRIM ARY trx id 0 290328327 lock_mode X waiting Record lock, heap no 1 RECORD: info bits 0 0: len 9; hex 73757072656d756d00; asc supremum.;; ------------------ ---TRANSACTION 0 290328284, ACTIVE 0 sec, process no 3195, OS thread id 34831 ro llback of SQL statement ROLLING BACK 14 lock struct(s), heap size 2496, undo log entries 9 MySQL thread id 25, query id 4668733 localhost heikki update insert into ibtest11a (D, B, C) values (5, 'khDk' ,'khDk') ---TRANSACTION 0 290327208, ACTIVE 1 sec, process no 3190, OS thread id 32782 58 lock struct(s), heap size 5504, undo log entries 159 MySQL thread id 23, query id 4668732 localhost heikki update REPLACE INTO alex1 VALUES(86, 46, 538,'aa95666','bb','c95666','d9486t','e200498f ','g86814','h538',date_format('2001-04-03 12:54:22','%Y-%m-%d %H:%i'), ---TRANSACTION 0 290323325, ACTIVE 3 sec, process no 3185, OS thread id 30733 in serting 4 lock struct(s), heap size 1024, undo log entries 165 MySQL thread id 21, query id 4668735 localhost heikki update INSERT INTO alex1 VALUES(NULL, 49, NULL,'aa42837','','c56319','d1719t','', NULL, 'h321', NULL, NULL, 7.31,7.31,7.31,200) -------- FILE I/O -------- I/O thread 0 state: waiting for i/o request (insert buffer thread) I/O thread 1 state: waiting for i/o request (log thread) I/O thread 2 state: waiting for i/o request (read thread) I/O thread 3 state: waiting for i/o request (write thread) Pending normal aio reads: 0, aio writes: 0, ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0 Pending flushes (fsync) log: 0; buffer pool: 0 151671 OS file reads, 94747 OS file writes, 8750 OS fsyncs 25.44 reads/s, 18494 avg bytes/read, 17.55 writes/s, 2.33 fsyncs/s ------------------------------------- INSERT BUFFER AND ADAPTIVE HASH INDEX ------------------------------------- Ibuf for space 0: size 1, free list len 19, seg size 21, 85004 inserts, 85004 merged recs, 26669 merges Hash table size 207619, used cells 14461, node heap has 16 buffer(s) 1877.67 hash searches/s, 5121.10 non-hash searches/s --- LOG --- Log sequence number 18 1212842764 Log flushed up to 18 1212665295 Last checkpoint at 18 1135877290 0 pending log writes, 0 pending chkp writes 4341 log i/o's done, 1.22 log i/o's/second ---------------------- BUFFER POOL AND MEMORY ---------------------- Total memory allocated 84966343; in additional pool allocated 1402624 Buffer pool size 3200 Free buffers 110 Database pages 3074 Modified db pages 2674 Pending reads 0 Pending writes: LRU 0, flush list 0, single page 0 Pages read 171380, created 51968, written 194688 28.72 reads/s, 20.72 creates/s, 47.55 writes/s Buffer pool hit rate 999 / 1000 -------------- ROW OPERATIONS -------------- 0 queries inside InnoDB, 0 queries in queue Main thread process no. 3004, id 7176, state: purging Number of rows inserted 3738558, updated 127415, deleted 33707, read 755779 1586.13 inserts/s, 50.89 updates/s, 28.44 deletes/s, 107.88 reads/s ---------------------------- END OF INNODB MONITOR OUTPUT ============================ 1 row in set (0.05 sec)
Some notes on the output:
TRANSACTIONS
section reports lock waits, your
application may have lock contention. The output can also help to
trace the reasons for transaction deadlocks.
SEMAPHORES
section reports threads waiting for a semaphore and
statistics on how many times threads have needed a spin or a wait on a
mutex or a rw-lock semaphore. A large number of threads waiting for
semaphores may be a result of disk I/O, or contention problems inside
InnoDB
. Contention can be due to heavy parallelism of queries, or
problems in operating system thread scheduling. Setting
innodb_thread_concurrency
smaller than the default value of 8
can
help in such situations.
BUFFER POOL AND MEMORY
section gives you statistics on pages
read and written. You can calculate from these numbers how many data
file I/O operations your queries currently are doing.
ROW OPERATIONS
section shows what the main thread is doing.
Beginning with MySQL 4.0.19, InnoDB
sends diagnostic output to stderr
or files instead of stdout or fixed-size memory buffers, to avoid potential
buffer overflow errors. As a side effect, the output of SHOW INNODB
STATUS
is written to a status file every fifteen seconds. The name of the
file is `innodb_status.pid', where pid is the server
process ID. This file is created in the MySQL data directory. InnoDB
removes the file for a normal shutdown. If abnormal shutdowns have occurred,
instances of these status files may be present and must be removed manually.
Before removing them, you might want to examine them to see if they contain
useful information to the cause of abnormal shutdowns. Beginning with
MySQL 4.0.21, the `innodb_status.pid' file will only be created
if the configuration option innodb_status_file=1
is set.
Because InnoDB
is a multi-versioned database, it must keep information
about old versions of rows in the tablespace. This information is stored
in a data structure called a rollback segment after an analogous
data structure in Oracle.
Internally, InnoDB
adds two fields to each row stored in the database.
A 6-byte field indicates the transaction identifier for the last
transaction that inserted or updated the row. Also, a deletion
is treated internally 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, 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 needed only 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, including those
transactions that 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 the InnoDB
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 can it 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 that did the deletion.
In a scenario where the user inserts and deletes rows in smallish batches at about the same rate in the table, it is possible that the purge thread will start to lag behind, and the table grows bigger and bigger, making everything disk-bound and very slow. Even if the table would carry just 10 MB of useful data, it may grow to occupy 10 GB with all the dead rows. In such a case, it would be good to throttle new row operations, and allocate more resources for the purge thread.
The InnoDB transaction system maintains a list of transactions that
have delete-marked index records by UPDATE
or DELETE
operations. Let the length of this list be purge_lag.
Starting with MySQL/InnoDB-4.1.6 and 4.0.22, there is a startup option
and settable global variable innodb_max_purge_lag
, which is
zero by default. When this parameter is non-zero, InnoDB may delay new
row operations. When the purge_lag exceeds
innodb_max_purge_lag
, each INSERT
, UPDATE
and
DELETE
operation will be delayed by
purge_lag/innodb_max_purge_lag
*10-5 milliseconds. The
delay is computed in the beginning of a purge batch, every ten
seconds. The operations will not be delayed if purge cannot run
because of an old consistent read view that could see the rows to be
purged. A typical setting for a problematic workload might be 1
million, assuming that our transactions are small, only 100 bytes in
size, and we can allow 100 MB of unpurged rows in our tables.
MySQL stores its data dictionary information for tables in `.frm'
files in database directories. This is true for all MySQL storage engines.
But every InnoDB
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 an `.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. It is also the reason why
DROP DATABASE
did not work for InnoDB
type tables
before MySQL 3.23.44.
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, the index of the primary key
will be the clustered index.
If you do not define a PRIMARY KEY
for
your table, MySQL picks the first UNIQUE
index that has only
NOT NULL
columns as the primary key and
InnoDB
uses it as the clustered index.
If there is no such index in the table,
InnoDB
internally generates a clustered index
where the rows are ordered by the row ID that InnoDB
assigns
to the rows in such a table. The row ID is a 6-byte field that
increases monotonically 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. If a table is large, the clustered index architecture often saves a disk I/O when compared to the traditional solution. (In many databases, the data is traditionally stored on a different page from the index record.)
In InnoDB
, the records in non-clustered indexes (also called secondary
indexes) 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 use more space.
InnoDB
compares CHAR
and VARCHAR
strings
of different lengths such that the remaining length in the shorter
string is treated as if padded with spaces.
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 16KB. 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 order (ascending or descending),
the resulting index pages will be about 15/16 full.
If records are inserted in a random order, the pages will be from
1/2 to 15/16 full. If the fillfactor of an index page drops below 1/2,
InnoDB
tries 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
into secondary indexes happen in a relatively random order. This would
cause a lot of random disk I/O operations without a special mechanism used
in InnoDB
.
If an index record should be inserted to a non-unique secondary index,
InnoDB
checks whether the secondary index page is in the buffer
pool. If that is the case, InnoDB
does the insertion directly to
the index page. If the index page is not found in the buffer
pool, InnoDB
inserts the record to a special insert buffer structure.
The insert buffer is kept so small that it fits entirely in the buffer
pool, and insertions can be done very fast.
Periodically, the insert buffer is merged into the secondary index trees in the database. Often it is possible to merge several insertions to the same page of the index tree, saving disk I/O operations. It has been measured that the insert buffer can speed up insertions into a table up to 15 times.
If a table fits almost entirely in main memory, the fastest way
to perform queries on it is to use hash indexes. InnoDB
has an
automatic mechanism that monitors index searches made to the indexes
defined for a table. If InnoDB
notices that queries could
benefit from building a hash index, it does so automatically.
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 the
pattern of searches that InnoDB
observes for 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 for those pages of the index that are
often accessed.
In a sense, InnoDB
tailors itself through the adaptive hash index
mechanism to ample main memory, coming closer to the architecture of main
memory databases.
Records in InnoDB
tables have the following characteristics:
InnoDB
contains a header of six bytes. The header
is used to link consecutive records together, and also in row-level
locking.
InnoDB
stores fixed-length character columns such as
CHAR(10)
in a fixed-length format.
InnoDB
truncates trailing spaces
from VARCHAR
columns.
Note that MySQL may internally convert CHAR
columns to
VARCHAR
. See section 13.2.6.1 Silent Column Specification Changes.
NULL
value reserves 1 or 2 bytes in the record directory.
Besides that, an SQL NULL
value reserves zero bytes in the data
part of the record if stored in a variable length column.
In a fixed-length column, it reserves the fixed length of the column
in the data part of the record.
The motivation behind reserving the fixed space for NULL
values
is that then an update of the column from NULL
to a
non-NULL
value can be done in place and does not cause
fragmentation of the index page.
InnoDB
uses simulated asynchronous disk I/O: InnoDB
creates a number of
threads to take care of I/O operations, such as read-ahead.
There are two read-ahead heuristics in InnoDB
:
InnoDB
notices that the access pattern to a
segment in the tablespace is sequential, it posts in
advance a batch of reads of database pages to the I/O system.
InnoDB
notices that some area in a tablespace
seems to be in the process of being fully read into the buffer pool, it
posts the remaining reads to the I/O system.
Starting from MySQL 3.23.40b, 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 before writing pages to a data file, InnoDB
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 does InnoDB
write the pages to their proper
positions in the data file. If the operating system crashes in the
middle of a page write, InnoDB
later will find a good
copy of the page from the doublewrite buffer during recovery.
Starting from MySQL 3.23.41, you can use raw disk partitions as tablespace data files. By using a raw disk, you can perform non-buffered I/O on Windows and on some Unix systems without filesystem overhead, which might improve performance.
When you create a new data file, you must put the keyword newraw
immediately after the data file size in innodb_data_file_path
.
The partition must be at least as large as the size that you specify.
Note that 1MB in InnoDB
is 1024 * 1024 bytes, whereas 1MB usually
means 1,000,000 bytes in disk specifications.
[mysqld] innodb_data_home_dir= innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
The next time you start the server, InnoDB
notices the newraw
keyword and initializes the new partition. However, do not create or change
any InnoDB
tables yet. Otherwise, when you next restart the server,
InnoDB
will reinitialize the partition and your changes will be lost.
(Starting from 3.23.44, as a safety measure InnoDB
prevents users from
modifying data when any partition with newraw
is specified.)
After InnoDB
has initialized the new partition, stop the server, change
newraw
in the data file specification to raw
:
[mysqld] innodb_data_home_dir= innodb_data_file_path=/dev/hdd1:5Graw;/dev/hdd2:2Graw
Then restart the server and InnoDB
will allow changes to be made.
On Windows, starting from 4.1.1, you can allocate a disk partition as a data file like this:
[mysqld] innodb_data_home_dir= innodb_data_file_path=//./D::10Gnewraw
The `//./' corresponds to the Windows syntax of `\\.\' for accessing physical drives.
When you use raw disk partitions, be sure that they have permissions that allow read and write access by the account used for running the MySQL server.
The data files you define in the configuration file form the tablespace of
InnoDB
. The files are simply concatenated to form the tablespace.
There is no striping in use. Currently you cannot define where in the
tablespace your tables will be allocated. However, in a newly created
tablespace, InnoDB
allocates space starting from the first
data file.
The tablespace consists of database pages with a default size of 16KB.
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 confusing because it
actually contains many segments in the tablespace.
Two segments are allocated for each index in InnoDB
. 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 ask for available free space in the tablespace by issuing
a SHOW TABLE STATUS
, InnoDB
reports the extents that 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 whether that frees
individual pages or extents to the tablespace, so that the freed
space becomes 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 will be physically removed only in an
(automatic) purge operation after they are no longer needed in
transaction rollback or consistent read.
If there are random insertions into or deletions from the indexes of a table, the indexes may become fragmented. Fragmentation means that the physical ordering of the index pages on the disk is not close to the index ordering of the records on the pages, or that there are many unused pages in the 64-page blocks that were allocated to the index.
A symptom of fragmentation is that a table takes more space than it 'should take'. How much exactly is that, is difficult to determine. All InnoDB data and indexes are stored in B-trees, and their fillfactor may vary 50 % - 100 %. Another symptom of fragmentation is that a table scan:
SELECT COUNT(*) FROM t WHERE a_non_indexed_column <> 12345;
takes more time than 'it should take'. (Above we are fooling the SQL optimizer to scan the clustered index, not a secondary index.) Most disks can read 10 - 50 MB/s. That can be used to estimate how fast a table scan should run.
It can speed up index scans if you periodically perform a ``null''
ALTER TABLE
operation:
ALTER TABLE tbl_name TYPE=InnoDB
That causes MySQL to rebuild the table. Another way to perform a
defragmention operation is to use mysqldump
to dump the table to a text
file, drop the table, and reload it from the dump file.
If the insertions to an index are always ascending and records are deleted
only from the end, the InnoDB
file space management algorithm
guarantees that fragmentation in the index will not occur.
Error handling in InnoDB
is not always the same as specified in the
SQL standard. According to the 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
items describe how InnoDB
performs error handling:
Table is full
error
and InnoDB
rolls back the SQL statement.
InnoDB
to roll back the whole transaction.
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.
InnoDB
storage engine level), and
they roll back the corresponding SQL statement.
During such implicit rollbacks, as well as during the explicit ROLLBACK
SQL command, SHOW PROCESSLIST
will display "Rolling back" in the
State
column for the connection (starting from MySQL 4.1.8).
InnoDB
Error Codes
The following is a non-exhaustive list of common
InnoDB
-specific errors that you may encounter, with information
about why they occur and how to resolve the problem.
1005 (ER_CANT_CREATE_TABLE
)
errno
150, table creation failed because a foreign key
constraint was not correctly formed.
1016 (ER_CANT_OPEN_FILE
)
InnoDB
table from the InnoDB
data files though
the `.frm' file for the table exists.
See section 15.18.1 Troubleshooting InnoDB
Data Dictionary Operations.
1114 (ER_RECORD_FILE_FULL
)
InnoDB
has run out of free space in the tablespace.
You should reconfigure the tablespace to add a new data file.
1205 (ER_LOCK_WAIT_TIMEOUT
)
1213 (ER_LOCK_DEADLOCK
)
1216 (ER_NO_REFERENCED_ROW
)
1217 (ER_ROW_IS_REFERENCED
)
To print the meaning of an operating system error number,
use the perror
program that comes with the MySQL distribution.
The following table provides a list of some common Linux system error codes. For a more complete list, see Linux source code.
1 (EPERM
)
2 (ENOENT
)
3 (ESRCH
)
4 (EINTR
)
5 (EIO
)
6 (ENXIO
)
7 (E2BIG
)
8 (ENOEXEC
)
9 (EBADF
)
10 (ECHILD
)
11 (EAGAIN
)
12 (ENOMEM
)
13 (EACCES
)
14 (EFAULT
)
15 (ENOTBLK
)
16 (EBUSY
)
17 (EEXIST
)
18 (EXDEV
)
19 (ENODEV
)
20 (ENOTDIR
)
21 (EISDIR
)
22 (EINVAL
)
23 (ENFILE
)
24 (EMFILE
)
25 (ENOTTY
)
26 (ETXTBSY
)
27 (EFBIG
)
28 (ENOSPC
)
29 (ESPIPE
)
30 (EROFS
)
31 (EMLINK
)
The following table provides a list of some common Windows system error codes. For a complete list see the Microsoft website.
1 (ERROR_INVALID_FUNCTION
)
2 (ERROR_FILE_NOT_FOUND
)
3 (ERROR_PATH_NOT_FOUND
)
4 (ERROR_TOO_MANY_OPEN_FILES
)
5 (ERROR_ACCESS_DENIED
)
6 (ERROR_INVALID_HANDLE
)
7 (ERROR_ARENA_TRASHED
)
8 (ERROR_NOT_ENOUGH_MEMORY
)
9 (ERROR_INVALID_BLOCK
)
10 (ERROR_BAD_ENVIRONMENT
)
11 (ERROR_BAD_FORMAT
)
12 (ERROR_INVALID_ACCESS
)
13 (ERROR_INVALID_DATA
)
14 (ERROR_OUTOFMEMORY
)
15 (ERROR_INVALID_DRIVE
)
16 (ERROR_CURRENT_DIRECTORY
)
17 (ERROR_NOT_SAME_DEVICE
)
18 (ERROR_NO_MORE_FILES
)
19 (ERROR_WRITE_PROTECT
)
20 (ERROR_BAD_UNIT
)
21 (ERROR_NOT_READY
)
22 (ERROR_BAD_COMMAND
)
23 (ERROR_CRC
)
24 (ERROR_BAD_LENGTH
)
25 (ERROR_SEEK
)
26 (ERROR_NOT_DOS_DISK
)
27 (ERROR_SECTOR_NOT_FOUND
)
28 (ERROR_OUT_OF_PAPER
)
29 (ERROR_WRITE_FAULT
)
30 (ERROR_READ_FAULT
)
31 (ERROR_GEN_FAILURE
)
32 (ERROR_SHARING_VIOLATION
)
33 (ERROR_LOCK_VIOLATION
)
34 (ERROR_WRONG_DISK
)
36 (ERROR_SHARING_BUFFER_EXCEEDED
)
38 (ERROR_HANDLE_EOF
)
39 (ERROR_HANDLE_DISK_FULL
)
87 (ERROR_INVALID_PARAMETER
)
innodb_file_per_table
in
`my.cnf' or `my.ini', then this is Bug #8021, and a workaround
is to put the line innodb_flush_method=unbuffered
to your `my.cnf' or `my.ini'.)
112 (ERROR_DISK_FULL
)
123 (ERROR_INVALID_NAME
)
1450 (ERROR_NO_SYSTEM_RESOURCES
)
InnoDB
TablesBLOB
and TEXT
columns,
is slightly less than half of a database page. That is, the maximum row
length is about 8000 bytes. LONGBLOB
and LONGTEXT
columns
must be less than 4GB, and the total row length, including also BLOB
and TEXT
columns, must be less than 4GB. InnoDB
stores
the first 512 bytes of a BLOB
or TEXT
column in the row,
and the rest into separate pages.
InnoDB
log files must be less than 4GB.
InnoDB
tables do not support FULLTEXT
indexes.
InnoDB
tables do not support spatial column types.
ANALYZE TABLE
counts cardinality
by doing 10 random
dives to each of the index trees and updating index cardinality
estimates accordingly. Note that because these are only estimates,
repeated runs of ANALYZE TABLE
may produce different numbers.
This makes ANALYZE TABLE
fast on InnoDB
tables but not 100%
accurate as it doesn't take all rows into account.
MySQL uses index cardinality estimates only in join optimization. If
some join is not optimized in the right way, you may try using
ANALYZE TABLE
. In the few cases that ANALYZE TABLE
doesn't
produce values good enough for your particular tables, you can use
FORCE INDEX
with your queries to force the usage of a particular
index, or set max_seeks_for_key
to ensure that MySQL prefers index
lookups over table scans. See section 5.2.3 Server System Variables. See section A.6 Optimizer-Related Issues.
InnoDB
always stores database and table names
internally in lowercase. To move databases in binary format
from Unix to Windows or from Windows to Unix, you should have all database
and table names in lowercase.
mysql
database from
MyISAM
to InnoDB
tables! This is an unsupported operation.
If you do this, MySQL
will not restart until you restore the old system tables from a backup
or re-generate them with the mysql_install_db
script.
InnoDB
does not keep an internal count of rows in a table. (This
would actually be somewhat complicated because of multi-versioning.)
To process a SELECT COUNT(*) FROM T
statement, InnoDB
must
scan an index of the table, which will take some time if the index
is not entirely in the buffer pool. To get a fast count, you have to
use a counter table you create yourself and let your application
update it according to the inserts and deletes it does. If your table
does not change often, using the MySQL query cache is a good
solution.
SHOW TABLE STATUS
also can be used if an approximate row count is
sufficient.
See section 15.12 InnoDB
Performance Tuning Tips.
AUTO_INCREMENT
column, you must always define an index for
the table, and that index must contain just the AUTO_INCREMENT
column. In MyISAM
tables, the AUTO_INCREMENT
column may
be part of a multi-column index.
InnoDB
does not support the AUTO_INCREMENT
table option for
setting the initial sequence value in a
CREATE TABLE
or ALTER TABLE
statement.
To set the value with InnoDB
, insert a dummy row with a value
one less and delete that dummy row, or insert the first row with an
explicit value specified.
InnoDB
may reuse an old
value for an AUTO_INCREMENT
column (that is, a value that was
assigned to an old transaction that was rolled back).
AUTO_INCREMENT
column runs out of values, InnoDB
wraps a BIGINT
to -9223372036854775808
and BIGINT
UNSIGNED
to 1
. However, BIGINT
values have 64 bits, so do
note that if you were to insert one million rows per second, it would still
take nearly three hundred thousand years before BIGINT
reached its upper bound.
With all other integer type columns, a duplicate-key error will result.
This is similar to how MyISAM
works, because it is mostly general MySQL
behavior and not about any storage engine in particular.
DELETE FROM tbl_name
does not regenerate the table but
instead deletes all rows, one by one.
TRUNCATE tbl_name
is mapped to DELETE FROM tbl_name
for InnoDB
and doesn't reset the AUTO_INCREMENT
counter.
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 optimization.
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.
LOCK TABLES
operation
does not know about InnoDB
row-level locks set by
completed SQL statements. This means that you can get a table lock on
a table even if there still exist transactions by other users who 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.
LOCK
TABLES
operation acquires two locks on each table if
innodb_table_locks=1
. (1 is the default.)
In addition to a table lock on the MySQL
layer, it will also acquire an InnoDB
table lock. Older
versions of MySQL do not acquire InnoDB
table locks. Beginning
with MySQL 4.0.22 and 4.1.7, the old behavior can be selected by
setting innodb_table_locks=0
. If no InnoDB
table lock
is acquired, LOCK TABLES
will complete even if some records of
the tables are being locked by other transactions.
InnoDB
locks held by a transaction will be released when the
transaction is committed or aborted. Thus, it does not make much
sense to invoke LOCK TABLES
on InnoDB
tables in
AUTOCOMMIT=1
mode, because the acquired InnoDB
table
locks would be released immediately.
LOCK TABLES
in MySQL performs an
implicit COMMIT
and UNLOCK TABLES
. An InnoDB variant of
LOCK TABLES
has been planned that can be executed in the middle
of a transaction.
LOAD TABLE FROM MASTER
statement for setting up replication
slave servers does not yet work for InnoDB
tables. A workaround
is to alter the table to MyISAM
on the master, do then the load,
and after that alter the master table back to InnoDB
.
InnoDB
is 16KB. By recompiling the
code, you can set it to values ranging from 8KB to 64KB.
You have to update the values of UNIV_PAGE_SIZE
and
UNIV_PAGE_SIZE_SHIFT
in the `univ.i' source file.
InnoDB
Troubleshootingmysqld_safe
wrapper or as a Windows service.
You will then see what mysqld
prints to the command prompt
window, and you have a better grasp of what is going on.
On Windows, you must start the server with the `--console'
option to direct the output to the console window.
InnoDB
Monitors to obtain information about a problem.
If the problem is performance-related, or your server appears to be
hung, you should use innodb_monitor
to print information
about the internal state of InnoDB
. If the problem is with locks, use
innodb_lock_monitor
. If the problem is in creation of tables or
other data dictionary operations, use innodb_table_monitor
to
print the contents of the InnoDB
internal data dictionary.
CHECK TABLE
on that
table.
InnoDB
Data Dictionary Operations
A specific issue with tables is that the MySQL server keeps data
dictionary information in `.frm' files it stores in the database
directories, while InnoDB
also stores the information into its own
data dictionary inside the tablespace files.
If you move `.frm' files around, or use DROP DATABASE
in
MySQL versions before 3.23.44, or the server crashes in the middle of a
data dictionary operation, the `.frm' files may end up
out of sync with the InnoDB
internal data dictionary.
A symptom of an out-of-sync data dictionary is that a CREATE TABLE
statement fails. If this occurs, you should look in the server's error
log. If the log says that the table already exists inside the InnoDB
internal data dictionary, you have an orphaned table inside the InnoDB
tablespace files that has no corresponding `.frm' file. The error message
looks like this:
InnoDB: Error: table test/parent already exists in InnoDB internal InnoDB: data dictionary. Have you deleted the .frm file InnoDB: and not used DROP TABLE? Have you used DROP DATABASE InnoDB: for InnoDB tables in MySQL version <= 3.23.43? InnoDB: See the Restrictions section of the InnoDB manual. InnoDB: You can drop the orphaned table inside InnoDB by InnoDB: creating an InnoDB table with the same name in another InnoDB: database and moving the .frm file to the current database. InnoDB: Then MySQL thinks the table exists, and DROP TABLE will InnoDB: succeed.
You can drop the orphaned table by following the instructions given in the error message.
Another symptom of an out-of-sync data dictionary is that MySQL prints an error that it cannot open an `.InnoDB' file:
ERROR 1016: Can't open file: 'child2.InnoDB'. (errno: 1)
In the error log you will find a message like this:
InnoDB: Cannot find table test/child2 from the internal data dictionary InnoDB: of InnoDB though the .frm file for the table exists. Maybe you InnoDB: have deleted and recreated InnoDB data files but have forgotten InnoDB: to delete the corresponding .frm files of InnoDB tables?
This means that there is an orphaned `.frm' file without a
corresponding table inside InnoDB
. You can drop the orphaned
`.frm' file by deleting it manually.
If MySQL crashes in the middle of an ALTER TABLE
operation, you
may end up with an orphaned temporary table inside the InnoDB
tablespace. With innodb_table_monitor
you see a table whose
name is `#sql-...'. Starting from MySQL 4.0.6, you can perform
SQL statements also on tables whose name contains the character `#'
if you enclose the name in backticks.
Thus, you can drop such an orphaned table like any other orphaned
table with the method described above. Note that to copy or rename a file
in the Unix shell, you need to put the file name in double quotes if the
file name contains `#'.
Older MySQL versions did not allow accessing any
table with a name containing `#'. The solution in older MySQL
versions is to use a special InnoDB mechanism available starting from
MySQL 3.23.48. When you have an orphaned table `#sql-id' inside
the tablespace, you can cause InnoDB
to rename it to
`rsql-id_recover_innodb_tmp_table' with the following statement:
CREATE TABLE `rsql-id_recover_innodb_tmp_table`(...) TYPE=InnoDB;
MySQL Cluster uses the new NDB Cluster
storage engine to enable running
several MySQL servers in a cluster.
The NDB Cluster
storage engine is available in BitKeeper from MySQL
release 4.1.2, and in binary releases from MySQL-Max 4.1.3.
Currently supported operating systems are Linux, Mac OS X, and Solaris.
We are working to make NDB Cluster
run on all operating systems
supported by MySQL, including Windows.
This chapter represents work in progress. Other documents describing MySQL Cluster can be found at http://www.mysql.com/cluster/.
You may also wish to subscribe to the MySQL Cluster mailing list. See http://lists.mysql.com/. You may also find the MySQL forums at http://forums.mysql.com/to be useful.
MySQL Cluster
is a new technology to enable clustering of in-memory
databases in a share-nothing system. The share-nothing architecture allows
the system to work with very inexpensive hardware, and without any specific
requirements on hardware or software. It also does not have any single
point of failure because each component has its own memory and disk.
MySQL Cluster integrates the standard MySQL server with an
in-memory clustered storage engine called NDB
. In our
documentation, the term NDB
refers to the
part of the setup that is specific to the storage engine, whereas
MySQL Cluster
refers to the combination
of MySQL and the new storage engine.
A MySQL Cluster consists of a set of computers, each running a number of processes including MySQL servers, storage nodes for NDB Cluster, management servers and (possibly) specialized data access programs. All these programs work together to form MySQL Cluster. When data is stored in the NDB Cluster storage engine, the tables are stored in the storage nodes for NDB Cluster. Such tables are directly accessible from all other MySQL servers in the cluster. Thus, in a payroll application storing data in a cluster, if one application updates the salary of an employee, all other MySQL servers that query this data can see the change immediately.
The data stored in the storage nodes for MySQL Cluster can be mirrored; the cluster can handle failures of individual storage nodes with no other impact than that a number of transactions are aborted due to losing the transaction state. Since transactional applications are expected to handle transaction failure, this should not be a source of problems.
By bringing MySQL Cluster to the Open Source world, MySQL makes clustered data management with high availability, high performance, and scalability available to all who need it.
NDB
is an in-memory storage engine offering high-availability
and data-persistence features.
The NDB
storage engine can be configured with a range of failover and
load-balancing options, but it is easiest to start with the storage
engine at the cluster level. MySQL Cluster's NDB
storage engine
contains a complete set of data, dependent only on other data within
the cluster itself.
We will describe how to set up a MySQL Cluster consisting of an
NDB
storage engine and some MySQL servers.
The cluster portion of MySQL Cluster is currently configured independently
of the MySQL servers. In a MySQL Cluster, each part of the cluster
is considered to be a node
.
Note: A node is in many contexts a computer, but for MySQL Cluster it is a process. There can be any number of nodes on a single computer.
Each node has a type, and there can be multiple nodes of each type in a MySQL Cluster. In a minimal MySQL Cluster configuration, there will be at least three nodes:
MGM
) node: The role of this type of node is to
manage the other nodes within the MySQL Cluster, such as providing
configuration data, starting and stopping nodes, running backup, and so forth.
Because this node type manages the configuration of the other nodes, a
node of this type should be started first, before any other
node. With a running cluster, the MGM node does not necessarily have to
be running all the time. A MGM node is started with the command
ndb_mgmd
; for this reason NDB_MGMD is provided as an alias for
MGM when configuring the cluster.
DB
) node: This is the type of node that
manages and stores the database itself. There are as many DB nodes
as you have replicas times the number of fragments. For example, with
two replicas, each having two fragments, you will need four DB nodes.
It is not necessary to have more than one replica, so a minimal
MySQL Cluster may contain just one DB node. A DB node is started with the
command ndbd
, and so NDBD is provided as an alias for
DB when configuring the cluster.
API
) node: This is the client node that will access
the cluster. In the case of MySQL Cluster, a client node is a traditional
MySQL server that uses the NDB Cluster
storage engine, enabling
access to clustered tables. Basically, the MySQL server acts as a client
of the NDB cluster. Applications using the NDB API directly are also
considered API nodes. Since a MySQL server is typically started with the
command mysqld
or mysqld_safe
, MYSQLD is provided as
an alias for API when configuring the cluster.
Cluster processes are also referred to as cluster nodes. Configuration of the cluster involves configuring each individual node in the cluster and setting up individual communication links between nodes. MySQL Cluster is currently designed with the intention that storage nodes are homogeneous in terms of processor power, memory space, and communication bandwidth. In addition, in order to provide a single point of configuration, all configuration data for the cluster as a whole is located in one configuration file.
The management server manages the cluster configuration file and the cluster log. Each node in the cluster retrieves the configuration data from the management server, and so requires a way to determine where the management server resides. When interesting events occur in the storage nodes, the nodes transfer information about these events to the management server, which then writes the information to the cluster log.
In addition, there can be any number of clients to the cluster. These are of two types.
A MySQL server that is part of a MySQL Cluster differs in only one
respect from a normal (non-clustered) MySQL server, employing the
NDBCLUSTER
) storage engine. This engine is also referred to
simply as NDB
, and the two forms of the name are synonymous.
In order to avoid unnecessary resources allocation, the server is
configured by default with the NDB
storage engine disabled. To
enable NDB
, you will need to modify the server's `my.cnf'
configuration file.
Since the MySQL server is a part of the cluster, it will also need to
know how to access an MGM node in order to obtain the cluster
configuration data. The default behavior is to look for the MGM node on
localhost
. However, should you need to specify its location
elsewhere, this is can be done in `my.cnf' or on the MySQL server
command line. Before the NDB
storage engine can be used, at
least one MGM node must be operational, as well as any desired DB
nodes.
NDB
, the Cluster storage engine, is available in binary
distributions beginning with MySQL-Max 4.1.3 for Linux, Mac OS X, and
Solaris. It is not yet supported on Windows, but we intend to make it
available for win32 platforms in the near future.
If you choose to build from a source tarball or the MySQL 4.1 BitKeeper
tree, be sure to use the --with-ndbcluster
option when running
configure
. You can instead use the
BUILD/compile-pentium-max
build script. Note that this script
includes OpenSSL, so you must have or obtain OpenSSL to build
successfully; otherwise you will need to modify
compile-pentium-max
to exclude this requirement. Of course, you
can also just follow the standard instructions for compiling your own
binaries, then perform the usual tests and installation procedure.
See section 2.8.3 Installing from the Development Source Tree.
In the next few sections, we assume that you are familiar with installing MySQL, and here we cover only the differences between configuring MySQL Cluster and configuring MySQL without clustering. (See section 2 Installing MySQL if you require more information about the latter.)
You will find Cluster configuration easiest if you have have all MGM and DB nodes running first; this is likely to be the most time-consuming part of the configuration. Editing the `my.cnf' file is fairly straightforward, and this section will cover only any differences from configuring MySQL without clustering.
In order to familiarize you with the basics, we will describe the simplest possible configuration for a functional MySQL Cluster. After this, you should be able to design your desired setup from the information provided in the other relevant sections of this chapter.
First, you need to create a configuration directory, for example
`/var/lib/mysql-cluster', by executing the following command as
root
:
shell> mkdir /var/lib/mysql-cluster
In this directory, create a file named `config.ini' with the
following information, substituting appropriate values for
HostName
and DataDir
as necessary for your system.
# file "config.ini" - showing minimal setup consisting of 1 DB node, # 1 management server, and 3 MySQL servers. # The empty default sections are not required, and are shown only for # the sake of completeness. # Storage nodes are required to provide a hostname but MySQL Servers # are not. # If you don't know the hostname for your machine, use localhost. # The DataDir parameter also has a default value, but it is recommended to # set it explicitly. # NDBD, MYSQLD, and NDB_MGMD are aliases for DB, API, and MGM respectively # [NDBD DEFAULT] NoOfReplicas= 1 [MYSQLD DEFAULT] [NDB_MGMD DEFAULT] [TCP DEFAULT] [NDB_MGMD] HostName= myhost.example.com [NDBD] HostName= myhost.example.com DataDir= /var/lib/mysql-cluster [MYSQLD] [MYSQLD] [MYSQLD]
You can start the management server as follows:
shell> cd /var/lib/mysql-cluster shell> ndb_mgmd
Then start a single DB node by running ndbd
. When starting
ndbd
for a given DB node for the very first time, you should
use the --initial
option:
shell> ndbd --initial
For subsequent ndbd
starts, you will generally not want to use
--initial
:
shell> ndbd
This is because the --initial
option will delete all existing
data and log files (as well as all table metadata) for this storage
node and create new ones.
By default, ndbd
will look for the management server at
localhost
at port 1186. (Prior to MySQL 4.1.8, the default port
was 2200.)
Note: If you have installed MySQL from a binary tarball, you
will need to specify the path of the ndb_mgmd
and ndbd
servers explicitly. (Normally, these will be found in
`/usr/local/mysql/bin'.)
Finally, go to the MySQL data directory (usually `/var/lib/mysql'
or `/usr/local/mysql/data'), and make sure that the `my.cnf'
file contains the option necessary to enable the NDB
storage
engine:
[mysqld] ndbcluster
You can start the MySQL server as usual:
shell> mysqld_safe --user=mysql &
Wait a moment to make sure the MySQL server is running properly. If you
see the notice mysql ended
, check the server's `.err' file
to find out what went wrong.
If all has gone well so far, you can start using the cluster:
shell> mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 4.1.7 Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> SHOW ENGINES; +------------+---------+------------------------------------------------------------+ | Engine | Support | Comment | +------------+---------+------------------------------------------------------------+ ... | NDBCLUSTER | DEFAULT | Clustered, fault-tolerant, memory-based tables | | NDB | YES | Alias for NDBCLUSTER | ... mysql> USE test; Database changed mysql> CREATE TABLE ctest (i INT) ENGINE=NDBCLUSTER; Query OK, 0 rows affected (0.09 sec) mysql> SHOW CREATE TABLE ctest \G *************************** 1. row *************************** Table: ctest Create Table: CREATE TABLE `ctest` ( `i` int(11) default NULL ) ENGINE=ndbcluster DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
To check that your nodes were set up properly, start the management client as shown:
shell> ndb_mgm
You can then use the SHOW
command from within the management
client in order to obtain a report on the cluster's status:
NDB> SHOW Cluster Configuration --------------------- [ndbd(NDB)] 1 node(s) id=2 @127.0.0.1 (Version: 3.5.3, Nodegroup: 0, Master) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (Version: 3.5.3) [mysqld(API)] 3 node(s) id=3 @127.0.0.1 (Version: 3.5.3) id=4 (not connected, accepting connect from any host) id=5 (not connected, accepting connect from any host)
At this point, you have successfully set up a working MySQL Cluster.
You can store data in the cluster by using any table created with
ENGINE=NDBCLUSTER
or its alias ENGINE=NDB
.
Configuring MySQL Cluster requires working with two files:
We are continuously making improvements in Cluster configuration and attempting to simplify this process. While we strive to maintain backward compatibility, there may be times when introduce an incompatible change. In such cases we will try to let Cluster users know in advance if a change is not backward compatible. If you find such a change which we have not documented, please use our Bugs Database to report it.
In order to support MySQL Cluster, you will need to update `my.cnf' as shown in the example below.
From version 4.1.8 some simplifications in `my.cnf' were made,
including new sections for the ndbcluster
executables. However,
these should not be confused with those occurring in `config.ini'
files. As always, you may specify these parameters when invoking those
executables from the command line.
# my.cnf # example additions to my.cnf for MySQL Cluster # (valid from 4.1.8) # enable ndbcluster storage engine, and provide connectstring for # management server host (default port is 1186) [mysqld] ndbcluster ndb-connectstring=ndb_mgmd.mysql.com # provide connectstring for management server host (default port: 1186) [ndbd] connect-string=ndb_mgmd.mysql.com # provide connectstring for management server host (default port: 1186) [ndb_mgm] connect-string=ndb_mgmd.mysql.com # provide location of cluster configuration file [ndb_mgmd] config-file=/etc/config.ini
(For more information on connectstrings, see
section 16.3.4.2 The MySQL Cluster connectstring
.)
# my.cnf # example additions to my.cnf for MySQL Cluster # (will work on all versions) # enable ndbcluster storage engine, and provide connectstring for management # server host to the default port 2200 [mysqld] ndbcluster ndb-connectstring=ndb_mgmd.mysql.com:2200
Also starting with MySQL 4.1.8, the `my.cnf' file supports a
separate [mysql_cluster]
section for settings to be read by and
affecting all executables in the cluster:
# cluster-specific settings [mysql_cluster] ndb-connectstring=ndb_mgmd.mysql.com:2200
Currently the configuration file is in INI format, and is named
`config.ini' by default. It is read by ndb_mgmd
at
startup and it can be placed anywhere. Its location and name are
specified by using --config-file=[<path>]<filename>
on the
command line with ndb_mgmd
. If the configuration file is not
specified, ndb_mgmd
will by default try to read a
`config.ini' located in the current working directory.
Default values are defined for most parameters, and can also be
specified in `config.ini'. To create a default value section,
simply add the word DEFAULT
to the section name. For example, DB
nodes are configured using [DB]
sections. If all DB nodes use the
same data memory size, and this is not the same as the default size,
create a [DB DEFAULT]
section containing a DataMemory
line to specify the default data memory size for all DB nodes.
The INI format consists of sections preceded by section headings (surrounded by square brackets), followed by the appropriate parameter names and values. One deviation from the standard format is that the parameter name and value can be separated by a colon (`:') as well as the equals sign (`='); another is that sections are not uniquely identified by name. Instead, unique entries (such as two different nodes of the same type) are identified by a unique ID.
At a minimum, the configuration file must define the computers and nodes involved in the cluster and on which computers these nodes are located. An example of a simple configuration file for a cluster consisting of one management server, two storage nodes and two MySQL servers is shown below:
# file "config.ini" - 2 DB nodes and 2 mysqld # This file is placed in the startup directory of ndb_mgmd, # i.e., the management server. # The first MySQL Server can be started from any host and the second # can only be started at the host mysqld_5.mysql.com # NDBD, MYSQLD, and NDB_MGMD are aliases for DB, API, and MGM respectively # [NDBD DEFAULT] NoOfReplicas= 2 DataDir= /var/lib/mysql-cluster [NDB_MGMD] Hostname= ndb_mgmd.mysql.com DataDir= /var/lib/mysql-cluster [NDBD] HostName= ndbd_2.mysql.com [NDBD] HostName= ndbd_3.mysql.com [MYSQLD] [MYSQLD] HostName= mysqld_5.mysql.com
There are six different sections in this configuration file:
[COMPUTER]
: Defines the computers in the cluster.
[DB|NDBD]
: Defines the cluster's storage nodes.
[API|MYSQLD]
: Defines the cluster's MySQL server nodes.
[MGM|NDB_MGMD]
: Defines the management server node in the cluster.
[TCP]
: Defines TCP/IP connections between nodes in the cluster,
with TCP/IP being the default connection protocol.
[SHM]
: Defines shared-memory connections between nodes. This
type of connection is available only in binaries
that have been built with --with-ndb-shm
.
Note that each node has its own section in the `config.ini'. For
instance, since this cluster has two storage nodes, the configuration
file contains two sections defining these nodes. (In the example above,
these sections are labeled with [NDBD]
, but either or both of
them could have been labeled with [DB]
instead.)
One can define DEFAULT
values for each section. As of MySQL
4.1.5, all parameter names are case insensitive.
connectstring
With the exception of the MySQL Cluster management server
(ndb_mgmd
), each node making up a MySQL Cluster requires a
connectstring
which points to the management server's location.
This is used in establishing a connection to the management server as
well as in performing other tasks depending on the node's role in the
cluster. The syntax for a connectstring
is as follows:
<connectstring> := [<nodeid-specification>,]<host-specification>[,<host-specification>] <nodeid-specification> := nodeid=<id> <host-specification> := <host>[:<port>] <id> is an integer larger than 1 identifying a node in config.ini <port> is an integer referring to a regular unix port <host> is a string which is a valid Internet host address
example 1 (long): "nodeid=2,myhost1:1100,myhost2:1100,192.168.0.3:1200" example 2 (short): "myhost1"
All nodes will use localhost:1186
as the default
connectstring
value if none is provided. If <port>
is
omitted from the connectstring
, the default port is 1186.
(Note: Prior to MySQL 4.1.8, the default port was 2200.) This
port should always be available on the network, since it has been
assigned by IANA for this purpose (see
http://www.iana.org/assignments/port-numbers for details).
By listing multiple <host-specification>
values, it is possible
to designate several redundant management servers. A cluster node will
attempt to contact successive management servers on each host in the
order specified, until a successful connection has been established.
There are a number of different ways to specify the connectstring:
connectstring
to be used by all nodes in the cluster by placing
it in a [mysql_cluster]
section in the management server's
`my.cnf' file.
NDB_CONNECTSTRING
environment variable to contain the
connectstring.
connectstring
for each executable into a text file
named `Ndb.cfg' and place this file in the executable's startup
directory.
The recommended method for specifying the connectstring
is to
set it on the command line or `my.cnf' file for each executable.
The [COMPUTER]
section has no real significance other than serving as
a way to avoid the need of defining host names for each node in the system.
All parameters mentioned here are required.
[COMPUTER]Id
[COMPUTER]HostName
The [MGM]
section (or its alias [NDB_MGMD]
) is used to
configure the behavior of the management server. Either the
ExecuteOnComputer
or HostName
parameter must be present.
All other parameters can be omitted and if so will assume their
default values.
[MGM]Id
[MGM]ExecuteOnComputer
[COMPUTER]
section.
[MGM]PortNumber
[MGM]LogDestination
CONSOLE
, SYSLOG
, and
FILE
.
CONSOLE
outputs the log to stdout
:
CONSOLE
SYSLOG
sends the log to a syslog
facility, possible
values being one of auth
, authpriv
, cron
,
daemon
, ftp
, kern
, lpr
, mail
,
news
, syslog
, user
, uucp
, local0
,
local1
, local2
, local3
, local4
,
local5
, local6
, or local7
. (Note: Not
every facility is necessarily supported by every operating system.)
SYSLOG:facility=syslog
FILE
pipes the cluster log ouput to a regular file on the same
machine. The following values can be specified:
filename
: The name of the logfile.
maxsize
: The maximum size to which the file can grow before
logging rolls over to a new file. When this occurs, the old logfile is
renamed by appending `.x' to the filename, where x
is the
next number not yet used with this name.
maxfiles
: The maximum number of logfiles.
FILE:filename=cluster.log,maxsize=1000000,maxfiles=6It is possible to specify multiple log destinations as shown here, using a semicolon-delimited string:
CONSOLE;SYSLOG:facility=local0;FILE:filename=/var/log/mgmdThe default value for the
FILE
parameter is
FILE:filename=ndb_<id>_cluster.log,maxsize=1000000,maxfiles=6
,
where <id>
is the ID of the node.
[MGM]ArbitrationRank
0
: The node will never be used as an arbitrator.
1
: The node has high priority; that is, it will be preferred as
an arbitrator over low-priority nodes.
2
: Indicates a low-priority node which be used as an arbitrator
only if a node with a higher priority is not available for that
purpose.
ArbitrationRank
to 1 (the default) and that of all
API or server nodes to 0.
[MGM]ArbitrationDelay
[MGM]DataDir
FILE
parameter for
[MGM]LogDestination
as discussed previously in this section.)
The [DB]
section (or its alias [NDBD]
) is used to configure
the behavior of the storage nodes. There are many parameters specified that
controls the buffer sizes, pool sizes, timeout parameters and so forth. The
only mandatory parameter is either ExecuteOnComputer
or
HostName
and the parameter NoOfReplicas
which need to be
defined in the [DB DEFAULT]
section. Most parameters should be set in
the [DB DEFAULT]
section. Only parameters explicitly stated as
possible to have local values are allowed to be changed in the [DB]
section. HostName
, Id
and ExecuteOnComputer
needs to be
defined in the local [DB]
section.
The Id
value (that is, the identification of the storage node)
can be allocated when the node is started. It is possible to
assign a node ID in the configuration file.
For each parameter it is possible to use k, M, or G as a suffix to indicate units of 1024, 1024*1024, or 1024*1024*1024. For example, 100k means 102400. Parameters and values are case sensitive.
[DB]Id
[DB]ExecuteOnComputer
[DB]HostName
ExecuteOnComputer
is required.
[DB]ServerPort
[DB]NoOfReplicas
[DB DEFAULT]
section because it is a
global parameter. It defines the number of replicas for each table
stored in the cluster. This parameter also specifies the size of node
groups. A node group is a set of nodes that all store the same information.
Node groups are formed implicitly. The first node group is formed by the
storage nodes with the lowest node identities. And the next by the next
lowest node identities. As an example presume we have 4 storage nodes and
NoOfReplicas
is set to 2. The four storage nodes have node IDs 2, 3,
4 and 5. Then the first node group will be formed by node 2 and node 3. The
second node group will be formed by node 4 and node 5. It is important to
configure the cluster in such a manner such that nodes in the same node
groups are not placed on the same computer. This would cause a single HW
failure to cause a cluster crash.
If no node identities are provided then the order of the storage nodes will
be the determining factor for the node group. The actual node group assigned
will be printed by the SHOW
command in the management client.
There is no default value and the maximum number is 4.
[DB]DataDir
[DB]FileSystemPath
DataDir
. The directory must be created before
starting the ndbd
process.
If you use the recommended directory hierarchy, you will use a directory
`/var/lib/mysql-cluster'. Under this directory a directory `ndb_2_fs'
will be created (if node ID was 2) which will be the file system for that
node.
[DB]BackupDataDir
FileSystemPath/
`BACKUP' will be chosen.
DataMemory
and IndexMemory
are the parameters that specify
the size of memory segments used to store the actual records and their
indexes. It is important to understand how DataMemory
and
IndexMemory
are used to understand how to set these parameters.
For most uses, they need to be updated to reflect the usage of the
cluster.
[DB]DataMemory
DataMemory
will be allocated in memory so it is important that the
machine contains enough memory to handle the DataMemory
size.
The DataMemory
is used to store two things. It stores the actual
records. Each record is currently of fixed size. So VARCHAR
columns are
stored as fixed size columns. There is an overhead on each record of 16
bytes normally. Additionally each record is stored in a 32KB page with
128 byte page overhead. There will also be a small amount of waste for
each page because records are only stored in one page. The maximum record
size for the columns currently is 8052 bytes.
The DataMemory
is also used to store ordered indexes. Ordered
indexes uses about 10 bytes per record. Each record in the table is always
represented in the ordered index.
The DataMemory
consists of 32KB pages. These pages are allocated
to partitions of the tables. Each table is normally partitioned with the
same number of partitions as there are storage nodes in the cluster. Thus
for each node there are the same number of partitions (=fragments) as the
NoOfReplicas
is set to. Once a page has been allocated to a
partition it is currently not possible to bring it back to the pool of
free pages. The method to restore pages to the pool is by deleting the
table. Performing a node recovery also will compress the partition because
all records are inserted into an empty partition from another live node.
Another important aspect is that the DataMemory
also contains UNDO
information for records. For each update of a record a copy record is
allocated in the DataMemory
. Also each copy record will also have an
instance in the ordered indexes of the table. Unique hash indexes are
updated only when the unique index columns are updated and in that case a new
entry in the index table is inserted and at commit the old entry is
deleted. Thus it is necessary also to allocate memory to be able to handle
the largest transactions which are performed in the cluster.
Performing large transactions has no advantage in MySQL Cluster other than
the consistency of using transactions which is the whole idea of
transactions. It is not faster and consumes large amounts of memory.
The default DataMemory
size is 80MB. The minimum size is 1MB.
There is no maximum size, but in reality the
maximum size has to be adapted so that the process doesn't start swapping
when using the maximum size of the memory.
[DB]IndexMemory
IndexMemory
is the parameter that controls the amount of storage
used for hash indexes in MySQL Cluster. Hash indexes are always used for
primary key indexes, unique indexes, and unique constraints. Actually
when defining a primary key and a unique index there will be two indexes
created in MySQL Cluster. One index is a hash index which is used for all
tuple accesses and also for lock handling. It is also used to ensure unique
constraints.
The size of the hash index is 25 bytes plus the size of the primary key.
For primary keys larger than 32 bytes another 8 bytes is added for some
internal references.
Thus for a table defined as
CREATE TABLE example ( a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, PRIMARY KEY(a), UNIQUE(b) ) ENGINE=NDBCLUSTER;We will have 12 bytes overhead (having no nullable columns saves 4 bytes of overhead) plus 12 bytes of data per record. In addition we will have two ordered indexes on a and b consuming about 10 bytes each per record. We will also have a primary key hash index in the base table with roughly 29 bytes per record. The unique constraint is implemented by a separate table with b as primary key and a as a column. This table will consume another 29 bytes of index memory per record in the table and also 12 bytes of overhead plus 8 bytes of data in the record part. Thus for one million records, we will need 58MB of index memory to handle the hash indexes for the primary key and the unique constraint. For the
DataMemory
part we will need 64MB of memory to handle the
records of the base table and the unique index table plus the two ordered
index tables.
The conclusion is that hash indexes takes up a fair amount of memory space
but in return they provide very fast access to the data. They are also used
in MySQL Cluster to handle uniqueness constraints.
Currently the only partitioning algorithm is hashing and the ordered
indexes are local to each node and can thus not be used to handle
uniqueness constraints in the general case.
An important point for both IndexMemory
and DataMemory
is
that the total database size is the sum of all DataMemory
and
IndexMemory
in each node group. Each node group is used to store
replicated information, so if there are four nodes with 2 replicas there
will be two node groups and thus the total DataMemory
available is
2*DataMemory
in each of the nodes.
Another important point is about changes of DataMemory
and
IndexMemory
. First of all, it is highly recommended to have the same
amount of DataMemory
and IndexMemory
in all nodes. Since data
is distributed evenly over all nodes in the cluster the size available is
no better than the smallest sized node in the cluster times the number of
node groups.
DataMemory
and IndexMemory
can be changed, but it is dangerous to
decrease them because that can easily lead to a node that will not be able to
restart or even a cluster not being able to restart since there is not
enough memory space for the tables needed to restore into the starting
node. Increasing them should be quite okay, but it is recommended that such
upgrades are performed in the same manner as a software upgrade where first
the configuration file is updated, then the management server is restarted
and then one storage node at a time is restarted by command.
More IndexMemory
is not used due to updates but inserts are inserted
immediately and deletes are not deleted until the transaction is committed.
The default IndexMemory
size is 18MB. The minimum size is 1MB.
The next three parameters are important because they affect the number of
parallel transactions and the sizes of transactions that can be handled by
the system. MaxNoOfConcurrentTransactions
sets the number of
parallel transactions possible in a node and
MaxNoOfConcurrentOperations
sets the number of records that can be
in update phase or locked simultaneously.
Both of these parameters and particularly
MaxNoOfConcurrentOperations
are likely targets for users setting
specific values and not using the default value. The default value is set
for systems using small transactions and to ensure not using too much
memory in the default case.
[DB]MaxNoOfConcurrentTransactions
[DB]MaxNoOfConcurrentOperations
MaxNoOfConcurrentOperations
will always be used
to calculate the number of operation records in the transaction coordinator
part of the node.
It is also important to have an idea of the memory requirements for those
operation records. In MySQL 4.1.5, operation records consume
about 1KB per record. This figure will shrink in future 5.x versions.
[DB]MaxNoOfLocalOperations
MaxNoOfConcurrentOperations
which fits systems with many simultaneous, not very large transactions. If
the configuration needs to handle one very large transaction at a time and
there are many nodes then it is a good idea to configure this separately.
The next set of parameters are used for temporary storage in the midst of executing a part of a query in the cluster. All of these records will have been released when the query part is completed and is waiting for the commit or rollback.
Most of the defaults for these parameters will be okay for most users. Some high-end users might want to increase those to enable more parallelism in the system and some low-end users might want to decrease them to save memory.
[DB]MaxNoOfConcurrentIndexOperations
MaxNoOfConcurrentOperations
.
The default value of this parameter is 8192. Only in rare cases of
extremely high parallelism using unique hash indexes should this parameter
be necessary to increase. To decrease could be performed for memory savings
if the DBA is certain that such high parallelism is not occurring in the
cluster.
[DB]MaxNoOfFiredTriggers
MaxNoOfFiredTriggers
is 4000. Normally this
value should be sufficient for most systems. In some cases it could be
decreased if the DBA feels certain the parallelism in the cluster is not so
high.
This record is used when an operation is performed that affects a unique
hash index. Updating a column that is part of a unique hash index or
inserting/deleting a record in a table with unique hash indexes will fire
an insert or delete in the index table. This record is used to represent
this index table operation while its waiting for the original operation
that fired it to complete. Thus it is short lived but can still need a
fair amount of records in its pool for temporary situations with many
parallel write operations on a base table containing a set of unique hash
indexes.
[DB]TransactionBufferMemory
ZATTRBUF_FILESIZE
in
Dbtc.hpp. A similar buffer for key info exists which contains 4000*16
bytes, 62.5KB of buffer space. The parameter in this case is
ZDATABUF_FILESIZE
in Dbtc.hpp. Dbtc
is the module for
handling the transaction coordination.
Similar parameters exist in the Dblqh
module taking care of the reads
and updates where the data is located. In `Dblqh.hpp' with
ZATTRINBUF_FILESIZE
set to 10000*128 bytes (1250KB) and
ZDATABUF_FILE_SIZE
, set to 10000*16 bytes (roughly 156KB) of buffer
space. No known instances of that any of those compile time limits haven't
been big enough has been reported so far or discovered by any of our
extensive test suites.
The default size of the TransactionBufferMemory
is 1MB.
[DB]MaxNoOfConcurrentScans
MaxNoOfConcurrentScans
is 256. The maximum value
is 500.
This parameter will always specify the number of scans possible in the
transaction coordinator. If the number of local scan records is not provided
it is calculated as the product of MaxNoOfConcurrentScans
and the number
of storage nodes in the system.
[DB]MaxNoOfLocalScans
[DB]BatchSizePerLocalScan
ScanBatchSize
defined in the API nodes.
[DB]LongMessageBuffer
[DB]NoOfFragmentLogFiles
Out of log file space temporarily
.
This condition will prevail until a checkpoint has completed and the log tail
can be moved forward.
[DB]MaxNoOfSavedMessages
The next set of parameters defines the pool sizes for metadata objects. It is necessary to define the maximum number of attributes, tables, indexes, and trigger objects used by indexes, events and replication between clusters.
[DB]MaxNoOfAttributes
[DB]MaxNoOfTables
BLOB
data type an extra table is used to
store most of the BLOB
data. These tables also must be taken into account
when defining the number of tables.
The default value of this parameter is 128. The minimum is 8 and the
maximum is 1600. Each table object consumes around 20KB in each node.
[DB]MaxNoOfOrderedIndexes
[DB]MaxNoOfUniqueHashIndexes
USING HASH
option in the unique index definition.
The default value is 64. Each index will consume around 15KB per node.
[DB]MaxNoOfTriggers
[DB]MaxNoOfIndexes
MaxNoOfOrderedIndexes
and MaxNoOfUniqueHashIndexes
instead.
This parameter is only used by unique hash indexes. There needs to be one
record in this pool for each unique hash index defined in the cluster.
The default value of this parameter is 128.
There is a set of boolean parameters affecting the behavior of storage nodes. Boolean parameters can be specified to true by setting it to Y or 1 and to false by setting it to N or 0.
[DB]LockPagesInMainMemory
[DB]StopOnError
[DB]Diskless
Diskless
, in this case even
the tables doesn't exist anymore after a crash. Enabling this feature can
be done by either setting it to Y or 1.
When this feature is enabled, backups will be performed but will not be
stored because there is no "disk". In future releases it is likely to make
the backup diskless a separate configurable parameter.
The default is that this feature is not enabled.
[DB]RestartOnErrorInsert
There are quite a few parameters specifying timeouts and time intervals between various actions in the storage nodes. Most of the timeouts are specified in milliseconds with a few exceptions which will be mentioned below.
[DB]TimeBetweenWatchDogCheck
[DB]StartPartialTimeout
[DB]StartPartitionedTimeout
StartPartialTimeout
but
is still in a possibly partitioned state one waits until also this timeout
has passed.
The default timeout is 60000 milliseconds (60 seconds).
[DB]StartFailureTimeout
[DB]HeartbeatIntervalDbDb
[DB]HeartbeatIntervalDbApi
[DB]TimeBetweenLocalCheckpoints
[DB]TimeBetweenGlobalCheckpoints
[DB]TimeBetweenInactiveTransactionAbortCheck
[DB]TransactionInactiveTimeout
[DB]TransactionDeadlockDetectionTimeout
[DB]NoOfDiskPagesToDiskAfterRestartTUP
NoOfDiskPagesToDiskAfterRestartACC
. This
parameter handles the limitation of writes from the DataMemory
.
So this parameter specifies how quickly local checkpoints will be executed.
This parameter is important in connection with NoOfFragmentLogFiles
,
DataMemory
, IndexMemory
.
The default value is 40 (3.2MB of data pages per second).
[DB]NoOfDiskPagesToDiskAfterRestartACC
NoOfDiskPagesToDiskAfterRestartTUP
but limits the speed of writing
index pages from IndexMemory
.
The default value of this parameter is 20 (1.6MB per second).
[DB]NoOfDiskPagesToDiskDuringRestartTUP
NoOfDiskPagesToDiskAfterRestartTUP
and
NoOfDiskPagesToDiskAfterRestartACC
, only it does it for local
checkpoints executed in the node as part of a local checkpoint when the
node is restarting. As part of all node restarts a local checkpoint is
always performed. Since during a node restart it is possible to use a
higher speed of writing to disk because fewer activities are performed in the
node due to the restart phase.
This parameter handles the DataMemory
part.
The default value is 40 (3.2MB per second).
[DB]NoOfDiskPagesToDiskDuringRestartACC
IndexMemory
part of local checkpoint.
The default value is 20 (1.6MB per second).
[DB]ArbitrationTimeout
A number of new configuration parameters were introduced in MySQL 4.1.5. These correspond to values that previously were compile time parameters. The main reason for this is to enable the advanced user to have more control of the size of the process and adjust various buffer sizes according to his needs.
All of these buffers are used as front-ends to the file system when
writing log records of various kinds to disk. If the node runs with
Diskless then these parameters can most definitely be set to their
minimum values because all disk writes are faked as okay by the file system
abstraction layer in the NDB
storage engine.
[DB]UndoIndexBuffer
NDB
storage engine
uses a recovery scheme based on a consistent checkpoint together with an
operational REDO log. In order to produce a consistent checkpoint without
blocking the entire system for writes, UNDO logging is done while performing
the local checkpoint. The UNDO logging is only activated on one fragment of
one table at a time. This optimization is possible because tables are
entirely stored in main memory.
This buffer is used for the updates on the primary key hash index. Inserts
and deletes rearrange the hash index and the NDB
storage engine writes
UNDO log records that map all physical changes to an index page such that
they can be undone at a system restart. It also logs all active insert
operations at the start of a local checkpoint for the fragment.
Reads and updates only set lock bits and update a header in the hash index
entry. These changes are handled by the page write algorithm to ensure that
these operations need no UNDO logging.
This buffer is 2MB by default. The minimum value is 1MB. For most
applications this is good enough. Applications doing extremely heavy inserts
and deletes together with large transactions using large primary keys
might need to extend this buffer.
If this buffer is too small, the NDB
storage engine issues the internal
error code 677 which will be translated into "Index UNDO buffers overloaded".
[DB]UndoDataBuffer
UndoIndexBuffer
but is
used for the data part. This buffer is used during local checkpoint of a
fragment and inserts, deletes, and updates use the buffer.
Since these UNDO log entries tend to be bigger and more things are logged,
the buffer is also bigger by default. It is set to 16MB by default.
For some applications this might be too conservative and they might want
to decrease this size, the minimum size is 1MB. It should be rare that
applications need to increase this buffer size. If there is a need for this
it is a good idea to check if the disks can actually handle the load that
the update activity in the database causes. If they cannot then no size of
this buffer will be big enough.
If this buffer is too small and gets congested, the NDB
storage engine
issues the internal error code 891 which will be translated to
"Data UNDO buffers overloaded".
[DB]RedoBuffer
NDB
storage engine issues the internal
error code 1221 which will be translated into "REDO log buffers overloaded".
For cluster management, it is important to be able to control the amount of log messages sent to stdout for various event types. The possible events will be listed in this manual soon. There are 16 levels possible from level 0 to level 15. Setting event reporting to level 15 means receiving all event reports of that category and setting it to 0 means getting no event reports in that category.
The reason why most defaults are set to 0 and thus not causing any output to stdout is that the same message is sent to the cluster log in the management server. Only the startup message is by default generated to stdout.
A similar set of levels can be set in management client to define what levels to record in the cluster log.
[DB]LogLevelStartup
[DB]LogLevelShutdown
[DB]LogLevelStatistic
[DB]LogLevelCheckpoint
[DB]LogLevelNodeRestart
[DB]LogLevelConnection
[DB]LogLevelError
[DB]LogLevelInfo
There is a set of parameters defining memory buffers that are set aside for online backup execution.
[DB]BackupDataBufferSize
BackupWriteSize
parameter.
When sending data to the disk, the backup can continue filling this buffer
until it runs out of buffer space. When running out of buffer space, it will
simply stop the scan and wait until some disk writes return and thus free
up memory buffers to use for further scanning.
The default value is 2MB.
[DB]BackupLogBufferSize
BackupDataBufferSize
except
that when this part runs out of buffer space, it causes the backup to
fail due to lack of backup buffers. Thus the size of this buffer must be
big enough to handle the load caused by write activities during the backup
execution.
The default parameter should be big enough. Actually it is more likely that
a backup failure is caused by a disk not able to write as quickly as it
should. If the disk subsystem is not dimensioned for the write load caused
by the applications this will create a cluster which will have great
difficulties to perform the desired actions.
It is important to dimension the nodes in such a manner that the processors
becomes the bottleneck rather than the disks or the network connections.
The default value is 2MB.
[DB]BackupMemory
BackupDataBufferSize
and BackupLogBufferSize
.
The default value is 4MB.
[DB]BackupWriteSize
The [API]
section (with its alias [MYSQLD]
) defines the
behavior of the MySQL server. No parameter is mandatory. If no computer or
host name is provided, then any host can use this API node.
[API]Id
[API]ExecuteOnComputer
[API]ArbitrationRank
[API]ArbitrationDelay
[API]BatchByteSize
[API]BatchSize
[API]MaxScanBatchSize
TCP/IP is the default transport mechanism for establishing connections in MySQL Cluster. It is actually not necessary to define any connection because there will be a one connection setup between each of the storage nodes, between each storage node, and all MySQL server nodes and between each storage node and the management server.
It is only necessary to define a connection if it is necessary to change
the default values of the connection. In that case it is necessary to
define at least NodeId1
, NodeId2
and the parameters to
change.
It is also possible to change the default values by setting the parameters
in the [TCP DEFAULT]
section.
[TCP]NodeId1
[TCP]NodeId2
NodeId1
and NodeId2
.
[TCP]SendBufferMemory
[TCP]SendSignalId
[TCP]Checksum
[TCP]PortNumber
[TCP DEFAULT]
section
normally.
This parameter should no longer be used. Use the parameter ServerPort on
storage nodes instead.
[TCP]ReceiveBufferMemory
Shared memory segments are currently supported only for special builds of
MySQL Cluster using the configure
parameter --with-ndb-shm
. Its
implementation will most likely change. When defining shared memory as the
connection method it is necessary to define at least NodeId1
,
NodeId2
and ShmKey
. All other parameters have default values
that will work out fine in most cases.
[SHM]NodeId1
[SHM]NodeId2
NodeId1
and NodeId2
.
[SHM]ShmKey
[SHM]ShmSize
[SHM]SendSignalId
[SHM]Checksum
SCI Transporters as connection between nodes in the MySQL Cluster is only
supported for special builds of MySQL Cluster using the configure
parameter --with-ndb-sci=/your/path/to/SCI
. The path should point
to a directory that contains at least a lib and a include directory where
SISCI libraries and header files are provided.
It is strongly recommended to only use SCI Transporters for communication between ndbd processes. Also using SCI Transporters will mean that the ndbd process will never sleep so use SCI Transporters only for machines with at least 2 CPU's which are dedicated for use by ndbd process(es). There should be at least 1 CPU per ndbd process in this case and in addition at least one more is needed to also handle OS activities.
[SCI]NodeId1
[SCI]NodeId2
NodeId1
and NodeId2
.
[SCI]Host1SciId0
[SCI]Host1SciId1
[SCI]Host2SciId0
[SCI]Host2SciId1
[SCI]SharedBufferSize
[SCI]SendLimit
[SCI]SendSignalId
[SCI]Checksum
There are four processes that are important to know about when using MySQL Cluster. We will cover how to work with those processes, which options to use when starting and so forth.
mysqld
is the traditional MySQL server process. To be used with
MySQL Cluster it needs to be built with support for the NDB Cluster storage
engine. If the mysqld
binary has been built in such a manner, the
NDB Cluster storage engine is still disabled by default.
To enable the NDB Cluster storage engine there are two ways. Either use
--ndbcluster
as a startup option when starting mysqld
or
insert a line with ndbcluster
in the [mysqld]
section of your
`my.cnf' file.
An easy way to verify that your server runs with support for the
NDB Cluster
storage engine is to issue the command
SHOW ENGINES
from a mysql
client.
You should see YES
for the row listing NDBCLUSTER
.
If you see NO
, you are not running a mysqld
that is compiled
with NDB Cluster
support enabled. If you see DISABLED
, then you
need to enable it in the `my.cnf' configuration file.
The MySQL server needs to know how to get the configuration of the cluster. To access this configuration, it needs to know three things:
The node ID can be skipped from MySQL 4.1.5 on, because a node ID can be dynamically allocated.
The mysqld
parameter ndb-connectstring
is used to specify the
connectstring either when starting mysqld
or in `my.cnf'.
See also section 16.3.4.2 The MySQL Cluster connectstring
for more info on connectstrings.
shell> mysqld --ndb-connectstring=ndb_mgmd.mysql.com:1186
ndb_mgmd.mysql.com
is the host where the management server resides,
and it is listening to port 1186.
With this setup the MySQL server will be a full citizen of MySQL Cluster and will be fully aware of all storage nodes in the cluster and their status. It will setup connection to all storage nodes and will be able to use any storage node as a transaction coordinator and to access their data for reading and updating.
ndbd
, the Storage Engine Node Process
ndbd
is the process that is used to handle all the data in the
tables using the NDB Cluster storage engine. This is the process that
contains all the logic of distributed transaction handling, node recovery,
checkpointing to disk, online backup, and lots of other functionality.
In a cluster there is a set of ndbd
processes cooperating in
handling the data. These processes can execute on the same computer or on
different computers, in a completely configurable manner.
Before MySQL 4.1.5, ndbd
process should start from a separate
directory. The reason for this was that ndbd
generates a set of log
files in its starting directory.
In MySQL 4.1.5, this was changed such that the files are placed in the
directory specified by DataDir
in the configuration file. Thus
ndbd
can be started from anywhere.
These log files are (the 2 is the node ID):
ndbd
process has
encountered and a smaller error string and reference to a trace file for
this crash. An entry could like this:
Date/Time: Saturday 31 January 2004 - 00:20:01 Type of error: error Message: Internal program error (failed ndbrequire) Fault ID: 2341 Problem data: DbtupFixAlloc.cpp Object of reference: DBTUP (Line: 173) ProgramName: NDB Kernel ProcessID: 14909 TraceFile: ndb_2_trace.log.2 ***EOM***
MySQL
Cluster Troubleshooting
. There can be a configurable number of those trace
files in the directory before old files are overwritten. 1 in this context
is simply the number of the trace file.
ndbd
process. 2 in this context
is the node ID. (this file only applies if ndbd
is started in daemon mode
which is default from 4.1.5, was `node2.out' in version 4.1.3)
ndbd
where it is possible to
trace all incoming, outgoing and internal messages with their data in the
ndbd
process.
It is recommended to not use a directory mounted through NFS because in some environments that can cause problems with the lock on the pid-file remaining even after the process has stopped.
Also when starting the ndbd
process it may be necessary to specify
the hostname of the management server and the port it is listening to,
optionally one may specify node ID the process is to use,
see section 16.3.4.2 The MySQL Cluster connectstring
.
shell> ndbd --connect-string="nodeid=2;host=ndb_mgmd.mysql.com:1186"
When ndbd
starts it will actually start two processes. The starting
process is called the "angel" and its only job is to discover when the
execution process has completed, and then restart the ndbd
process if
configured to do so. Thus if one attempts to kill ndbd
through the
kill
command in Unix, it is necessary to kill both processes. A
more proper way to handle the stopping of ndbd
processes is to use
the management client and stop the process from there.
The execution process uses one thread for all activities in reading,
writing, and scanning data and all other activities. This thread is designed
with asynchronous programming so it can easily handle thousands of
concurrent activities. In addition there is a watch-dog thread supervising
the execution thread to ensure it doesn't stop in an eternal loop or other
problem. There is a pool of threads handling file I/O. Each thread can
handle one open file. In addition threads can be used for connection
activities of the transporters in the ndbd
process. Thus in a system
that performs a large number of activities including update activities the
ndbd
process will consume up to about 2 CPUs if allowed to. Thus in
a large SMP box with many CPUs it is recommended to use several
ndbd
processes which are configured to be part of different node
groups.
ndb_mgmd
, the Management Server ProcessThe management server is the process that reads the configuration file of the cluster and distributes this information to all nodes in the cluster requesting it. It also maintains the log of cluster activities. Management clients can connect to the management server and use commands to check status of the cluster in various aspects.
As of MySQL 4.1.5, it is no longer necessary to specify a connectstring when starting the management server. However, if you are using several management servers, a connectstring should be provided and each node in the cluster should specify its nodeid explicitly.
The following files are created or used by ndb_mgmd
in its starting
directory of ndb_mgmd
. From MySQL 4.1.5, the log and PID files will
be placed in the DataDir
specified in the configuration file:
MySQL Cluster Configuration
.
ndb_mgm
, the Management Client ProcessThe final important process to know about is the management client. This process is not needed to run the cluster. Its value lies in its ability to check status of the cluster, start backups, and perform other management activities. It does so by providing access to a set of commands.
Actually the management client is using a C API that is used to access the management server so for advanced users it is also possible to program dedicated management processes which can do similar things as the management client can do.
When starting the management client, it is necessary to state the hostname and port of the management server as in the example below. The default is localhost as host and port number 1186 (was 2200 prior to version 4.1.8).
shell> ndb_mgm localhost 1186
All MySQL Cluster executables (except mysqld
) takes the
following options as of 4.1.8. If you're running an earlier version
please read carefully, as we have made changes in some of these
switches in order to make them consistent between the different
executables and with mysqld
. (For example: -V
was
-v
in earlier versions.) Note also that you can use the
-?
option to see what is supported in your version.
-?, --usage, --help
-V, --version
ndbd
process. The version number is
the MySQL Cluster version number. It is important because at
startup the MySQL Cluster processes verifies that the versions of the
processes in the cluster can co-exist in the cluster. It is also important
for online software upgrade of MySQL Cluster (see section
Software Upgrade of MySQL Cluster
).
-c connect_string (not ndb_mgmd
), --connect-string connect_string
ndb_mgmd
does not take
the -c option until 5.0, as it currently specifies the config file).
Available with ndb_mgm
from 4.1.8.
shell> ndbd --connect-string="nodeid=2;host=ndb_mgmd.mysql.com:1186"
--debug[=options]
mysqld
process.
mysqld
--ndbcluster
NDB Cluster
storage engine the
default disabling of support for the NDB
storage engine can be
overruled by using this option. Using the NDB Cluster
storage engine
is necessary for using MySQL Cluster.
--skip-ndbcluster
NDB Cluster
storage engine. This is disabled by default
for binaries where it is included. So this option only applies if the
server was configured to use the NDB Cluster
storage engine.
--ndb-connectstring=connect_string
NDB
storage engine, it is possible to point out the
management server that distributes the cluster configuration by setting the
connect string option.
ndbd
For common options see section 16.4.5 Command Options for MySQL Cluster Processes.
-d, --daemon
ndbd
to execute as a daemon process. From MySQL 4.1.5 on, this
is the default behavior.
--nodaemon
ndbd
not to start as a daemon process. Useful when
ndbd
is debugged and one wants printouts on the screen.
--initial
ndbd
to perform an initial start. An initial start will
erase any files created by earlier ndbd
instances for recovery. It
will also recreate recovery log files which on some operating systems can
take a substantial amount of time.
An initial start is only to be used at the very first start of the
ndbd
process. It removes all files from the file system and
creates all REDO log files. When performing a software upgrade which has
changed the file contents on any files it is also necessary to use this
option when restarting the node with a new software version of
ndbd
. Finally it could also be used as a final resort if for some
reason the node restart or system restart doesn't work. In this case be
aware that destroying the contents of the file system means that this node
can no longer be used to restore data.
This option does not affect any backup files created.
The previous possibility to use -i
for this option was removed to
ensure that this option is not used by mistake.
--nostart
ndbd
not to automatically start. ndbd
will connect
to the management server and get the configuration and initialize
communication objects. It will not start the execution engine until
requested to do so by the management server. The management server can
request by command issued by the management client.
ndb_mgmd
For common options see section 16.4.5 Command Options for MySQL Cluster Processes.
-f filename (from 4.1.8), --config-file=filename, -c filename (obsolete from 5.0)
config.ini
.
-d, --daemon
ndb_mgmd
to start as a daemon process. This is the
default behavior.
-nodaemon
ndb_mgm
For common options see section 16.4.5 Command Options for MySQL Cluster Processes.
[host_name [port_num]]
localhost
and the default port is 1186
(was 2200 prior to version 4.1.8).
--try-reconnect=number
Managing a MySQL Cluster involves a number of activities. The first activity is to configure and startup MySQL Cluster. This is covered by the sections section 16.3 MySQL Cluster Configuration and section 16.4 Process Management in MySQL Cluster. This section covers how to manage a running MySQL Cluster.
There are essentially two ways of actively managing a running MySQL Cluster.
The first is by commands entered into the management client where status of
cluster can be checked, log levels changed, backups started and stopped and
nodes can be stopped and started. The second method is to study the output
in the cluster log. The cluster log is directed toward the
`ndb_2_cluster.log' in the DataDir
directory of the management
server. The cluster log contains event reports generated from the
ndbd
processes in the cluster. It is also possible to send the
cluster log entries to a Unix system log.
In addition to the central configuration file, the cluster may also be controlled through a command line interface. The command line interface is available through a separate management client process. This is the main administrative interface to a running cluster.
The management client has the following basic commands.
Below, <id>
denotes either a database node id (e.g. 21) or the
keyword ALL
that indicates that the command should be applied
to all database nodes in the cluster.
HELP
SHOW
<id> START
<id>
or all database nodes.
<id> STOP
<id>
or all database nodes.
<id> RESTART [-N] [-I]
<id>
or all database nodes.
<id> STATUS
<id>
(or ALL
database nodes).
ENTER SINGLE USER MODE <id>
<id>
is
allowed to access the database system.
EXIT SINGLE USER MODE
QUIT
SHUTDOWN
Commands for the event logs are given in the next section and commands for backup and restore are given in a separate section on these topics.
MySQL Cluster has two event logs, the cluster log and the node log.
Note: The cluster log is the recommended log. The node log is only intended to be used during application development or for debugging application code.
Each reportable event has the following properties:
The two logs (the cluster log and the node log) can be filtered on these properties.
The following management commands are related to the cluster log:
CLUSTERLOG ON
CLUSTERLOG OFF
CLUSTERLOG INFO
<id> CLUSTERLOG <category>=<threshold>
CLUSTERLOG FILTER <severity>
The following table describes the default setting (for all database nodes) of the cluster log category threshold. If an event has a priority with a value lower than or equal to the priority threshold, then it is reported in the cluster log.
Note that the events are reported per database node and that the thresholds can be set differently on different nodes.
Category | Default threshold (All database nodes) |
STARTUP | 7 |
SHUTDOWN | 7 |
STATISTICS | 7 |
CHECKPOINT | 7 |
NODERESTART | 7 |
CONNECTION | 7 |
ERROR | 15 |
INFO | 7 |
The threshold is used to filter events within each category.
For example: a STARTUP
event with a priority of 3 is never sent
unless the threshold for STARTUP
is changed to 3 or lower.
Only events with priority 3 or lower are sent if the threshold is 3.
The event severities are (corresponds to UNIX syslog levels):
1 | ALERT | A condition that should be corrected immediately, such as a corrupted system database |
2 | CRITICAL | Critical conditions, such as device errors or out of resources |
3 | ERROR | Conditions that should be corrected, such as configuration errors |
4 | WARNING | Conditions that are not error conditions but might require handling |
5 | INFO | Informational messages |
6 | DEBUG | Messages used during development of NDB Cluster |
Syslog's LOG_EMERG
and LOG_NOTICE
are not used/mapped.
The event severities can be turned on or off. If the severity is on then all events with priority less than or equal to the category thresholds are logged. If the severity is off then no events belonging to the severity are logged.
All reportable events are listed below.
Event | Category | Priority | Severity | Description |
DB nodes connected | CONNECTION | 8 | INFO | |
DB nodes disconnected | CONNECTION | 8 | INFO | |
Communication closed | CONNECTION | 8 | INFO | API & DB nodes connection closed |
Communication opened | CONNECTION | 8 | INFO | API & DB nodes connection opened |
Global checkpoint started | CHECKPOINT | 9 | INFO | Start of a GCP, i.e., REDO log is written to disk |
Global checkpoint completed | CHECKPOINT | 10 | INFO | GCP finished |
Local checkpoint started | CHECKPOINT | 7 | INFO | Start of local check pointing, i.e., data is written to disk. LCP Id and GCI Ids (keep and oldest restorable) |
Local checkpoint completed | CHECKPOINT | 8 | INFO | LCP finished |
LCP stopped in calc keep GCI | CHECKPOINT | 0 | ALERT | LCP stopped! |
Local checkpoint fragment completed | CHECKPOINT | 11 | INFO | A LCP on a fragment has been completed |
Report undo log blocked | CHECKPOINT | 7 | INFO | Reports undo logging blocked due buffer near to overflow |
DB node start phases initiated | STARTUP | 1 | INFO | NDB Cluster starting |
DB node all start phases completed | STARTUP | 1 | INFO | NDB Cluster started |
Internal start signal received STTORRY | STARTUP | 15 | INFO | Internal start signal to blocks received after restart finished |
DB node start phase X completed | STARTUP | 4 | INFO | A start phase has completed |
Node has been successfully included into the cluster | STARTUP | 3 | INFO | President node, own node and dynamic id is shown |
Node has been refused to be included into the cluster | STARTUP | 8 | INFO | |
DB node neighbours | STARTUP | 8 | INFO | Show left and right DB nodes neighbours |
DB node shutdown initiated | STARTUP | 1 | INFO | |
DB node shutdown aborted | STARTUP | 1 | INFO | |
New REDO log started | STARTUP | 10 | INFO | GCI keep X, newest restorable GCI Y |
New log started | STARTUP | 10 | INFO | Log part X, start MB Y, stop MB Z |
Undo records executed | STARTUP | 15 | INFO | |
Completed copying of dictionary information | NODERESTART | 8 | INFO | |
Completed copying distribution information | NODERESTART | 8 | INFO | |
Starting to copy fragments | NODERESTART | 8 | INFO | |
Completed copying a fragment | NODERESTART | 10 | INFO | |
Completed copying all fragments | NODERESTART | 8 | INFO | |
Node failure phase completed | NODERESTART | 8 | ALERT | Reports node failure phases |
Node has failed, node state was X | NODERESTART | 8 | ALERT | Reports that a node has failed |
Report whether an arbitrator is found or not | NODERESTART | 6 | INFO | 7 different cases |
- President restarts arbitration thread [state=X] | ||||
- Prepare arbitrator node X [ticket=Y] | ||||
- Receive arbitrator node X [ticket=Y] | ||||
- Started arbitrator node X [ticket=Y] | ||||
- Lost arbitrator node X - process failure [state=Y] | ||||
- Lost arbitrator node X - process exit [state=Y] | ||||
- Lost arbitrator node X <error msg>[state=Y] | ||||
Report arbitrator results | NODERESTART | 2 | ALERT | 8 different results |
- Arbitration check lost - less than 1/2 nodes left | ||||
- Arbitration check won - node group majority | ||||
- Arbitration check lost - missing node group | ||||
- Network partitioning - arbitration required | ||||
- Arbitration won - positive reply from node X | ||||
- Arbitration lost - negative reply from node X | ||||
- Network partitioning - no arbitrator available | ||||
- Network partitioning - no arbitrator configured | ||||
GCP take over started | NODERESTART | 7 | INFO | |
GCP take over completed | NODERESTART | 7 | INFO | |
LCP take over started | NODERESTART | 7 | INFO | |
LCP take completed (state = X) | NODERESTART | 7 | INFO | |
Report transaction statistics | STATISTICS | 8 | INFO | # of: transactions, commits, reads, simple reads, writes, concurrent operations, attribute info, aborts |
Report operations | STATISTICS | 8 | INFO | # of operations |
Report table create | STATISTICS | 7 | INFO | |
Report job scheduling statistics | STATISTICS | 9 | INFO | Mean Internal job scheduling statistics |
Sent # of bytes | STATISTICS | 9 | INFO | Mean # of bytes sent to node X |
Received # of bytes | STATISTICS | 9 | INFO | Mean # of bytes received from node X |
Memory usage | STATISTICS | 5 | INFO | Data and Index memory usage (80%, 90% and 100%) |
Transporter errors | ERROR | 2 | ERROR | |
Transporter warnings | ERROR | 8 | WARNING | |
Missed heartbeats | ERROR | 8 | WARNING | Node X missed heartbeat # Y |
Dead due to missed heartbeat | ERROR | 8 | ALERT | Node X declared dead due to missed heartbeat |
General warning events | ERROR | 2 | WARNING | |
Sent heartbeat | INFO | 12 | INFO | Heartbeat sent to node X |
Create log bytes | INFO | 11 | INFO | Log part, log file, MB |
General info events | INFO | 2 | INFO |
An event report has the following format in the logs:
<date & time in GMT> [<any string>] <event severity> -- <log message> 09:19:30 2003-04-24 [NDB] INFO -- Node 4 Start phase 4 completed
Single user mode allows the database administrator to restrict access to the database system to only one application (API node). When entering single user mode all connections to all APIs will be gracefully closed and no transactions are allowed to be started. All running transactions are aborted.
When the cluster has entered single user mode (use the all status command to see when the state has entered the single user mode), only the allowed API node is granted access to the database.
Example:
ENTER SINGLE USER MODE 5
After executing this command and after cluster has entered the single user mode, the API node with node id 5 becomes the single user of the cluster.
The node specified in the command above must be a MySQL Server node. Any attempt to specify any other type of node will be rejected.
Note: if the node with id 5 is running when executing
ENTER SINGLE USER MODE 5
, all transactions running on node 5
will be aborted, the connection is closed, and the server must be
restarted.
The command EXIT SINGLE USER MODE
alters the state of the
cluster DB nodes from ``single user mode'' to ``started''.
MySQL Servers waiting for a connection, i.e. for the cluster to become
ready, are allowed to connect. The MySQL Server denoted as the
single user continues to run, if it is connected, during and after the
state transition.
Example:
EXIT SINGLE USER MODE
Best practice in case of node failures when running in single user mode is to:
Or restart database nodes prior to entering single user mode.
This section describes how to create a backup and later restore the backup to a database.
A backup is a snapshot of the database at a given time. The backup contains three main parts:
Each of these parts is saved on all nodes participating in a backup.
During backup each node saves these three parts to disk into three files:
Above <BackupId> is an identifier for the backup and <NodeId> is the node id of the node creating the file.
Before starting make sure that the cluster is properly configured for backups.
START BACKUP
.
Using the management server to abort a backup:
ABORT BACKUP <BACKUPID>
.
The number <BackupId> is the identifier of the backup that is included
in the response of the management server when the backup is started,
i.e. in the message ``Backup <BackupId> started''.
The identifier is also saved in the cluster log (cluster.log).
Note that if there is not any backup with id <BackupId> running when it is aborted, the management server will not reply anything. However there will be a line in the cluster.log mentioning that an ``invalid'' abort command has been filed.
The restore program is implemented as separate command line utility. It reads the files created from the backup and inserts the stored information into the database. The restore program has to be executed once for each set of backup files, i.e. as many times as there were database nodes running when the backup we created.
The first time you run the restore program you also need to restore
the meta data, i.e. create tables. The restore program acts as an
API to the cluster and therefore needs a free connection to connect
to. This can be verified with the ndb_mgm
command SHOW.
The switch -c <connectstring>
may
be used to locate the MGM node (see section 16.3.4.2 The MySQL Cluster connectstring
for
info on connectstrings).
The backup files must be present in
the directory given as an argument to the restore program. The backup
can be restored to a database with a different configuration than it was
created from. For example, consider if a backup (with id 12) created
in a cluster with two database nodes (with node id 2 and node id 3)
that should be restored to a cluster with four nodes. The restore
program then has to be executed two times (one for each database node
in the cluster where the backup was taken) as described in the box
below.
Note: for rapid restore, the data may be restored in parallel (provided that there are enough free API connections available). Note however that the data files must always be applied before the logs.
Note: the cluster should have an empty database when starting to restore a backup.
There are four configuration parameters for backup:
If an error code is returned when issuing a backup request, then check that there is enough memory allocated for the backup (i.e. the configuration parameters). Also check that there is enough space on the hard drive partition of the backup target.
Before design of NDB Cluster started in 1996 it was evident that one of the major problems of building parallel databases is the communication between the nodes in the network. Thus from the very beginning NDB Cluster was designed with a transporter concept to allow for different transporters.
At the moment the code base includes 4 different transporters where 3 of them are currently working. Most users today uses TCP/IP over Ethernet since this exists in all machines. This is also by far the most well-tested transporter in MySQL Cluster.
Within MySQL we are working hard to ensure that communication with the ndbd process is made in as large chunks as possible since this will benefit all communication medias since all means of transportation benefits from sending large messages over small messages.
For users which desire top performance it is however also possible to use cluster interconnects to increase performance even further. There are two ways to achieve this, either a transporter can be designed to handle this case, or one can use socket implementations that bypass the TCP/IP stack to a small or large extent.
We have made some experiments with both those variants using SCI technology developed by Dolphin (www.dolphinics.no).
In this section we will show how one can use a cluster configured for normal TCP/IP communication to instead use SCI Sockets. Prerequisites for doing this is that the machines to communicate needs to be equipped with SCI cards. This documentation is based on the SCI Socket version 2.3.0 as of 1 october 2004.
To use SCI Sockets one can use any version of MySQL Cluster. The tests were performed on an early 4.1.6 version. No special builds are needed since it uses normal socket calls which is the normal configuration set-up for MySQL Cluster. SCI Sockets are only supported on Linux 2.4 and 2.6 kernels at the moment. SCI Transporters works on more OS's although only Linux 2.4 have been verified.
There are essentially four things needed to enable SCI Sockets. First it is necessary to build the SCI Socket libraries. Second the SCI Socket kernel libraries need to be installed. Third one or two configuration files needs to be installed. At last the SCI Socket kernel library needs to be enabled either for the entire machine or for the shell where the MySQL Cluster processes are started from. This process needs to be repeated for each machine in cluster which will use SCI Sockets to communicate.
Two packages need to be retrieved to get SCI Sockets working. The first package builds the libraries which SCI Sockets are built upon and the second is the actual SCI Socket libraries. Currently the distribution is only in source code format.
The latest versions of these packages is currently found at. Check
http://www.dolphinics.no/support/downloads.html
for latest versions.
http://www.dolphinics.no/ftp/source/DIS_GPL_2_5_0_SEP_10_2004.tar.gz http://www.dolphinics.no/ftp/source/SCI_SOCKET_2_3_0_OKT_01_2004.tar.gz
The next step is to unpack those directories, SCI Sockets is unpacked below the DIS code. Then the code base is compiled. The example below shows the commands used in Linux/x86 to perform this.
shell> tar xzf DIS_GPL_2_5_0_SEP_10_2004.tar.gz shell> cd DIS_GPL_2_5_0_SEP_10_2004/src/ shell> tar xzf ../../SCI_SOCKET_2_3_0_OKT_01_2004.tar.gz shell> cd ../adm/bin/Linux_pkgs shell> ./make_PSB_66_release
If the build is made on an Opteron box and is to use the 64 bit extensions then use make_PSB_66_X86_64_release instead, if the build is made on an Itanium box then use make_PSB_66_IA64_release instead. The X86-64 variant should work for Intel EM64T architectures but no known tests of this exists yet.
After building the code base it has been put into a zipped tar filed DIS and OS and date. It is time to install the package in the proper place. In this example we will place the installation in /opt/DIS. These actions will most likely require you to log in as root-user.
shell> cp DIS_Linux_2.4.20-8_181004.tar.gz /opt/ shell> cd /opt shell> tar xzf DIS_Linux_2.4.20-8_181004.tar.gz shell> mv DIS_Linux_2.4.20-8_181004 DIS
Once all the libraries and binaries are in their proper place we need to ensure that SCI cards gets proper node identities within the SCI address space. Since SCI is a networking gear it is necessary to decide on the network structure at first.
There are three types of network structures, the first is a simple one-dimensional ring, the second uses SCI switch(es) with one ring per switch port and finally there are 2D/3D torus. Each has its standard of providing node ids.
A simple ring uses simply node ids displaced by 4.
4, 8, 12, ....
The next possibility uses switch(es). The SCI switch has 8 ports. On each port it is possible to place a ring. It is here necessary to ensure that the rings on the switch uses different node id spaces. So the first port uses node ids below 64 and the next 64 node ids are allocated for the next port and so forth.
4,8, 12, ... , 60 Ring on first port 68, 72, .... , 124 Ring on second port 132, 136, ..., 188 Ring on third port .. 452, 456, ..., 508 Ring on the eight port
2D/3D torus network structures takes into account where each node is in each dimension, increment by 4 for each node in the first dimension, by 64 in the second dimension and by 1024 in the third dimension. Please look in the Dolphin for more thorough documentation on this.
In our testing we have used switches. Most of the really big cluster installations uses 2D/3D torus. The extra feature which switches provide is that with dual SCI cards and dual switches we can easily build a redundant network where failover times on the SCI network is around 100 microseconds. This feature is supported by the SCI transporter and is currently also developed for the SCI Socket implementation.
Failover for 2D/3D torus is also possible but requires sending out new routing indexes to all nodes. Even this will complete in around 100 milliseconds and should be ok for most high-availability cases.
By placing the NDB nodes in proper places in the switched architecture it is possible to use 2 switches to build a structure where 16 computers can be interconnected and no single failure can hamper more than one computer. With 32 computers and 2 switches it is possible to configure the cluster in such a manner that no single failure can hamper more than two nodes and in this case it is also known which pair will be hit. Thus by placing those two in separate NDB node groups it is possible to build a safe MySQL Cluster installation. We won't go into details in how this is done, since it is likely to be only of interest for users wanting to go real deep into this.
To set the node id of an SCI card use the following command still being
in the /opt/DIS/sbin
directory. -c 1 refers to the number of the SCI
card, where 1 is this number if only 1 card is in the machine. In this case
use adapter 0 always (set by -a 0). 68 is the node id set in this example.
shell> ./sciconfig -c 1 -a 0 -n 68
In case you have several SCI cards in your machine the only safe to discover which card has which slot is by issuing the following command
shell> ./sciconfig -c 1 -gsn
This will give the serial number which can be found at the back of the SCI card and on the card itself. Do this then for -c 2 and onwards as many cards there are in the machine. This will identify which cards uses which id. Then set node ids for all cards.
We have installed the necessary libraries and binaries. We have also set the SCI node ids. The next step is to set the mapping from hostnames (or IP addresses) to SCI node ids.
The configuration file for SCI Sockets is to be placed in the file
/etc/sci/scisock.conf
. This file contains a mapping from hostnames
(or IP addresses) to SCI node ids. The SCI node id will map the hostname
to communicate through the proper SCI card. Below is a very simple such
configuration file.
#host #nodeId alpha 8 beta 12 192.168.10.20 16
It is also possible to limit this configuration to only apply for a subset of
the ports of these hostnames. To do this another configuration is used which
is placed in /etc/sci/scisock_opt.conf
.
#-key -type -values EnablePortsByDefault yes EnablePort tcp 2200 DisablePort tcp 2201 EnablePortRange tcp 2202 2219 DisablePortRange tcp 2220 2231
We are ready to install the drivers. We need to first install the low-level drivers and then the SCI Socket driver.
shell> cd DIS/sbin/ shell> ./drv-install add PSB66 shell> ./scisocket-install add
If desirable one can check the installation by invoking a script which checks that all nodes in the SCI Socket config files are accessible.
shell> cd /opt/DIS/sbin/ shell> ./status.sh
If you discover an error and need to change the SCI Socket config files then it is necessary to use a program ksocketconfig to change the configuration.
shell> cd /opt/DIS/util shell> ./ksocketconfig -f
To check that SCI Sockets are actually used you can use a test program
latency_bench
which needs to have a server component and clients can
connect to the server to test the latency, whether SCI is enabled is very clear
from the latency you get. Before you use those programs you also need to set
the LD_PRELOAD variable in the same manner as shown below.
To set up a server use the command
shell> cd /opt/DIS/bin/socket shell> ./latency_bench -server
To run a client use the following command
shell> cd /opt/DIS/bin/socket shell> ./latency_bench -client hostname_of_server
The SCI Socket configuration is completed. MySQL Cluster is now ready to use both SCI Sockets and the SCI transporter documented in section 16.3.4.9 MySQL Cluster SCI Transport Connections.
The next step is to start-up MySQL Cluster. To enable usage of SCI Sockets it is necessary to set the environment variable LD_PRELOAD before starting the ndbd, mysqld and ndb_mgmd processes to use SCI Sockets. The LD_PRELOAD variable should point to the kernel library for SCI Sockets.
So as an example to start up ndbd in a bash-shell use the following commands.
bash-shell> export LD_PRELOAD=/opt/DIS/lib/libkscisock.so bash-shell> ndbd
From a tcsh environment the same thing would be accomplished with the following commands.
tcsh-shell> setenv LD_PRELOAD=/opt/DIS/lib/libkscisock.so tcsh-shell> ndbd
Noteworthy here is that MySQL Cluster can only use the kernel variant of SCI Sockets.
The ndbd process has a number of simple constructs which are used to access the data in MySQL Cluster. We made a very simple benchmark to check the performance of each such statement and the effect various interconnects have on their performance.
There are four access methods:
Primary key access
Unique key access
Full table scan
Range scan using ordered index
To check the base performance of these access methods we developed a set of benchmarks. One such benchmark, testReadPerf issues, simple primary and unique key access, batched primary and unique key accesses. The benchmark also measures the set-up cost of range scans by issuing scans returning a single record and finally there is a variant which uses a range scan to fetch a batch of records.
In this manner we can test the cost of issuing single key access and single record scan accesses and measure the impact of the communication media implementation of these base access methods.
We executed those base benchmark both using a normal transporter using TCP/IP sockets and a similar set-up using SCI sockets. The figures reported below is for small accesses of 20 records per of data per access. The difference between serial and batched goes down by a factor of 3-4 when using 2 kB records instead. SCI Sockets were not tested with 2 kB record2 kB records. Tests were performed on a 2-node cluster with 2 dual CPU machines equipped with AMD MP1900+ processors.
Access type: TCP/IP sockets SCI Socket Serial pk access: 400 microseconds 160 microseconds Batched pk access: 28 microseconds 22 microseconds Serial uk access: 500 microseconds 250 microseconds Batched uk access: 70 microseconds 36 microseconds Indexed eq-bound: 1250 microseconds 750 microseconds Index range: 24 microseconds 12 microseconds
We did also another set of tests to check the performance of SCI Sockets compared to using the SCI transporter and all compared to the TCP/IP transporter. All these tests used primary key accesses either serially, multi-threaded and multi-threaded and batched simultaneously.
More or less all of these tests showed that SCI sockets were about 100% faster compared to TCP/IP. The SCI transporter was faster in most cases compared to SCI sockets. One notable case however with many threads in the test program showed that the SCI transporter behaved really bad if used in the mysqld process.
Thus our conclusion overall is that for most benchmarks SCI sockets improves performance with around 100% compared to TCP/IP except in rare cases when communication performance is not an issue such as when scan filters make up most of processing time or when very large batches of primary key accesses are achieved. In that case the CPU processing in the ndbd processes becomes a fairly large part of the cost.
Using the SCI transporter instead of SCI Sockets is only of interest in communicating between ndbd processes. Using the SCI transporter is also only of interest if a CPU can be dedicated for the ndbd process since the SCI transporter ensures that the ndbd will never go to sleep. It is also important to ensure that the ndbd process priority is set in such a way that the process doesn't lose in priority due to running for a long time (as can be done by locking processes to CPU's in Linux 2.6). If this is a possible configuration then ndbd process will benefit by 10-70% compared to using SCI sockets (the larger figures when performing updates and probably also on parallel scan activities).
There are several other implementations of optimized socket variants for clusters reported in various papers. These include optimized socket variants for Myrinet, Gigabit Ethernet, Infiniband and the VIA interface. We have only tested MySQL Cluster so far with SCI sockets and we also include documentation above on how to set-up SCI sockets using ordinary TCP/IP configuration for MySQL Cluster.
Below is a list of known limitations with release 4.1 when comparing to the storage engines MyISAM and InnoDB. Currently there are no plans to address these in coming releases of 4.1 (but well in 5.0 or later releases). At http://bugs.mysql.com, category cluster, you fill find known bugs which are intended to be fixed in upcoming releases of 4.1 (if marked 4.1). This list is intended to be complete with respect to the above, please report discrepancies at http://bugs.mysql.com, category cluster. If this discrepancy will not be fixed in 4.1 it will be added to this list.
DataMemory
and IndexMemory
respectively.
MaxNoOfConcurrentOperations
(bulk load, truncate table and alter table are handled specially by running
several transactions, and thus does not have this limitation)
MaxNoOfOrderedIndexes
etc.
USE INDEX
or FORCE INDEX
to work around non optimal query plans.
USING HASH
) cannot be used for accessing table
if NULL is given as part of the key.
mysql
clients
that may be accessing the cluster.
MaxDB is an enterprise-level database. MaxDB is the new name of a database management system formerly called SAP DB.
The history of SAP DB goes back to the early 1980s when it was developed as a commercial product (Adabas). The database has changed names several times since then. When SAP AG, a company based in Walldorf, Germany, took over the development of that database system, it was called SAP DB.
SAP developed that database system to serve as a storage system for all heavy-duty SAP applications, namely R/3. SAP DB was meant to provide an alternative to third-party database systems such as Oracle, Microsoft SQL Server, and DB2 by IBM. In October 2000, SAP AG released SAP DB under the GNU GPL license (see section H GNU General Public License), thus making it Open Source software. In October 2003, more than 2,000 customers of SAP AG were using SAP DB as their main database system, and more than another 2,000 customers were using it as a separate database system besides their main database, as part of the APO/LiveCache solution.
In May 2003, a technology partnership was formed between MySQL AB and SAP AG. That partnership entitles MySQL AB to further develop SAP DB, rename it, and sell commercial licenses of the renamed SAP DB to customers who do not want to be bound to the restrictions imposed on them when using that database system under the GNU GPL (see section H GNU General Public License). In August 2003, SAP DB was renamed MaxDB by MySQL AB.
MaxDB can be used under the same licenses available for the other products distributed by MySQL AB. Thus, MaxDB will be available under the GNU General Public License, and a commercial license. For more information on licensing, see http://www.mysql.com/company/legal/licensing/.
MySQL will offer MaxDB support to non-SAP customers.
The first rebranded version was MaxDB 7.5.00, which was released in November 2003.
The main page for information about MaxDB is http://www.mysql.com/products/maxdb. Information formerly available at http://www.sapdb.org has been moved there.
MaxDB operates as a client/server product. It was developed to meet the demands of installations processing a high volume of online transactions. Both online backup and expansion of the database are supported. Microsoft Clustered Server is supported directly for multiple server implementations; other failover solutions must be scripted manually. Database management tools are provided in both Windows and browser-based implementations.
The following list provides a short summary of the main differences between MaxDB and MySQL; it is not complete.
As part of MaxDB 7.6, the MaxDB Synchronization Manager is released. The Synchronization Manager supports creation of asynchronous replication scenarios between several MaxDB instances. However, interoperability features also are planned, so that the Synchronization Manager will support replication to and from a MySQL server.
In the first release, the Synchronization Manager will support inserting data into MySQL. This means that initially only replication from MaxDB to MySQL will be supported. In the course of 2005, exporting of data from a MySQL server to the Synchronization Manager will be added, thus adding support for MySQL to MaxDB replication scenarios.
MaxDB 7.6, with the Synchronization Manager, will be released as a beta version in January 2005. The production release is planned for April 2005.
Like MySQL, MaxDB has a number of reserved words that have special meanings. Normally, they cannot be used as names of identifiers, such as database or table names. The following table lists reserved words in MaxDB, indicates the context in which those words are used, and indicates whether or not they have counterparts in MySQL. If such a counterpart exists, the meaning in MySQL might be identical or differing in some aspects. The main purpose is to list in which respects MaxDB differs from MySQL; therefore, this list is not complete.
For the list of reserved words in MySQL, see section 9.6 Treatment of Reserved Words in MySQL.
Reserved in MaxDB | Context of usage in MaxDB | MySQL counterpart |
@
| Can prefix identifier, like ``@table'' | Not allowed |
ADDDATE()
| SQL function | ADDDATE() ; new in MySQL 4.1.1
|
ADDTIME()
| SQL function | ADDTIME() ; new in MySQL 4.1.1
|
ALPHA
| SQL function | Nothing comparable |
ARRAY
| Data type | Not implemented |
ASCII()
| SQL function | ASCII() , but implemented with a different meaning
|
AUTOCOMMIT
| Transactions; ON by default
| Transactions; OFF by default
|
BOOLEAN
| Column types; BOOLEAN accepts as values only TRUE , FALSE , and NULL
| BOOLEAN was added in MySQL 4.1.0; it is a synonym for BOOL which is mapped to TINYINT(1) . It accepts integer values in the same range as TINYINT as well as NULL . TRUE and FALSE can be used as aliases for 1 and 0 .
|
CHECK
| CHECK TABLE
| CHECK TABLE ; similar, but not identical usage
|
COLUMN
| Column types | COLUMN ; noise word
|
CHAR()
| SQL function | CHAR() ; identical syntax; similar, not identical usage
|
COMMIT
| Implicit commits of transactions happen when data definition statements are issued | Implicit commits of transactions happen when data definition statements are issued, and also with a number of other statements |
COSH()
| SQL function | Nothing comparable |
COT()
| SQL function | COT() ; identical syntax and implementation
|
CREATE
| SQL, data definition language | CREATE
|
DATABASE
| SQL function | DATABASE() ; DATABASE is used in a different context; for example, CREATE DATABASE
|
DATE()
| SQL function | CURRENT_DATE
|
DATEDIFF()
| SQL function | DATEDIFF() ; new in MySQL 4.1.1
|
DAY()
| SQL function | Nothing comparable |
DAYOFWEEK()
| SQL function | DAYOFWEEK() ; by default, 1 represents Monday in MaxDB and Sunday in MySQL
|
DISTINCT
| SQL functions AVG , MAX , MIN , SUM
| DISTINCT ; but used in a different context: SELECT DISTINCT
|
DROP
| DROP INDEX , for example
| DROP INDEX ; similar, but not identical usage
|
EBCDIC()
| SQL function | Nothing comparable |
EXPAND()
| SQL function | Nothing comparable |
EXPLAIN
| Optimization | EXPLAIN ; similar, but not identical usage
|
FIXED()
| SQL function | Nothing comparable |
FLOAT()
| SQL function | Nothing comparable |
HEX()
| SQL function | HEX() ; similar, but not identical usage
|
INDEX()
| SQL function | INSTR() or LOCATE() ; similar, but not identical syntaxes and meanings
|
INDEX
| USE INDEX , IGNORE INDEX and similar hints are used right after SELECT ; for example, SELECT ... USE INDEX
| USE INDEX , IGNORE INDEX and similar hints are used in the FROM clause of a SELECT query; for example, in SELECT ... FROM ... USE INDEX
|
INITCAP()
| SQL function | Nothing comparable |
LENGTH()
| SQL function | LENGTH() ; identical syntax, but slightly different implementation
|
LFILL()
| SQL function | Nothing comparable |
LIKE
| Comparisons | LIKE ; but the extended LIKE MaxDB provides rather resembles the MySQL REGEX
|
LIKE wildcards
| MaxDB supports ``%'', ``_'', ``Control-underline'', ``Control-up arrow'', ``*'', and ``?'' as wildcards in LIKE comparisons
| MySQL supports ``%'', and ``_'' as wildcards in LIKE comparisons
|
LPAD()
| SQL function | LPAD() ; slightly different implementation
|
LTRIM()
| SQL function | LTRIM() ; slightly different implementation
|
MAKEDATE()
| SQL function | MAKEDATE() ; new in MySQL 4.1.1
|
MAKETIME()
| SQL function | MAKETIME() ; new in MySQL 4.1.1
|
MAPCHAR()
| SQL function | Nothing comparable |
MICROSECOND()
| SQL function | MICROSECOND() ; new in MySQL 4.1.1
|
NOROUND()
| SQL function | Nothing comparable |
NULL
| Column types; comparisons | NULL ; MaxDB supports special NULL values that are returned by arithmetic operations that lead to an overflow or a division by zero; MySQL does not support such special values
|
PI
| SQL function | PI() ; identical syntax and implementation, but parentheses are mandatory in MySQL
|
REF
| Data type | Nothing comparable |
RFILL()
| SQL function | Nothing comparable |
ROWNO
| Predicate in WHERE clause
| Similar to LIMIT clause
|
RPAD()
| SQL function | RPAD() ; slightly different implementation
|
RTRIM()
| SQL function | RTRIM() ; slightly different implementation
|
SEQUENCE
| CREATE SEQUENCE , DROP SEQUENCE
| AUTO_INCREMENT ; similar concept, but different implementation
|
SINH()
| SQL function | Nothing comparable |
SOUNDS()
| SQL function | SOUNDEX() ; slightly different syntax
|
STATISTICS
| UPDATE STATISTICS
| ANALYZE TABLE ; similar concept, but different implementation
|
SUBSTR()
| SQL function | SUBSTRING() ; slightly different implementation
|
SUBTIME()
| SQL function | SUBTIME() ; new in MySQL 4.1.1
|
SYNONYM
| Data definition language: CREATE [PUBLIC] SYNONYM , RENAME SYNONYM , DROP SYNONYM
| Nothing comparable |
TANH()
| SQL function | Nothing comparable |
TIME()
| SQL function | CURRENT_TIME
|
TIMEDIFF()
| SQL function | TIMEDIFF() ; new in MySQL 4.1.1
|
TIMESTAMP()
| SQL function | TIMESTAMP() ; new in MySQL 4.1.1
|
TIMESTAMP() as argument to DAYOFMONTH() and DAYOFYEAR()
| SQL function | Nothing comparable |
TIMEZONE()
| SQL function | Nothing comparable |
TRANSACTION()
| Returns the ID of the current transaction | Nothing comparable |
TRANSLATE()
| SQL function | REPLACE() ; identical syntax and implementation
|
TRIM()
| SQL function | TRIM() ; slightly different implementation
|
TRUNC()
| SQL function | TRUNCATE() ; slightly different syntax and implementation
|
USE
| Switches to a new database instance; terminates the connection to the current database instance; all subsequent commands are referred to this database instance | USE ; identical syntax, but does not terminate the connection to
the current database
|
USER
| SQL function | USER() ; identical syntax, but slightly different implementation, and parentheses are mandatory in MySQL
|
UTC_DIFF()
| SQL function | UTC_DATE() ; provides a means to calculate the same result as UTC_DIFF()
|
VALUE()
| SQL function, alias for COALESCE()
| COALESCE() ; identical syntax and implementation
|
VARIANCE()
| SQL function | VARIANCE() ; new in MySQL 4.1.0
|
WEEKOFYEAR()
| SQL function | WEEKOFYEAR() ; new in MySQL 4.1.1
|
MySQL 4.1 introduces spatial extensions to allow the
generation, storage, and analysis of geographic features.
Currently, these features are available for MyISAM
tables only.
This chapter covers the following topics:
MySQL implements spatial extensions following the specification of
the Open GIS Consortium
(OGC). This is an international consortium
of more than 250 companies, agencies, and universities participating
in the development of publicly available conceptual solutions that can be
useful with all kinds of applications that manage spatial data.
The OGC maintains a Web site at http://www.opengis.org/.
In 1997, the Open GIS Consortium published the OpenGIS (R) Simple Features Specifications For SQL, a document that proposes several conceptual ways for extending an SQL RDBMS to support spatial data. This specification is available from the Open GIS Web site at http://www.opengis.org/docs/99-049.pdf. It contains additional information relevant to this chapter.
MySQL implements a subset of the SQL with Geometry Types environment proposed by OGC. This term refers to an SQL environment that has been extended with a set of geometry types. A geometry-valued SQL column is implemented as a column that has a geometry type. The specifications describe a set of SQL geometry types, as well as functions on those types to create and analyze geometry values.
A geographic feature is anything in the world that has a location. A feature can be:
You can also find documents that use the term geospatial feature to refer to geographic features.
Geometry is another word that denotes a geographic feature. Originally the word geometry meant measurement of the earth. Another meaning comes from cartography, referring to the geometric features that cartographers use to map the world.
This chapter uses all of these terms synonymously: geographic feature, geospatial feature, feature, or geometry. The term most commonly used here is geometry.
Let's define a geometry as a point or an aggregate of points representing anything in the world that has a location.
The set of geometry types proposed by OGC's SQL with Geometry Types environment is based on the OpenGIS Geometry Model. In this model, each geometric object has the following general properties:
The geometry classes define a hierarchy as follows:
Geometry
(non-instantiable)
Point
(instantiable)
Curve
(non-instantiable)
LineString
(instantiable)
Line
LinearRing
Surface
(non-instantiable)
Polygon
(instantiable)
GeometryCollection
(instantiable)
MultiPoint
(instantiable)
MultiCurve
(non-instantiable)
MultiLineString
(instantiable)
MultiSurface
(non-instantiable)
MultiPolygon
(instantiable)
It is not possible to create objects in non-instantiable classes. It is possible to create objects in instantiable classes. All classes have properties, and instantiable classes may also have assertions (rules that define valid class instances).
Geometry
is the base class. It's an abstract class.
The instantiable subclasses of Geometry
are restricted to zero-, one-,
and two-dimensional geometric objects that exist in
two-dimensional coordinate space. All instantiable geometry classes are
defined so that valid instances of a geometry class are topologically closed
(that is, all defined geometries include their boundary).
The base Geometry
class has subclasses for Point
,
Curve
, Surface
, and GeometryCollection
:
Point
represents zero-dimensional objects.
Curve
represents one-dimensional objects, and has subclass
LineString
, with sub-subclasses Line
and LinearRing
.
Surface
is designed for two-dimensional objects and
has subclass Polygon
.
GeometryCollection
has specialized zero-, one-, and two-dimensional collection classes named
MultiPoint
, MultiLineString
, and MultiPolygon
for modeling geometries corresponding to collections of
Points
, LineStrings
, and Polygons
, respectively.
MultiCurve
and MultiSurface
are introduced as abstract superclasses
that generalize the collection interfaces to handle Curves
and Surfaces
.
Geometry
, Curve
, Surface
, MultiCurve
,
and MultiSurface
are defined as non-instantiable classes.
They define a common set of methods for their subclasses and
are included for extensibility.
Point
, LineString
, Polygon
, GeometryCollection
,
MultiPoint
, MultiLineString
, and
MultiPolygon
are instantiable classes.
Geometry
Geometry
is the root class of the hierarchy. It is a
non-instantiable class but has a number of properties that are common to
all geometry values created from any of the Geometry
subclasses.
These properties are described in the following list. (Particular
subclasses have their own specific properties, described later.)
A geometry value has the following properties:
((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
LineString
, MultiPoint
,
MultiLineString
)
are either simple or non-simple. Each type determines its own assertions
for being simple or non-simple.
LineString
, MultiString
) are
either closed
or not closed. Each type determines its own assertions for being closed
or not closed.
NULL
value).
An empty geometry is defined to be always simple and has an area of 0.
Point
objects have a dimension of zero. LineString
objects have a dimension of 1. Polygon
objects have a
dimension of 2. The dimensions of MultiPoint
,
MultiLineString
, and MultiPolygon
objects are the
same as the dimensions of the elements they consist of.
Point
A Point
is a geometry that represents a single
location in coordinate space.
Point
ExamplesPoint
object could represent each city.
Point
object could represent a bus stop.
Point
PropertiesPoint
is defined as a zero-dimensional geometry.
Point
is the empty set.
Curve
A Curve
is a one-dimensional geometry, usually represented by a sequence
of points. Particular subclasses of Curve
define the type of
interpolation between points. Curve
is a non-instantiable class.
Curve
PropertiesCurve
has the coordinates of its points.
Curve
is defined as a one-dimensional geometry.
Curve
is simple if it does not pass through the same point twice.
Curve
is closed if its start point is equal to its end point.
Curve
is empty.
Curve
consists of its two end points.
Curve
that is simple and closed is a LinearRing
.
LineString
A LineString
is a Curve
with linear interpolation between points.
LineString
ExamplesLineString
objects could represent rivers.
LineString
objects could represent streets.
LineString
PropertiesLineString
has coordinates of segments, defined by each consecutive pair of points.
LineString
is a Line
if it consists of exactly two points.
LineString
is a LinearRing
if it is both closed and simple.
Surface
A Surface
is a two-dimensional geometry. It is a non-instantiable
class. Its only instantiable subclass is Polygon
.
Surface
PropertiesSurface
is defined as a two-dimensional geometry.
Surface
as a geometry that
consists of a single ``patch'' that is associated with a single exterior
boundary and zero or more interior boundaries.
Surface
is the set of closed curves
corresponding to its exterior and interior boundaries.
Polygon
A Polygon
is a planar Surface
representing a multisided
geometry. It is defined by a single exterior boundary and zero or more
interior boundaries, where
each interior boundary defines a hole in the Polygon
.
Polygon
ExamplesPolygon
objects could represent forests, districts, an
so on.
Polygon
AssertionsPolygon
consists of a set of LinearRing
objects
(that is, LineString
objects that are both simple and closed) that make up its
exterior and interior boundaries.
Polygon
has no rings that cross. The rings in the boundary of a
Polygon
may intersect at a Point
, but only as a tangent.
Polygon
has no lines, spikes, or punctures.
Polygon
has an interior that is a connected point set.
Polygon
may have holes.
The exterior of a Polygon
with holes is not connected.
Each hole defines a connected component of the exterior.
The preceding assertions make a Polygon
a simple geometry.
GeometryCollection
A GeometryCollection
is a geometry that is a collection of one or more
geometries of any class.
All the elements in a GeometryCollection
must be in
the same Spatial Reference System (that is, in the same coordinate system).
There are no other constraints on the elements of a GeometryCollection
,
although the
subclasses of GeometryCollection
described in the following sections
may restrict membership. Restrictions may be based on:
MultiPoint
may contain only Point
elements)
MultiPoint
A MultiPoint
is a geometry collection composed of
Point
elements. The points are not connected or ordered
in any way.
MultiPoint
ExamplesMultiPoint
could represent a chain of small islands.
MultiPoint
could represent the outlets for a ticket
office.
MultiPoint
PropertiesMultiPoint
is a zero-dimensional geometry.
MultiPoint
is simple if no two of its Point
values are
equal (have identical coordinate values).
MultiPoint
is the empty set.
MultiCurve
A MultiCurve
is a geometry collection composed of
Curve
elements. MultiCurve
is a non-instantiable class.
MultiCurve
PropertiesMultiCurve
is a one-dimensional geometry.
MultiCurve
is simple if and only if all of its elements are simple;
the only intersections between any two elements occur at points that are
on the boundaries of both elements.
MultiCurve
boundary is obtained by applying the ``mod 2 union
rule'' (also known as the ``odd-even rule''):
A point is in the boundary of a MultiCurve
if it is in the
boundaries of an odd number of MultiCurve
elements.
MultiCurve
is closed if all of its elements are closed.
MultiCurve
is always empty.
MultiLineString
A MultiLineString
is a MultiCurve
geometry collection composed
of LineString
elements.
MultiLineString
ExamplesMultiLineString
could represent a river system or
a highway system.
MultiSurface
A MultiSurface
is a geometry collection composed of surface elements.
MultiSurface
is a non-instantiable class. Its only instantiable
subclass is MultiPolygon
.
MultiSurface
AssertionsMultiSurface
surfaces have no interiors that intersect.
MultiSurface
elements have boundaries that
intersect at most at a finite number of points.
MultiPolygon
A MultiPolygon
is a MultiSurface
object composed of
Polygon
elements.
MultiPolygon
ExamplesMultiPolygon
could represent a system of lakes.
MultiPolygon
AssertionsMultiPolygon
has no two Polygon
elements with interiors
that intersect.
MultiPolygon
has no two Polygon
elements that cross
(crossing is also forbidden by the previous assertion), or that
touch at an infinite number of points.
MultiPolygon
may not have cut lines, spikes, or punctures. A
MultiPolygon
is a regular, closed point set.
MultiPolygon
that has more than one Polygon
has an
interior that is not connected. The number of connected components of the interior
of a MultiPolygon
is equal to the number of Polygon
values in
the MultiPolygon
.
MultiPolygon
PropertiesMultiPolygon
is a two-dimensional geometry.
MultiPolygon
boundary is a set of closed curves
(LineString
values) corresponding to the boundaries of its
Polygon
elements.
Curve
in the boundary of the MultiPolygon
is in the
boundary of exactly one Polygon
element.
Curve
in the boundary of an Polygon
element is
in the boundary of the MultiPolygon
.
This section describes the standard spatial data formats that are used to represent geometry objects in queries. They are:
Internally, MySQL stores geometry values in a format that is not identical to either WKT or WKB format.
The Well-Known Text (WKT) representation of Geometry is designed to exchange geometry data in ASCII form.
Examples of WKT representations of geometry objects are:
Point
:
POINT(15 20)Note that point coordinates are specified with no separating comma.
LineString
with four points:
LINESTRING(0 0, 10 10, 20 25, 50 60)Note that point coordinate pairs are separated by commas.
Polygon
with one exterior ring and one interior ring:
POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))
MultiPoint
with three Point
values:
MULTIPOINT(0 0, 20 20, 60 60)
MultiLineString
with two LineString
values:
MULTILINESTRING((10 10, 20 20), (15 15, 30 15))
MultiPolygon
with two Polygon
values:
MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)),((5 5,7 5,7 7,5 7, 5 5)))
GeometryCollection
consisting of two Point
values and one
LineString
:
GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
A Backus-Naur grammar that specifies the formal production rules for writing WKT values can be found in the OGC specification document referenced near the beginning of this chapter.
The Well-Known Binary (WKB) representation for geometric values is defined by the OpenGIS specifications. It is also defined in the ISO ``SQL/MM Part 3: Spatial'' standard.
WKB is used to exchange geometry data as binary streams represented by
BLOB
values containing geometric WKB information.
WKB uses one-byte unsigned integers, four-byte unsigned integers, and eight-byte double-precision numbers (IEEE 754 format). A byte is eight bits.
For example, a WKB value that corresponds to POINT(1 1)
consists of
this sequence of 21 bytes (each represented here by two hex digits):
0101000000000000000000F03F000000000000F03F
The sequence may be broken down into these components:
Byte order : 01 WKB type : 01000000 X : 000000000000F03F Y : 000000000000F03F
Component representation is as follows:
Point
,
LineString
,
Polygon
,
MultiPoint
,
MultiLineString
,
MultiPolygon
,
and
GeometryCollection
.
Point
value has X and Y coordinates, each represented as a
double-precision value.
WKB values for more complex geometry values are represented by more complex data structures, as detailed in the OpenGIS specification.
This section describes the data types you can use for representing spatial data in MySQL, and the functions available for creating and retrieving spatial values.
MySQL has data types that correspond to OpenGIS classes. Some of these types hold single geometry values:
GEOMETRY
POINT
LINESTRING
POLYGON
GEOMETRY
can store geometry values of any type.
The other single-value types,
POINT
and LINESTRING
and POLYGON
,
restrict their values to a particular geometry type.
The other data types hold collections of values:
MULTIPOINT
MULTILINESTRING
MULTIPOLYGON
GEOMETRYCOLLECTION
GEOMETRYCOLLECTION
can store a collection of objects
of any type. The other collection types,
MULTIPOINT
and MULTILINESTRING
and MULTIPOLYGON
and GEOMETRYCOLLECTION
,
restrict collection members to those having a particular geometry type.
This section describes how to create spatial values using Well-Known Text and Well-Known Binary functions that are defined in the OpenGIS standard, and using MySQL-specific functions.
MySQL provides a number of functions that take as input parameters a Well-Known Text representation and, optionally, a spatial reference system identifier (SRID). They return the corresponding geometry.
GeomFromText()
accepts a WKT of any geometry type as its first
argument. An implementation also provides type-specific construction
functions for construction of geometry values of each geometry type.
GeomCollFromText(wkt[,srid])
GeometryCollectionFromText(wkt[,srid])
GEOMETRYCOLLECTION
value using its WKT representation and SRID.
GeomFromText(wkt[,srid])
GeometryFromText(wkt[,srid])
LineFromText(wkt[,srid])
LineStringFromText(wkt[,srid])
LINESTRING
value using its WKT representation and SRID.
MLineFromText(wkt[,srid])
MultiLineStringFromText(wkt[,srid])
MULTILINESTRING
value using its WKT representation and SRID.
MPointFromText(wkt[,srid])
MultiPointFromText(wkt[,srid])
MULTIPOINT
value using its WKT representation and SRID.
MPolyFromText(wkt[,srid])
MultiPolygonFromText(wkt[,srid])
MULTIPOLYGON
value using its WKT representation and SRID.
PointFromText(wkt[,srid])
POINT
value using its WKT representation and SRID.
PolyFromText(wkt[,srid])
PolygonFromText(wkt[,srid])
POLYGON
value using its WKT representation and SRID.
The OpenGIS specification also describes optional functions for constructing
Polygon
or MultiPolygon
values based on the WKT representation
of a collection of rings or closed LineString
values. These values
may intersect. MySQL does not implement these functions:
BdMPolyFromText(wkt,srid)
MultiPolygon
value from a
MultiLineString
value in WKT format containing
an arbitrary collection of closed LineString
values.
BdPolyFromText(wkt,srid)
Polygon
value from a
MultiLineString
value in WKT format containing
an arbitrary collection of closed LineString
values.
MySQL provides a number of functions that take as input parameters a
BLOB
containing a Well-Known Binary representation
and, optionally, a spatial reference
system identifier (SRID). They return the corresponding geometry.
GeomFromWKT()
accepts a WKB of any geometry type as its first
argument. An implementation also provides type-specific construction
functions for construction of geometry values of each geometry type.
GeomCollFromWKB(wkb[,srid])
GeometryCollectionFromWKB(wkt[,srid])
GEOMETRYCOLLECTION
value using its WKB representation and SRID.
GeomFromWKB(wkb[,srid])
GeometryFromWKB(wkt[,srid])
LineFromWKB(wkb[,srid])
LineStringFromWKB(wkb[,srid])
LINESTRING
value using its WKB representation and SRID.
MLineFromWKB(wkb[,srid])
MultiLineStringFromWKB(wkb[,srid])
MULTILINESTRING
value using its WKB representation and SRID.
MPointFromWKB(wkb[,srid])
MultiPointFromWKB(wkb[,srid])
MULTIPOINT
value using its WKB representation and SRID.
MPolyFromWKB(wkb[,srid])
MultiPolygonFromWKB(wkb[,srid])
MULTIPOLYGON
value using its WKB representation and SRID.
PointFromWKB(wkb[,srid])
POINT
value using its WKB representation and SRID.
PolyFromWKB(wkb[,srid])
PolygonFromWKB(wkb[,srid])
POLYGON
value using its WKB representation and SRID.
The OpenGIS specification also describes optional functions for constructing
Polygon
or MultiPolygon
values based on the WKB representation
of a collection of rings or closed LineString
values. These values
may intersect. MySQL does not implement these functions:
BdMPolyFromWKB(wkb,srid)
MultiPolygon
value from a
MultiLineString
value in WKB format containing
an arbitrary collection of closed LineString
values.
BdPolyFromWKB(wkb,srid)
Polygon
value from a
MultiLineString
value in WKB format containing
an arbitrary collection of closed LineString
values.
Note: MySQL does not implement the functions listed in this section.
MySQL provides a set of useful functions for creating geometry WKB
representations. The functions described in this section are MySQL
extensions to the OpenGIS specifications. The results of these
functions are BLOB
values containing WKB representations of geometry
values with no SRID.
The results of these functions can be substituted as the first argument
for any function in the GeomFromWKB()
function family.
GeometryCollection(g1,g2,...)
GeometryCollection
. If any argument is not a
well-formed WKB representation of a geometry, the return value is
NULL
.
LineString(pt1,pt2,...)
LineString
value from a number of WKB Point
arguments. If any argument is not a WKB Point
, the return value
is NULL
. If the number of Point
arguments is less than two,
the return value is NULL
.
MultiLineString(ls1,ls2,...)
MultiLineString
value using WKB LineString
arguments. If any argument is not a WKB LineString
, the return
value is NULL
.
MultiPoint(pt1,pt2,...)
MultiPoint
value using WKB Point
arguments.
If any argument is not a WKB Point
, the return value is NULL
.
MultiPolygon(poly1,poly2,...)
MultiPolygon
value from a set of WKB Polygon
arguments.
If any argument is not a WKB Polygon
, the return value is NULL
.
Point(x,y)
Point
using its coordinates.
Polygon(ls1,ls2,...)
Polygon
value from a number of WKB LineString
arguments. If any argument does not represent the WKB of a LinearRing
(that is, not a closed and simple LineString
) the return value
is NULL
.
MySQL provides a standard way of creating spatial columns for
geometry types, for example, with CREATE TABLE
or ALTER TABLE
.
Currently, spatial columns are supported only for MyISAM
tables.
CREATE TABLE
statement to create a table with a spatial column:
mysql> CREATE TABLE geom (g GEOMETRY); Query OK, 0 rows affected (0.02 sec)
ALTER TABLE
statement to add or drop a spatial column to or
from an existing table:
mysql> ALTER TABLE geom ADD pt POINT; Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> ALTER TABLE geom DROP pt; Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0
After you have created spatial columns, you can populate them with spatial data.
Values should be stored in internal geometry format, but you can convert them to that format from either Well-Known Text (WKT) or Well-Known Binary (WKB) format. The following examples demonstrate how to insert geometry values into a table by converting WKT values into internal geometry format.
You can perform the conversion directly in the INSERT
statement:
INSERT INTO geom VALUES (GeomFromText('POINT(1 1)')); SET @g = 'POINT(1 1)'; INSERT INTO geom VALUES (GeomFromText(@g));
Or you can perform the conversion prior to the INSERT
:
SET @g = GeomFromText('POINT(1 1)'); INSERT INTO geom VALUES (@g);
The following examples insert more complex geometries into the table:
SET @g = 'LINESTRING(0 0,1 1,2 2)'; INSERT INTO geom VALUES (GeomFromText(@g)); SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'; INSERT INTO geom VALUES (GeomFromText(@g)); SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'; INSERT INTO geom VALUES (GeomFromText(@g));
The preceding examples all use GeomFromText()
to create geometry
values. You can also use type-specific functions:
SET @g = 'POINT(1 1)'; INSERT INTO geom VALUES (PointFromText(@g)); SET @g = 'LINESTRING(0 0,1 1,2 2)'; INSERT INTO geom VALUES (LineStringFromText(@g)); SET @g = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'; INSERT INTO geom VALUES (PolygonFromText(@g)); SET @g = 'GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'; INSERT INTO geom VALUES (GeomCollFromText(@g));
Note that if a client application program wants to use WKB representations of geometry values, it is responsible for sending correctly formed WKB in queries to the server. However, there are several ways of satisfying this requirement. For example:
POINT(1 1)
value with hex literal syntax:
mysql> INSERT INTO geom VALUES -> (GeomFromWKB(0x0101000000000000000000F03F000000000000F03F));
BLOB
type:
INSERT INTO geom VALUES (GeomFromWKB(?))Other programming interfaces may support a similar placeholder mechanism.
mysql_real_escape_string()
and include the result in a query string
that is sent to the server.
See section 22.2.3.47 mysql_real_escape_string()
.
Geometry values stored in a table can be fetched in internal format. You can also convert them into WKT or WKB format.
Fetching geometry values using internal format can be useful in table-to-table transfers:
CREATE TABLE geom2 (g GEOMETRY) SELECT g FROM geom;
The AsText()
function converts a geometry from internal format into a WKT string.
mysql> SELECT AsText(g) FROM geom; +-------------------------+ | AsText(p1) | +-------------------------+ | POINT(1 1) | | LINESTRING(0 0,1 1,2 2) | +-------------------------+
The AsBinary()
function converts a geometry from internal format into a BLOB
containing
the WKB value.
SELECT AsBinary(g) FROM geom;
After populating spatial columns with values, you are ready to query and analyze them. MySQL provides a set of functions to perform various operations on spatial data. These functions can be grouped into four major categories according to the type of operation they perform:
Spatial analysis functions can be used in many contexts, such as:
mysql
or MySQLCC
MySQL supports the following functions for converting geometry values between internal format and either WKT or WKB format:
AsBinary(g)
AsText(g)
mysql> SET @g = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(GeomFromText(@g)); +--------------------------+ | AsText(GeomFromText(@G)) | +--------------------------+ | LINESTRING(1 1,2 2,3 3) | +--------------------------+
GeomFromText(wkt[,srid])
PointFromText()
and LineFromText()
; see
section 18.4.2.1 Creating Geometry Values Using WKT Functions.
GeomFromWKB(wkb[,srid])
PointFromWKB()
and LineFromWKB()
; see
section 18.4.2.2 Creating Geometry Values Using WKB Functions.
Geometry
Functions
Each function that belongs to this group takes a geometry value as its
argument and returns some quantitative or qualitative property of the
geometry. Some functions restrict their argument type. Such functions
return NULL
if the argument is of an incorrect geometry
type. For example, Area()
returns NULL
if the object
type is neither Polygon
nor MultiPolygon
.
The functions listed in this section do not restrict their argument and accept a geometry value of any type.
Dimension(g)
Geometry
.)
mysql> SELECT Dimension(GeomFromText('LineString(1 1,2 2)')); +------------------------------------------------+ | Dimension(GeomFromText('LineString(1 1,2 2)')) | +------------------------------------------------+ | 1 | +------------------------------------------------+
Envelope(g)
Polygon
value.
mysql> SELECT AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))); +-------------------------------------------------------+ | AsText(Envelope(GeomFromText('LineString(1 1,2 2)'))) | +-------------------------------------------------------+ | POLYGON((1 1,2 1,2 2,1 2,1 1)) | +-------------------------------------------------------+The polygon is defined by the corner points of the bounding box:
POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
GeometryType(g)
Geometry
subclasses.
mysql> SELECT GeometryType(GeomFromText('POINT(1 1)')); +------------------------------------------+ | GeometryType(GeomFromText('POINT(1 1)')) | +------------------------------------------+ | POINT | +------------------------------------------+
SRID(g)
mysql> SELECT SRID(GeomFromText('LineString(1 1,2 2)',101)); +-----------------------------------------------+ | SRID(GeomFromText('LineString(1 1,2 2)',101)) | +-----------------------------------------------+ | 101 | +-----------------------------------------------+
The OpenGIS specification also defines the following functions, which MySQL does not implement:
Boundary(g)
IsEmpty(g)
NULL
.
If the geometry is empty, it represents the empty point set.
IsSimple(g)
IsSimple()
returns 0 if the
argument is not simple, and -1 if it is NULL
.
The description of each instantiable geometric class given earlier in
the chapter includes the specific conditions that cause an instance of
that class to be classified as not simple.
Point
Functions
A Point
consists of X and Y coordinates, which may be obtained
using the following functions:
X(p)
mysql> SELECT X(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | X(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 56.7 | +--------------------------------------+
Y(p)
mysql> SELECT Y(GeomFromText('Point(56.7 53.34)')); +--------------------------------------+ | Y(GeomFromText('Point(56.7 53.34)')) | +--------------------------------------+ | 53.34 | +--------------------------------------+
LineString
Functions
A LineString
consists of Point
values. You can extract
particular points of a LineString
, count the number of points that it
contains, or obtain its length.
EndPoint(ls)
Point
that is the end point of the LineString
value
ls.
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(EndPoint(GeomFromText(@ls))); +-------------------------------------+ | AsText(EndPoint(GeomFromText(@ls))) | +-------------------------------------+ | POINT(3 3) | +-------------------------------------+
GLength(ls)
LineString
value ls in its associated spatial reference.
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT GLength(GeomFromText(@ls)); +----------------------------+ | GLength(GeomFromText(@ls)) | +----------------------------+ | 2.8284271247462 | +----------------------------+
IsClosed(ls)
LineString
value ls is closed
(that is, its StartPoint()
and EndPoint()
values are the same).
Returns 0 if ls is not closed, and -1 if it is NULL
.
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT IsClosed(GeomFromText(@ls)); +-----------------------------+ | IsClosed(GeomFromText(@ls)) | +-----------------------------+ | 0 | +-----------------------------+
NumPoints(ls)
LineString
value ls.
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT NumPoints(GeomFromText(@ls)); +------------------------------+ | NumPoints(GeomFromText(@ls)) | +------------------------------+ | 3 | +------------------------------+
PointN(ls,n)
Linestring
value ls.
Point numbers begin at 1.
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(PointN(GeomFromText(@ls),2)); +-------------------------------------+ | AsText(PointN(GeomFromText(@ls),2)) | +-------------------------------------+ | POINT(2 2) | +-------------------------------------+
StartPoint(ls)
Point
that is the start point of the LineString
value
ls.
mysql> SET @ls = 'LineString(1 1,2 2,3 3)'; mysql> SELECT AsText(StartPoint(GeomFromText(@ls))); +---------------------------------------+ | AsText(StartPoint(GeomFromText(@ls))) | +---------------------------------------+ | POINT(1 1) | +---------------------------------------+
The OpenGIS specification also defines the following function, which MySQL does not implement:
IsRing(ls)
LineString
value ls is closed
(that is, its StartPoint()
and EndPoint()
values are the same)
and is simple (does not pass through the same point more than once).
Returns 0 if ls is not a ring, and -1 if it is NULL
.
MultiLineString
FunctionsGLength(mls)
MultiLineString
value mls. The length of
mls is equal to the sum of the lengths of its elements.
mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))'; mysql> SELECT GLength(GeomFromText(@mls)); +-----------------------------+ | GLength(GeomFromText(@mls)) | +-----------------------------+ | 4.2426406871193 | +-----------------------------+
IsClosed(mls)
MultiLineString
value mls is closed
(that is, the StartPoint()
and EndPoint()
values are the same
for each LineString
in mls).
Returns 0 if mls is not closed, and -1 if it is NULL
.
mysql> SET @mls = 'MultiLineString((1 1,2 2,3 3),(4 4,5 5))'; mysql> SELECT IsClosed(GeomFromText(@mls)); +------------------------------+ | IsClosed(GeomFromText(@mls)) | +------------------------------+ | 0 | +------------------------------+
Polygon
FunctionsArea(poly)
Polygon
value
poly, as measured in its spatial reference system.
mysql> SET @poly = 'Polygon((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))'; mysql> SELECT Area(GeomFromText(@poly)); +---------------------------+ | Area(GeomFromText(@poly)) | +---------------------------+ | 4 | +---------------------------+
ExteriorRing(poly)
Polygon
value poly
as a LineString
.
mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT AsText(ExteriorRing(GeomFromText(@poly))); +-------------------------------------------+ | AsText(ExteriorRing(GeomFromText(@poly))) | +-------------------------------------------+ | LINESTRING(0 0,0 3,3 3,3 0,0 0) | +-------------------------------------------+
InteriorRingN(poly,n)
Polygon
value
poly as a LineString
.
Ring numbers begin at 1.
mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT AsText(InteriorRingN(GeomFromText(@poly),1)); +----------------------------------------------+ | AsText(InteriorRingN(GeomFromText(@poly),1)) | +----------------------------------------------+ | LINESTRING(1 1,1 2,2 2,2 1,1 1) | +----------------------------------------------+
NumInteriorRings(poly)
Polygon
value poly.
mysql> SET @poly = -> 'Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1))'; mysql> SELECT NumInteriorRings(GeomFromText(@poly)); +---------------------------------------+ | NumInteriorRings(GeomFromText(@poly)) | +---------------------------------------+ | 1 | +---------------------------------------+
MultiPolygon
FunctionsArea(mpoly)
MultiPolygon
value mpoly, as measured in its spatial reference system.
mysql> SET @mpoly = -> 'MultiPolygon(((0 0,0 3,3 3,3 0,0 0),(1 1,1 2,2 2,2 1,1 1)))'; mysql> SELECT Area(GeomFromText(@mpoly)); +----------------------------+ | Area(GeomFromText(@mpoly)) | +----------------------------+ | 8 | +----------------------------+
The OpenGIS specification also defines the following functions, which MySQL does not implement:
Centroid(mpoly)
MultiPolygon
value
mpoly as a Point
. The result is not guaranteed to be on
the MultiPolygon
.
PointOnSurface(mpoly)
Point
value that is guaranteed to be on the
MultiPolygon
value mpoly.
GeometryCollection
FunctionsGeometryN(gc,n)
GeometryCollection
value
gc. Geometry numbers begin at 1.
mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))'; mysql> SELECT AsText(GeometryN(GeomFromText(@gc),1)); +----------------------------------------+ | AsText(GeometryN(GeomFromText(@gc),1)) | +----------------------------------------+ | POINT(1 1) | +----------------------------------------+
NumGeometries(gc)
GeometryCollection
value
gc.
mysql> SET @gc = 'GeometryCollection(Point(1 1),LineString(2 2, 3 3))'; mysql> SELECT NumGeometries(GeomFromText(@gc)); +----------------------------------+ | NumGeometries(GeomFromText(@gc)) | +----------------------------------+ | 2 | +----------------------------------+
In the section section 18.5.2 Geometry
Functions,
we've discussed some functions that can construct new geometries
from the existing ones:
Envelope(g)
StartPoint(ls)
EndPoint(ls)
PointN(ls,n)
ExteriorRing(poly)
InteriorRingN(poly,n)
GeometryN(gc,n)
OpenGIS proposes a number of other functions that can produce geometries. They are designed to implement spatial operators.
These functions are not implemented in MySQL. They may appear in future releases.
Buffer(g,d)
ConvexHull(g)
Difference(g1,g2)
Intersection(g1,g2)
SymDifference(g1,g2)
Union(g1,g2)
The functions described in these sections take two geometries as input parameters and return a qualitative or quantitative relation between them.
MySQL provides some functions that can test relations
between minimal bounding rectangles of two geometries g1
and g2
.
They include:
MBRContains(g1,g2)
mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); mysql> SET @g2 = GeomFromText('Point(1 1)'); mysql> SELECT MBRContains(@g1,@g2), MBRContains(@g2,@g1); ----------------------+----------------------+ | MBRContains(@g1,@g2) | MBRContains(@g2,@g1) | +----------------------+----------------------+ | 1 | 0 | +----------------------+----------------------+
MBRDisjoint(g1,g2)
MBREqual(g1,g2)
MBRIntersects(g1,g2)
MBROverlaps(g1,g2)
MBRTouches(g1,g2)
MBRWithin(g1,g2)
mysql> SET @g1 = GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); mysql> SET @g2 = GeomFromText('Polygon((0 0,0 5,5 5,5 0,0 0))'); mysql> SELECT MBRWithin(@g1,@g2), MBRWithin(@g2,@g1); +--------------------+--------------------+ | MBRWithin(@g1,@g2) | MBRWithin(@g2,@g1) | +--------------------+--------------------+ | 1 | 0 | +--------------------+--------------------+
The OpenGIS specification defines the following functions. Currently,
MySQL does not implement them according to the specification. Those that
are implemented return the same result as the corresponding
MBR-based functions. This includes functions in the following list
other than Distance()
and Related()
.
These functions may be implemented in future releases with full support for spatial analysis, not just MBR-based support.
The functions operate on two geometry values g1
and g2
.
Contains(g1,g2)
Crosses(g1,g2)
NULL
if g1
is a Polygon
or a MultiPolygon
,
or if g2 is a Point
or a MultiPoint
.
Otherwise, returns 0.
The term spatially crosses denotes a spatial relation between two given
geometries that has the following properties:
Disjoint(g1,g2)
Distance(g1,g2)
Equals(g1,g2)
Intersects(g1,g2)
Overlaps(g1,g2)
Related(g1,g2,pattern_matrix)
NULL
.
The pattern matrix is a string. Its specification will be noted here if this
function is implemented.
Touches(g1,g2)
Within(g1,g2)
Search operations in non-spatial databases can be optimized using indexes. This is true for spatial databases as well. With the help of a great variety of multi-dimensional indexing methods that have previously been designed, it is possible to optimize spatial searches. The most typical of these are:
MySQL uses R-Trees with quadratic splitting to index spatial columns. A spatial index is built using the MBR of a geometry. For most geometries, the MBR is a minimum rectangle that surrounds the geometries. For a horizontal or a vertical linestring, the MBR is a rectangle degenerated into the linestring. For a point, the MBR is a rectangle degenerated into the point.
MySQL can create spatial indexes using syntax similar to that for creating
regular indexes, but extended with the SPATIAL
keyword.
Spatial columns that are indexed currently must be declared NOT NULL
.
The following examples demonstrate how to create spatial indexes.
CREATE TABLE
:
mysql> CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g));
ALTER TABLE
:
mysql> ALTER TABLE geom ADD SPATIAL INDEX(g);
CREATE INDEX
:
mysql> CREATE SPATIAL INDEX sp_index ON geom (g);
To drop spatial indexes, use ALTER TABLE
or DROP INDEX
:
ALTER TABLE
:
mysql> ALTER TABLE geom DROP INDEX g;
DROP INDEX
:
mysql> DROP INDEX sp_index ON geom;
Example: Suppose that a table geom
contains more than 32,000 geometries,
which are stored in the column g
of type GEOMETRY
.
The table also has an AUTO_INCREMENT
column fid
for storing
object ID values.
mysql> DESCRIBE geom; +-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | fid | int(11) | | PRI | NULL | auto_increment | | g | geometry | | | | | +-------+----------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> SELECT COUNT(*) FROM geom; +----------+ | count(*) | +----------+ | 32376 | +----------+ 1 row in set (0.00 sec)
To add a spatial index on the column g
, use this statement:
mysql> ALTER TABLE geom ADD SPATIAL INDEX(g); Query OK, 32376 rows affected (4.05 sec) Records: 32376 Duplicates: 0 Warnings: 0
The optimizer investigates whether available spatial indexes can
be involved in the search for queries that use a function such as
MBRContains()
or MBRWithin()
in the WHERE
clause.
For example, let's say we want to find all objects that are in the
given rectangle:
mysql> SELECT fid,AsText(g) FROM geom WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-----+-----------------------------------------------------------------------------+ | fid | AsText(g) | +-----+-----------------------------------------------------------------------------+ | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8) | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4) | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2) | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823) | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2) | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) | | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2) | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121) | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113) | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6) | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2) | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077) | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4) | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019) | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8) | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8) | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134) | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4) | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001) | +-----+-----------------------------------------------------------------------------+ 20 rows in set (0.00 sec)
Lets use EXPLAIN
to check the way this query is executed (the
id
column has been removed so the output better fits the page):
mysql> EXPLAIN SELECT fid,AsText(g) FROM geom WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-------------+-------+-------+---------------+------+---------+------+------+-------------+ | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------------+-------+-------+---------------+------+---------+------+------+-------------+ | SIMPLE | geom | range | g | g | 32 | NULL | 50 | Using where | +-------------+-------+-------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
Lets check what would happen without a spatial index:
mysql> EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-------------+-------+------+---------------+------+---------+------+-------+-------------+ | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------------+-------+------+---------------+------+---------+------+-------+-------------+ | SIMPLE | geom | ALL | NULL | NULL | NULL | NULL | 32376 | Using where | +-------------+-------+------+---------------+------+---------+------+-------+-------------+ 1 row in set (0.00 sec)
Let's execute the SELECT
statement, ignoring the spatial key we have:
mysql> SELECT fid,AsText(g) FROM geom IGNORE INDEX (g) WHERE mysql> MBRContains(GeomFromText('Polygon((30000 15000,31000 15000,31000 16000,30000 16000,30000 15000))'),g); +-----+-----------------------------------------------------------------------------+ | fid | AsText(g) | +-----+-----------------------------------------------------------------------------+ | 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2) | | 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121) | | 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113) | | 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6) | | 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2) | | 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077) | | 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4) | | 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019) | | 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8) | | 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8) | | 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8) | | 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4) | | 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2) | | 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823) | | 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2) | | 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2) | | 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134) | | 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4) | | 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001) | | 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4) | +-----+-----------------------------------------------------------------------------+ 20 rows in set (0.46 sec)
When the index is not used, the execution time for this query rises from 0.00 seconds to 0.46 seconds.
In future releases, spatial indexes may also be used for optimizing other functions. See section 18.5.4 Functions for Testing Spatial Relations Between Geometric Objects.
GEOMETRY_COLUMNS
contains a
description of geometry columns, one row for each geometry column
in the database.
Length()
on LineString
and MultiLineString
currently should be called in MySQL as GLength()
Length()
which calculates the length of string values,
and sometimes it is not possible to distinguish whether the function is
called in a textual or spatial context. We need either to solve this
somehow, or decide on another function name.
Stored procedures and functions are a new feature in MySQL version 5.0. A stored procedure is a set of SQL statements that can be stored in the server. Once this has been done, clients don't need to keep reissuing the individual statements but can refer to the stored procedure instead.
Some situations where stored procedures can be particularly useful:
Stored procedures can provide improved performance because less information needs to be sent between the server and the client. The tradeoff is that this does increase the load on the database server system because more of the work is done on the server side and less is done on the client (application) side. Consider this if many client machines (such as Web servers) are serviced by only one or a few database servers.
Stored procedures also allow you to have libraries of functions in the database server. This is a feature shared by modern application languages that allow such design internally, for example, by using classes. Using these client application language features is beneficial for the programmer even outside the scope of database use.
MySQL follows the SQL:2003 syntax for stored procedures, which is also used by IBM's DB2.
The MySQL implementation of stored procedures is still in progress. All syntax described in this chapter is supported and any limitations and extensions are documented where appropriate.
Stored procedures require the proc
table in the mysql
database.
This table is created during the MySQL 5.0 installation procedure.
If you are upgrading to MySQL 5.0 from an earlier version, be sure to update
your grant tables to make sure that the proc
table exists.
See section 2.10.7 Upgrading the Grant Tables.
Beginning with MySQL 5.0.3, the grant system has been modified to take stored routines into account as follows:
CREATE ROUTINE
is needed to create stored routines.
ALTER ROUTINE
privilege is needed to alter or drop stored routines.
This privilege is granted automatically to the creator of a routine.
EXECUTE
privilege is required to execute stored routines.
However, this privilege is granted automatically to the creator of a
routine. Also, the default SQL SECURITY
characteristic for a routine is
DEFINER
, which allows users who have access to the database with
which the routine is associated to execute the routine.
Stored procedures and functions are routines that are created with
CREATE PROCEDURE
and CREATE FUNCTION
statements.
A routine is either a procedure or a function.
A procedure is invoked using a CALL
statement, and can only
pass back values using output variables. A function can be called from
inside a statement just like any other function (that is, by invoking the
function's name), and can return a scalar value.
Stored routines may call other stored routines.
As of MySQL 5.0.1, a stored procedure or function is associated with a particular database. This has several implications:
USE
db_name
is performed (and undone when the routine terminates).
USE
statements within stored routines are disallowed.
p
or function f
that is associated with the test
database, you can say
CALL test.p()
or test.f()
.
(In MySQL 5.0.0, stored routines are global and not associated with
a database. They inherit the default database from the caller. If a
USE db_name
is executed within the routine, the original default
database is restored upon routine exit.)
MySQL supports the very useful extension that allows the use of regular
SELECT
statements (that is, without using cursors or local variables)
inside a stored procedure. The result set of such a query is simply sent
directly to the client.
Multiple SELECT
statements generate multiple result sets, so the client
must use a MySQL client library that supports multiple result sets. This means
the client must use a client library from a version of MySQL at least as
recent as 4.1.
This following section describes the syntax used to create, alter, drop, and query stored procedures and functions.
CREATE PROCEDURE
and CREATE FUNCTION
CREATE PROCEDURE sp_name ([parameter[,...]]) [characteristic ...] routine_body CREATE FUNCTION sp_name ([parameter[,...]]) RETURNS type [characteristic ...] routine_body parameter: [ IN | OUT | INOUT ] param_name type type: Any valid MySQL data type characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | SQL SECURITY {DEFINER | INVOKER} | COMMENT 'string' routine_body: Valid SQL procedure statements or statements
These statements create a stored routine. As of MySQL 5.0.3, to create a
routine, it is necessary to have the CREATE ROUTINE
privilege for
it, and the ALTER ROUTINE
and EXECUTE
privileges are granted
automatically to its creator.
By default, the routine is associated with the current database. To associate the routine explicitly with a given database, specify the name as db_name.sp_name when you create it.
If the routine name is the same as the name of a built-in SQL function, you will need to use a space between the name and the following parenthesis when defining the routine, or a syntax error will occur. This is also true when you invoke the routine later.
The RETURNS
clause may be specified only for a FUNCTION
,
for which it is mandatory.
It is used to indicate the return type of the function, and the function
body must contain a RETURN value
statement.
The parameter list enclosed within parentheses must always be present.
If there are no parameters, an empty parameter list of ()
should
be used. Each parameter is an IN
parameter by default. To specify
otherwise for a parameter, use the keyword OUT
or INOUT
before
the parameter name. Specifying IN
, OUT
, or INOUT
is only
valid for a PROCEDURE
.
The CREATE FUNCTION
statement is used in
earlier versions of MySQL to support UDFs (User Defined Functions).
See section 25.2 Adding New Functions to MySQL.
UDFs continue to be supported, even with the existence of stored functions.
A UDF can be regarded as an external stored function. However, do
note that stored functions share their namespace with UDFs.
A framework for external stored procedures will be introduced in the near future. This will allow you to write stored procedures in languages other than SQL. Most likely, one of the first languages to be supported will be PHP because the core PHP engine is small, thread-safe, and can easily be embedded. Because the framework will be public, it is expected that many other languages will also be supported.
A function is considered ``deterministic'' if it always returns the same
result for the same input parameters, and ``not deterministic'' otherwise.
Currently, the DETERMINISTIC
characteristic is accepted, but not yet
used by the optimizer.
The SQL SECURITY
characteristic can be used to specify whether the
routine should be executed using the permissions of the user who creates the
routine or the user who invokes it. The default value is DEFINER
.
This feature is new in SQL:2003. The creator or invoker must have
permission to access the database with which the routine is associated. As
of MySQL 5.0.3, it is necessary to have the EXECUTE
privilege to be
able to execute the routine. The user that must have this privilege is
either the definer or invoker, depending on how the SQL SECURITY
characteristic is set.
MySQL stores the sql_mode
system variable setting that is in effect
at the time a routine is created, and will always execute the routine with
this setting in force.
The COMMENT
clause is a MySQL extension, and may be used to describe
the stored procedure. This information is displayed by the
SHOW CREATE PROCEDURE
and SHOW CREATE FUNCTION
statements.
MySQL allows routines to contain DDL statements (such as CREATE
and
DROP
) and SQL transaction statements (such as COMMIT
). This is
not required by the standard and therefore is implementation-specific.
Note:
Currently, stored functions created with CREATE FUNCTION
may not
contain references to tables. Please note that this includes some SET
statements, but excludes some SELECT
statements. This limitation
will be lifted as soon as possible.
The following is an example of a simple stored procedure that uses
an OUT
parameter.
The example uses the mysql
client delimiter
command to change
the statement delimiter from ;
to //
while the procedure is
being defined.
This allows the ;
delimiter used in the procedure body to be passed
through to the server rather than being interpreted by mysql
itself.
mysql> delimiter // mysql> CREATE PROCEDURE simpleproc (OUT param1 INT) -> BEGIN -> SELECT COUNT(*) INTO param1 FROM t; -> END -> // Query OK, 0 rows affected (0.00 sec) mysql> delimiter ; mysql> CALL simpleproc(@a); Query OK, 0 rows affected (0.00 sec) mysql> SELECT @a; +------+ | @a | +------+ | 3 | +------+ 1 row in set (0.00 sec)
The following is an example of a function that takes a parameter, performs an operation using an SQL function, and returns the result:
mysql> delimiter // mysql> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50) -> RETURN CONCAT('Hello, ',s,'!'); -> // Query OK, 0 rows affected (0.00 sec) mysql> delimiter ; mysql> SELECT hello('world'); +----------------+ | hello('world') | +----------------+ | Hello, world! | +----------------+ 1 row in set (0.00 sec)
ALTER PROCEDURE
and ALTER FUNCTION
ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...] characteristic: SQL SECURITY {DEFINER | INVOKER} | COMMENT 'string'
This statement can be used to change the characteristics of a stored
procedure or function. You must have the ALTER ROUTINE
privilege for
the routine as of MySQL 5.0.3. This privilege is granted automatically to
the routine creator.
More than one change may be specified in an ALTER PROCEDURE
or
ALTER FUNCTION
statement.
DROP PROCEDURE
and DROP FUNCTION
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
This statement is used to drop a stored procedure or function. That is, the
specified routine is removed from the server. You must have the ALTER
ROUTINE
privilege for the routine as of MySQL 5.0.3. This privilege is
granted automatically to the routine creator.
The IF EXISTS
clause is a MySQL extension.
It prevents an error from occurring if the procedure or function does not
exist. A warning is produced that can be viewed with SHOW WARNINGS
.
SHOW CREATE PROCEDURE
and SHOW CREATE FUNCTION
SHOW CREATE {PROCEDURE | FUNCTION} sp_name
This statement is a MySQL extension. Similar to SHOW CREATE TABLE
, it
returns the exact string that can be used to re-create the named routine.
mysql> SHOW CREATE FUNCTION test.hello\G *************************** 1. row *************************** Function: hello sql_mode: Create Function: CREATE FUNCTION `test`.`hello`(s CHAR(20)) RETURNS CHAR(50) RETURN CONCAT('Hello, ',s,'!')
SHOW PROCEDURE STATUS
and SHOW FUNCTION STATUS
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
This statement is a MySQL extension. It returns characteristics of routines, such as the database, name, type, creator, and creation and modification dates. If no pattern is specified, the information for all stored procedures or all stored functions is listed, depending on which statement you use.
mysql> SHOW FUNCTION STATUS LIKE 'hello'\G *************************** 1. row *************************** Db: test Name: hello Type: FUNCTION Definer: testuser@localhost Modified: 2004-08-03 15:29:37 Created: 2004-08-03 15:29:37 Security_type: DEFINER Comment:
CALL
StatementCALL sp_name([parameter[,...]])
The CALL
statement is used to invoke a procedure that was defined
previously with CREATE PROCEDURE
.
CALL
can return values through its parameters. It also ``returns''
the number of rows affected, which a client program can obtain at the SQL
level by calling the ROW_COUNT()
function and from C by calling the
mysql_affected_rows()
C API function.
BEGIN ... END
Compound Statement[begin_label:] BEGIN [statement_list] END [end_label]
Stored routines may contain multiple statements, using a
BEGIN ... END
compound statement.
begin_label and end_label must be the same, if both are specified.
Please note that the optional [NOT] ATOMIC
clause is not yet
supported. This means that no transactional savepoint is set at the start of
the instruction block and the BEGIN
clause used in this context has
no effect on the current transaction.
Using multiple statements requires that a client is able to send query
strings containing the ;
statement delimiter. This is handled in the
mysql
command-line client with the delimiter
command. Changing
the ;
end-of-query delimiter (for example, to //
) allows
;
to be used in a routine body.
DECLARE
Statement
The DECLARE
statement is used to define various items local to a
routine:
local variables (see section 19.1.6 Variables in Stored Procedures),
conditions and handlers (see section 19.1.7 Conditions and Handlers) and
cursors (see section 19.1.8 Cursors).
SIGNAL
and RESIGNAL
statements are not currently supported.
DECLARE
may be used only inside a BEGIN ... END
compound
statement and must be at its start, before any other statements.
Cursors must be declared before declaring handlers, and variables must be declared before declaring either cursors or handlers.
You may declare and use variables within a routine.
DECLARE
Local VariablesDECLARE var_name[,...] type [DEFAULT value]
This statement is used to declare local variables. The scope of a variable is
within the BEGIN ... END
block.
SET
StatementSET var_name = expr [, var_name = expr] ...
The SET
statement in stored procedures is an extended version of
the general SET
statement. Referenced variables may be ones declared
inside a routine, or global server variables.
The SET
statement in stored procedures is implemented as part of the
pre-existing SET
syntax. This allows an extended syntax of
SET a=x, b=y, ...
where different variable types (locally declared
variables, server variables, and global and session server variables) can be
mixed. This also allows combinations of local variables and some options
that make sense only for global/system variables; in that case, the options
are accepted but ignored.
SELECT ... INTO
StatementSELECT col_name[,...] INTO var_name[,...] table_expr
This SELECT
syntax stores selected columns directly into variables.
Therefore, only a single row may be retrieved. This statement is also
extremely useful when used in combination with cursors.
SELECT id,data INTO x,y FROM test.t1 LIMIT 1;
Certain conditions may require specific handling. These conditions can relate to errors, as well as general flow control inside a routine.
DECLARE
ConditionsDECLARE condition_name CONDITION FOR condition_value condition_value: SQLSTATE [VALUE] sqlstate_value | mysql_error_code
This statement specifies conditions that will need
specific handling. It associates a name with a specified error
condition. The name can subsequently be used in a
DECLARE HANDLER
statement.
See section 19.1.7.2 DECLARE
Handlers.
In addition to SQLSTATE values, MySQL error codes are also supported.
DECLARE
HandlersDECLARE handler_type HANDLER FOR condition_value[,...] sp_statement handler_type: CONTINUE | EXIT | UNDO condition_value: SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mysql_error_code
This statement specifies handlers that each may deal with one or more conditions. If one of these conditions occurs, the specified statement is executed.
For a CONTINUE
handler, execution of the current routine continues
after execution of the handler statement.
For an EXIT
handler, execution of the current BEGIN...END
compound statement is terminated.
The UNDO
handler type statement is not yet supported.
SQLWARNING
is shorthand for all SQLSTATE codes that begin with 01
.
NOT FOUND
is shorthand for all SQLSTATE codes that begin with 02
.
SQLEXCEPTION
is shorthand for all SQLSTATE codes not caught by
SQLWARNING
or NOT FOUND
.
In addition to SQLSTATE values, MySQL error codes are also supported.
For example:
mysql> CREATE TABLE test.t (s1 int,primary key (s1)); Query OK, 0 rows affected (0.00 sec) mysql> delimiter // mysql> CREATE PROCEDURE handlerdemo () -> BEGIN -> DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1; -> SET @x = 1; -> INSERT INTO test.t VALUES (1); -> SET @x = 2; -> INSERT INTO test.t VALUES (1); -> SET @x = 3; -> END; -> // Query OK, 0 rows affected (0.00 sec) mysql> CALL handlerdemo()// Query OK, 0 rows affected (0.00 sec) mysql> SELECT @x// +------+ | @x | +------+ | 3 | +------+ 1 row in set (0.00 sec)
Notice that @x
is 3
, which shows that MySQL executed to the end of
the procedure. If the line
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
had not been present, MySQL would have taken the default (EXIT
) path
after the second INSERT
failed due to the PRIMARY KEY
constraint, and SELECT @x
would have returned 2
.
Simple cursors are supported inside stored procedures and functions. The syntax is as in embedded SQL. Cursors are currently asensitive, read-only, and non-scrolling. Asensitive means that the server may or may not make a copy of its result table.
Cursors must be declared before declaring handlers, and variables must be declared before declaring either cursors or handlers.
For example:
CREATE PROCEDURE curdemo() BEGIN DECLARE done INT DEFAULT 0; DECLARE a CHAR(16); DECLARE b,c INT; DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1; DECLARE cur2 CURSOR FOR SELECT i FROM test.t2; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN cur1; OPEN cur2; REPEAT FETCH cur1 INTO a, b; FETCH cur2 INTO c; IF NOT done THEN IF b < c THEN INSERT INTO test.t3 VALUES (a,b); ELSE INSERT INTO test.t3 VALUES (a,c); END IF; END IF; UNTIL done END REPEAT; CLOSE cur1; CLOSE cur2; END
DECLARE cursor_name CURSOR FOR select_statement
This statement declares a cursor. Multiple cursors may be defined in a routine, but each must have a unique name.
The SELECT
statement cannot have an INTO
clause.
OPEN
StatementOPEN cursor_name
This statement opens a previously declared cursor.
FETCH
StatementFETCH cursor_name INTO var_name [, var_name] ...
This statement fetches the next row (if a row exists) using the specified open cursor, and advances the cursor pointer.
CLOSE
StatementCLOSE cursor_name
This statement closes a previously opened cursor.
If not closed explicitly, a cursor is closed at the end of the compound statement in which it was declared.
The IF
, CASE
, LOOP
, WHILE
, ITERATE
, and
LEAVE
constructs are fully implemented.
These constructs may each contain either a single statement, or a block of
statements using the BEGIN ... END
compound statement. Constructs
may be nested.
FOR
loops are not currently supported.
IF
StatementIF search_condition THEN statement_list [ELSEIF search_condition THEN statement_list] ... [ELSE statement_list] END IF
IF
implements a basic conditional construct. If the
search_condition evaluates to true, the corresponding SQL statement list
is executed. If no search_condition matches, the statement list in the
ELSE
clause is executed. statement_list can consist of one or
more statements.
Please note that there is also an IF()
function.
See section 12.2 Control Flow Functions.
CASE
StatementCASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list ...] [ELSE statement_list] END CASE
Or:
CASE WHEN search_condition THEN statement_list [WHEN search_condition THEN statement_list ...] [ELSE statement_list] END CASE
The
CASE
statement for stored procedures implements a complex conditional
construct. If a
search_condition evaluates to true, the corresponding SQL statement is executed. If no search condition matches, the statement in the ELSE
clause is executed.
Note: The syntax of a CASE
statement shown here
for use inside a stored procedure differs slightly from that of the SQL
CASE
expression described in section 12.2 Control Flow Functions.
The CASE
statement cannot have an ELSE NULL
clause, and it
is terminated with END CASE
instead of END
.
LOOP
Statement[begin_label:] LOOP statement_list END LOOP [end_label]
LOOP
implements a simple loop construct, enabling repeated execution
of a particular statement or statements. The statements within the
loop are repeated until the loop is exited; usually this is accomplished
with a LEAVE
statement.
begin_label and end_label must be the same, if both are specified.
LEAVE
StatementLEAVE label
This statement is used to exit any flow control construct.
ITERATE
StatementITERATE label
ITERATE
can only appear within LOOP
, REPEAT
, and
WHILE
statements. ITERATE
means ``do the loop iteration again.''
For example:
CREATE PROCEDURE doiterate(p1 INT) BEGIN label1: LOOP SET p1 = p1 + 1; IF p1 < 10 THEN ITERATE label1; END IF; LEAVE label1; END LOOP label1; SET @x = p1; END
REPEAT
Statement[begin_label:] REPEAT statement_list UNTIL search_condition END REPEAT [end_label]
The statement or statements within a REPEAT
statement are repeated
until the search_condition is true.
begin_label and end_label must be the same, if both are specified.
For example:
mysql> delimiter // mysql> CREATE PROCEDURE dorepeat(p1 INT) -> BEGIN -> SET @x = 0; -> REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; -> END -> // Query OK, 0 rows affected (0.00 sec) mysql> CALL dorepeat(1000)// Query OK, 0 rows affected (0.00 sec) mysql> SELECT @x// +------+ | @x | +------+ | 1001 | +------+ 1 row in set (0.00 sec)
WHILE
Statement[begin_label:] WHILE search_condition DO statement_list END WHILE [end_label]
The statement or statements within a WHILE
statement are repeated as
long as the search_condition is true.
begin_label and end_label must be the same, if both are specified.
For example:
CREATE PROCEDURE dowhile() BEGIN DECLARE v1 INT DEFAULT 5; WHILE v1 > 0 DO ... SET v1 = v1 - 1; END WHILE; END
Rudimentary support for triggers is included beginning with MySQL 5.0.2.
A trigger is a named database object that is associated with a table, and
that activates when a particular event occurs for the table. For example,
the following statements set up a table, as well as a trigger for INSERT
statements into the table. The trigger sums the values inserted into one of
the table's columns:
mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2)); mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account -> FOR EACH ROW SET @sum = @sum + NEW.amount;
This chapter describes the syntax for creating and dropping triggers, and show some examples of how to use them.
CREATE TRIGGER
SyntaxCREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_stmt
A trigger is a named database object that is associated with a table, and that activates when a particular event occurs for the table.
The trigger becomes associated with the table named tbl_name.
tbl_name must refer to a permanent table. You cannot associate a
trigger with a TEMPORARY
table or a view.
trigger_time is the trigger action time. It can be BEFORE
or
AFTER
to indicate that the trigger activates before or after the
statement that activated it.
trigger_event indicates the kind of statement that activates the
trigger. It can be INSERT
, UPDATE
, or DELETE
.
For example, a BEFORE
trigger for INSERT
statements could be
used to check the values to be inserted into new rows.
There cannot be two triggers for a given table that have the same trigger
action time and event. For example, you cannot have two BEFORE
UPDATE
triggers for a table. But you can have a BEFORE UPDATE
and a BEFORE INSERT
trigger, or a BEFORE UPDATE
and an
AFTER UPDATE
trigger.
trigger_stmt is the statement to execute when the trigger activates.
If you want to execute multiple statements, use the BEGIN ... END
compound statement construct. This also enables you to use the same
statements that are allowable within stored routines.
See section 19.1.4 BEGIN ... END
Compound Statement.
Note: Currently, triggers have the same limitation as stored functions that they may not contain direct references to tables by name. This limitation will be lifted as soon as possible.
However, in the triggered statement, you can refer to columns in the table
associated with the trigger by using the names OLD
and NEW
.
OLD.col_name
refers to a column of a an existing row before
it is updated or deleted. NEW.col_name
refers to the column
of a new row to be inserted or an existing row after it is updated.
Use of SET NEW.col_name = value
requires the UPDATE
privilege on the column. Use of SET value = NEW.col_name
requires the SELECT
privilege on the column.
The CREATE TRIGGER
statement requires the SUPER
privilege.
It was added in MySQL 5.0.2.
DROP TRIGGER
SyntaxDROP TRIGGER tbl_name.trigger_name
Drops a trigger. The name of the trigger to drop must include the table name because each trigger is associated with a particular table.
The DROP TRIGGER
statement requires the SUPER
privilege.
It was added in MySQL 5.0.2.
Support for triggers is included beginning with MySQL 5.0.2. Currently, trigger support is rudimentary, so there are certain limitations on what you can do with them. This section discusses how to use triggers and what the current limitations are.
A trigger is a named database object that is associated with a table, and that activates when a particular event occurs for the table. Some uses for triggers are to perform checks of values to be inserted into a table or to perform calculations on values involved in an update.
A trigger is associated with a table and is defined to activate when an
INSERT
, DELETE
, or UPDATE
statement for the table
executes. A trigger can be set to activate either before or after the
triggering statement. For example, you can have a trigger activate before
each row that is deleted from a table or after each row that is updated.
To create a trigger or drop a trigger, use the CREATE TRIGGER
or
DROP TRIGGER
statement. The syntax for these statements is described
in section 20.1 CREATE TRIGGER
Syntax and
section 20.2 DROP TRIGGER
Syntax.
Here is a simple example that associates a trigger with a table for
INSERT
statements. It acts as an accumulator to sum the values
inserted into one of the columns of the table.
The following statements create a table and a trigger for it:
mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2)); mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account -> FOR EACH ROW SET @sum = @sum + NEW.amount;
The CREATE TRIGGER
statement creates a trigger named ins_sum
that is associated with the account
table. It also includes clauses
that specify the trigger activation time, the triggering event, and what to
do with the trigger activates:
BEFORE
indicates the trigger action time. In this case,
the trigger should activate before each row inserted into the table. The
other allowable keyword here is AFTER
.
INSERT
indicates the event that activates the trigger.
In the example, INSERT
statements cause trigger activation. You can
also create triggers for DELETE
and UPDATE
statements.
FOR EACH ROW
defines the statement to execute
each time the trigger activates, which occurs once for each row affected by
the triggering statement In the example, the triggered statement is a
simple SET
that accumulates the values inserted into the
amount
column. The statement refers to the column as
NEW.amount
which means ``the value of the amount
column to be
inserted into the new row.''
To use the trigger, set the accumulator variable to zero, execute an
INSERT
statement, and then see what value the variable has afterward:
mysql> SET @sum = 0; mysql> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00); mysql> SELECT @sum AS 'Total amount inserted'; +-----------------------+ | Total amount inserted | +-----------------------+ | 1852.48 | +-----------------------+
In this case, the value of @sum
after the INSERT
statement
has executed is 14.98 + 1937.50 - 100
or 1852.48
.
To destroy the trigger, use a DROP TRIGGER
statement. The
trigger name must include the table name:
mysql> DROP TRIGGER account.ins_sum;
Because a trigger is associated with a particular table, you cannot have multiple triggers for a table that have the same name. You should also be aware that the namespace for triggers might change in the future from table to database. That is, the requirement that trigger names be unique for a given table might be strengthened to the requirement that they be unique within the database. For better forward compatibility with future development, try to use trigger names that do not overlap within a database.
In addition to the requirement that trigger names be unique for a table,
there are other limitations on the types of triggers you can create.
In particular, you cannot have two triggers for a table that have the same
activate time and activation event. For example, you cannot define two
BEFORE INSERT
triggers or two AFTER UPDATE
triggers for a table.
This should rarely be a significant limitation, because it is possible to
define a trigger that executes multiple statements by using the BEGIN
… END
compound statement construct after FOR EACH ROW
. (An example
appears later in this section.)
There are also limitations on what can appear in the statement that the trigger executes when activated:
OLD
and NEW
. OLD
refers to an existing row to be
deleted or a row to be updated before the update occurs. NEW
refers
to a new row to be inserted or an updated row after the update occurs.
CALL
statement.
(This means, for example, that you cannot get around the prohibition on
referring to tables by name by invoking a stored procedure that refers to
the tables.)
START TRANSACTION
, COMMIT
, or ROLLBACK
.
The OLD
and NEW
keywords enable you to access columns in
the rows affected by a trigger. (OLD
and NEW
are not case
sensitive.) In an INSERT
trigger, only NEW.col_name
can be used; there is no old row. In a DELETE
trigger, only
OLD.col_name
can be used; there is no new row. In an
UPDATE
trigger, you can use OLD.col_name
to refer to
the columns of a row before it is updated and NEW.col_name
to refer to the columns of the row after it is updated.
A column named with OLD
is read-only. You can refer to it but not
modify it. A column named with NEW
can be referred to if you have
the SELECT
privilege for it. In a BEFORE
trigger, you can also
change its value with SET NEW.col_name = value
if you
have the UPDATE
privilege for it. This means you can use a trigger to
modify the values to be inserted into a new row or that are used to update a
row.
OLD
and NEW
are MySQL extensions to triggers.
By using the BEGIN … END
construct, you can define a trigger
that executes multiple statements. Within the BEGIN
block, you also
can use other syntax that is allowed within stored routines such as
conditionals and loops. However, just as for stored routines, when you
define a trigger that executes multiple statements, it becomes necessary to
redefine the statement delimiter if you are entering the trigger with the
mysql
program so that you can use the `;' character within
the trigger definition. The following example illustrates these points. It
defines an UPDATE
trigger that checks the new value to be used for
updating each row, and modifies the value to be within the range
from 0 to 100. This must be a BEFORE
trigger because the value needs
to be checked before it is used to update the row:
mysql> delimiter // mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account -> FOR EACH ROW -> BEGIN -> IF NEW.amount < 0 THEN -> SET NEW.amount = 0; -> ELSEIF NEW.amount > 100 THEN -> SET NEW.amount = 100; -> END IF; -> END// mysql> delimiter ;
It might occur to you that it would be easier to define a stored procedure
separately and then invoke it from the trigger using a simple CALL
statement. That would also be advantageous if you wanted to invoke the same
routine from within several triggers. However, a limitation on triggers
is that CALL
cannot be used. You have to write
out the compound statement in each CREATE TRIGGER
statement where you
want to use it.
INFORMATION_SCHEMA
Information Database
INFORMATION_SCHEMA
support is available in MySQL 5.0.2 and later.
It provides access to database metadata.
``Metadata'' is data about the data, such as the name of a database or table, the data type of a column, or access privileges. Other terms that sometimes are used for this information are ``data dictionary'' or ``system catalog.''
Here is an example:
mysql> SELECT table_name, table_type, engine -> FROM information_schema.tables -> WHERE table_schema = 'db5' -> ORDER BY table_name DESC; +------------+------------+--------+ | table_name | table_type | engine | +------------+------------+--------+ | v56 | VIEW | NULL | | v3 | VIEW | NULL | | v2 | VIEW | NULL | | v | VIEW | NULL | | tables | BASE TABLE | MyISAM | | t7 | BASE TABLE | MyISAM | | t3 | BASE TABLE | MyISAM | | t2 | BASE TABLE | MyISAM | | t | BASE TABLE | MyISAM | | pk | BASE TABLE | InnoDB | | loop | BASE TABLE | MyISAM | | kurs | BASE TABLE | MyISAM | | k | BASE TABLE | MyISAM | | into | BASE TABLE | MyISAM | | goto | BASE TABLE | MyISAM | | fk2 | BASE TABLE | InnoDB | | fk | BASE TABLE | InnoDB | +------------+------------+--------+ 17 rows in set (0.01 sec)
Explanation: The statement requests a list of all the tables in database
db5
, in reverse alphabetical order, showing just three pieces of
information: the name of the table, its type, and its engine.
INFORMATION_SCHEMA
is the ``information database'', the place that
stores information about all the other databases that the MySQL server
maintains. Inside INFORMATION_SCHEMA
there are several read-only
tables. They are actually views, not base tables, so you won't actually see
any file associated with them.
Each MySQL user has the right to access these tables, but only the rows in the tables that correspond to objects for which the user has the proper access privileges.
Advantages of SELECT
The SELECT ... FROM INFORMATION_SCHEMA
statement is intended as a
more consistent way to provide access to the information provided by the
various SHOW
statements that MySQL supports (SHOW DATABASES
,
SHOW TABLES
, and so forth). Using SELECT
has these
advantages, compared to SHOW
:
SELECT
works, they only need to learn the object names.
However, because SHOW
is popular with MySQL employees and users, and
because it might be confusing were it to disappear, the advantages of
conventional syntax are not a sufficient reason to eliminate SHOW
.
In fact, there are enhancements to SHOW
in MySQL 5.0, too.
These are described in section 21.2 Extensions to SHOW
Statements.
Standards
The implementation for the INFORMATION_SCHEMA
table structures in
MySQL follows the ANSI/ISO SQL:2003 standard Part 11 ``Schemata.'' Our
intent is approximate compliance with SQL:2003 core feature F021 ``Basic
information schema.''
Users of SQL Server 2000 (which also follows the standard) will notice a
strong similarity. However, MySQL has omitted many columns that are not
relevant for our implementation, and added columns that are MySQL-specific.
One such column is the engine
column in the
INFORMATION_SCHEMA.TABLES
table.
Although other DBMSs use a variety of names, like syscat or system, the
standard name is INFORMATION_SCHEMA
.
In effect, we have a new ``database'' named information_schema
,
though there is never a need to make a file by that name. It will not be
possible to say USE INFORMATION_SCHEMA
. The only thing you can do
with these tables is SELECT
. You cannot update, insert, delete, or
even reference them.
Privileges
There is no difference between the current (SHOW
)
privilege requirement and the SELECT
requirement.
In either case, you have to have some privilege
on an object in order to see information about it.
INFORMATION_SCHEMA
TablesExplanation of following sections
In the following sections, we take the tables
and columns that are in INFORMATION_SCHEMA
.
For each column, there are three pieces of information:
SHOW
name'' indicates what the equivalent
field name is in the closest SHOW
statement, if any.
To avoid using any name that's reserved in the standard or in DB2 or in SQL
Server or in Oracle we changed the names of columns marked ``MySQL
extension.'' (For example, we changed COLLATION
to
TABLE_COLLATION
in the TABLES
table.) See the list of reserved
words near the end of this article:
http://www.dbazine.com/gulutzan5.shtml.
The definition for character columns (for example,
TABLES.TABLE_NAME
), is generally VARCHAR(N) CHARACTER SET
utf8
where N is at least 64.
Each section indicates what SHOW
statement is equivalent to a
SELECT
that retrieves information from INFORMATION_SCHEMA
, or
else that there is no such equivalent statement.
Note: At present, there are some missing columns and some columns out of order. We are working on that and will update the documentation as changes are made.
INFORMATION_SCHEMA SCHEMATA
Table
A schema is a database, so the SCHEMATA
table provides information
about databases.
Standard Name | SHOW name | Remarks |
CATALOG_NAME | - | NULL
|
SCHEMA_NAME | Database | |
SCHEMA_OWNER | omit | |
DEFAULT_CHARACTER_SET_CATALOG | omit | |
DEFAULT_CHARACTER_SET_SCHEMA | omit | |
DEFAULT_CHARACTER_SET_NAME | ||
SQL_PATH | NULL
|
Notes:
SQL_PATH
, we might eventually support
something in MySQL 5.x. For now, it's always NULL
.
The following statements are equivalent:
SELECT SCHEMA_NAME AS `Database` FROM INFORMATION_SCHEMA.SCHEMATA [WHERE SCHEMA_NAME LIKE 'wild'] SHOW DATABASES [LIKE 'wild']
INFORMATION_SCHEMA TABLES
Table
The TABLES
table provides information about tables in databases.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL
| |
TABLE_SCHEMA | Table_ ... | |
TABLE_NAME | Table_ ... | |
TABLE_TYPE | ||
SELF_REFERENCING_COLUMN_NAME | omit | |
REFERENCE_GENERATION | omit | |
USER_DEFINED_TYPE_NAME | omit | |
IS_INSERTABLE_INTO | omit | |
IS_TYPED | omit | |
COMMIT_ACTION | omit | |
ENGINE | Engine | MySQL extension |
VERSION | Version | MySQL extension |
ROW_FORMAT | Row_format | MySQL extension |
TABLE_ROWS | Rows | MySQL extension |
AVG_ROW_LENGTH | Avg_row_length | MySQL extension |
DATA_LENGTH | Data_length | MySQL extension |
MAX_DATA_LENGTH | Max_data_length | MySQL extension |
INDEX_LENGTH | Index_length | MySQL extension |
DATA_FREE | Data_free | MySQL extension |
AUTO_INCREMENT | Auto_increment | MySQL extension |
CREATE_TIME | Create_time | MySQL extension |
UPDATE_TIME | Update_time | MySQL extension |
CHECK_TIME | Check_time | MySQL extension |
TABLE_COLLATION | Collation | MySQL extension |
CHECKSUM | Checksum | MySQL extension |
CREATE_OPTIONS | Create_options | MySQL extension |
TABLE_COMMENT | Comment | MySQL extension |
Notes:
TABLE_SCHEMA
and TABLE_NAME
are a single field in a
SHOW
display, for example Table_in_db1
.
TABLE_TYPE
should be BASE TABLE
or VIEW
. If table is
temporary, then TABLE_TYPE
= TEMPORARY
. (There are no
temporary views, so this is not ambiguous.)
TABLE_COLLATION
is close, because collation names begin with a
character set name.
The following statements are equivalent:
SELECT table_name FROM INFORMATION_SCHEMA.TABLES [WHERE table_schema = 'db_name'] [WHERE|AND table_name LIKE 'wild'] SHOW TABLES [FROM db_name] [LIKE 'wild']
INFORMATION_SCHEMA COLUMNS
Table
The COLUMNS
table provides information about columns in tables.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL
| |
TABLE_SCHEMA | ||
TABLE_NAME | ||
COLUMN_NAME | Field | |
ORDINAL_POSITION | see notes | |
COLUMN_DEFAULT | Default | |
IS_NULLABLE | Null | |
DATA_TYPE | Type | |
CHARACTER_MAXIMUM_LENGTH | Type | |
CHARACTER_OCTET_LENGTH | ||
NUMERIC_PRECISION | Type | |
NUMERIC_PRECISION_RADIX | omit | |
NUMERIC_SCALE | Type | |
DATETIME_PRECISION | omit | |
INTERVAL_TYPE | omit | |
INTERVAL_PRECISION | omit | |
CHARACTER_SET_CATALOG | omit | |
CHARACTER_SET_SCHEMA | omit | |
CHARACTER_SET_NAME | ||
COLLATION_CATALOG | omit | |
COLLATION_SCHEMA | omit | |
COLLATION_NAME | Collation | |
DOMAIN_NAME | omit | |
UDT_CATALOG | omit | |
UDT_SCHEMA | omit | |
UDT_NAME | omit | |
SCOPE_CATALOG | omit | |
SCOPE_SCHEMA | omit | |
SCOPE_NAME | omit | |
MAXIMUM_CARDINALITY | omit | |
DTD_IDENTIFIER | omit | |
IS_SELF_REFERENCING | omit | |
IS_IDENTITY | omit | |
IDENTITY_GENERATION | omit | |
IDENTITY_START | omit | |
IDENTITY_INCREMENT | omit | |
IDENTITY_MAXIMUM | omit | |
IDENTITY_MINIMUM | omit | |
IDENTITY_CYCLE | omit | |
IS_GENERATED | omit | |
GENERATION_EXPRESSION | omit | |
COLUMN_KEY | Key | MySQL extension |
EXTRA | Extra | MySQL extension |
COLUMN_COMMENT | Comment | MySQL extension |
Notes:
SHOW
, the Type
display includes values from several
different COLUMNS
columns.
ORDINAL_POSITION
is necessary because you might someday want to say
ORDER BY ORDINAL_POSITION
. Unlike SHOW
, SELECT
does not
have automatic ordering.
CHARACTER_OCTET_LENGTH
should be the same as
CHARACTER_MAXIMUM_LENGTH
, except for multi-byte character sets.
CHARACTER_SET_NAME
can be derived from Collation
. For
example, if you say SHOW FULL COLUMNS FROM t
, and you see in the
Collation
column a value of latin1_swedish_ci
, the character
set is what's before the first underscore: latin1
.
The following statements are nearly equivalent:
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'tbl_name' [AND schema_name = 'db_name'] [AND column_name LIKE 'wild'] SHOW COLUMNS FROM tbl_name [FROM db_name] [LIKE wild]
INFORMATION_SCHEMA STATISTICS
Table
The STATISTICS
table provides information about table indexes.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL
| |
TABLE_SCHEMA | = Database | |
TABLE_NAME | Table | |
NON_UNIQUE | Non_unique | |
INDEX_SCHEMA | = Database | |
INDEX_NAME | Key_name | |
TYPE | omit | |
SEQ_IN_INDEX | Seq_in_index | |
COLUMN_NAME | Column_name | |
COLLATION | Collation | |
CARDINALITY | Cardinality | |
PAGES | omit | |
FILTER_CONDITION | omit | |
SUB_PART | Sub_part | MySQL extension |
PACKED | Packed | MySQL extension |
NULLABLE | Null | MySQL extension |
INDEX_TYPE | Index_type | MySQL extension |
COMMENT | Comment | MySQL extension |
Notes:
sp_statistics
, except
that we replaced the name QUALIFIER
with CATALOG
and we replaced the name OWNER
with SCHEMA
.
Clearly, the preceding table and the output from SHOW INDEX
are
derived from the same parent. So the correlation is already close.
The following statements are equivalent:
SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'tbl_name' [AND schema_name = 'db_name' SHOW INDEX FROM tbl_name [FROM db_name]
INFORMATION_SCHEMA USER_PRIVILEGES
Table
The USER_PRIVILEGES
table provides information about global
privileges. This information comes from the mysql.user
grant table.
Standard Name | SHOW name | Remarks |
GRANTEE | e.g. 'user'@'host' | |
TABLE_CATALOG | NULL
| |
PRIVILEGE_TYPE | ||
IS_GRANTABLE |
Notes:
mysql.user
table.
INFORMATION_SCHEMA SCHEMA_PRIVILEGES
Table
The SCHEMA_PRIVILEGES
table provides information about schema
(database) privileges. This information comes from the mysql.db
grant table.
Standard Name | SHOW name | Remarks |
GRANTEE | e.g. 'user'@'host' | |
TABLE_CATALOG | NULL
| |
TABLE_SCHEMA | ||
PRIVILEGE_TYPE | ||
IS_GRANTABLE |
Notes:
mysql.db
table.
INFORMATION_SCHEMA TABLE_PRIVILEGES
Table
The TABLE_PRIVILEGES
table provides information about table
privileges. This information comes from the mysql.tables_priv
grant table.
Standard Name | SHOW name | Remarks |
GRANTOR | omit | |
GRANTEE | e.g. 'user'@'host' | |
TABLE_CATALOG | NULL
| |
TABLE_SCHEMA | ||
TABLE_NAME | ||
PRIVILEGE_TYPE | ||
IS_GRANTABLE | ||
WITH_HIERARCHY | omit |
The following statements are not equivalent:
SELECT ... FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES SHOW GRANTS ...
PRIVILEGE_TYPE
can contain one (and only one) of these values:
SELECT
, INSERT
, UPDATE
, REFERENCES
,
ALTER
, INDEX
, DROP
, CREATE VIEW
.
INFORMATION_SCHEMA COLUMN_PRIVILEGES
Table
The COLUMN_PRIVILEGES
table provides information about column
privileges. This information comes from the mysql.columns_priv
grant table.
Standard Name | SHOW name | Remarks |
GRANTOR | omit | |
GRANTEE | e.g. 'user'@'host' | |
TABLE_CATALOG | NULL
| |
TABLE_SCHEMA | ||
TABLE_NAME | ||
COLUMN_NAME | ||
PRIVILEGE_TYPE | ||
IS_GRANTABLE |
Notes:
SHOW FULL COLUMNS
, the privileges are all in one
field and in lowercase, for example,
select,insert,update,references
.
In COLUMN_PRIVILEGES
, there is one row per privilege,
and it's uppercase.
PRIVILEGE_TYPE
can contain one (and only one) of these values:
SELECT
, INSERT
, UPDATE
, REFERENCES
.
GRANT OPTION
privilege, then IS_GRANTABLE
should be YES
. Otherwise, IS_GRANTABLE
should be NO
.
The output does not list GRANT OPTION
as a separate privilege.
The following statements are not equivalent:
SELECT ... FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES SHOW GRANTS ...
INFORMATION_SCHEMA CHARACTER_SETS
Table
The CHARACTER_SETS
table provides information about available
character sets.
Standard Name | SHOW name | Remarks |
CHARACTER_SET_CATALOG | omit | |
CHARACTER_SET_SCHEMA | omit | |
CHARACTER_SET_NAME | Charset | |
CHARACTER_REPERTOIRE | omit | |
FORM_OF_USE | omit | |
NUMBER_OF_CHARACTERS | omit | |
DEFAULT_COLLATE_CATALOG | omit | |
DEFAULT_COLLATE_SCHEMA | omit | |
DEFAULT_COLLATE_NAME | Default collation | |
DESCRIPION | Description | MySQL extension |
MAXLEN | Maxlen | MySQL extension |
Notes:
Description
and Maxlen
columns in the output from SHOW
CHARACTER SET
.
The following statements are equivalent:
SELECT * FROM INFORMATION_SCHEMA.CHARACTER_SETS [WHERE name LIKE 'wild'] SHOW CHARACTER SET [LIKE 'wild']
INFORMATION_SCHEMA COLLATIONS
Table
The COLLATIONS
table provides information about collations for each
character set.
Standard Name | SHOW name | Remarks |
COLLATION_CATALOG | omit | |
COLLATION_SCHEMA | omit | |
COLLATION_NAME | Collation | |
PAD_ATTRIBUTE | omit | |
COLLATION_TYPE | omit | |
COLLATION_DEFINITION | omit | |
COLLATION_DICTIONARY | omit | |
CHARACTER_SET_NAME | omit MySQL extension | |
ID | omit MySQL extension | |
IS_DEFAULT | omit MySQL extension | |
IS_COMPILED | omit MySQL extension | |
SORTLEN | omit MySQL extension |
Notes:
Charset
,
Id
, Default
, Compiled
, and Sortlen
columns in
the output from SHOW COLLATION
.
The following statements are equivalent:
SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLLATIONS [WHERE collation_name LIKE 'wild'] SHOW COLLATION [LIKE 'wild']
INFORMATION_SCHEMA COLLATION_CHARACTER_SET_APPLICABILITY
Table
The COLLATION_CHARACTER_SET_APPLICABILITY
table indicates what
character set is applicable for what collation. The columns are equivalent
to the first two display fields that we get from SHOW COLLATION
.
Standard Name | SHOW name | Remarks |
COLLATION_CATALOG | omit | |
COLLATION_SCHEMA | omit | |
COLLATION_NAME | Collation | |
CHARACTER_SET_CATALOG | omit | |
CHARACTER_SET_SCHEMA | omit | |
CHARACTER_SET_NAME | Charset |
INFORMATION_SCHEMA TABLE_CONSTRAINTS
Table
The TABLE_CONSTRAINTS
table describes which tables have
constraints.
Standard Name | SHOW name | Remarks |
CONSTRAINT_CATALOG | NULL
| |
CONSTRAINT_SCHEMA | ||
CONSTRAINT_NAME | ||
TABLE_CATALOG | omit | |
TABLE_SCHEMA | ||
TABLE_NAME | ||
CONSTRAINT_TYPE | ||
IS_DEFERRABLE | omit | |
INITIALLY_DEFERRED | omit |
Notes:
CONSTRAINT_TYPE
value can be UNIQUE
, PRIMARY KEY
,
or FOREIGN KEY
.
UNIQUE
and PRIMARY KEY
information is about the same as
what you get from the Key_name
field in the output from SHOW
INDEX
when the Non_unique
field is 0
.
CONSTRAINT_TYPE
column can contain one of these values:
UNIQUE
, PRIMARY KEY
, FOREIGN KEY
, CHECK
This is
a CHAR
(not ENUM
) column. The CHECK
value will not be
possible until we support CHECK
.
INFORMATION_SCHEMA KEY_COLUMN_USAGE
Table
The KEY_COLUMN_USAGE
table describes which key columns have
constraints.
Standard Name | SHOW name | Remarks |
CONSTRAINT_CATALOG | NULL
| |
CONSTRAINT_SCHEMA | ||
CONSTRAINT_NAME | ||
TABLE_CATALOG | ||
TABLE_SCHEMA | ||
TABLE_NAME | ||
COLUMN_NAME | ||
ORDINAL_POSITION | ||
POSITION_IN_UNIQUE_CONSTRAINT |
Notes:
ORDINAL_POSITION
is the column's position within
the constraint, not the column's position within the table.
Column positions are numbered beginning with 1.
POSITION_IN_UNIQUE_CONSTRAINT
is NULL
for
unique and primary-key constraints. For foreign-key constraints,
it is the ordinal position in key of the table that is being
referenced.
For example, suppose that there are two tables name t1
and t3
that have the following definitions:
CREATE TABLE t1 ( s1 INT, s2 INT, s3 INT, PRIMARY KEY(s3) ) ENGINE=InnoDB; CREATE TABLE t3 ( s1 INT, s2 INT, s3 INT, KEY(s1), CONSTRAINT CO FOREIGN KEY (s2) REFERENCES t1(s3) ) ENGINE=InnoDB;For those two tables, the
KEY_COLUMN_USAGE
table will have two rows:
CONSTRAINT_NAME
='PRIMARY',
TABLE_NAME
='t1', COLUMN_NAME
='s3', ORDINAL_POSITION
=1,
POSITION_IN_UNIQUE_CONSTRAINT
=NULL.
CONSTRAINT_NAME
='CO',
TABLE_NAME
='t3', COLUMN_NAME
='s2', ORDINAL_POSITION
=1,
POSITION_IN_UNIQUE_CONSTRAINT
=1.
INFORMATION_SCHEMA ROUTINES
Table
The ROUTINES
table provides information about stored routines (both
procedures and functions). The ROUTINES
table does not include
user-defined functions (UDFs) at this time.
The column named ``mysql.proc
name'' indicates the mysql.proc
table column that corresponds to the INFORMATION_SCHEMA.ROUTINES
table
column, if any.
Standard Name | mysql.proc name | Remarks |
SPECIFIC_CATALOG | omit | |
SPECIFIC_SCHEMA | db | omit |
SPECIFIC_NAME | specific_name | |
ROUTINE_CATALOG | NULL
| |
ROUTINE_SCHEMA | db | |
ROUTINE_NAME | name | |
MODULE_CATALOG | omit | |
MODULE_SCHEMA | omit | |
MODULE_NAME | omit | |
USER_DEFINED_TYPE_CATALOG | omit | |
USER_DEFINED_TYPE_SCHEMA | omit | |
USER_DEFINED_TYPE_NAME | omit | |
ROUTINE_TYPE | type | {PROCEDURE|FUNCTION}
|
DTD_IDENTIFIER | (data type descriptor) | |
ROUTINE_BODY | SQL
| |
ROUTINE_DEFINITION | body | |
EXTERNAL_NAME | NULL
| |
EXTERNAL_LANGUAGE | language | NULL
|
PARAMETER_STYLE | SQL
| |
IS_DETERMINISTIC | is_deterministic | |
SQL_DATA_ACCESS | sql_data_access | |
IS_NULL_CALL | omit | |
SQL_PATH | NULL
| |
SCHEMA_LEVEL_ROUTINE | omit | |
MAX_DYNAMIC_RESULT_SETS | omit | |
IS_USER_DEFINED_CAST | omit | |
IS_IMPLICITLY_INVOCABLE | omit | |
SECURITY_TYPE | security_type | |
TO_SQL_SPECIFIC_CATALOG | omit | |
TO_SQL_SPECIFIC_SCHEMA | omit | |
TO_SQL_SPECIFIC_NAME | omit | |
AS_LOCATOR | omit | |
CREATED | created | |
LAST_ALTERED | modified | |
NEW_SAVEPOINT_LEVEL | omit | |
IS_UDT_DEPENDENT | omit | |
RESULT_CAST_FROM_DTD_IDENTIFIER | omit | |
RESULT_CAST_AS_LOCATOR | omit | |
SQL_MODE | sql_mode | MySQL extension |
ROUTINE_COMMENT | comment | MySQL extension |
DEFINER | definer | MySQL extension |
Notes:
EXTERNAL_LANGUAGE
thus:
mysql.proc.language='SQL'
, then EXTERNAL_LANGUAGE
is
NULL
EXTERNAL_LANGUAGE
will be what's in
mysql.proc.language
. However, we don't have external languages yet,
so it's always NULL
.
INFORMATION_SCHEMA VIEWS
Table
The VIEWS
table provides information about views in databases.
Standard Name | SHOW name | Remarks |
TABLE_CATALOG | NULL
| |
TABLE_SCHEMA | ||
TABLE_NAME | ||
VIEW_DEFINITION | ||
CHECK_OPTION | ||
IS_UPDATABLE | ||
INSERTABLE_INTO | omit |
Notes:
SHOW VIEW
, without which
you cannot see the VIEWS
table.
VIEW_DEFINITION
column has most of what you see in the
Create Table
field that SHOW CREATE VIEW
produces. Skip the
words before SELECT
and skip the words WITH CHECK OPTION
. For
example, if the original statement was:
CREATE VIEW v AS SELECT s2,s1 FROM t WHERE s1 > 5 ORDER BY s1 WITH CHECK OPTION;then the view definition is:
SELECT s2,s1 FROM t WHERE s1 > 5 ORDER BY s1
CHECK_OPTION
column always has a value of NONE
.
IS_UPDATABLE
column is YES
if the view is updatable,
NO
if the view is not updatable.
INFORMATION_SCHEMA
Tables
We will add more INFORMATION_SCHEMA
tables soon. Particularly, we
acknowledge the need for INFORMATION_SCHEMA.PARAMETERS
and for
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
and for
INFORMATION_SCHEMA.TRIGGERS
.
SHOW
Statements
Some extensions to SHOW
statements accompany the implementation of
INFORMATION_SCHEMA
:
SHOW
can be used to get information about the structure of
INFORMATION_SCHEMA
itself.
SHOW
statements accept a WHERE
clause that provides
more flexibility in specifying which rows to display.
These extensions are available beginning with MySQL 5.0.3.
INFORMATION_SCHEMA
is an information database, so its name is
included in the output from SHOW DATABASES
. Similarly, SHOW
TABLES
can be used with INFORMATION_SCHEMA
to obtain a list of its
tables:
mysql> SHOW TABLES FROM INFORMATION_SCHEMA; +---------------------------------------+ | Tables_in_information_schema | +---------------------------------------+ | SCHEMATA | | TABLES | | COLUMNS | | CHARACTER_SETS | | COLLATIONS | | COLLATION_CHARACTER_SET_APPLICABILITY | | ROUTINES | | STATISTICS | | VIEWS | | USER_PRIVILEGES | | SCHEMA_PRIVILEGES | | TABLE_PRIVILEGES | | COLUMN_PRIVILEGES | | TABLE_CONSTRAINTS | | KEY_COLUMN_USAGE | +---------------------------------------+
SHOW COLUMNS
and DESCRIBE
can display information about the
columns in individual INFORMATION_SCHEMA
tables.
Several SHOW
statement have been extended to allow a WHERE
clause:
SHOW CHARACTER SET SHOW COLLATION SHOW COLUMNS SHOW DATABASES SHOW FUNCTION STATUS SHOW KEYS SHOW OPEN TABLES SHOW PROCEDURE STATUS SHOW STATUS SHOW TABLE STATUS SHOW TABLES SHOW VARIABLES
The WHERE
clause, if present, is evaluated against the column names
displayed by the SHOW
statement. For example, the SHOW
COLLATION
statement produces these output columns:
For example, the SHOW CHARACTER SET
statement produces these output
columns:
mysql> SHOW CHARACTER SET; +----------+-----------------------------+---------------------+--------+ | Charset | Description | Default collation | Maxlen | +----------+-----------------------------+---------------------+--------+ | big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 | | dec8 | DEC West European | dec8_swedish_ci | 1 | | cp850 | DOS West European | cp850_general_ci | 1 | | hp8 | HP West European | hp8_english_ci | 1 | | koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 | | latin1 | ISO 8859-1 West European | latin1_swedish_ci | 1 | | latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 | ...
To use a WHERE
clause with SHOW CHARACTER SET
, you would refer
to those column names. As an example, the following statement displays
information about character sets for which the default collation contains the
string "japanese"
:
mysql> SHOW CHARACTER SET WHERE `Default collation` LIKE '%japanese%'; +---------+---------------------------+---------------------+--------+ | Charset | Description | Default collation | Maxlen | +---------+---------------------------+---------------------+--------+ | ujis | EUC-JP Japanese | ujis_japanese_ci | 3 | | sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 | | cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 | | eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 | +---------+---------------------------+---------------------+--------+
This statement displays the multi-byte character sets:
mysql> SHOW CHARACTER SET WHERE Maxlen > 1; +---------+---------------------------+---------------------+--------+ | Charset | Description | Default collation | Maxlen | +---------+---------------------------+---------------------+--------+ | big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 | | ujis | EUC-JP Japanese | ujis_japanese_ci | 3 | | sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 | | euckr | EUC-KR Korean | euckr_korean_ci | 2 | | gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 | | gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 | | utf8 | UTF-8 Unicode | utf8_general_ci | 3 | | ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 | | cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 | | eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 | +---------+---------------------------+---------------------+--------+
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, because it was developed by the MySQL team, and is the basis for most of the other APIs.
This section describes some utilities that you may find useful when developing MySQL programs.
msql2mysql
mSQL
programs to MySQL. It doesn't
handle every case, but it gives a good start when converting.
mysql_config
msql2mysql
, Convert mSQL Programs for Use with MySQLInitially, the MySQL C API was developed to be very similar to that for the mSQL database system. Because of this, mSQL programs often can be converted relatively easily for use with MySQL by changing the names of the C API functions.
The msql2mysql
utility performs the conversion of mSQL C API function
calls to their MySQL equivalents.
msql2mysql
converts the input file in place, so make a copy of the
original before converting it. For example, use msql2mysql
like
this:
shell> cp client-prog.c client-prog.c.orig shell> msql2mysql client-prog.c client-prog.c converted
Then examine `client-prog.c' and make any post-conversion revisions that may be necessary.
msql2mysql
uses the replace
utility to make the function name
substitutions.
See section 8.13 The replace
String-Replacement Utility.
mysql_config
, Get compile options for compiling clients
mysql_config
provides you with useful information for compiling
your MySQL client and connecting it to MySQL.
mysql_config
supports the following options:
--cflags
libmysqlclient
library.
--include
--cflags
instead of this option.)
--libmysqld-libs, --embedded
--libs
--libs_r
--port
--socket
--version
If you invoke mysql_config
with no options, it displays a list of all
options that it supports, and their values:
shell> mysql_config Usage: /usr/local/mysql/bin/mysql_config [options] Options: --cflags [-I/usr/local/mysql/include/mysql -mcpu=pentiumpro] --include [-I/usr/local/mysql/include/mysql] --libs [-L/usr/local/mysql/lib/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib -lssl -lcrypto] --libs_r [-L/usr/local/mysql/lib/mysql -lmysqlclient_r -lpthread -lz -lcrypt -lnsl -lm -lpthread] --socket [/tmp/mysql.sock] --port [3306] --version [4.0.16] --libmysqld-libs [-L/usr/local/mysql/lib/mysql -lmysqld -lpthread -lz -lcrypt -lnsl -lm -lpthread -lrt]
You can use mysql_config
within a command line to include the value
that it displays for a particular option. For example, to compile a MySQL
client program, use mysql_config
as follows:
CFG=/usr/local/mysql/bin/mysql_config sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"
When you use mysql_config
this way, be sure to invoke it within
backtick (``') characters. That tells the shell to execute it and
substitute its output into the surrounding command.
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 8 MySQL Client and Utility Programs, for a list of these variables.
The client has a maximum communication buffer size. The size of the buffer that is allocated initially (16KB) is automatically increased up to the maximum size (the maximum is 16MB). 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 16MB of data, you must have a
communication buffer limit of at least 16MB (in both server and client). The
client's default maximum is 16MB, but the default maximum in the server is
1MB. You can increase this by changing the value of the
max_allowed_packet
parameter when the server is started. See section 7.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 22.2.15 How to Make a Threaded Client. For creating a standalone application which includes the "server" and "client" in the same program (and does not communicate with an external MySQL server), see section 22.2.16 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 | CHAR field
|
FIELD_TYPE_VAR_STRING | 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 summarized here and described in greater detail in a later section. See section 22.2.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_charset_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 statement
CREATE DATABASE instead.
|
mysql_data_seek() | Seeks to an arbitrary row number 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 statement
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 an 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 statement. |
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 as a string. |
mysql_get_client_version() | Returns client version information as an integer. |
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 initializes 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_library_end() | Finalize MySQL C API library. |
mysql_library_init() | Initialize MySQL C API library. |
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 an 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 an SQL statement, taking into account the current charset of the connection. |
mysql_real_query() | Executes an SQL query specified as a counted string. |
mysql_reload() | Tells the server to reload the grant tables. |
mysql_row_seek() |
Seeks to a row offset 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_server_end() | Finalize embedded server library. |
mysql_server_init() | Initialize embedded server library. |
mysql_set_server_option() |
Sets an option for the connection (like multi-statements ).
|
mysql_sqlstate() | Returns the SQLSTATE error code for the last error. |
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_warning_count() | Returns the warning count for the previous SQL statement. |
mysql_commit() | Commits the transaction. |
mysql_rollback() | Rolls back the transaction. |
mysql_autocommit() | Toggles autocommit mode on/off. |
mysql_more_results() | Checks whether any more results exist. |
mysql_next_result() | Returns/initiates the next result in multiple-statement executions. |
Application programs should use this general outline for interacting with MySQL:
mysql_library_init()
.
The library can be either the mysqlclient
C client library or the
mysqld
embedded server library, depending on whether the application
was linked with the -libmysqlclient
or -libmysqld
flag.
mysql_init()
.
mysql_close()
.
mysql_library_end()
.
The purpose of calling mysql_library_init()
and
mysql_library_end()
is to provide proper initialization and
finalization of the MySQL library. For applications that are linked with
the client library, they provide improved memory management. If you don't
use these functions, a block of memory remains allocated. (This does not
increase the amount of memory used by the application, but some memory
leak detectors will complain about it.) For applications that are linked
with the embedded server, these calls start and stop the server.
mysql_library_init()
and mysql_library_end()
are available
as of MySQL 4.1.10 and 5.0.3. These actually are #define
symbols that make them equivalent to mysql_server_init()
and
mysql_server_end()
, but the names more clearly indicate that they
should be called when beginning and ending use of a MySQL library no
matter whether the application uses the mysqlclient
or
mysqld
library. For older versions of MySQL, you can call
mysql_server_init()
and mysql_server_end()
instead.
To connect to the server, call mysql_init()
to initialize a
connection handler, then call mysql_real_connect()
with that
handler (along with other information such as the hostname, username,
and password). Upon connection, mysql_real_connect()
sets the
reconnect
flag (part of the MYSQL
structure) to a value of
1
in versions of the API strictly older than 5.0.3, of 0
in newer
versions. A value of 1
for 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 initializes 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
previously 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 were 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()
. Because mysql_affected_rows()
returns an unsigned value, you can check for -1 by comparing the
return value to (my_ulonglong)-1
(or to (my_ulonglong)~0
,
which is equivalent).
None.
mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10"); printf("%ld products updated",(long) mysql_affected_rows(&mysql));
If you specify 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 you use a REPLACE
command,
mysql_affected_rows()
returns 2 if the new row replaced an
old row. This is because in this case one row was inserted after the
duplicate was deleted.
If you use INSERT ... ON DUPLICATE KEY UPDATE
to insert a row,
mysql_affected_rows()
returns 1 if the row is inserted as a new row and
2 if an existing row is updated.
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 3.23.3.
mysql_change_user()
fails if the connected user cannot be
authenticated or 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 an 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. The offset
value is a row number and should be in the range from 0
to
mysql_num_rows(result)-1
.
This function requires that the result set structure contains the
entire result of the query, so mysql_data_seek()
may be
used only in conjunction with mysql_store_result()
, not with
mysql_use_result()
.
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 an 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 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'.
The server error codes also are listed at section 24 Error Handling in MySQL.
Note that some functions like mysql_fetch_row()
don't set
mysql_errno()
if they succeed.
A rule of thumb is that all functions that have to ask the server for
information will reset mysql_errno()
if they succeed.
An error code value for the last mysql_xxx()
call, if it failed.
zero means no error occurred.
None.
mysql_error()
const char *mysql_error(MYSQL *mysql)
For the connection specified by mysql
, mysql_error()
returns a null-terminated string containing the error message for the
most recently invoked API function that failed. If a function didn't
fail, the return value of mysql_error()
may be the previous error
or an empty string to indicate no error.
A rule of thumb is that all functions that have to ask the server for
information will reset mysql_error()
if they succeed.
For functions that reset mysql_errno()
, 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 5.8.2 Setting the Error Message Language.
A null-terminated 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 (8KB) if you call mysql_fetch_field()
to ask
for the length of a BLOB
field. (The 8KB 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
optimization, 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.
Note that error is not reset between calls to mysql_fetch_row()
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 22.2.13.1 Why mysql_store_result()
Sometimes Returns NULL
After mysql_query()
Returns Success.
An unsigned integer representing the number of columns 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()
.
Do not attempt to access a result set after freeing it.
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_client_version()
unsigned long mysql_get_client_version(void)
Returns an integer that represents the client library version.
The value has the format XYYZZ
where X
is the major
version, YY
is the release level, and ZZ
is the version
number within the release level. For example, a value of 40102
represents a client library version of 4.1.2
.
This function was added in MySQL 4.0.16.
An integer that represents the MySQL client library version.
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 hostname.
A character string representing the server hostname 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_get_server_version()
unsigned long mysql_get_server_version(MYSQL *mysql)
Returns the version number of the server as an integer.
This function was added in MySQL 4.1.0.
A number that represents the MySQL server version in this format:
major_version*10000 + minor_version *100 + sub_version
For example, 4.1.2 is returned as 40102.
This function is useful in client programs for quickly determining whether some version-specific server capability exists.
None.
mysql_hex_string()
unsigned long mysql_hex_string(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 9.1.1 Strings.
The string in from
is encoded to hexadecimal format, with each
character encoded as two hexadecimal digits. The result is placed in
to
and a terminating null byte is appended.
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. When mysql_hex_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.
The return value can be placed into an SQL statement using either
0xvalue
or X'value'
format. However, the
return value does not include the 0x
or X'...'
. The caller
must supply whichever of those is desired.
mysql_hex_string()
was added in MySQL 4.0.23 and 4.1.8.
char query[1000],*end; end = strmov(query,"INSERT INTO test_table values("); end = strmov(end,"0x"); end += mysql_hex_string(end,"What's this",11); end = strmov(end,",0x"); end += mysql_hex_string(end,"binary data: \0\r\n",16); *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_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
INSERT ... VALUES
only for the multiple-row form
of the statement (that is, only if multiple value lists are
specified).
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 initializes a MYSQL
object suitable for
mysql_real_connect()
. If mysql
is a NULL
pointer, the
function allocates, initializes, and returns a new object. Otherwise, the
object is initialized 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.
To avoid a memory leak, use the following procedure, which should be done
whether the application is linked with the libmysqlclient
or
libmysqld
library:
mysql_library_init()
before the first call to mysql_init()
mysql_library_end()
after the application has closed any open
connections and is done using the MySQL C API.
mysql_library_init()
may be omitted,
because mysql_init()
will invoke it automatically as necessary.
See section 22.2.3.35 mysql_library_init()
.
See section 22.2.3.36 mysql_library_end()
.
An initialized 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 value generated for an AUTO_INCREMENT
column by the
previous INSERT
or UPDATE
statement. Use this function after
you have performed an INSERT
statement into a table that contains an
AUTO_INCREMENT
field.
More precisely, mysql_insert_id()
is updated under these conditions:
INSERT
statements that store a value into an AUTO_INCREMENT
column. This is true whether the value is automatically generated by
storing the special values NULL
or 0
into the column, or is
an explicit non-special value.
INSERT
statement, mysql_insert_id()
returns the first automatically generated AUTO_INCREMENT
value; if no such value is generated, it returns the last last
explicit value inserted into the AUTO_INCREMENT
column.
INSERT
statements that generate an AUTO_INCREMENT
value by
inserting LAST_INSERT_ID(expr)
into any column.
INSERT
statements that generate an AUTO_INCREMENT
value by
updating any column to LAST_INSERT_ID(expr)
.
mysql_insert_id()
is not affected by statements such as
SELECT
that return a result set.
mysql_insert_id()
is undefined.
Note that mysql_insert_id()
returns 0
if the previous statement
does not use an AUTO_INCREMENT
value. If you need to save
the value for later, be sure to call mysql_insert_id()
immediately
after the statement that generates the value.
The value of mysql_insert_id()
is affected only by statements issued
within the current client connection. It is not affected by statements issued
by other clients.
See section 12.8.3 Information 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 statements because the value of that function is maintained
in the server. Another difference is that LAST_INSERT_ID()
is not
updated if you set an AUTO_INCREMENT
column to a specific non-special
value.
The reason for the difference between LAST_INSERT_ID()
and
mysql_insert_id()
is that LAST_INSERT_ID()
is made easy to
use in scripts while mysql_insert_id()
tries to provide a little
more exact information of what happens to the AUTO_INCREMENT
column.
Described in the preceding discussion.
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_library_init()
int mysql_library_init(int argc, char **argv, char **groups)
This is a synonym for the mysql_server_init()
function.
It was added in MySQL 4.1.10 and 5.0.3.
See section 22.2.2 C API Function Overview for usage information.
mysql_library_end()
void mysql_library_end(void)
This is a synonym for the mysql_server_end()
function.
It was added in MySQL 4.1.10 and 5.0.3.
See section 22.2.2 C API Function Overview for usage information.
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 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 22.2.13.1 Why mysql_store_result()
Sometimes Returns NULL
After mysql_query()
Returns Success.
An unsigned integer representing the number of columns 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 whether
mysql_field_count(&mysql)
is = 0. This will happen only 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 behavior 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 option values:
Option | Argument Type | Function |
MYSQL_INIT_COMMAND | char * | Command to execute when connecting to the MySQL server. Will automatically be re-executed when reconnecting. |
MYSQL_OPT_COMPRESS | Not used | Use the compressed client/server protocol. |
MYSQL_OPT_CONNECT_TIMEOUT | unsigned int * | Connect timeout in seconds. |
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_OPT_PROTOCOL | unsigned int * | Type of protocol to use. Should be one of the enum values of mysql_protocol_type defined in `mysql.h'. New in 4.1.0.
|
MYSQL_OPT_READ_TIMEOUT | unsigned int * | Timeout for reads from server (works currently only on Windows on TCP/IP connections). New in 4.1.1. |
MYSQL_OPT_WRITE_TIMEOUT | unsigned int * | Timeout for writes to server (works currently only on Windows on TCP/IP connections). New in 4.1.1. |
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 .
|
MYSQL_REPORT_DATA_TRUNCATION | my_bool * | Enable or disable reporting of data truncation errors for prepared statements via MYSQL_BIND.error . (Default: disabled) New in 5.0.3.
|
MYSQL_SECURE_AUTH | my_bool* | Whether to connect to a server that does not support the new 4.1.1 password hashing. New in 4.1.1. |
MYSQL_SET_CHARSET_DIR | char* | The pathname to the directory that contains character set definition files. |
MYSQL_SET_CHARSET_NAME | char* | The name of the character set to use as the default character set. |
MYSQL_SHARED_MEMORY_BASE_NAME | char* | Named of shared memory object for communication to server. Should be same as the option -shared-memory-base-name used for the mysqld server you want's to connect to. New in 4.1.0.
|
Note that the client
group 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 hostname. |
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 22.2.3.46 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. |
multi-results | Allow multiple result sets from multiple-statement executions or stored procedures. New in 4.1.1. |
multi-statements | Allow the client to send multiple statements in a single string (separated by `;'). New in 4.1.9. |
password | Default password. |
pipe | Use named pipes to connect to a MySQL server on NT. |
protocol={TCP | SOCKET | PIPE | MEMORY} | The 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 file. |
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.3.2 Using 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)); }
This code 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
.
Normally, the string must consist of a single SQL statement and you should
not add a terminating semicolon (`;') or \g
to the statement.
If multiple-statement execution has been enabled, the string can contain
several statements separated by semicolons.
See section 22.2.9 C API Handling of Multiple Query Execution.
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 whether the query should return a result set, you can
use mysql_field_count()
to check for this.
See section 22.2.3.20 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 long 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 initialize the MYSQL
structure. You can
change a lot of connect options with the mysql_options()
call. See section 22.2.3.43 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
or the empty string ""
, the current
user is assumed. Under Unix, this is the current login name. Under
Windows ODBC, the current username must be specified explicitly.
See section 23.1.9.2 Configuring a MyODBC DSN on Windows.
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. The client's session wait_timeout variable will be set to the value of the session interactive_timeout variable.
|
CLIENT_LOCAL_FILES | Enable LOAD DATA LOCAL handling.
|
CLIENT_MULTI_STATEMENTS | Tell the server that the client may send multiple statements in a single string (separated by `;'). If this flag is not set, multiple-statement execution is disabled. New in 4.1. |
CLIENT_MULTI_RESULTS | Tell the server that the client can handle multiple result sets from multiple-statement executions or stored procedures. This is automatically set if CLIENT_MULTI_STATEMENTS is set. New in 4.1.
|
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). This option should not be set by application programs; it is set internally in the client library. |
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 than 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
in versions of the API strictly older than 5.0.3, of 0
in newer
versions. A value of 1
for 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)
Note that mysql
must be a valid, open connection. This is needed
because the escaping depends on the character-set in use by the server.
This function is used to create a legal SQL string that you can use in a SQL statement. See section 9.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 9.1 Literal Values).
(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.
Normally, the string must consist of a single SQL statement and you should
not add a terminating semicolon (`;') or \g
to the statement.
If multiple-statement execution has been enabled, the string can contain
several statements separated by semicolons.
See section 22.2.9 C API Handling of Multiple Query Execution.
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 whether the query should return a result set, you can
use mysql_field_count()
to check for this.
See section 22.2.3.20 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 an 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.
The offset
value is a row offset that should be a value returned
from mysql_row_tell()
or from mysql_row_seek()
.
This value is not a row number; if you want to seek to a row within a
result set by number, use mysql_data_seek()
instead.
This function requires that the result set structure contains the
entire result of the query, so mysql_row_seek()
may be used
only in conjunction with mysql_store_result()
, not with
mysql_use_result()
.
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_set_server_option()
int mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)
Enables or disables an option for the connection. option
can have one
of the following values:
MYSQL_OPTION_MULTI_STATEMENTS_ON | Enable multi statement support. |
MYSQL_OPTION_MULTI_STATEMENTS_OFF | Disable multi statement support. |
This function was added in MySQL 4.1.1.
Zero for success. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
ER_UNKNOWN_COM_ERROR
mysql_set_server_option()
(which is the
case that the server is older than 4.1.1) or the server didn't support
the option one tried to set.
mysql_shutdown()
int mysql_shutdown(MYSQL *mysql, enum enum_shutdown_level shutdown_level)
Asks the database server to shut down. The connected user must have
SHUTDOWN
privileges.
The shutdown_level
argument was added in MySQL 4.1.3 (and 5.0.1). The
MySQL server currently supports only one type (level of gracefulness) of
shutdown; shutdown_level
must be equal to
SHUTDOWN_DEFAULT
. Later we will add more levels and then the
shutdown_level
argument will enable to choose the desired level.
MySQL servers and MySQL clients before and after 4.1.3 are compatible; MySQL
servers newer than 4.1.3 accept the mysql_shutdown(MYSQL *mysql)
call,
and MySQL servers older than 4.1.3 accept the new mysql_shutdown()
call. But dynamically linked executables which have been compiled with older
versions of libmysqlclient
headers, and call mysql_shutdown()
,
need to be used with the old libmysqlclient
dynamic library.
The shutdown process is described in section 5.3 The MySQL Server Shutdown Process.
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_sqlstate()
const char *mysql_sqlstate(MYSQL *mysql)
Returns a null-terminated string containing the SQLSTATE error code for the
last error. The error code consists of five characters.
'00000'
means ``no error.''
The values are specified by ANSI SQL and ODBC.
For a list of possible values, see section 24 Error Handling in MySQL.
Note that not all MySQL errors are yet mapped to SQLSTATE's.
The value 'HY000'
(general error) is used
for unmapped errors.
This function was added to MySQL 4.1.1.
A null-terminated character string containing the SQLSTATE error code.
See section 22.2.3.12 mysql_errno()
.
See section 22.2.3.13 mysql_error()
.
See section 22.2.7.26 mysql_stmt_sqlstate()
.
mysql_ssl_set()
int mysql_ssl_set(MYSQL *mysql, const char *key,
const char *cert, const char *ca,
const char *capath, const char *cipher)
mysql_ssl_set()
is used for establishing secure connections using
SSL. It must be called before mysql_real_connect()
.
mysql_ssl_set()
does nothing unless OpenSSL support is enabled in
the client library.
mysql
is the connection handler returned from mysql_init()
.
The other parameters are specified as follows:
key
is the pathname to the key file.
cert
is the pathname to the certificate file.
ca
is the pathname to the certificate authority file.
capath
is the pathname to a directory that contains trusted
SSL CA certificates in pem format.
cipher
is a list of allowable ciphers to use for SSL encryption.
Any unused SSL parameters may be given as NULL
.
This function always returns 0
. If SSL setup is incorrect,
mysql_real_connect()
will return an error when you attempt to connect.
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
, CHECK TABLE
, and so forth).
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 on).
If you want to know whether the query should return a result set, you can
use mysql_field_count()
to check for this.
See section 22.2.3.20 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 whether an error occurred by checking if
mysql_error()
returns a non-empty string, if
mysql_errno()
returns non-zero, or if mysql_field_count()
returns zero.
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 22.2.13.1 Why mysql_store_result()
Sometimes Returns NULL
After mysql_query()
Returns Success.
A MYSQL_RES
result structure with the results. NULL
if
an error occurred.
mysql_store_result()
resets mysql_error()
and
mysql_errno()
if it succeeds.
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 allocate memory only 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.
mysql_use_result()
resets mysql_error()
and
mysql_errno()
if it succeeds.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_warning_count()
unsigned int mysql_warning_count(MYSQL *mysql)
Returns the number of warnings generated during execution of the previous SQL statement.
This function was added in MySQL 4.1.0.
The warning count.
None.
mysql_commit()
my_bool mysql_commit(MYSQL *mysql)
Commits the current transaction.
This function was added in MySQL 4.1.0.
Zero if successful. Non-zero if an error occurred.
None.
mysql_rollback()
my_bool mysql_rollback(MYSQL *mysql)
Rolls back the current transaction.
This function was added in MySQL 4.1.0.
Zero if successful. Non-zero if an error occurred.
None.
mysql_autocommit()
my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)
Sets autocommit mode on if mode
is 1, off if mode
is 0.
This function was added in MySQL 4.1.0.
Zero if successful. Non-zero if an error occurred.
None.
mysql_more_results()
my_bool mysql_more_results(MYSQL *mysql)
Returns true if more results exist from the currently executed query,
and the application must call mysql_next_result()
to fetch the
results.
This function was added in MySQL 4.1.0.
TRUE
(1) if more results exist. FALSE
(0) if no more results
exist.
In most cases, you can call mysql_next_result()
instead to
test whether more results exist and initiate retrieval if so.
See section 22.2.9 C API Handling of Multiple Query Execution.
See section 22.2.3.66 mysql_next_result()
.
None.
mysql_next_result()
int mysql_next_result(MYSQL *mysql)
If more query results exist, mysql_next_result()
reads the
next query results and returns the status back to application.
You must call mysql_free_result()
for the preceding
query if it returned a result set.
After calling mysql_next_result()
the state of the connection
is as if you had called mysql_real_query()
or mysql_query()
for the next query.
This means that you can call mysql_store_result()
,
mysql_warning_count()
, mysql_affected_rows()
, and so forth.
If mysql_next_result()
returns an error, no other statements will
be executed and there are no more results to fetch.
See section 22.2.9 C API Handling of Multiple Query Execution.
This function was added in MySQL 4.1.0.
Return Value | Description |
0 | Successful and there are more results |
-1 | Successful and there are no more results |
>0 | An error occurred |
CR_COMMANDS_OUT_OF_SYNC
mysql_use_result()
for a previous result set.
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
As of MySQL 4.1, the client/server protocol provides for the use of
prepared statements. This capability uses the
MYSQL_STMT
statement handler data structure returned by the
mysql_stmt_init()
initialization function.
Prepared execution is an efficient way to execute a statement more than
once. The statement is first parsed to prepare it for execution. Then
it is executed one or more times at a later time, using the statement
handle returned by the initialization function.
Prepared execution is faster than direct execution for statements executed more than once, primarily because the query is parsed only once. In the case of direct execution, the query is parsed every time it is executed. Prepared execution also can provide a reduction of network traffic because for each execution of the prepared statement, it is necessary only to send the data for the parameters.
Another advantage of prepared statements is that it uses a binary protocol that makes data transfer between client and server more efficient.
The following statements can be used as prepared statements:
CREATE TABLE
,
DELETE
,
DO
,
INSERT
,
REPLACE
,
SELECT
,
SET
,
UPDATE
,
and most
SHOW
,
statements.
Other statements are not yet supported.
Note: Some incompatible changes were made in MySQL 4.1.2. See section 22.2.7 C API Prepared Statement Function Descriptions for details.
Prepared statements mainly use the MYSQL_STMT
and
MYSQL_BIND
data structures. A third structure, MYSQL_TIME
,
is used to transfer temporal data.
MYSQL_STMT
mysql_stmt_init()
,
which returns a statement handle, that is, a pointer to a
MYSQL_STMT
.
The handle is used for all subsequent statement-related functions until you
close it with mysql_stmt_close()
.
The MYSQL_STMT
structure has no members that are for application
use.
Multiple statement handles can be associated with a single connection.
The limit on the number of handles depends on the available system resources.
MYSQL_BIND
mysql_stmt_bind_param()
to bind parameter data values to
buffers for use by mysql_stmt_execute()
. For output, it is
used with mysql_stmt_bind_result()
to bind result set
buffers for use in fetching rows with mysql_stmt_fetch()
.
The MYSQL_BIND
structure contains the following members for
use by application programs.
Each is used both for input and for output, although sometimes for different
purposes depending on the direction of data transfer.
enum enum_field_types buffer_type
buffer_type
values are listed
later in this section. For input, buffer_type
indicates what type of
value you are binding to a statement parameter. For output, it indicates what
type of value you expect to receive in a result buffer.
void *buffer
buffer
should point to a variable of the proper
C type. (If you are associating the variable with a column that has the
UNSIGNED
attribute, the variable should be an unsigned
C type.
Indicate whether the variable is signed or unsigned by using the
is_unsigned
member, described later in this list.)
For date and time column types, buffer
should point to a
MYSQL_TIME
structure. For character and binary string column types,
buffer
should point to a character buffer.
unsigned long buffer_length
*buffer
in bytes. This indicates the maximum amount
of data that can be stored in the buffer. For character and binary C data,
the buffer_length
value specifies the length of *buffer
when used with mysql_stmt_bind_param()
,
or the maximum number of data bytes that can be fetched into the buffer
when used with mysql_stmt_bind_result()
.
unsigned long *length
unsigned long
variable that indicates the actual number
of bytes of data stored in *buffer
.
length
is used for character or binary C data.
For input parameter data binding, length
points to an unsigned long
variable that indicates the
length of the parameter value stored in *buffer
; this is used by
mysql_stmt_execute()
.
For output value binding, mysql_stmt_fetch()
places
the length of the column value that is returned
into the variable that length
points to.
length
is ignored for numeric and temporal data types because the length
of the data value is determined by the buffer_type
value.
my_bool *is_null
my_bool
variable that is true if a value is
NULL
, false if it is not NULL
. For input, set *is_null
to true to
indicate that you are passing a NULL
value as a statement parameter. For
output, this value will be set to true after you fetch a row if the result
set column value returned from the statement is NULL
.
my_bool is_unsigned
MYSQL_TYPE_TINY
, MYSQL_TYPE_SHORT
,
MYSQL_TYPE_LONG
, and MYSQL_TYPE_LONGLONG
type codes.)
is_unsigned
should be set to true for unsigned types and false for signed types.
my_bool error
mysql_options()
with the MYSQL_REPORT_DATA_TRUNCATION
option. When enabled,
mysql_stmt_fetch()
returns MYSQL_DATA_TRUNCATED
and
error
is true in the MYSQL_BIND
structures for parameters
in which truncation occurred. Truncation indicates loss of sign or
significant digits, or that a string was too long to fit in a column.
The error
member was added in MySQL 5.0.3.
MYSQL_BIND
structure, you should zero its contents
to initialize it, and then set the members just described appropriately.
For example, to declare and initialize an array of three MYSQL_BIND
structures, use this code:
MYSQL_BIND bind[3]; memset(bind, 0, sizeof(bind));
MYSQL_TIME
DATE
, TIME
,
DATETIME
, and TIMESTAMP
data directly to and from the server.
This is done by setting the buffer_type
member of a MYSQL_BIND
structure to one of the temporal types, and setting the buffer
member
to point to a MYSQL_TIME
structure.
The MYSQL_TIME
structure contains the following members:
unsigned int year
unsigned int month
unsigned int day
unsigned int hour
unsigned int minute
unsigned int second
my_bool neg
unsigned long second_part
MYSQL_TIME
structure that apply to a given
type of temporal value are used:
The year
, month
, and day
elements are used for
DATE
, DATETIME
, and TIMESTAMP
values.
The hour
, minute
, and second
elements are used for
TIME
, DATETIME
, and TIMESTAMP
values.
See section 22.2.10 C API Handling of Date and Time Values.
The following table shows the allowable values that may be specified in the
buffer_type
member of MYSQL_BIND
structures.
The table also shows those SQL types that correspond most closely to each
buffer_type
value, and, for numeric and temporal types, the
corresponding C type.
buffer_type Value | SQL Type | C Type |
MYSQL_TYPE_TINY | TINYINT | char
|
MYSQL_TYPE_SHORT | SMALLINT | short int
|
MYSQL_TYPE_LONG | INT | int
|
MYSQL_TYPE_LONGLONG | BIGINT | long long int
|
MYSQL_TYPE_FLOAT | FLOAT | float
|
MYSQL_TYPE_DOUBLE | DOUBLE | double
|
MYSQL_TYPE_TIME | TIME | MYSQL_TIME
|
MYSQL_TYPE_DATE | DATE | MYSQL_TIME
|
MYSQL_TYPE_DATETIME | DATETIME | MYSQL_TIME
|
MYSQL_TYPE_TIMESTAMP | TIMESTAMP | MYSQL_TIME
|
MYSQL_TYPE_STRING | CHAR | |
MYSQL_TYPE_VAR_STRING | VARCHAR | |
MYSQL_TYPE_TINY_BLOB | TINYBLOB/TINYTEXT | |
MYSQL_TYPE_BLOB | BLOB/TEXT | |
MYSQL_TYPE_MEDIUM_BLOB | MEDIUMBLOB/MEDIUMTEXT | |
MYSQL_TYPE_LONG_BLOB | LONGBLOB/LONGTEXT |
Implicit type conversion may be performed in both directions.
Note: Some incompatible changes were made in MySQL 4.1.2. See section 22.2.7 C API Prepared Statement Function Descriptions for details.
The functions available for prepared statement processing are summarized here and described in greater detail in a later section. See section 22.2.7 C API Prepared Statement Function Descriptions.
Function | Description |
mysql_stmt_affected_rows() |
Returns the number of rows changes, deleted, or inserted by prepared
UPDATE , DELETE , or INSERT statement.
|
mysql_stmt_attr_get() | Get value of an attribute for a prepared statement. |
mysql_stmt_attr_set() | Sets an attribute for a prepared statement. |
mysql_stmt_bind_param() | Associates application data buffers with the parameter markers in a prepared SQL statement. |
mysql_stmt_bind_result() | Associates application data buffers with columns in the result set. |
mysql_stmt_close() | Frees memory used by prepared statement. |
mysql_stmt_data_seek() | Seeks to an arbitrary row number in a statement result set. |
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_stmt_execute() | Executes the prepared statement. |
mysql_stmt_fetch() | Fetches the next row of data from the result set and returns data for all bound columns. |
mysql_stmt_fetch_column() | Fetch data for one column of the current row of the result set. |
mysql_stmt_field_count() | Returns the number of result columns for the most recent statement. |
mysql_stmt_free_result() | Free the resources allocated to the statement handle. |
mysql_stmt_init() |
Allocates memory for MYSQL_STMT structure and initializes it.
|
mysql_stmt_insert_id() |
Returns the ID generated for an AUTO_INCREMENT column by prepared
statement.
|
mysql_stmt_num_rows() | Returns total rows from the statement buffered result set. |
mysql_stmt_param_count() | Returns the number of parameters in a prepared SQL statement. |
mysql_stmt_param_metadata() | Return parameter metadata in the form of a result set. |
mysql_stmt_prepare() | Prepares an SQL string for execution. |
mysql_stmt_reset() | Reset the statement buffers in the server. |
mysql_stmt_result_metadata() | Returns prepared statement metadata in the form of a result set. |
mysql_stmt_row_seek() |
Seeks to a row offset in a statement result set, using value returned from
mysql_stmt_row_tell() .
|
mysql_stmt_row_tell() | Returns the statement row cursor position. |
mysql_stmt_send_long_data() | Sends long data in chunks to server. |
mysql_stmt_sqlstate() | Returns the SQLSTATE error code for the last statement execution. |
mysql_stmt_store_result() | Retrieves the complete result set to the client. |
Call mysql_stmt_init()
to create a statement
handle, then mysql_stmt_prepare
to prepare it,
mysql_stmt_bind_param()
to supply the parameter
data, and mysql_stmt_execute()
to execute the statement. You can
repeat the mysql_stmt_execute()
by changing parameter values in the
respective buffers supplied through mysql_stmt_bind_param()
.
If the statement is a SELECT
or any other statement that produces
a result set, mysql_stmt_prepare()
will also return the result
set metadata information in the form of a MYSQL_RES
result set
through mysql_stmt_result_metadata()
.
You can supply the result buffers using mysql_stmt_bind_result()
, so
that the mysql_stmt_fetch()
will automatically return data to these
buffers. This is row-by-row fetching.
You can also send the text or binary data in chunks to server using
mysql_stmt_send_long_data()
.
See section 22.2.7.25 mysql_stmt_send_long_data()
.
When statement execution has been completed, the statement handle must be
closed using mysql_stmt_close()
so that all resources associated
with it can be freed.
If you obtained a SELECT
statement's result set metadata by calling
mysql_stmt_result_metadata()
, you should also free the metadata using
mysql_free_result()
.
To prepare and execute a statement, an application follows these steps:
msyql_stmt_init()
.
To prepare the statement on the server, call mysql_stmt_prepare()
and
pass it a string containing the SQL statement.
mysql_stmt_result_metadata()
to obtain the result set metadata. This metadata is itself in the form of
result set, albeit a separate one from the one that contains the rows returned
by the query. The metadata result set indicates how many columns are in the
result and contains information about each column.
mysql_stmt_bind_param()
. All
parameters must be set. Otherwise, statement execution will return an error or
produce unexpected results.
mysql_stmt_execute()
to execute the statement.
mysql_stmt_bind_result()
.
mysql_stmt_fetch()
repeatedly until no more rows are found.
When mysql_stmt_prepare()
is called, the MySQL client/server protocol
performs these actions:
When mysql_stmt_execute()
is called, the MySQL
client/server protocol performs these actions:
When mysql_stmt_fetch()
is called, the MySQL client/server protocol
performs these actions:
If an error occurs,
you can get the statement error code, error message, and SQLSTATE value using
mysql_stmt_errno()
, mysql_stmt_error()
, and
mysql_stmt_sqlstate()
, respectively.
To prepare and execute queries, use the functions in the following sections.
In MySQL 4.1.2, the names of several prepared statement functions were changed:
Old Name | New Name |
mysql_bind_param() | mysql_stmt_bind_param()
|
mysql_bind_result() | mysql_stmt_bind_result()
|
mysql_prepare() | mysql_stmt_prepare()
|
mysql_execute() | mysql_stmt_execute()
|
mysql_fetch() | mysql_stmt_fetch()
|
mysql_fetch_column() | mysql_stmt_fetch_column()
|
mysql_param_count() | mysql_stmt_param_count()
|
mysql_param_result() | mysql_stmt_param_metadata()
|
mysql_get_metadata() | mysql_stmt_result_metadata()
|
mysql_send_long_data() | mysql_stmt_send_long_data()
|
All functions that operate with a MYSQL_STMT
structure begin with
the prefix mysql_stmt_
.
Also in 4.1.2, the signature of the mysql_stmt_prepare()
function was
changed to int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length)
. To create a MYSQL_STMT
handle, you should
use the mysql_stmt_init()
function.
mysql_stmt_affected_rows()
my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)
Returns the total number of rows changed, deleted, or inserted by the last
executed statement. May be called immediately after mysql_stmt_execute()
for UPDATE
, DELETE
, or INSERT
statements. For
SELECT
statements, mysql_stmt_affected_rows()
works like
mysql_num_rows()
.
This function was added in MySQL 4.1.0.
An integer greater than zero indicates the number of rows affected
or retrieved. Zero indicates that no records were 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_stmt_store_result()
.
Because mysql_stmt_affected_rows()
returns an unsigned value, you can check for -1 by comparing the
return value to (my_ulonglong)-1
(or to (my_ulonglong)~0
,
which is equivalent).
See section 22.2.3.1 mysql_affected_rows()
for additional
information on the return value.
None.
For the usage of mysql_stmt_affected_rows()
, refer to the Example
from section 22.2.7.10 mysql_stmt_execute()
.
mysql_stmt_attr_get()
int mysql_stmt_attr_get(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, void *arg)
Can be used to get the current value for a statement attribute.
The option
argument is the option that you want to get; the
arg
should point to a variable that should contain the option
value. If the option is an integer, then arg
should point to the
value of the integer.
See mysql_stmt_attr_set()
for a list of options and option
types. See section 22.2.7.3 mysql_stmt_attr_set()
.
This function was added in MySQL 4.1.2.
0
if okay. Non-zero if option
is unknown.
None.
mysql_stmt_attr_set()
int mysql_stmt_attr_set(MYSQL_STMT *stmt, enum enum_stmt_attr_type option, const void *arg)
Can be used to set affect behavior for a statement. This function may be called multiple times to set several options.
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 |
STMT_ATTR_UPDATE_MAX_LENGTH | my_bool * | If set to 1: Update metadata MYSQL_FIELD->max_length in mysql_stmt_store_result() .
|
This function was added in MySQL 4.1.2.
0
if okay. Non-zero if option
is unknown.
None.
mysql_stmt_bind_param()
my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
mysql_stmt_bind_param()
is used to bind data for the parameter markers
in the SQL statement that was passed to mysql_stmt_prepare()
. It uses
MYSQL_BIND
structures to supply the data. bind
is the address
of an array of MYSQL_BIND
structures.
The client library expects the array to contain an element for each
`?' parameter marker that is present in the query.
Suppose that you prepare the following statement:
INSERT INTO mytbl VALUES(?,?,?)
When you bind the parameters, the array of MYSQL_BIND
structures must
contain three elements, and can be declared like this:
MYSQL_BIND bind[3];
The members of each MYSQL_BIND
element that should be set are described
in section 22.2.5 C API Prepared Statement Data types.
This function was added in MySQL 4.1.2.
Zero if the bind was successful. Non-zero if an error occurred.
CR_INVALID_BUFFER_USE
CR_UNSUPPORTED_PARAM_TYPE
buffer_type
value is
illegal or is not one of the supported types.
CR_OUT_OF_MEMORY
CR_UNKNOWN_ERROR
For the usage of mysql_stmt_bind_param()
, refer to the Example from
section 22.2.7.10 mysql_stmt_execute()
.
mysql_stmt_bind_result()
my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
mysql_stmt_bind_result()
is used to associate (bind) columns in the
result set to data buffers and length buffers. When
mysql_stmt_fetch()
is
called to fetch data, the MySQL client/server protocol places the data for the
bound columns into the specified buffers.
All columns must be bound to buffers prior to calling
mysql_stmt_fetch()
.
bind
is the address of an array of MYSQL_BIND
structures.
The client library expects the array to contain
an element for each column of the result set.
If you do not bind columns to MYSQL_BIND
structures,
mysql_stmt_fetch()
simply ignores
the data fetch. The buffers should be large enough to hold the
data values, because the protocol doesn't return data values in chunks.
A column can be bound or rebound at any time, even after a result set has been
partially retrieved. The new binding takes effect the next time
mysql_stmt_fetch()
is called. Suppose that an application binds
the columns in a result set and calls mysql_stmt_fetch()
.
The client/server
protocol returns data in the bound buffers. Then suppose the application
binds the columns to a different set of buffers. The protocol does
not place data into the newly bound
buffers until the next call to mysql_stmt_fetch()
occurs.
To bind a column, an application calls mysql_stmt_bind_result()
and
passes the type, address, and the address of the length buffer.
The members of each MYSQL_BIND
element that should be set are described
in section 22.2.5 C API Prepared Statement Data types.
This function was added in MySQL 4.1.2.
Zero if the bind was successful. Non-zero if an error occurred.
CR_UNSUPPORTED_PARAM_TYPE
buffer_type
value is
illegal or is not one of the supported types.
CR_OUT_OF_MEMORY
CR_UNKNOWN_ERROR
For the usage of mysql_stmt_bind_result()
, refer to the Example from
section 22.2.7.13 mysql_stmt_fetch()
.
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 statement has pending or unread results, this function cancels them so that the next query can be executed.
This function was added in MySQL 4.1.0.
Zero if the statement was freed successfully. Non-zero if an error occurred.
CR_SERVER_GONE_ERROR
CR_UNKNOWN_ERROR
For the usage of mysql_stmt_close()
, refer to the Example from
section 22.2.7.10 mysql_stmt_execute()
.
mysql_stmt_data_seek()
void mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset)
Seeks to an arbitrary row in a statement result set. The offset
value is a row number and should be in the range from 0
to
mysql_stmt_num_rows(stmt)-1
.
This function requires that the statement result set structure
contains the entire result of the last executed query, so
mysql_stmt_data_seek()
may be used only in conjunction with
mysql_stmt_store_result()
.
This function was added in MySQL 4.1.1.
None.
None.
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 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'.
The server error codes also are listed at section 24 Error Handling in MySQL.
This function was added in MySQL 4.1.0.
An error code value. Zero if no error occurred.
None.
mysql_stmt_error()
const char *mysql_stmt_error(MYSQL_STMT *stmt)
For the statement specified by stmt
, mysql_stmt_error()
returns a null-terminated string containing the error message for the most recently invoked statement 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_stmt_errno(stmt)) { // an error occurred } if (mysql_stmt_error(stmt)[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.
This function was added in MySQL 4.1.0.
A character string that describes the error. An empty string if no error occurred.
None.
mysql_stmt_execute()
int mysql_stmt_execute(MYSQL_STMT *stmt)
mysql_stmt_execute()
executes the prepared query associated with the
statement handle. The currently bound parameter marker values are sent
to server during this call, and the server replaces the markers with this newly
supplied data.
If the statement is an UPDATE
, DELETE
, or INSERT
,
the total number of
changed, deleted, or inserted rows can be found by calling
mysql_stmt_affected_rows()
. If this is a result set query such as
SELECT
, you
must call mysql_stmt_fetch()
to fetch the data prior to calling any
other functions that result in query processing. For more information on
how to fetch the results, refer to
section 22.2.7.13 mysql_stmt_fetch()
.
This function was added in MySQL 4.1.2.
Zero if execution was successful. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
The following example demonstrates how to create and populate a table using
mysql_stmt_init()
,
mysql_stmt_prepare()
,
mysql_stmt_param_count()
, mysql_stmt_bind_param()
,
mysql_stmt_execute()
,
and mysql_stmt_affected_rows()
. The mysql
variable is assumed
to be a valid connection handle.
#define STRING_SIZE 50 #define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table" #define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(col1 INT,\ col2 VARCHAR(40),\ col3 SMALLINT,\ col4 TIMESTAMP)" #define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)" MYSQL_STMT *stmt; MYSQL_BIND bind[3]; my_ulonglong affected_rows; int param_count; short small_data; int int_data; char str_data[STRING_SIZE]; unsigned long str_length; my_bool is_null; if (mysql_query(mysql, DROP_SAMPLE_TABLE)) { fprintf(stderr, " DROP TABLE failed\n"); fprintf(stderr, " %s\n", mysql_error(mysql)); exit(0); } if (mysql_query(mysql, CREATE_SAMPLE_TABLE)) { fprintf(stderr, " CREATE TABLE failed\n"); fprintf(stderr, " %s\n", mysql_error(mysql)); exit(0); } /* Prepare an INSERT query with 3 parameters */ /* (the TIMESTAMP column is not named; the server */ /* will set it to the current date and time) */ stmt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(stmt, INSERT_SAMPLE, strlen(INSERT_SAMPLE))) { fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } fprintf(stdout, " prepare, INSERT successful\n"); /* Get the parameter count from the statement */ param_count= mysql_stmt_param_count(stmt); fprintf(stdout, " total parameters in INSERT: %d\n", param_count); if (param_count != 3) /* validate parameter count */ { fprintf(stderr, " invalid parameter count returned by MySQL\n"); exit(0); } /* Bind the data for all 3 parameters */ memset(bind, 0, sizeof(bind)); /* INTEGER PARAM */ /* This is a number type, so there is no need to specify buffer_length */ bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&int_data; bind[0].is_null= 0; bind[0].length= 0; /* STRING PARAM */ bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= (char *)str_data; bind[1].buffer_length= STRING_SIZE; bind[1].is_null= 0; bind[1].length= &str_length; /* SMALLINT PARAM */ bind[2].buffer_type= MYSQL_TYPE_SHORT; bind[2].buffer= (char *)&small_data; bind[2].is_null= &is_null; bind[2].length= 0; /* Bind the buffers */ if (mysql_stmt_bind_param(stmt, bind)) { fprintf(stderr, " mysql_stmt_bind_param() failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Specify the data values for the first row */ int_data= 10; /* integer */ strncpy(str_data, "MySQL", STRING_SIZE); /* string */ str_length= strlen(str_data); /* INSERT SMALLINT data as NULL */ is_null= 1; /* Execute the INSERT statement - 1*/ if (mysql_stmt_execute(stmt)) { fprintf(stderr, " mysql_stmt_execute(), 1 failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Get the total number of affected rows */ affected_rows= mysql_stmt_affected_rows(stmt); fprintf(stdout, " total affected rows(insert 1): %lu\n", (unsigned long) affected_rows); if (affected_rows != 1) /* validate affected rows */ { fprintf(stderr, " invalid affected rows by MySQL\n"); exit(0); } /* Specify data values for second row, then re-execute the statement */ int_data= 1000; strncpy(str_data, "The most popular Open Source database", STRING_SIZE); str_length= strlen(str_data); small_data= 1000; /* smallint */ is_null= 0; /* reset */ /* Execute the INSERT statement - 2*/ if (mysql_stmt_execute(stmt)) { fprintf(stderr, " mysql_stmt_execute, 2 failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Get the total rows affected */ affected_rows= mysql_stmt_affected_rows(stmt); fprintf(stdout, " total affected rows(insert 2): %lu\n", (unsigned long) affected_rows); if (affected_rows != 1) /* validate affected rows */ { fprintf(stderr, " invalid affected rows by MySQL\n"); exit(0); } /* Close the statement */ if (mysql_stmt_close(stmt)) { fprintf(stderr, " failed while closing the statement\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); }
Note: For complete examples on the use of prepared statement functions, refer to the file `tests/mysql_client_test.c'. This file can be obtained from a MySQL source distribution or from the BitKeeper source repository.
mysql_stmt_free_result()
my_bool mysql_stmt_free_result(MYSQL_STMT *stmt)
Releases memory associated with the result set produced by execution of the prepared statement.
This function was added in MySQL 4.1.1.
Zero if the result set was freed successfully. Non-zero if an error occurred.
mysql_stmt_insert_id()
my_ulonglong mysql_stmt_insert_id(MYSQL_STMT *stmt)
Returns the value generated for an AUTO_INCREMENT
column by the
prepared INSERT
or UPDATE
statement. Use this function after
you have executed prepared INSERT
statement into a table which
contains an AUTO_INCREMENT
field.
See section 22.2.3.33 mysql_insert_id()
for more
information.
This function was added in MySQL 4.1.2.
Value for AUTO_INCREMENT
column which was automatically generated or
explicitly set during execution of prepared statement, or value generated
by LAST_INSERT_ID(expr)
function. Return value is undefined if statement
does not set AUTO_INCREMENT
value.
None.
mysql_stmt_fetch()
int mysql_stmt_fetch(MYSQL_STMT *stmt)
mysql_stmt_fetch()
returns the next row in the result set. It can
be called only while the result set exists, that is, after a call to
mysql_stmt_execute()
that creates a result set or after
mysql_stmt_store_result()
, which is called after
mysql_stmt_execute()
to buffer the entire result set.
mysql_stmt_fetch()
returns row data using the buffers bound by
mysql_stmt_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.
All columns must be bound by the application before calling
mysql_stmt_fetch()
.
If a fetched data value is a NULL
value, the *is_null
value of the corresponding MYSQL_BIND
structure contains TRUE
(1). Otherwise, the data and its length are returned in the *buffer
and *length
elements based on the buffer type specified by the
application. Each numeric and temporal type has a fixed length,
as listed in the following table.
The length of the string types depends on the length of the actual data value,
as indicated by data_length
.
Type | Length |
MYSQL_TYPE_TINY | 1 |
MYSQL_TYPE_SHORT | 2 |
MYSQL_TYPE_LONG | 4 |
MYSQL_TYPE_LONGLONG | 8 |
MYSQL_TYPE_FLOAT | 4 |
MYSQL_TYPE_DOUBLE | 8 |
MYSQL_TYPE_TIME | sizeof(MYSQL_TIME)
|
MYSQL_TYPE_DATE | sizeof(MYSQL_TIME)
|
MYSQL_TYPE_DATETIME | sizeof(MYSQL_TIME)
|
MYSQL_TYPE_STRING | data length
|
MYSQL_TYPE_BLOB | data_length
|
This function was added in MySQL 4.1.2.
Return Value | Description |
0 | Successful, the data has been fetched to application data buffers. |
1 | Error occurred. Error code and
message can be obtained by calling mysql_stmt_errno() and
mysql_stmt_error() .
|
MYSQL_NO_DATA | No more rows/data exists |
MYSQL_DATA_TRUNCATED | Data truncation occurred |
MYSQL_DATA_TRUNCATED
is not returned unless truncation reporting is
enabled with mysql_options()
. To determine which parameters were
truncated when this value is returned, check the error
members of
the MYSQL_BIND
parameter structures.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
CR_UNSUPPORTED_PARAM_TYPE
MYSQL_TYPE_DATE
,
MYSQL_TYPE_TIME
,
MYSQL_TYPE_DATETIME
,
or
MYSQL_TYPE_TIMESTAMP
,
but the data type is not DATE
, TIME
, DATETIME
, or
TIMESTAMP
.
mysql_stmt_bind_result()
.
The following example demonstrates how to fetch data from a table using
mysql_stmt_result_metadata()
,
mysql_stmt_bind_result()
, and mysql_stmt_fetch()
.
(This example expects to retrieve the two rows inserted by the example shown
in section 22.2.7.10 mysql_stmt_execute()
.)
The mysql
variable is assumed to be a valid connection handle.
#define STRING_SIZE 50 #define SELECT_SAMPLE "SELECT col1, col2, col3, col4 FROM test_table" MYSQL_STMT *stmt; MYSQL_BIND bind[4]; MYSQL_RES *prepare_meta_result; MYSQL_TIME ts; unsigned long length[4]; int param_count, column_count, row_count; short small_data; int int_data; char str_data[STRING_SIZE]; my_bool is_null[4]; /* Prepare a SELECT query to fetch data from test_table */ stmt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(stmt, SELECT_SAMPLE, strlen(SELECT_SAMPLE))) { fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } fprintf(stdout, " prepare, SELECT successful\n"); /* Get the parameter count from the statement */ param_count= mysql_stmt_param_count(stmt); fprintf(stdout, " total parameters in SELECT: %d\n", param_count); if (param_count != 0) /* validate parameter count */ { fprintf(stderr, " invalid parameter count returned by MySQL\n"); exit(0); } /* Fetch result set meta information */ prepare_meta_result = mysql_stmt_result_metadata(stmt); if (!prepare_meta_result) { fprintf(stderr, " mysql_stmt_result_metadata(), returned no meta information\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Get total columns in the query */ column_count= mysql_num_fields(prepare_meta_result); fprintf(stdout, " total columns in SELECT statement: %d\n", column_count); if (column_count != 4) /* validate column count */ { fprintf(stderr, " invalid column count returned by MySQL\n"); exit(0); } /* Execute the SELECT query */ if (mysql_stmt_execute(stmt)) { fprintf(stderr, " mysql_stmt_execute(), failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Bind the result buffers for all 4 columns before fetching them */ memset(bind, 0, sizeof(bind)); /* INTEGER COLUMN */ bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&int_data; bind[0].is_null= &is_null[0]; bind[0].length= &length[0]; /* STRING COLUMN */ bind[1].buffer_type= MYSQL_TYPE_STRING; bind[1].buffer= (char *)str_data; bind[1].buffer_length= STRING_SIZE; bind[1].is_null= &is_null[1]; bind[1].length= &length[1]; /* SMALLINT COLUMN */ bind[2].buffer_type= MYSQL_TYPE_SHORT; bind[2].buffer= (char *)&small_data; bind[2].is_null= &is_null[2]; bind[2].length= &length[2]; /* TIMESTAMP COLUMN */ bind[3].buffer_type= MYSQL_TYPE_TIMESTAMP; bind[3].buffer= (char *)&ts; bind[3].is_null= &is_null[3]; bind[3].length= &length[3]; /* Bind the result buffers */ if (mysql_stmt_bind_result(stmt, bind)) { fprintf(stderr, " mysql_stmt_bind_result() failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Now buffer all results to client */ if (mysql_stmt_store_result(stmt)) { fprintf(stderr, " mysql_stmt_store_result() failed\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); } /* Fetch all rows */ row_count= 0; fprintf(stdout, "Fetching results ...\n"); while (!mysql_stmt_fetch(stmt)) { row_count++; fprintf(stdout, " row %d\n", row_count); /* column 1 */ fprintf(stdout, " column1 (integer) : "); if (is_null[0]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %d(%ld)\n", int_data, length[0]); /* column 2 */ fprintf(stdout, " column2 (string) : "); if (is_null[1]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %s(%ld)\n", str_data, length[1]); /* column 3 */ fprintf(stdout, " column3 (smallint) : "); if (is_null[2]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %d(%ld)\n", small_data, length[2]); /* column 4 */ fprintf(stdout, " column4 (timestamp): "); if (is_null[3]) fprintf(stdout, " NULL\n"); else fprintf(stdout, " %04d-%02d-%02d %02d:%02d:%02d (%ld)\n", ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, length[3]); fprintf(stdout, "\n"); } /* Validate rows fetched */ fprintf(stdout, " total rows fetched: %d\n", row_count); if (row_count != 2) { fprintf(stderr, " MySQL failed to return all rows\n"); exit(0); } /* Free the prepared result metadata */ mysql_free_result(prepare_meta_result); /* Close the statement */ if (mysql_stmt_close(stmt)) { fprintf(stderr, " failed while closing the statement\n"); fprintf(stderr, " %s\n", mysql_stmt_error(stmt)); exit(0); }
mysql_stmt_fetch_column()
int mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind, unsigned int column, unsigned long offset)
Fetch one column from the current result set row. bind
provides the
buffer where data should be placed. It should be set up the same way as for
mysql_stmt_bind_result()
. column
indicates which column to
fetch. The first column is numbered 0. offset
is the offset within the
data value at which to begin retrieving data. This can be used for fetching
the data value in pieces. The beginning of the value is offset 0.
This function was added in MySQL 4.1.2.
Zero if the value was fetched successfully. Non-zero if an error occurred.
CR_INVALID_PARAMETER_NO
CR_NO_DATA
mysql_stmt_field_count()
unsigned int mysql_stmt_field_count(MYSQL_STMT *stmt)
Returns the number of columns for the most recent statement for the statement
handler. This value will be zero for statements such as INSERT
or
DELETE
that do not produce result sets.
mysql_stmt_field_count()
can be called after you have prepared a
statement by invoking mysql_stmt_prepare()
.
This function was added in MySQL 4.1.3.
An unsigned integer representing the number of columns in a result set.
None.
mysql_stmt_init()
MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)
Create a MYSQL_STMT
handle.
The handle should be freed with mysql_stmt_close(MYSQL_STMT *)
.
This function was added in MySQL 4.1.2.
A pointer to a MYSQL_STMT
structure in case of success.
NULL
if out of memory.
CR_OUT_OF_MEMORY
mysql_stmt_num_rows()
my_ulonglong mysql_stmt_num_rows(MYSQL_STMT *stmt)
Returns the number of rows in the result set.
The use of mysql_stmt_num_rows()
depends on whether or not you used
mysql_stmt_store_result()
to buffer the entire result set in the
statement handle.
If you use mysql_stmt_store_result()
, mysql_stmt_num_rows()
may be
called immediately.
This function was added in MySQL 4.1.1.
The number of rows in the result set.
None.
mysql_stmt_param_count()
unsigned long mysql_stmt_param_count(MYSQL_STMT *stmt)
Returns the number of parameter markers present in the prepared statement.
This function was added in MySQL 4.1.2.
An unsigned long integer representing the number of parameters in a statement.
None.
For the usage of mysql_stmt_param_count()
, refer to the Example from
section 22.2.7.10 mysql_stmt_execute()
.
mysql_stmt_param_metadata()
MYSQL_RES *mysql_stmt_param_metadata(MYSQL_STMT *stmt)
To be added.
This function was added in MySQL 4.1.2.
mysql_stmt_prepare()
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned
long length)
Given the statement handle returned by mysql_stmt_init()
,
prepares the SQL statement pointed to by the string
query
and returns a status value.
The string length should be given by the length
argument.
The string 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 by embedding question mark (`?') characters into the SQL string at the appropriate positions.
The markers are legal only in certain places in SQL statements. For
example, they are allowed in the VALUES()
list of an INSERT
statement (to specify column values for a row), or in a comparison with a
column in a WHERE
clause to specify a comparison value.
However, they are not allowed for identifiers (such as table or column
names), or to specify both
operands of a binary operator such as the =
equal sign.
The latter restriction is necessary because 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 Definition Language (DDL) statements.
The parameter markers must be bound to application variables using
mysql_stmt_bind_param()
before executing the statement.
This function was added in MySQL 4.1.2.
Zero if the statement was prepared successfully. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
If the prepare operation was unsuccessful (that is,
mysql_stmt_prepare()
returns non-zero), the error message can be
obtained by calling mysql_stmt_error()
.
For the usage of mysql_stmt_prepare()
, refer to the Example from
section 22.2.7.10 mysql_stmt_execute()
.
mysql_stmt_reset()
my_bool mysql_stmt_reset(MYSQL_STMT *stmt)
Reset prepared statement on client and server to state after prepare.
This is mainly used to reset data sent with
mysql_stmt_send_long_data()
.
To re-prepare the statement with another query, use
mysql_stmt_prepare()
.
This function was added in MySQL 4.1.1.
Zero if the statement was reset successfully. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
mysql_stmt_result_metadata()
MYSQL_RES *mysql_stmt_result_metadata(MYSQL_STMT *stmt)
If a statement passed to mysql_stmt_prepare()
is one that produces a result
set,
mysql_stmt_result_metadata()
returns the result set
metadata in the form of a pointer to a
MYSQL_RES
structure that can be used to process the
meta information such as total number of fields and individual field
information. This result set pointer can be passed as an argument to
any of the field-based API functions that process result set metadata, such
as:
mysql_num_fields()
mysql_fetch_field()
mysql_fetch_field_direct()
mysql_fetch_fields()
mysql_field_count()
mysql_field_seek()
mysql_field_tell()
mysql_free_result()
The result set structure should be freed when you are done with it, which
you can do by passing it to mysql_free_result()
. This is similar
to the way you free a result set obtained from a call to
mysql_store_result()
.
The result set returned by mysql_stmt_result_metadata()
contains only
metadata. It does not contain any row results. The rows are obtained by using
the statement handle with mysql_stmt_fetch()
.
This function was added in MySQL 4.1.2.
A MYSQL_RES
result structure. NULL
if no meta information exists
for the prepared query.
CR_OUT_OF_MEMORY
CR_UNKNOWN_ERROR
For the usage of mysql_stmt_result_metadata()
, refer to the
Example from section 22.2.7.13 mysql_stmt_fetch()
.
mysql_stmt_row_seek()
MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET offset)
Sets the row cursor to an arbitrary row in a statement result set.
The offset
value is a row offset that should be a value returned
from mysql_stmt_row_tell()
or from mysql_stmt_row_seek()
.
This value is not a row number; if you want to seek to a row within a
result set by number, use mysql_stmt_data_seek()
instead.
This function requires that the result set structure contains the entire
result of the query, so mysql_stmt_row_seek()
may be used only
in conjunction with mysql_stmt_store_result()
.
This function was added in MySQL 4.1.1.
The previous value of the row cursor. This value may be passed to a
subsequent call to mysql_stmt_row_seek()
.
None.
mysql_stmt_row_tell()
MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT *stmt)
Returns the current position of the row cursor for the last
mysql_stmt_fetch()
. This value can be used as an argument to
mysql_stmt_row_seek()
.
You should use mysql_stmt_row_tell()
only after mysql_stmt_store_result()
.
This function was added in MySQL 4.1.1.
The current offset of the row cursor.
None.
mysql_stmt_send_long_data()
my_bool mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int
parameter_number, const char *data, unsigned long length)
Allows an application to send parameter data to the server in pieces
(or ``chunks'').
This function can be called multiple times to send the parts of a
character or binary data value for a column, which must be one of the
TEXT
or BLOB
data types.
parameter_number
indicates which parameter to associate the data with.
Parameters are numbered beginning with 0.
data
is a pointer to a buffer containing data to be sent, and
length
indicates the number of bytes in the buffer.
Note: The next mysql_stmt_execute()
call will ignore the
bind buffer for all parameters that have been used with
mysql_stmt_send_long_data()
since last
mysql_stmt_execute()
or mysql_stmt_reset()
.
If you want to reset/forget the sent data, you can do it with
mysql_stmt_reset()
. See section 22.2.7.21 mysql_stmt_reset()
.
This function was added in MySQL 4.1.2.
Zero if the data is sent successfully to server. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_SERVER_GONE_ERROR
CR_OUT_OF_MEMORY
CR_UNKNOWN_ERROR
The following example demonstrates how to send the data for a
TEXT
column in chunks. It inserts the data value
'MySQL - The most popular Open Source database'
into the text_column
column.
The mysql
variable is assumed to be a valid connection handle.
#define INSERT_QUERY "INSERT INTO test_long_data(text_column) VALUES(?)" MYSQL_BIND bind[1]; long length; smtt = mysql_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(stmt, INSERT_QUERY, strlen(INSERT_QUERY))) { fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed"); fprintf(stderr, "\n %s", mysql_stmt_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_stmt_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_stmt_send_long_data(stmt,0,"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_stmt_send_long_data(stmt,0," - 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_stmt_execute(stmt)) { fprintf(stderr, "\n mysql_stmt_execute failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); }
mysql_stmt_sqlstate()
const char *mysql_stmt_sqlstate(MYSQL_STMT *stmt)
For the statement specified by stmt
, mysql_stmt_sqlstate()
returns a null-terminated string containing the SQLSTATE error code for the
most recently invoked prepared statement API function that can succeed or fail.
The error code consists of five characters.
"00000"
means ``no error.''
The values are specified by ANSI SQL and ODBC.
For a list of possible values, see section 24 Error Handling in MySQL.
Note that not all MySQL errors are yet mapped to SQLSTATE's.
The value "HY000"
(general error) is used
for unmapped errors.
This function was added to MySQL 4.1.1.
A null-terminated character string containing the SQLSTATE error code.
mysql_stmt_store_result()
int mysql_stmt_store_result(MYSQL_STMT *stmt)
You must call mysql_stmt_store_result()
for every statement that
successfully produces a result set
(SELECT
, SHOW
, DESCRIBE
, EXPLAIN
), and only
if you want to buffer the complete result set by the client, so that the
subsequent mysql_stmt_fetch()
call returns buffered data.
It is unnecessary to call mysql_stmt_store_result()
for other
statements, but if you do, it will not harm or cause any notable performance
problem.
You can detect whether the statement produced a result set by checking
if mysql_stmt_result_metadata()
returns NULL
.
For more information, refer to section 22.2.7.22 mysql_stmt_result_metadata()
.
Note:
MySQL doesn't by default calculate MYSQL_FIELD->max_length
for
all columns in mysql_stmt_store_result()
because calculating this
would slow down mysql_stmt_store_result()
considerably and most
applications doesn't need max_length
. If you want
max_length
to be updated, you can call
mysql_stmt_attr_set(MYSQL_STMT, STMT_ATTR_UPDATE_MAX_LENGTH, &flag)
to enable this. See section 22.2.7.3 mysql_stmt_attr_set()
.
This function was added in MySQL 4.1.0.
Zero if the results are buffered successfully. Non-zero if an error occurred.
CR_COMMANDS_OUT_OF_SYNC
CR_OUT_OF_MEMORY
CR_SERVER_GONE_ERROR
CR_SERVER_LOST
CR_UNKNOWN_ERROR
Here follows a list of the currently known problems with prepared statements:
TIME
, TIMESTAMP
, and DATETIME
don't support sub seconds
(for example from DATE_FORMAT()
.
ZEROFILL
is honored with prepared
statements
in some cases where the MySQL server doesn't print the leading zeros.
(For example, with MIN(number-with-zerofill)
).
From version 4.1, MySQL supports the execution of multiple statements
specified in a single query string. To use this capability with a given
connection, you must specify the CLIENT_MULTI_STATEMENTS
option in
the flags parameter of mysql_real_connect()
when opening the connection. You can also set this for an existing connection
by calling mysql_set_server_option(MYSQL_OPTION_MULTI_STATEMENTS_ON)
By default, mysql_query()
and mysql_real_query()
return
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_STATEMENTS */ mysql_real_connect(..., CLIENT_MULTI_STATEMENTS); /* 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"); do { /* Process all results */ ... printf("total affected rows: %lld", mysql_affected_rows(mysql)); ... if (!(result= mysql_store_result(mysql))) { printf(stderr, "Got fatal error processing query\n"); exit(1); } process_result_set(result); /* client function */ mysql_free_result(result); } while (!mysql_next_result(mysql));
The new binary protocol available in MySQL 4.1 and above allows you to
send and receive date and time values (DATE
, TIME
,
DATETIME
, and TIMESTAMP
), using
the MYSQL_TIME
structure. The members of this structure are described
in section 22.2.5 C API Prepared Statement Data types.
To send temporal data values, you create a prepared statement with
mysql_stmt_prepare()
. Then, before calling
mysql_stmt_execute()
to execute the statement, use the following
procedure to set up each temporal parameter:
MYSQL_BIND
structure associated with the data value, set the
buffer_type
member to the type that indicates what kind of temporal
value you're sending. For
DATE
,
TIME
,
DATETIME
,
or
TIMESTAMP
values, set buffer_type
to
MYSQL_TYPE_DATE
,
MYSQL_TYPE_TIME
,
MYSQL_TYPE_DATETIME
,
or
MYSQL_TYPE_TIMESTAMP
,
respectively.
buffer
member of the MYSQL_BIND
structure to the address
of the MYSQL_TIME
structure in which you will pass the temporal value.
MYSQL_TIME
structure that are appropriate
for the type of temporal value you're passing.
Use mysql_stmt_bind_param()
to bind the parameter data to the statement.
Then you can call mysql_stmt_execute()
.
To retrieve temporal values, the procedure is similar, except that you set
the buffer_type
member to the type of value you expect to receive, and
the buffer
member to the address of a MYSQL_TIME
structure into
which the returned value should be placed.
Use mysql_bind_results()
to bind the buffers to the statement after
calling mysql_stmt_execute()
and before fetching the results.
Here is a simple example that inserts DATE
, TIME
, and
TIMESTAMP
data.
The mysql
variable is assumed to be a valid connection handle.
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_stmt_init(mysql); if (!stmt) { fprintf(stderr, " mysql_stmt_init(), out of memory\n"); exit(0); } if (mysql_stmt_prepare(mysql, query, strlen(query))) { fprintf(stderr, "\n mysql_stmt_prepare(), INSERT failed"); fprintf(stderr, "\n %s", mysql_stmt_error(stmt)); exit(0); } /* set up 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_stmt_bind_param(stmt, bind); /* supply the data to be sent in the ts structure */ ts.year= 2002; ts.month= 02; ts.day= 03; ts.hour= 10; ts.minute= 45; ts.second= 20; mysql_stmt_execute(stmt); ..
You need to use the following functions when you want to create a threaded client. See section 22.2.15 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 initializes 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_library_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 initialize thread-specific variables.
This is automatically called by my_init()
and mysql_connect()
.
Zero if successful. Non-zero if an error occurred.
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.
If you want to allow your application to be linked against the embedded
MySQL server library, you must use the mysql_server_init()
and
mysql_server_end()
functions.
See section 22.2.16 libmysqld, the Embedded MySQL Server Library.
However, to provide improved memory management, even programs that are
linked with -lmysqlclient
rather than -lmysqld
should include
calls to begin and end use of the library. As of MySQL 4.1.10 and 5.0.3,
the mysql_library_init()
and mysql_library_end()
functions can
be used to do this. These actually are #define
symbols that make them
equivalent to mysql_server_init()
and mysql_server_end()
, but
the names more clearly indicate that they should be called when beginning
and ending use of a MySQL C API library no matter whether the application
uses libmysqlclient
or libmysqld
. For more information,
see section 22.2.2 C API Function Overview.
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
the server and initializes any subsystems (mysys
, InnoDB
, etc.)
that the server uses. If this function is not called, the next call to
mysql_init()
executes mysql_server_init()
.
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.
If you want to connect to an external server without starting the embedded
server, you have to specify a negative value for argc
.
The NULL
-terminated list of strings in groups
selects which groups in the option files will be active.
See section 4.3.2 Using Option Files. For convenience, groups
may be
NULL
, in which case the [server]
and [embedded]
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) { if (mysql_server_init(sizeof(server_args) / sizeof(char *), server_args, server_groups)) exit(1); /* 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_store_result()
Sometimes Returns NULL
After mysql_query()
Returns Success
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
.
In MySQL 3.23, there is an exception when DELETE
is used without
a WHERE
clause. In this case, the table is re-created as an empty
table and mysql_affected_rows()
returns zero for the number of
records affected. In MySQL 4.0, DELETE
always returns the correct
number of rows deleted. For a fast recreate, use TRUNCATE TABLE
.
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 22.2.3.33 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 into a table that contains an AUTO_INCREMENT
column, you can obtain the value stored into that column by calling the
mysql_insert_id()
function.
You can check from your C applications whether a value was stored into an
AUTO_INCREMENT
column by executing the following code (which assumes
that you've checked that the statement succeeded). It determines
whether the query was an INSERT
with an AUTO_INCREMENT
index:
if ((result = mysql_store_result(&mysql)) == 0 && mysql_field_count(&mysql) == 0 && mysql_insert_id(&mysql) != 0) { used_id = mysql_insert_id(&mysql); }
For more information, see section 22.2.3.33 mysql_insert_id()
.
When a new AUTO_INCREMENT
value has been generated, you can also
obtain it by executing a SELECT LAST_INSERT_ID()
statement with
mysql_query()
and retrieving the value from the result set returned
by the statement.
For LAST_INSERT_ID()
,
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
Note that mysql_insert_id()
returns the value stored into an
AUTO_INCREMENT
column, whether that value is automatically generated
by storing NULL
or 0
or was specified as an explicit value.
LAST_INSERT_ID()
returns only automatically generated
AUTO_INCREMENT
values. If you store an explicit value other than
NULL
or 0
, it does not affect the value returned by
LAST_INSERT_ID()
.
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 it simpler to compile MySQL programs on Unix, we have provided the
mysql_config
script for you. See section 22.1.2 mysql_config
, Get compile options for compiling clients.
You can use it to compile a MySQL client as follows:
CFG=/usr/local/mysql/bin/mysql_config sh -c "gcc -o progname `$CFG --cflags` progname.c `$CFG --libs`"
The sh -c
is needed to get the shell not to treat 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.
New in 4.0.16: To not abort the program when a connection terminates,
MySQL blocks SIGPIPE
on the first call to
mysql_server_init
(), mysql_init()
or
mysql_connect()
. If you want to have your own SIGPIPE
handler, you should first call mysql_server_init()
and then
install your handler. In older versions of MySQL SIGPIPE
was blocked,
but only in the thread safe client library, for every call to
mysql_init()
.
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 22.2 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 22.2.11 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 that 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 a client application. The main benefits are increased speed and more simple management for embedded applications.
The embedded server library is based on the client/server version of MySQL, which is written in C/C++. Consequently, the embedded server also is written in C/C++. There is no embedded server available in other languages.
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 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 22.2.12.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:
ISAM
tables. (This is mainly done to make the library smaller)
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.3.2 Using Option Files.
[server]
section. These will be read by
both MySQL versions.
[mysqld]
section.
[embedded]
section.
[ApplicationName_SERVER]
section.
stderr
. We will add an option to specify a
filename for these.
InnoDB
to not be so verbose when using in the embedded
version.
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 * initialize 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); mysql_free_result(res); } else (void)printf("Affected rows: %lld\n", mysql_affected_rows(db)); 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
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 license for the MySQL code from MySQL AB. For details, please see http://www.mysql.com/company/legal/licensing/.
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
.
The Perl DBI
module provides a generic interface for database access.
You can write a DBI script that works with many different database engines
without change. To use DBI, you must install the DBI
module, as well
as a DataBase Driver (DBD) module for each type of server you want to access.
For MySQL, this driver is the DBD::mysql
module.
Perl DBI is the recommended Perl interface. It replaces an older
interface called mysqlperl
, which should be considered obsolete.
Installation instructions for Perl DBI support are given in section 2.13 Perl Installation Notes.
DBI information is available at the command line, online, or in printed form:
DBI
and DBD::mysql
modules installed, you can
get information about them at the command line with the perldoc
command:
shell> perldoc DBI shell> perldoc DBI::FAQ shell> perldoc DBD::mysqlYou can also use
pod2man
, pod2html
, and so forth to translate
this information into other formats.
DBD::mysql
; see
section 1.4.1.1 The MySQL Mailing Lists.
MySQL++
is the 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++. To avoid this problem, only call
mysql_init()
with NULL
as an argument, not a pre-allocated
MYSQL
structure.
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 MySQL Connectors, drivers that provide connectivity to the MySQL server for client programs.
MySQL provides support for ODBC by means of MySQL Connector/ODBC, the family of MyODBC drivers. This is the reference for the Connector/ODBC product family of MyODBC drivers that provide ODBC 3.5x compliant access to the MySQL Database System. It will teach you how to install MyODBC and how to use it. You will also information about common programs that are known to work with MyODBC and answers to some of the most frequently asked questions about MyODBC.
This reference applies to MyODBC . You can find a manual for an older version of MyODBC in the binary or source distribution for that version.
This is a reference to the MySQL ODBC drivers, not a general ODBC reference. For more information about ODBC, refer to http://www.microsoft.com/data/.
The application development part of this reference assumes a good working knowledge of C, general DBMS knowledge, and finally, but not least, familiarity with MySQL. For more information about MySQL functionality and its syntax, refer to http://dev.mysql.com/doc/.
If you have questions that are not answered in this document, please send a mail message to myodbc@lists.mysql.com.
ODBC (Open Database Connectivity) provides a way for client programs to access a wide range of databases or data sources. ODBC is a standardized API that allows connections to SQL database servers. It was developed according to the specifications of the SQL Access Group and defines a set of function calls, error codes, and data types that can be used to develop database-independent applications. ODBC usually is used when database independence or simultaneous access to different data sources is required.
For more information about ODBC, refer to http://www.microsoft.com/data/.
Connector/ODBC is the term designating the MySQL AB product family of MySQL ODBC drivers. These are known as the MyODBC drivers.
MyODBC 2.50 is a 32-bit ODBC driver from MySQL AB that is based on ODBC 2.50 specification level 0 (with level 1 and 2 features). This is one of the most popular ODBC drivers in the Open Source market, used by many users to access the MySQL functionality.
MyODBC 3.51 is a 32-bit ODBC driver, also known as the MySQL ODBC 3.51 driver. This version is enhanced compared to the existing MyODBC 2.50 driver. It has support for ODBC 3.5x specification level 1 (complete core API + level 2 features) in order to continue to provide all functionality of ODBC for accessing MySQL.
MySQL AB distributes all its products under the General Public License (GPL). You can get a copy of the latest version of MyODBC binaries and sources from the MySQL AB Web site http://dev.mysql.com/downloads/.
For more information about MyODBC, visit http://www.mysql.com/products/myodbc/.
For more information about licensing, visit http://www.mysql.com/company/legal/licensing/.
MyODBC can be used on all major platforms supported by MySQL, such as:
If a binary distribution is not available for downloading for a particular platform, you can build the driver yourself by downloading the driver sources. You can contribute the binaries to MySQL by sending a mail message to myodbc@lists.mysql.com, so that it becomes available for other users.
MySQL AB provides assistance to the user community by means of its mailing lists. For MyODBC-related issues, you can get help from experienced users by using the myodbc@lists.mysql.com mailing list.
For information about subscribing to MySQL mailing lists or to browse list archives, visit http://lists.mysql.com/.
Of particular interest is the ODBC forum in the MySQL Connectors section of the forums.
Community support from experienced users is available through the MySQL Forums, located at http://forums.mysql.com.
If you encounter difficulties or problems with MyODBC, you should start
by making a log file from the ODBC Manager
(the log you get when
requesting logs from ODBC ADMIN
) and MyODBC. The procedure for doing
this is described in section 23.1.9.7 Getting an ODBC Trace File.
Check the MyODBC trace file to find out what could be wrong.
You should be able to determine what statements were issued by searching for
the string >mysql_real_query
in the `myodbc.log' file.
You should also try issuing the statements from the mysql
client
program or from admndemo
. This will help you determine whether the
error is in MyODBC or MySQL.
If you find out something is wrong, please only send the relevant rows
(maximum 40 rows) to the myodbc
mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
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
create an archive in tar
or Zip format that contains a MyODBC trace file,
the ODBC log file, and a `README' file that explains the problem. You can send this
to ftp://ftp.mysql.com/pub/mysql/upload/. Only we at
MySQL AB will have access to the files you upload, and we will
be very discreet with the data.
If you can create a program that also demonstrates the problem, please include it in the archive as well.
If the program works with some other SQL server, you should include 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.
You can send a patch or suggest a better solution for any existing code or problems by sending a mail message to myodbc@lists.mysql.com.
Open Database Connectivity (ODBC) is a widely accepted application-programming interface (API) for database access. It is based on the Call-Level Interface (CLI) specifications from X/Open and ISO/IEC for database APIs and uses Structured Query Language (SQL) as its database access language.
A survey of ODBC functions supported by MyODBC is given at section 23.1.16 MyODBC API Reference. For general information about ODBC, see http://www.microsoft.com/data/.
The MyODBC architecture is based on five components, as shown in the following diagram:
An ODBC Driver Manager is a library that manages communication between the ODBC aware application and driver(s). Its main functionality includes:
The following driver managers are commonly used:
MyODBC 3.51 also is shipped with UnixODBC beginning with version 2.1.2.
MySQL AB supports two Open Source ODBC drivers for accessing MySQL functionality through the ODBC API: MyODBC (MyODBC 2.50) and MySQL ODBC 3.51 Driver (MyODBC 3.51).
Note: From this section onward, we refer both the drivers generically as MyODBC. Whenever there is a difference, we use the original names.
MyODBC works on Windows 9x, Me, NT, 2000, XP, and 2003, and on most Unix platforms.
MyODBC is Open Source. You can find the newest version at http://dev.mysql.com/downloads/connector/odbc/. 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 need to install MyODBC only on Windows machines. You need MyODBC for Unix only if you have a program like ColdFusion that is running on a Unix machine and uses ODBC to connect for database access.
If you want to install MyODBC on a Unix box, you will also need an ODBC manager. MyODBC is known to work with most Unix ODBC managers.
GRANT
command. See section 13.5.1.3 GRANT
and REVOKE
Syntax.
ODBC Data Sources 32-bit
icon.
User DSN
.
Add
button.
Create New Data Source
and click
the Finish
button.
Notice that other configuration options are shown on the MySQL screen that you can try if you run into problems (options such as trace, don't prompt on connect, and so forth).
To install MyODBC on Windows, you should download the appropriate
distribution file from http://dev.mysql.com/downloads/connector/odbc/,
unpack it, and execute the MyODBC-VERSION.exe
file.
On Windows, you may get the following error when trying to install the older MyODBC 2.50 driver:
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 is that some other program is using ODBC. Because of how
Windows is designed, you may not be able in this case to install new
ODBC drivers with Microsoft's ODBC setup program. In most cases, you can
continue by pressing Ignore
to copy the rest of the MyODBC files and
the final installation should still work. If it doesn't, the solution is
to re-boot your computer in ``safe mode.'' Choose safe mode by pressing F8
just before your machine starts Windows during re-booting, install MyODBC,
and re-boot to normal mode.
To install or upgrade MyODBC from an RPM distribution on
Linux, simply download the RPM distribution of the latest version
of MyODBC and follow the instructions below. Use su root
to become root
, then install the RPM file.
If you are installing for the first time:
shell> su root shell> rpm -ivh MyODBC-3.51.01.i386-1.rpm
If the driver exists, upgrade it like this:
shell> su root shell> rpm -Uvh MyODBC-3.51.01.i386-1.rpm
If there is any dependancy error for MySQL client library,
libmysqlclient
, simply ignore it by supplying the --nodeps
option, and then make sure the MySQL client shared library is in the path
or set through LD_LIBRARY_PATH
.
This installs the driver libraries and related documents to `/usr/local/lib' and `/usr/share/doc/MyODBC' respectively. Proceed onto section 23.1.9.3 Configuring a MyODBC DSN on Unix.
To uninstall the driver, become root
and execute
an rpm
command:
shell> su root shell> rpm -e MyODBC
To install the driver from a tarball distribution (`.tar.gz' file), download the latest version of the driver for your operating system and follow these steps:
shell> su root shell> gunzip MyODBC-3.51.01-i686-pc-linux.tar.gz shell> tar xvf MyODBC-3.51.01-i686-pc-linux.tar shell> cd MyODBC-3.51.01-i686-pc-linux
Read the installation instructions in the `INSTALL-BINARY' file and execute these commands.
shell> cp libmyodbc* /usr/local/lib shell> cp odbc.ini /usr/local/etc shell> export ODBCINI=/usr/local/etc/odbc.ini
Then proceed on to section 23.1.9.3 Configuring a MyODBC DSN on Unix to configure the DSN for MyODBC. For more information, refer to the `INSTALL-BINARY' file that comes with your distribution.
MyODBC 3.51 source distributions include `Makefiles' that
uses nmake
. In the distribution, you can find `Makefile'
for building the release version and `Makefile_debug' for building
debugging versions of the driver libraries and DLLs.
To build the driver, use this procedure:
C:\> cd myodbc3-src
C:\> nmake -f Makefile C:\> nmake -f Makefile install
nmake -f Makefile
builds the release version of the driver
and places the binaries in subdirectory called `Release'.
nmake -f Makefile install
installs (copies) the driver DLLs
and libraries(`myodbc3.dll', `myodbc3.lib') to your system
directory.
C:\> nmake -f Makefile_debug C:\> nmake -f Makefile_debug install
C:\> nmake -f Makefile clean C:\> nmake -f Makefile install
Note:
MYSQL_LIB_PATH
and
MYSQL_INCLUDE_PATH
variables). The default header file path is
assumed to be `C:\mysql\include'. The default library path is assumed
to be `C:\mysql\lib\opt' for release DLLs and `C:\mysql\lib\debug'
for debug versions.
nmake
, visit
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vcce4/html/evgrfRunningNMAKE.asp.
After the driver libraries are copied/installed to the system directory, you can test whether the libraries are properly built by using the samples provided in the `samples' subdirectory:
C:\> cd samples C:\> nmake -f Makefile all
The MyODBC 2.50 source distribution includes VC workspace files. You can build the driver using these files (`.dsp' and `.dsw') directly by loading them from Microsoft Visual Studio 6.0 or higher.
--enable-thread-safe-client
option.
libmysqlclient installed as a shared library.
iodbc
3.0 or later (http://www.iodbc.org)
unixodbc
Alpha 3 or later (http://www.unixodbc.org)
Once you have all the required files, unpack the source files to a separate directory and follow the instructions as given below:
configure
Options
The configure
script gives you a great deal of control over how
you configure your MyODBC build. Typically you do this using options on the
configure
command line. You can also affect configure
using certain environment variables. For a list of options and environment
variables supported by configure
, run this command:
shell> ./configure --help
Some of the more commonly used configure
options are described here:
--with-mysql-path=DIR
option, where
DIR is the directory where the MySQL is installed.
MySQL compile options can be determined by running
DIR/bin/mysql_config
.
iodbc
or unixobc
).
iodbc
and iodbc
is not installed in its default
location (`/usr/local'), you might have to use
the --with-iodbc=DIR
option, where
DIR is the directory where iodbc is installed.
If the iodbc headers do not reside in `DIR/include',
you can use the --with-iodbc-includes=INCDIR
option to
specify their location.
The applies to libraries. If they are not in `DIR/lib',
you can use the --with-iodbc-libs=LIBDIR
option.
unixODBC
, use the --with-unixODBC=DIR
option (case sensitive) to make configure
look for unixODBC
instead of iodbc
by default, DIR is the directory where
unixODBC is installed.
If the unixODBC headers and libraries aren't located in
`DIR/include' and `DIR/lib', use
the --with-unixODBC-includes=INCDIR
and --with-unixODBC-libs=LIBDIR
options.
--prefix=/usr/local/odbc
option.
The final configuration command will look something like this:
shell> ./configure --prefix=/usr/local \ --with-iodbc=/usr/local \ --with-mysql-path=/usr/local/mysql
In order to link the driver with MySQL thread safe client libraries
`libmysqlclient_r.so' or `libmysqlclient_r.a', you must specify the
following configure
option:
--enable-thread-safe
and can be disabled(default) using
--disable-thread-safe
This option enables the building of driver thread-safe library `libmyodbc3_r.so' from by linking with mysql thread-safe client library `libmysqlclient_r.so' (The extensions are OS dependent).
In case while configuring with thread-safe option, and gotten into a configure error; then look at the `config.log' and see if it is due to the lack of thread-libraries in the system; and supply one with LIBS options i.e.
LIBS="-lpthread" ./configure ..
You can enable or disable the shared and static versions using these options:
--enable-shared[=yes/no] --disable-shared --enable-static[=yes/no] --disable-static
By default, all the binary distributions are built as non-debugging versions
(configured with --without-debug
).
To enable debugging information,
build the driver from source distribution and use the
--with-debug
) when you run configure
.
This option is available only for BK
clone trees; not for
normal source distributions.
By default, the driver is built with (--without-docs
); And
in case if you want the documentation to be taken care in the normal
build, then configure with:
--with-docs
To build the driver libraries, you have to just execute make
,
which takes care of everything.
shell> make
If any errors occur, correct them and continue the build process. If you aren't able to build, then send a detailed email to myodbc@lists.mysql.com for further assistance.
On most platforms, MySQL doesn't build or support `.so' (shared) client libraries by default, because building with shared libraries has caused us problems in the past.
In cases like this, you have to download the MySQL distribution and configure it with these options:
--without-server --enable-shared
To build shared driver libraries, you must specify the
--enable-shared
option for configure
. By default,
configure
does not enable this option.
If you have configured with the --disable-shared
option, you can
build the `.so' file from the static libraries using the following
commands:
shell> cd MyODBC-3.51.01 shell> make shell> cd driver shell> CC=/usr/bin/gcc \ $CC -bundle -flat_namespace -undefined error \ -o .libs/libmyodbc3-3.51.01.so \ catalog.o connect.o cursor.o dll.o error.o execute.o \ handle.o info.o misc.o myodbc3.o options.o prepare.o \ results.o transact.o utility.o \ -L/usr/local/mysql/lib/mysql/ \ -L/usr/local/iodbc/lib/ \ -lz -lc -lmysqlclient -liodbcinst
Make sure to change -liodbcinst
to -lodbcinst
if you are
using unixODBC instead of iODBC, and configure the library paths
accordingly.
This builds and places the `libmyodbc3-3.51.01.so' file in the
`.libs' directory. Copy this file to MyODBC library directory
(`/usr/local/lib' (or the `lib' directory under the installation
directory that you supplied with the --prefix
).
shell> cd .libs shell> cp libmyodbc3-3.51.01.so /usr/local/lib shell> cd /usr/local/lib shell> ln -s libmyodbc3-3.51.01.so libmyodbc3.so
To build the thread-safe driver library:
shell> CC=/usr/bin/gcc \ $CC -bundle -flat_namespace -undefined error -o .libs/libmyodbc3_r-3.51.01.so catalog.o connect.o cursor.o dll.o error.o execute.o handle.o info.o misc.o myodbc3.o options.o prepare.o results.o transact.o utility.o -L/usr/local/mysql/lib/mysql/ -L/usr/local/iodbc/lib/ -lz -lc -lmysqlclient_r -liodbcinst
To install the driver libraries, execute the following command:
shell> make install
That command installs one of the following sets of libraries:
For MyODBC 3.51:
For thread-safe MyODBC 3.51:
For MyODBC 2.5.0:
For more information on build process, refer to the `INSTALL' file
that comes with the source distribution. Note that if you are trying to
use the make
from Sun, you may end up with errors. On
the other hand, GNU gmake
should work fine on all
platforms.
To run the basic samples provided in the distribution with the libraries that you built, just execute:
shell> make test
Make sure the DSN 'myodbc3' is configured first in `odbc.ini' and
environment variable ODBCINI
is pointing to the right
`odbc.ini' file; and MySQL server is running. You can find a sample
`odbc.ini' with the driver distribution.
You can even modify the `samples/run-samples' script to pass the desired DSN, UID, and PASSWORD values as the command line arguments to each sample.
To build the driver on Mac OS X (Darwin), make use of the
following configure
example:
shell> ./configure --prefix=/usr/local --with-unixODBC=/usr/local --with-mysql-path=/usr/local/mysql --disable-shared --enable-gui=no --host=powerpc-apple
The command assumes that the unixODBC and MySQL are installed in the default locations. If not, configure accordingly.
On Mac OS X, --enable-shared
builds `.dylib' files by default.
You can build `.so' files like this:
shell> make shell> cd driver shell> CC=/usr/bin/gcc \ $CC -bundle -flat_namespace -undefined error -o .libs/libmyodbc3-3.51.01.so *.o -L/usr/local/mysql/lib/ -L/usr/local/iodbc/lib -liodbcinst -lmysqlclient -lz -lc
To build the thread-safe driver library:
shell> CC=/usr/bin/gcc \ $CC -bundle -flat_namespace -undefined error -o .libs/libmyodbc3-3.51.01.so *.o -L/usr/local/mysql/lib/ -L/usr/local/iodbc/lib -liodbcinst -lmysqlclienti_r -lz -lc -lpthread
Make sure to change the -liodbcinst
to -lodbcinst
in case of
using unixODBC instead of iODBC and configure the libraries path
accordingly.
In Apple's version of GCC, both cc
and gcc
are actually
symbolic links to gcc3
.
Copy this library to the `$prefix/lib' directory and symlink to `libmyodbc3.so'.
You can cross-check the output shared-library properties using this command:
shell> otool -LD .libs/libmyodbc3-3.51.01.so
To build the driver on HP-UX 10.x or 11.x, make use of
the following configure
example:
If using cc
:
shell> CC="cc" \ CFLAGS="+z" \ LDFLAGS="-Wl,+b:-Wl,+s" \ ./configure --prefix=/usr/local --with-unixodbc=/usr/local --with-mysql-path=/usr/local/mysql/lib/mysql --enable-shared --enable-thread-safe
If using gcc
:
shell> CC="gcc" \ LDFLAGS="-Wl,+b:-Wl,+s" \ ./configure --prefix=/usr/local --with-unixodbc=/usr/local --with-mysql-path=/usr/local/mysql --enable-shared --enable-thread-safe
Once the driver is built, cross-check its attributes using
chatr .libs/libmyodbc3.sl
to see whether or not you need to have the MySQL client
libraries path using the SHLIB_PATH
environment variable. For
static versions, ignore all shared-library options and run configure
with the --disable-shared
option.
To build the driver on AIX, make use of
the following configure
example:
shell> ./configure --prefix=/usr/local --with-unixodbc=/usr/local --with-mysql-path=/usr/local/mysql --disable-shared --enable-thread-safe
NOTE: For more information about how to build and set up the static and shared libraries across the different platforms refer to ' Using static and shared libraries across platforms'.
Note: You should read this section only if you are interested in helping us test our new code.
To obtain our most recent development source tree, use these instructions:
shell> bk clone bk://mysql.bkbits.net/myodbc3 myodbc-3.51In the preceding example, the source tree will be set up in the `myodbc-3.51/' or by default `myodbc3/' subdirectory of your current directory. If you are behind the firewall and can only initiate HTTP connections, you can also use BitKeeper via HTTP. If you are required to use a proxy server, simply set the environment variable
http_proxy
to point to your proxy:
shell> export http_proxy="http://your.proxy.server:8080/"Replace the
bk://
with http://
when doing a
clone. Example:
shell> bk clone http://mysql.bkbits.net/myodbc3 myodbc-3.51The initial download of the source tree may take a while, depending on the speed of your connection; be patient.
autoconf 2.52
(or newer), automake 1.4
,
libtool 1.4
, and m4
to run the next set of commands.
shell> cd myodbc-3.51 shell> bk -r edit shell> aclocal; autoheader; autoconf; automake; shell> ./configure # Add your favorite options here shell> makeFor more information on how to build, refer to `INSTALL' file located in the same directory. On Windows, make use of Windows Makefiles `WIN-Makefile' and `WIN-Makefile_debug' in building the driver, for more information, see section 23.1.6 Installing MyODBC from a Source Distribution on Windows.
make install
to install the
MyODBC 3.51 driver on your system.
make
stage and the distribution does
not compile, please report it to myodbc@lists.mysql.com.
bk clone
operation to get the source tree, you
should run bk pull
periodically to get the updates.
bk sccstool
. If you see some funny diffs or code that you have a
question about, do not hesitate to send e-mail to
myodbc@lists.mysql.com.
Also, if you think you have a better idea on how to do something, send an
e-mail to the same address with a patch. bk diffs
will produce a
patch for you after you have made changes to the source. If you do not
have the time to code your idea, just send a description.
bk helptool
.
You can also browse changesets, comments and source code online by browsing to http://mysql.bkbits.net:8080/myodbc3.
This section describes how to configure MyODBC, including DSN creation and the different arguments that the driver takes as an input arguments in the connection string. It also describes how to create an ODBC trace file.
A "data source" is a place where data comes from. The data source must have a persistent identifier, the Data Source Name. Using the Data Source Name, MySQL can access initialization information. With the initialization information, MySQL knows where to access the database and what settings to use when the access starts.
In effect, the data source is the path to the data. In different contexts this might mean different things, but typically it identifies a running MySQL server (for example via a network address or service name), plus the default database for that server at connection time, plus necessary connection information such as the port. The MySQL drivers (and, on Windows systems, the ODBC Driver Manager) will use the data source for connecting. An administrative utility called the Microsoft ODBC Data Source Administrator may be useful for this purpose.
There are two places where the initialization information might be: in the Windows registry (on a Windows system), or in a DSN file (on any system).
If the information is in the Windows registry, it is called a "Machine data source". It might be a "User data source", in which case only one user can see it. Or it might be a "System data source" in which case it is accessible to all users on the computer, or indeed to all users connected to the computer, if the users are connected by Microsoft Windows NT services. When you run the ODBC Data Administration program, you will have a choice whether to use "User" or "System" -- there are separate tabs.
If the information is in a DSN file, it is called a "File data source". This is a text file. Its advantages are: (a) it is an option for any kind of computer, not just a computer with a Windows operating system; (b) its contents can be transmitted or copied relatively easily.
To add and configure a new MyODBC data source on Windows, use the
ODBC Data Source Administrator
. The ODBC Administrator
updates your data source connection information. As you
add data sources, the ODBC Administrator
updates the
registry information for you.
To open the ODBC Administrator
from the Control Panel:
Start
, point to Settings
, and then click Control
Panel
.
Administrative Tools
, and then double-click Data Sources
(ODBC)
. On computers running older versions of Windows, double-click
32-bit ODBC
or ODBC
.
ODBC Data Source Administrator
dialog box appears, as
shown here:
Help
for detailed information about each tab of the ODBC
Data Source Administrator
dialog box.
To add a data source on Windows:
ODBC Data Source Administrator
.
ODBC Data Source Administrator
dialog box, click
Add
. The Create New Data Source
dialog box appears.
MySQL ODBC 3.51 Driver
, and then click Finish
.
The MySQL ODBC 3.51 Driver - DSN Configuration
dialog box appears,
as shown here:
Data Source Name
box, enter the name of the data
source you want to access. It can be any valid name that you choose.
Description
box, enter the description needed for the DSN.
Host or Server Name (or IP)
box, enter the name of the MySQL
server host that you want to access. By default, it is localhost
.
Database Name
box, enter the name of the MySQL database
that you want to use as the default database.
User
box, enter your MySQL username (your database
user ID).
Password
box, enter your password.
Port
box, enter the port number if it is not the default (3306).
SQL Command
box, you can enter an optional SQL statement that
you want to issue automatically after the connection has been established.
The final dialog looks like this:
OK
to add this data source.
Note: Upon clicking OK
, the Data Sources
dialog
box appears, and the ODBC Administrator
updates the registry
information. The username and connect string that you entered become the
default connection values for this data source when you connect to it.
You can also test whether your settings are suitable for connecting to the
server using the button Test Data Source
. This feature is available
only for the MyODBC 3.51 driver. A successful test results in the following
window:
A failed test results in an error:
The DSN configuration dialog also has an Options
button. If you
select it, the following options dialog appears displaying that control
driver behavior. Refer to section 23.1.9.4 Connection Parameters for information
about the meaning of these options.
Note: The options listed under Driver Trace Options
are
disabled (grayed out) unless you are using the debugging version of the
driver DLL.
To modify a data source on Windows:
ODBC Data Source Administrator
. Click the appropriate
DSN tab.
Configure
. The MySQL ODBC 3.51 Driver - DSN Configuration
dialog box appears.
OK
.
When you have finished modifying the information in this dialog box, the
ODBC Administrator
updates the registry information.
On Unix
, you configure DSN entries directly in the
`odbc.ini' file. Here is a typical `odbc.ini' file that configures
myodbc
and myodbc3
as the DSN names for MyODBC 2.50 and MyODBC
3.51, respectively:
; ; odbc.ini configuration for MyODBC and MyODBC 3.51 drivers ; [ODBC Data Sources] myodbc = MyODBC 2.50 Driver DSN myodbc3 = MyODBC 3.51 Driver DSN [myodbc] Driver = /usr/local/lib/libmyodbc.so Description = MyODBC 2.50 Driver DSN SERVER = localhost PORT = USER = root Password = Database = test OPTION = 3 SOCKET = [myodbc3] Driver = /usr/local/lib/libmyodbc3.so Description = MyODBC 3.51 Driver DSN SERVER = localhost PORT = USER = root Password = Database = test OPTION = 3 SOCKET = [Default] Driver = /usr/local/lib/libmyodbc3.so Description = MyODBC 3.51 Driver DSN SERVER = localhost PORT = USER = root Password = Database = test OPTION = 3 SOCKET =
Refer to the section 23.1.9.4 Connection Parameters, for the list of connection parameters that can be supplied.
Note: If you are using unixODBC, you can use the following tools in order to set up the DSN:
In some cases when using unixODBC, you might get this error:
Data source name not found and no default driver specified
If this happens, make sure the ODBCINI
and ODBCSYSINI
environment variables are pointing to the right `odbc.ini' file. For
example, if your `odbc.ini' file is located in `/usr/local/etc',
set the environment variables like this:
export ODBCINI=/usr/local/etc/odbc.ini export ODBCSYSINI=/usr/local/etc
You can specify the following parameters for MyODBC in the [Data
Source Name]
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 | Options that specify how MyODBC should work. See below. |
port | 3306 | The TCP/IP port to use if server is not localhost .
|
stmt | A statement to execute when connecting to MySQL. | |
password | The password for the user account on server .
| |
socket | The Unix socket file or Windows named pipe to connect to if server is localhost .
|
The option
argument is used to tell MyODBC that the client isn't 100%
ODBC compliant. On Windows, you normally select options by toggling the
checkboxes in the connection screen, but you can also select them in the
option
argument. The following options are listed in the order
in which they appear in the MyODBC connect screen:
Value | 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, MySQL returns ``found rows'' instead. You 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'. (On Unix, the file is `/tmp/myodbc.log'.)
|
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 | Enable or disable the dynamic cursor support. (Not allowed in MyODBC 2.50.) |
64 | Ignore use of database name in db_name.tbl_name.col_name .
|
128 | Force use of ODBC manager cursors (experimental). |
256 | Disable the use of extended fetch (experimental). |
512 | Pad CHAR columns to full column length.
|
1024 | SQLDescribeCol() will return fully qualified column names.
|
2048 | Use the compressed client/server 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 be needed but...). |
262144 | Disable transactions. |
524288 | Enable query logging to `c:\myodbc.sql'(`/tmp/myodbc.sql') file. (Enabled only in debug mode.) |
1048576 | Do not cache the results locally in the driver,
instead read from server (mysql_use_result() ). This works only for
forward-only cursors. This option is very important in dealing
with large tables when you don't want the driver to cache the
entire result set.
|
2097152 | Force the use of Forward-only cursor type. In case
of applications setting the default static/dynamic cursor type, and one
wants driver to use non-cache result sets, then this option will ensure
the forward-only cursor behavior.
|
To select multiple options, add together their values. For example,
setting option
to 12 (4+8) gives you debugging without packet limits.
The default `myodbc3.dll' is compiled for optimal performance. If you want to debug MyODBC 3.51 (for example, to enable tracing), you should instead use `myodbc3d.dll'. To install this file, copy `myodbc3d.dll' over the installed `myodbc3.dll' file. Make sure to revert back to the release version of the driver DLL once you are done with the debugging because the debug version may cause performance issues.
For MyODBC 2.50, `myodbc.dll' and `myodbcd.dll' are used instead.
The following table shows some recommended option
values for
various configurations:
Configuration | Option Value |
Microsoft Access | 3 |
Microsoft Visual Basic | 3 |
Large tables with too many rows | 2049 |
Driver trace generation (Debug mode) | 4 |
Query log generation (Debug mode) | 524288 |
Generate driver trace as well as query log (Debug mode) | 524292 |
Large tables with no-cache results | 3145731 |
Yes. You can connect to the MySQL server using SQLDriverConnect, by
specifying the DRIVER
name field. Here are the connection strings
for MyODBC using DSN-Less connection:
For MyODBC 2.50:
ConnectionString = "DRIVER={MySQL};\ SERVER=localhost;\ DATABASE=test;\ USER=venu;\ PASSWORD=venu;\ OPTION=3;"
For MyODBC 3.51:
ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};\ SERVER=localhost;\ DATABASE=test;\ USER=venu;\ PASSWORD=venu;\ OPTION=3;"
If your programming language converts backslash followed by whitespace to a space, it is preferable to specify the connection string as a single long string, or to use a concatenation of multiple strings that does not add spaces in between. For example:
ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};" "SERVER=localhost;" "DATABASE=test;" "USER=venu;" "PASSWORD=venu;" "OPTION=3;"
Refer to the section 23.1.9.4 Connection Parameters, for the list of connection parameters that can be supplied.
If you want to connect to system A from system B with a username
and password of myuser
and mypassword
, here is a simple
procedure.
On system A, follow these steps:
GRANT
to set up an account with a username of myuser
that can
connect from system B using a password of myuser
:
GRANT ALL ON *.* to 'myuser'@'B' IDENTIFIED BY 'mypassword';
GRANT
statement grants all privileges to user `myuser' for
connecting
from system B using the password mypassword
. To execute this statement,
you should be either root
on system A (or another user who has
appropriate privileges). For more information about MySQL privileges, refer to
section 5.6 MySQL User Account Management.
On system B, follow these steps:
DSN = remote_test SERVER or HOST = A (or IP address of system A) DATABASE = test (The default database or an appropriate one) USER = myuser PASSWORD = mypasswordTo set up a DSN-less connection, refer to section 23.1.9.5 Connecting Without a Predefined DSN.
DSN=remote_test
. If it fails, trace the
MyODBC log, and take the further steps based on the error message
from the log. If you need further assistance, send a detailed mail message
to myodbc@lists.mysql.com.
You can also find a simple HOWTO at http://www.phphelp.com/tutorial/using-myodbc-to-connect-to-a-remote-database.html.
If you encounter difficulties or problems with MyODBC, you should start
by making a log file from the ODBC Manager
(the log you get when
requesting logs from ODBC ADMIN
) and MyODBC.
To get an ODBC trace through Driver Manager, do the following:
Start
, point to Settings
, and then click Control
Panel
.
Administrative Tools
, and then double-click Data Sources
(ODBC)
, as shown below.
32-bit ODBC
or ODBC
in the Control Panel.
ODBC Data Source Administrator
dialog box appears, as shown
below:
Tracing
tab of the ODBC Data Source Administrator
dialog box enables you to configure the way ODBC function calls are
traced.
Tracing
tab, the
Driver Manager
will log all ODBC function calls for all
subsequently run applications.
Stop Tracing Now
. Remember that
while tracing is on, the log file continues to increase in size and
that tracing affects the performance of all your ODBC applications.
Trace
option in the
`ODBC.INI' file.
Set the tracing ON
or OFF
by using TraceFile
and
Trace
parameters in `odbc.ini' as shown below:
TraceFile = /tmp/odbc.trace Trace = 1
TraceFile
specifies the name and full path of the trace file
and Trace
is set to ON
or OFF
. You can also use
1
or YES
for ON
and 0
or NO
for
OFF
. If you are using ODBCConfig
from unixODBC
,
then follow the instructions for tracing unixODBC
calls at
HOWTO-ODBCConfig.
Trace MyODBC
option flag in the MyODBC connect/configure
screen. The log will be written to file `C:\myodbc.log'. If the trace
option is not remembered when you are going back to the above screen, it
means that you are not using the `myodbcd.dll' driver (see above). On
Linux or if you are using DSN-Less connection, then you need to supply
OPTION=4
in the connection string.
MyODBC has been tested with the following applications:
If you know of any other applications that work with MyODBC, please send mail to myodbc@lists.mysql.com about them.
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. Many of the descriptions provide workarounds for problems that you might encounter.
Microsoft Data Access Components
) from
http://www.microsoft.com/data/. This will fix a bug in Access that
when you export data to MySQL, the table and column names aren't specified.
Another way to work around this bug is to upgrade to MyODBC 2.50.33 and
MySQL 3.23.x, which together provide a workaround for the problem.
You should also get and apply the Microsoft Jet 4.0 Service Pack 5 (SP5)
which can be found at
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114.
This will fix some cases where columns are marked as #DELETED#
in Access.
Note: If you are using MySQL 3.22, you must to apply the
MDAC patch and use MyODBC 2.50.32 or 2.50.34 and up to work around
this problem.
Return
matching rows
option. For Access 2.0, you should additionally enable
the Simulate ODBC 1.0
option.
TIMESTAMP
, not TIMESTAMP(n)
,
n < 14.
#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
column, the results will be displayed as #DELETED
. The
work around solution is:
TIMESTAMP
as the data type.
Change BIGINT columns to INT
option in the connection
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 a table
data sheet view. Instead, create 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 BLOB
columns 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 larger than 127 in the column.
CursorLocation Property
as adUseServer
will return a result of -1 for the
RecordCount Property
. To have the right value, you need to set
this property to adUseClient
, as shown 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
option.
Don't optimize column widths
and Return matching rows
options.
Active
property or the
Open
method. Note that Active
will start by automatically
issuing a SELECT * FROM ...
query. That may not be a good thing if
your tables are large.
VARCHAR
rather than ENUM
, as
it exports the latter in a manner that causes MySQL problems.
CONCAT()
function. For example:
SELECT CONCAT(rise_time), CONCAT(set_time) FROM sunrise_sunset;Values retrieved as strings this way should be correctly recognized 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 unfortunate when the source is an ODBC connection that reports
exact types for each column.
mysql
client command-line tool.
Database
tool bar, press the Insert Database
button.
Get Data
button.
Get Data
screen, press the Ms Query
button.
Ms Query
, create a new data source using the `my' DSN file.
Return Data to Microsoft Word
.
Finish
.
Insert Data
and select the records.
OK
and you see the rows in your Word document.
Don't optimize column width
option 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);
PRIMARY
, though this
has not been a problem.
Return matching rows
option.
SHOW PROCESSLIST
will not work properly. The fix is to use
OPTION=16384
in the ODBC connect string or to select
the Change BIGINT columns to INT
option in the MyODBC connect
screen. You may also want to select the Return matching rows
option.
BIGINT
in your result, you may get the error
[Microsoft][ODBC Driver Manager] Driver does not support this parameter
Try selecting the Change BIGINT
columns to INT
option in the MyODBC connect screen.
Don't optimize column widths
option.
This section answers MyODBC connection-related questions.
Could Not Load Translator or Setup Library
Error OccursFor more information, refer to MS KnowledgeBase Article(Q260558). Also, make sure you have the latest valid `ctl3d32.dll' in your system directory.
Access denied
Error Occurs
Refer to section 5.5.8 Causes of Access denied
Errors.
Refer to this document about connection pooling: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q169470.
This section of the document answers questions related to MyODBC with Microsoft Access.
The following must be done on your client PC in order to make Microsoft Access work with MyODBC.
Microsoft Data Access Components
) from
http://www.microsoft.com/data/. This will fix a bug in Access that
when you export data to MySQL, the table and column names aren't specified.
Another way to work around this bug is to upgrade to MyODBC 2.50.33 and
MySQL 3.23.x, which together provide a workaround for the problem.
You should also get and apply the Microsoft Jet 4.0 Service Pack 5 (SP5)
which can be found at
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114.
This will fix some cases where columns are marked as #DELETED#
in Access.
Note: If you are using MySQL 3.22, you must to apply the
MDAC patch and use MyODBC 2.50.32 or 2.50.34 and up to work around
this problem.
Return matching rows
option.
You cannot export a table or query to MySQL unless you have installed MyODBC.
To export a table from Access to MySQL, follow these instructions:
table
or query
you want to export,
and then in the File
menu, select Export
.
Export Object Type Object name To
dialog box, in the
Save As Type
box, select ODBC Databases ()
as shown here:
Export
dialog box, enter a name for the file (or use the
suggested name), and then select OK
.
Microsoft Access connects to the MySQL Server through this data source and exports new tables and or data.
You cannot export a table or query to MySQL database unless you have installed the MyODBC.
To import or link a table(s) from MySQL to Access, follow the instructions:
File
menu, point to Get External Data
,
and then click Import
.
To link tables, on the File menu, point to Get External Data
, and
then click Link Tables
.
Import
(or Link
) dialog box, in the Files Of Type
box, select ODBC Databases ()
.
The Select Data Source dialog box lists the defined data sources The Select Data
Source dialog box is displayed; it lists the defined data sources for any ODBC
drivers installed on your computer.
Click either the File Data Source or Machine Data Source tab, and then double-click
the MyODBC or MyODBC 3.51 data source that you want to export to. To
define a new data source for the MyODBC or MyODBC 3.51 driver, please
section 23.1.9.2 Configuring a MyODBC DSN on Windows.
OK
.
ODBC data source
and displays the list of tables that you can import
or link
.
import
or link
, and then click
OK
. If you're linking a table and it doesn't have an index that uniquely
identifies each record, then Microsoft Access displays a list of the fields in
the linked table. Click a field or a combination of fields that will uniquely
identify each record, and then click OK
.
Yes. Use the following procedure to view or to refresh links when the structure or location of a linked table has changed. The Linked Table Manager lists the paths to all currently linked tables.
To wiew or refresh links:
Tools
menu, point to Add-ins
, and then click Linked Table Manager
.
Microsoft Access confirms a successful refresh or, if the table wasn't
found, displays the Select New Location of
<table name> dialog box
in which you can specify its the table's new location.If several selected
tables have moved to the new location that you specify, the Linked Table
Manager searches that location for all selected tables, and updates all
links in one step.
To vhange the path for a set of linked tables:
Tools
menu, point to Add-ins
, and then click Linked Table Manager
.
Always Prompt For A New Location
check box.
OK
.
Select New Location of
<table name> dialog box, specify the new location, click
Open
, and then click OK
.
#DELETED#
If the inserted or updated records are shown as #DELETED#
in the access, then:
Microsoft Data Access Components
) from
http://www.microsoft.com/data/. This will fix a bug in Access that
when you export data to MySQL, the table and column names aren't specified.
Another way to work around this bug is to upgrade to MyODBC 2.50.33 and
MySQL 3.23.x, which together provide a workaround for the problem.
You should also get and apply the Microsoft Jet 4.0 Service Pack 5 (SP5)
which can be found at
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239114.
This will fix some cases where columns are marked as #DELETED#
in Access.
Note: If you are using MySQL 3.22, you must to apply the
MDAC patch and use MyODBC 2.50.32 or 2.50.34 and up to work around
this problem.
Return
matching rows
option. For Access 2.0, you should additionally enable
the Simulate ODBC 1.0
option.
TIMESTAMP
, not TIMESTAMP(n)
,
n < 14.
#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
column, the results will be displayed as #DELETED
. The
work around solution is:
TIMESTAMP
as the data type.
Change BIGINT columns to INT
option in the connection
dialog in ODBC DSN Administrator.
#DELETED#
, but newly
added/updated records will be displayed properly.
If you see the following errors,
select the Return Matching Rows
option in the DSN configuration
dialog, or specify OPTION=2
, as the connection parameter:
Write Conflict. Another user has changed your data. Row cannot be located for updating. Some values may have been changed since it was last read.
This is a strange issue from Access 97, and doesn't appear with Access 2000 or 2002. You can overcome this by upgrading the MyODBC driver to at least MyODBC 3.51.02.
Another user has modified the record that you have modified
While Editing Records
With some programs, this error may occur:
Another user has modified the record that you have modified
. In most
cases, this can be solved by doing one of the following things:
If these strategies don't help, 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 help you figure out why things go wrong. For instructions, see section 23.1.9.7 Getting an ODBC Trace File.
Read ``How to Trap ODBC Login Error Messages in Access'' at http://support.microsoft.com/support/kb/articles/Q124/9/01.asp?LN=EN-US&SD=gn&FR=0%3CP%3E.
If you have very large (long) tables in Access, it might take a very long
time to open them. Or you might run low on virtual memory and eventually get
an ODBC Query Failed
error and the table will not open. To deal with
this, select the following options:
These add up to a value of 10 (OPTION=10
).
Read ``Set the QueryTimeout Value for ODBC Connections'' at http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B153756.
Refer to converters section for list of available tools.
This section answers questions related to using MyODBC with Microsoft Visual Basic(ADO, DAO & RDO) and ASP.
SELECT COUNT(*) FROM tbl_name
Return an Error?
It's because the COUNT(*)
expression is returning a BIGINT
,
and ADO can't make sense of a number this big. Select the Change
BIGINT columns to INT
option (option value 16384).
AppendChunk()
or GetChunk()
ADO Methods, I Get an Error Multiple-step operation generated errors. Check each status value
.
The GetChunk()
and AppendChunk()
methods from ADO doesn't work as
expected when the cursor location is specified as adUseServer. On the other
hand, you can overcome this error by using adUseClient.
A simple example can be found from, http://www.dwam.net/iishelp/ado/docs/adomth02_4.htm
You can make use of RecordsAffected
property in the ADO execute method. For more
information on the usage of execute method, refer to
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdmthcnnexecute.asp.
Here is an excellent article from Mike Hillyer (m.hillyer@telusplanet.net); explaining how to insert and/or fetch data from blob columns through MyODBC from ADO: MySQL BLOB columns and Visual Basic 6.
Here is yet another good article from Mike Hillyer (m.hillyer@telusplanet.net): How to map Visual basic data type to MySQL types.
A simple examples for the usage of ADO, DAO and RDO with VB can be found her:
If you find any other good example or HOW-TO on ADO/DAO/RDO, then please send the details to myodbc@lists.mysql.com
For more information about how to access MySQL via ASP using MyODBC, refer to the following articles:
A Frequently Asked Questions list for ASP can be found at http://support.microsoft.com/default.aspx?scid=/Support/ActiveServer/faq/data/adofaq.asp.
For information, see ActiveX Data Objects(ADO) Freqently Asked Questions.
This section answers questions related to MyODBC with various ODBC-related tools; such as Microsoft Word, Excel and ColdFusion.
To retrieve data from MySQL to Word/Excel documents, you need to use the MyODBC driver and the Add-in Microsoft Query help.
For example, create a database with a table containing two columns of text:
mysql
client command-line tool.
Database
tool bar, press the Insert Database
button.
Get Data
button.
Get Data
screen, press the Ms Query
button.
Ms Query
, create a new data source using the `my' DSN file.
Return Data to Microsoft Word
.
Finish
.
Insert Data
and select the records.
OK
and you see the rows in your Word document.
This is an issue similar to that of Access 97 when your table consists
of TEXT
or VARCHAR
data types. You can fix this error by
upgrading your MyODBC driver to version 3.51.02 or higher.
Refer to MySQL ColdFusion unixODBC MyODBC and Solaris - how to succeed
This section of the document answers questions related to MyODBC general functionality.
AUTO_INCREMENT
Column in ODBC
A common problem is how to get the value of an automatically generated ID
from an INSERT
statement. With ODBC, you can do something like this (assuming
that auto
is an AUTO_INCREMENT
field):
INSERT INTO tbl (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 tbl (auto,text) VALUES(NULL,'text'); INSERT INTO tbl2 (id,text) VALUES(LAST_INSERT_ID(),'text');
See section 22.2.13.3 How to 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 WHERE auto IS NULL;
Yes. MyODBC 3.51 supports Dynamic cursor
type along with
Forward-only
and static
.
Due to the performance issues, the driver does not support this feature by
default. You can enable this by specifying the connection option flag as
OPTION=32
or by checking the Enable Dynamic Cursor
option
from the DSN configuration.
Transactions are not enabled
Errors?The driver returns this error when an application issues any transactional call but the underlying MySQL server either does not support transactions or they are not enabled.
To avoid this problem, you must use a server that has either or both of the
InnoDB
or BDB
storage engines enabled, and use tables of those
types. MySQL servers from version 4.0 and up support InnoDB
by
default. MySQL-Max servers also support BDB
on platforms where
BDB
is available.
Also, if your server supports transactional table types (InnoDB
and BDB
)
make sure the disable transactions
option is not set from the DSN
configuration.
Cursor not found
Errors?This is becuase the application is using old MyODBC 2.50 version, and it did not set the cursor name explicitly through SQLSetCursorName. The fix is to upgrade to MyODBC 3.51 version.
Yes. If you find something is not working with MyODBC 3.51 that works with MyODBC 2.50, then send a mail message to myodbc@lists.mysql.com
Yes. You can make use of odbc.net to connect to MySQL through MyODBC. Here are the few basic samples to connect to MySQL from VC.NET and VB.NET.
Here is yet another excellent article "Exploring MySQL on .NET environment" by Venu (MyODBC developer) that covers about all MySQL .NET interfaces along with some useful examples.
Caution: Using ODBC.NET with MyODBC, while fetching empty string (0 length), it starts giving the SQL_NO_DATA exception. You can get the patch for this from http://support.microsoft.com/default.aspx?scid=kb;EN-US;q319243.
MyODBC is a lot faster than any other ODBC driver. Slowness might be due to not using the following options.
Interacting with a MySQL server from MyODBC applications involves the following operations:
Most applications use some variation of these steps. The basic application steps are shown in the following diagram:
This section summarizes ODBC routines, categorized by functionality.
For the complete ODBC API reference, please refer to the ODBC Programer's Reference at http://msdn.microsoft.com/library/en-us/odbc/htm/odbcabout_this_manual.asp.
An application can call SQLGetInfo
function to obtain conformance
information about MyODBC. To obtain information about support for a specific
function in the driver, an application can call SQLGetFunctions
.
Note: For backward compatibility, the MyODBC 3.51 driver supports all deprecated functions.
The following tables list MyODBC API calls grouped by task:
Connecting to a data source:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLAllocHandle | No | Yes | ISO 92 | Obtains an environment, connection, statement, or descriptor handle. |
SQLConnect | Yes | Yes | ISO 92 | Connects to a specific driver by data source name, user ID, and password. |
SQLDriverConnect | Yes | Yes | ODBC | Connects to a specific driver by connection string or requests that the Driver Manager and driver display connection dialog boxes for the user. |
SQLAllocEnv | Yes | Yes | Deprecated | Obtains an environment handle allocated from driver. |
SQLAllocConnect | Yes | Yes | Deprecated | Obtains a connection handle |
Obtaining information about a driver and data source:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLDataSources | No | No | ISO 92 | Returns the list of available data sources, handled by the Driver Manager |
SQLDrivers | No | No | ODBC | Returns the list of installed drivers and their attributes, handles by Driver Manager |
SQLGetInfo | Yes | Yes | ISO 92 | Returns information about a specific driver and data source. |
SQLGetFunctions | Yes | Yes | ISO 92 | Returns supported driver functions. |
SQLGetTypeInfo | Yes | Yes | ISO 92 | Returns information about supported data types. |
Setting and retrieving driver attributes:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLSetConnectAttr | No | Yes | ISO 92 | Sets a connection attribute. |
SQLGetConnectAttr | No | Yes | ISO 92 | Returns the value of a connection attribute. |
SQLSetConnectOption | Yes | Yes | Deprecated | Sets a connection option |
SQLGetConnectOption | Yes | Yes | Deprecated | Returns the value of a connection option |
SQLSetEnvAttr | No | Yes | ISO 92 | Sets an environment attribute. |
SQLGetEnvAttr | No | Yes | ISO 92 | Returns the value of an environment attribute. |
SQLSetStmtAttr | No | Yes | ISO 92 | Sets a statement attribute. |
SQLGetStmtAttr | No | Yes | ISO 92 | Returns the value of a statement attribute. |
SQLSetStmtOption | Yes | Yes | Deprecated | Sets a statement option |
SQLGetStmtOption | Yes | Yes | Deprecated | Returns the value of a statement option |
Preparing SQL requests:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLAllocStmt | Yes | Yes | Deprecated | Allocates a statement handle |
SQLPrepare | Yes | Yes | ISO 92 | Prepares an SQL statement for later execution. |
SQLBindParameter | Yes | Yes | ODBC | Assigns storage for a parameter in an SQL statement. |
SQLGetCursorName | Yes | Yes | ISO 92 | Returns the cursor name associated with a statement handle. |
SQLSetCursorName | Yes | Yes | ISO 92 | Specifies a cursor name. |
SQLSetScrollOptions | Yes | Yes | ODBC | Sets options that control cursor behavior. |
Submitting requests:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLExecute | Yes | Yes | ISO 92 | Executes a prepared statement. |
SQLExecDirect | Yes | Yes | ISO 92 | Executes a statement |
SQLNativeSql | Yes | Yes | ODBC | Returns the text of an SQL statement as translated by the driver. |
SQLDescribeParam | Yes | Yes | ODBC | Returns the description for a specific parameter in a statement. |
SQLNumParams | Yes | Yes | ISO 92 | Returns the number of parameters in a statement. |
SQLParamData | Yes | Yes | ISO 92 | Used in conjunction with SQLPutData to supply parameter data at execution time. (Useful for long data values.)
|
SQLPutData | Yes | Yes | ISO 92 | Sends part or all of a data value for a parameter. (Useful for long data values.) |
Retrieving results and information about results:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLRowCount | Yes | Yes | ISO 92 | Returns the number of rows affected by an insert, update, or delete request. |
SQLNumResultCols | Yes | Yes | ISO 92 | Returns the number of columns in the result set. |
SQLDescribeCol | Yes | Yes | ISO 92 | Describes a column in the result set. |
SQLColAttribute | No | Yes | ISO 92 | Describes attributes of a column in the result set. |
SQLColAttributes | Yes | Yes | Deprecated | Describes attributes of a column in the result set. |
SQLFetch | Yes | Yes | ISO 92 | Returns multiple result rows. |
SQLFetchScroll | No | Yes | ISO 92 | Returns scrollable result rows. |
SQLExtendedFetch | Yes | Yes | Deprecated | Returns scrollable result rows. |
SQLSetPos | Yes | Yes | ODBC | Positions a cursor within a fetched block of data and allows an application to refresh data in the rowset or to update or delete data in the result set. |
SQLBulkOperations | No | Yes | ODBC | Performs bulk insertions and bulk bookmark operations, including update, delete, and fetch by bookmark. |
Retrieving error or diagnostic information:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLError | Yes | Yes | Deprecated | Returns additional error or status information |
SQLGetDiagField | Yes | Yes | ISO 92 | Returns additional diagnostic information (a single field of the diagnostic data structure). |
SQLGetDiagRec | Yes | Yes | ISO 92 | Returns additional diagnostic information (multiple fields of the diagnostic data structure). |
Obtaining information about the data source's system tables (catalog functions) item:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLColumnPrivileges | Yes | Yes | ODBC | Returns a list of columns and associated privileges for one or more tables. |
SQLColumns | Yes | Yes | X/Open | Returns the list of column names in specified tables. |
SQLForeignKeys | Yes | Yes | ODBC | Returns a list of column names that make up foreign keys, if they exist for a specified table. |
SQLPrimaryKeys | Yes | Yes | ODBC | Returns the list of column names that make up the primary key for a table. |
SQLSpecialColumns | Yes | Yes | X/Open | Returns information about the optimal set of columns that uniquely identifies a row in a specified table, or the columns that are automatically updated when any value in the row is updated by a transaction. |
SQLStatistics | Yes | Yes | ISO 92 | Returns statistics about a single table and the list of indexes associated with the table. |
SQLTablePrivileges | Yes | Yes | ODBC | Returns a list of tables and the privileges associated with each table. |
SQLTables | Yes | Yes | X/Open | Returns the list of table names stored in a specific data source. |
Performing transactions:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLTransact | Yes | Yes | Deprecated | Commits or rolls back a transaction |
SQLEndTran | No | Yes | ISO 92 | Commits or rolls back a transaction. |
Terminating a statement:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLFreeStmt | Yes | Yes | ISO 92 | Ends statement processing, discards pending results, and, optionally, frees all resources associated with the statement handle. |
SQLCloseCursor | Yes | Yes | ISO 92 | Closes a cursor that has been opened on a statement handle. |
SQLCancel | Yes | Yes | ISO 92 | Cancels an SQL statement. |
Terminating a connection:
Function name | MyODBC | MyODBC | Conformance | Purpose |
2.50 | 3.51 | |||
SQLDisconnect | Yes | Yes | ISO 92 | Closes the connection. |
SQLFreeHandle | No | Yes | ISO 92 | Releases an environment, connection, statement, or descriptor handle. |
SQLFreeConnect | Yes | Yes | Deprecated | Releases connection handle |
SQLFreeEnv | Yes | Yes | Deprecated | Releases an environment handle |
The following table illustrates how driver maps the server data types to default SQL and C data types:
Native Value | SQL Type | C Type |
bit | SQL_BIT | SQL_C_BIT
|
tinyint | SQL_TINYINT | SQL_C_STINYINT
|
tinyint unsigned | SQL_TINYINT | SQL_C_UTINYINT
|
bigint | SQL_BIGINT | SQL_C_SBIGINT
|
bigint unsigned | SQL_BIGINT | SQL_C_UBIGINT
|
long varbinary | SQL_LONGVARBINARY | SQL_C_BINARY
|
blob | SQL_LONGVARBINARY | SQL_C_BINARY
|
longblob | SQL_LONGVARBINARY | SQL_C_BINARY
|
tinyblob | SQL_LONGVARBINARY | SQL_C_BINARY
|
mediumblob | SQL_LONGVARBINARY | SQL_C_BINARY
|
long varchar | SQL_LONGVARCHAR | SQL_C_CHAR
|
text | SQL_LONGVARCHAR | SQL_C_CHAR
|
mediumtext | SQL_LONGVARCHAR | SQL_C_CHAR
|
char | SQL_CHAR | SQL_C_CHAR
|
numeric | SQL_NUMERIC | SQL_C_CHAR
|
decimal | SQL_DECIMAL | SQL_C_CHAR
|
integer | SQL_INTEGER | SQL_C_SLONG
|
integer unsigned | SQL_INTEGER | SQL_C_ULONG
|
int | SQL_INTEGER | SQL_C_SLONG
|
int unsigned | SQL_INTEGER | SQL_C_ULONG
|
mediumint | SQL_INTEGER | SQL_C_SLONG
|
mediumint unsigned | SQL_INTEGER | SQL_C_ULONG
|
smallint | SQL_SMALLINT | SQL_C_SSHORT
|
smallint unsigned | SQL_SMALLINT | SQL_C_USHORT
|
real | SQL_FLOAT | SQL_C_DOUBLE
|
double | SQL_FLOAT | SQL_C_DOUBLE
|
float | SQL_REAL | SQL_C_FLOAT
|
double precision | SQL_DOUBLE | SQL_C_DOUBLE
|
date | SQL_DATE | SQL_C_DATE
|
time | SQL_TIME | SQL_C_TIME
|
year | SQL_SMALLINT | SQL_C_SHORT
|
datetime | SQL_TIMESTAMP | SQL_C_TIMESTAMP
|
timestamp | SQL_TIMESTAMP | SQL_C_TIMESTAMP
|
text | SQL_VARCHAR | SQL_C_CHAR
|
varchar | SQL_VARCHAR | SQL_C_CHAR
|
enum | SQL_VARCHAR | SQL_C_CHAR
|
set | SQL_VARCHAR | SQL_C_CHAR
|
bit | SQL_CHAR | SQL_C_CHAR
|
bool | SQL_CHAR | SQL_C_CHAR
|
The following tables lists the error codes returned by the driver apart from the server errors.
Native Code | SQLSTATE 2 | SQLSTATE 3 | Error Message |
500 | 01000 | 01000 | General warning |
501 | 01004 | 01004 | String data, right truncated |
502 | 01S02 | 01S02 | Option value changed |
503 | 01S03 | 01S03 | No rows updated/deleted |
504 | 01S04 | 01S04 | More than one row updated/deleted |
505 | 01S06 | 01S06 | Attempt to fetch before the result set returned the first row set |
506 | 07001 | 07002 | SQLBindParameter not used for all parameters
|
507 | 07005 | 07005 | Prepared statement not a cursor-specification |
508 | 07009 | 07009 | Invalid descriptor index |
509 | 08002 | 08002 | Connection name in use |
510 | 08003 | 08003 | Connection does not exist |
511 | 24000 | 24000 | Invalid cursor state |
512 | 25000 | 25000 | Invalid transaction state |
513 | 25S01 | 25S01 | Transaction state unknown |
514 | 34000 | 34000 | Invalid cursor name |
515 | S1000 | HY000 | General driver defined error |
516 | S1001 | HY001 | Memory allocation error |
517 | S1002 | HY002 | Invalid column number |
518 | S1003 | HY003 | Invalid application buffer type |
519 | S1004 | HY004 | Invalid SQL data type |
520 | S1009 | HY009 | Invalid use of null pointer |
521 | S1010 | HY010 | Function sequence error |
522 | S1011 | HY011 | Attribute can not be set now |
523 | S1012 | HY012 | Invalid transaction operation code |
524 | S1013 | HY013 | Memory management error |
525 | S1015 | HY015 | No cursor name available |
526 | S1024 | HY024 | Invalid attribute value |
527 | S1090 | HY090 | Invalid string or buffer length |
528 | S1091 | HY091 | Invalid descriptor field identifier |
529 | S1092 | HY092 | Invalid attribute/option identifier |
530 | S1093 | HY093 | Invalid parameter number |
531 | S1095 | HY095 | Function type out of range |
532 | S1106 | HY106 | Fetch type out of range |
533 | S1117 | HY117 | Row value out of range |
534 | S1109 | HY109 | Invalid cursor position |
535 | S1C00 | HYC00 | Optional feature not implemented |
0 | 21S01 | 21S01 | Column count does not match value count |
0 | 23000 | 23000 | Integrity constraint violation |
0 | 42000 | 42000 | Syntax error or access violation |
0 | 42S02 | 42S02 | Base table or view not found |
0 | 42S12 | 42S12 | Index not found |
0 | 42S21 | 42S21 | Column already exists |
0 | 42S22 | 42S22 | Column not found |
0 | 08S01 | 08S01 | Communication link failure |
This section contains simple examples of the use of MySQL ODBC 3.51 Driver with ADO, DAO and RDO.
rs.addNew
, rs.delete
, and rs.update
The following ADO (ActiveX Data Objects) example creates a table
my_ado
and demonstrates the use of rs.addNew
, rs.delete
,
and rs.update
.
Private Sub myodbc_ado_Click() Dim conn As ADODB.Connection Dim rs As ADODB.Recordset Dim fld As ADODB.Field Dim sql As String 'connect to MySQL server using MySQL ODBC 3.51 Driver Set conn = New ADODB.Connection conn.ConnectionString = "DRIVER={MySQL ODBC 3.51 Driver};"_ & "SERVER=localhost;"_ & " DATABASE=test;"_ & "UID=venu;PWD=venu; OPTION=3" conn.Open 'create table conn.Execute "DROP TABLE IF EXISTS my_ado" conn.Execute "CREATE TABLE my_ado(id int not null primary key, name varchar(20)," _ & "txt text, dt date, tm time, ts timestamp)" 'direct insert conn.Execute "INSERT INTO my_ado(id,name,txt) values(1,100,'venu')" conn.Execute "INSERT INTO my_ado(id,name,txt) values(2,200,'MySQL')" conn.Execute "INSERT INTO my_ado(id,name,txt) values(3,300,'Delete')" Set rs = New ADODB.Recordset rs.CursorLocation = adUseServer 'fetch the initial table .. rs.Open "SELECT * FROM my_ado", conn Debug.Print rs.RecordCount rs.MoveFirst Debug.Print String(50, "-") & "Initial my_ado Result Set " & String(50, "-") For Each fld In rs.Fields Debug.Print fld.Name, Next Debug.Print Do Until rs.EOF For Each fld In rs.Fields Debug.Print fld.Value, Next rs.MoveNext Debug.Print Loop rs.Close 'rs insert rs.Open "select * from my_ado", conn, adOpenDynamic, adLockOptimistic rs.AddNew rs!Name = "Monty" rs!txt = "Insert row" rs.Update rs.Close 'rs update rs.Open "SELECT * FROM my_ado" rs!Name = "update" rs!txt = "updated-row" rs.Update rs.Close 'rs update second time.. rs.Open "SELECT * FROM my_ado" rs!Name = "update" rs!txt = "updated-second-time" rs.Update rs.Close 'rs delete rs.Open "SELECT * FROM my_ado" rs.MoveNext rs.MoveNext rs.Delete rs.Close 'fetch the updated table .. rs.Open "SELECT * FROM my_ado", conn Debug.Print rs.RecordCount rs.MoveFirst Debug.Print String(50, "-") & "Updated my_ado Result Set " & String(50, "-") For Each fld In rs.Fields Debug.Print fld.Name, Next Debug.Print Do Until rs.EOF For Each fld In rs.Fields Debug.Print fld.Value, Next rs.MoveNext Debug.Print Loop rs.Close conn.Close End Sub
rs.addNew
, rs.update
, and Scrolling
The following DAO (Data Access Objects) example creates a table my_dao
and demonstrates the use of rs.addNew
, rs.update
, and result
set scrolling.
Private Sub myodbc_dao_Click() Dim ws As Workspace Dim conn As Connection Dim queryDef As queryDef Dim str As String 'connect to MySQL using MySQL ODBC 3.51 Driver Set ws = DBEngine.CreateWorkspace("", "venu", "venu", dbUseODBC) str = "odbc;DRIVER={MySQL ODBC 3.51 Driver};"_ & "SERVER=localhost;"_ & " DATABASE=test;"_ & "UID=venu;PWD=venu; OPTION=3" Set conn = ws.OpenConnection("test", dbDriverNoPrompt, False, str) 'Create table my_dao Set queryDef = conn.CreateQueryDef("", "drop table if exists my_dao") queryDef.Execute Set queryDef = conn.CreateQueryDef("", "create table my_dao(Id INT AUTO_INCREMENT PRIMARY KEY, " _ & "Ts TIMESTAMP(14) NOT NULL, Name varchar(20), Id2 INT)") queryDef.Execute 'Insert new records using rs.addNew Set rs = conn.OpenRecordset("my_dao") Dim i As Integer For i = 10 To 15 rs.AddNew rs!Name = "insert record" & i rs!Id2 = i rs.Update Next i rs.Close 'rs update.. Set rs = conn.OpenRecordset("my_dao") rs.Edit rs!Name = "updated-string" rs.Update rs.Close 'fetch the table back... Set rs = conn.OpenRecordset("my_dao", dbOpenDynamic) str = "Results:" rs.MoveFirst While Not rs.EOF str = " " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print "DATA:" & str rs.MoveNext Wend 'rs Scrolling rs.MoveFirst str = " FIRST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print str rs.MoveLast str = " LAST ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print str rs.MovePrevious str = " LAST-1 ROW: " & rs!Id & " , " & rs!Name & ", " & rs!Ts & ", " & rs!Id2 Debug.Print str 'free all resources rs.Close queryDef.Close conn.Close ws.Close End Sub
rs.addNew
and rs.update
The following RDO (Remote Data Objects) example creates
a table my_rdo
and demonstrates the use of rs.addNew
and rs.update
.
Dim rs As rdoResultset Dim cn As New rdoConnection Dim cl As rdoColumn Dim SQL As String 'cn.Connect = "DSN=test;" cn.Connect = "DRIVER={MySQL ODBC 3.51 Driver};"_ & "SERVER=localhost;"_ & " DATABASE=test;"_ & "UID=venu;PWD=venu; OPTION=3" cn.CursorDriver = rdUseOdbc cn.EstablishConnection rdDriverPrompt 'drop table my_rdo SQL = "drop table if exists my_rdo" cn.Execute SQL, rdExecDirect 'create table my_rdo SQL = "create table my_rdo(id int, name varchar(20))" cn.Execute SQL, rdExecDirect 'insert - direct SQL = "insert into my_rdo values (100,'venu')" cn.Execute SQL, rdExecDirect SQL = "insert into my_rdo values (200,'MySQL')" cn.Execute SQL, rdExecDirect 'rs insert SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) rs.AddNew rs!id = 300 rs!Name = "Insert1" rs.Update rs.Close 'rs insert SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) rs.AddNew rs!id = 400 rs!Name = "Insert 2" rs.Update rs.Close 'rs update SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) rs.Edit rs!id = 999 rs!Name = "updated" rs.Update rs.Close 'fetch back... SQL = "select * from my_rdo" Set rs = cn.OpenResultset(SQL, rdOpenStatic, rdConcurRowVer, rdExecDirect) Do Until rs.EOF For Each cl In rs.rdoColumns Debug.Print cl.Value, Next rs.MoveNext Debug.Print Loop Debug.Print "Row count="; rs.RowCount 'close rs.Close cn.Close End Sub
This section contains simple examples that demonstrate the use of MyODBC drivers with ODBC.NET.
The following sample creates a table my_odbc_net
and
demonstrates the use in C#.
/** * @sample : mycon.cs * @purpose : Demo sample for ODBC.NET using MyODBC * @author : Venu, venu@mysql.com * * (C) Copyright MySQL AB, 1995-2004 * **/ /* build command * * csc /t:exe * /out:mycon.exe mycon.cs * /r:Microsoft.Data.Odbc.dll */ using Console = System.Console; using Microsoft.Data.Odbc; namespace myodbc3 { class mycon { static void Main(string[] args) { try { //Connection string for MyODBC 2.50 /*string MyConString = "DRIVER={MySQL};" + "SERVER=localhost;" + "DATABASE=test;" + "UID=venu;" + "PASSWORD=venu;" + "OPTION=3"; */ //Connection string for MyODBC 3.51 string MyConString = "DRIVER={MySQL ODBC 3.51 Driver};" + "SERVER=localhost;" + "DATABASE=test;" + "UID=venu;" + "PASSWORD=venu;" + "OPTION=3"; //Connect to MySQL using MyODBC OdbcConnection MyConnection = new OdbcConnection(MyConString); MyConnection.Open(); Console.WriteLine("\n !!! success, connected successfully !!!\n"); //Display connection information Console.WriteLine("Connection Information:"); Console.WriteLine("\tConnection String:" + MyConnection.ConnectionString); Console.WriteLine("\tConnection Timeout:" + MyConnection.ConnectionTimeout); Console.WriteLine("\tDatabase:" + MyConnection.Database); Console.WriteLine("\tDataSource:" + MyConnection.DataSource); Console.WriteLine("\tDriver:" + MyConnection.Driver); Console.WriteLine("\tServerVersion:" + MyConnection.ServerVersion); //Create a sample table OdbcCommand MyCommand = new OdbcCommand("DROP TABLE IF EXISTS my_odbc_net",MyConnection); MyCommand.ExecuteNonQuery(); MyCommand.CommandText = "CREATE TABLE my_odbc_net(id int, name varchar(20), idb bigint)"; MyCommand.ExecuteNonQuery(); //Insert MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(10,'venu', 300)"; Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery());; //Insert MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(20,'mysql',400)"; Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery()); //Insert MyCommand.CommandText = "INSERT INTO my_odbc_net VALUES(20,'mysql',500)"; Console.WriteLine("INSERT, Total rows affected:" + MyCommand.ExecuteNonQuery()); //Update MyCommand.CommandText = "UPDATE my_odbc_net SET id=999 WHERE id=20"; Console.WriteLine("Update, Total rows affected:" + MyCommand.ExecuteNonQuery()); //COUNT(*) MyCommand.CommandText = "SELECT COUNT(*) as TRows FROM my_odbc_net"; Console.WriteLine("Total Rows:" + MyCommand.ExecuteScalar()); //Fetch MyCommand.CommandText = "SELECT * FROM my_odbc_net"; OdbcDataReader MyDataReader; MyDataReader = MyCommand.ExecuteReader(); while (MyDataReader.Read()) { if(string.Compare(MyConnection.Driver,"myodbc3.dll") == 0) { Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " + MyDataReader.GetString(1) + " " + MyDataReader.GetInt64(2)); //Supported only by MyODBC 3.51 } else { Console.WriteLine("Data:" + MyDataReader.GetInt32(0) + " " + MyDataReader.GetString(1) + " " + MyDataReader.GetInt32(2)); //BIGINTs not supported by MyODBC } } //Close all resources MyDataReader.Close(); MyConnection.Close(); } catch (OdbcException MyOdbcException)//Catch any ODBC exception .. { for (int i=0; i < MyOdbcException.Errors.Count; i++) { Console.Write("ERROR #" + i + "\n" + "Message: " + MyOdbcException.Errors[i].Message + "\n" + "Native: " + MyOdbcException.Errors[i].NativeError.ToString() + "\n" + "Source: " + MyOdbcException.Errors[i].Source + "\n" + "SQL: " + MyOdbcException.Errors[i].SQLState + "\n"); } } } } }
The following sample creates a table my_vb_net
and
demonstrates the use in VB.
' @sample : myvb.vb ' @purpose : Demo sample for ODBC.NET using MyODBC ' @author : Venu, venu@mysql.com ' ' (C) Copyright MySQL AB, 1995-2004 ' ' ' ' build command ' ' vbc /target:exe ' /out:myvb.exe ' /r:Microsoft.Data.Odbc.dll ' /r:System.dll ' /r:System.Data.dll ' Imports Microsoft.Data.Odbc Imports System Module myvb Sub Main() Try 'MyODBC 3.51 connection string Dim MyConString As String = "DRIVER={MySQL ODBC 3.51 Driver};" & _ "SERVER=localhost;" & _ "DATABASE=test;" & _ "UID=venu;" & _ "PASSWORD=venu;" & _ "OPTION=3;" 'Connection Dim MyConnection As New OdbcConnection(MyConString) MyConnection.Open() Console.WriteLine ("Connection State::" & MyConnection.State.ToString) 'Drop Console.WriteLine ("Dropping table") Dim MyCommand As New OdbcCommand() MyCommand.Connection = MyConnection MyCommand.CommandText = "DROP TABLE IF EXISTS my_vb_net" MyCommand.ExecuteNonQuery() 'Create Console.WriteLine ("Creating....") MyCommand.CommandText = "CREATE TABLE my_vb_net(id int, name varchar(30))" MyCommand.ExecuteNonQuery() 'Insert MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(10,'venu')" Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery()) 'Insert MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')" Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery()) 'Insert MyCommand.CommandText = "INSERT INTO my_vb_net VALUES(20,'mysql')" Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery()) 'Insert MyCommand.CommandText = "INSERT INTO my_vb_net(id) VALUES(30)" Console.WriteLine("INSERT, Total rows affected:" & MyCommand.ExecuteNonQuery()) 'Update MyCommand.CommandText = "UPDATE my_vb_net SET id=999 WHERE id=20" Console.WriteLine("Update, Total rows affected:" & MyCommand.ExecuteNonQuery()) 'COUNT(*) MyCommand.CommandText = "SELECT COUNT(*) as TRows FROM my_vb_net" Console.WriteLine("Total Rows:" & MyCommand.ExecuteScalar()) 'Select Console.WriteLine ("Select * FROM my_vb_net") MyCommand.CommandText = "SELECT * FROM my_vb_net" Dim MyDataReader As OdbcDataReader MyDataReader = MyCommand.ExecuteReader While MyDataReader.Read If MyDataReader("name") Is DBNull.Value Then Console.WriteLine ("id = " & CStr(MyDataReader("id")) & " name = " & _ "NULL") Else Console.WriteLine ("id = " & CStr(MyDataReader("id")) & " name = " & _ CStr(MyDataReader("name"))) End If End While 'Catch ODBC Exception Catch MyOdbcException As OdbcException Dim i As Integer Console.WriteLine (MyOdbcException.ToString) 'Catch program exception Catch MyException As Exception Console.WriteLine (MyException.ToString) End Try End Sub End Module
These are the developers that have worked on the MyODBC and MyODBC 3.51 Drivers from MySQL AB.
There are two 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://dev.mysql.com/downloads/connector/j/.
For more information, consult any general JDBC documentation, plus each driver's own documentation for MySQL-specific features.
Documentation for MySQL Connector/J
is available online at the
MySQL AB Web site at http://dev.mysql.com/doc/.
This chapter lists the errors that may appear when you call MySQL from any host language. The first list displays server error messages. The second list displays client program messages.
Server error information comes from the following files:
Because updates are frequent, it is possible that these files will contain additional error information not listed here.
1000
SQLSTATE: HY000
(ER_HASHCHK
)
Message: hashchk
1001
SQLSTATE: HY000
(ER_NISAMCHK
)
Message: isamchk
1002
SQLSTATE: HY000
(ER_NO
)
Message: NO
1003
SQLSTATE: HY000
(ER_YES
)
Message: YES
1004
SQLSTATE: HY000
(ER_CANT_CREATE_FILE
)
Message: Can't create file '%s' (errno: %d)
1005
SQLSTATE: HY000
(ER_CANT_CREATE_TABLE
)
Message: Can't create table '%s' (errno: %d)
1006
SQLSTATE: HY000
(ER_CANT_CREATE_DB
)
Message: Can't create database '%s' (errno: %d)
1007
SQLSTATE: HY000
(ER_DB_CREATE_EXISTS
)
Message: Can't create database '%s'; database exists
1008
SQLSTATE: HY000
(ER_DB_DROP_EXISTS
)
Message: Can't drop database '%s'; database doesn't exist
1009
SQLSTATE: HY000
(ER_DB_DROP_DELETE
)
Message: Error dropping database (can't delete '%s', errno: %d)
1010
SQLSTATE: HY000
(ER_DB_DROP_RMDIR
)
Message: Error dropping database (can't rmdir '%s', errno: %d)
1011
SQLSTATE: HY000
(ER_CANT_DELETE_FILE
)
Message: Error on delete of '%s' (errno: %d)
1012
SQLSTATE: HY000
(ER_CANT_FIND_SYSTEM_REC
)
Message: Can't read record in system table
1013
SQLSTATE: HY000
(ER_CANT_GET_STAT
)
Message: Can't get status of '%s' (errno: %d)
1014
SQLSTATE: HY000
(ER_CANT_GET_WD
)
Message: Can't get working directory (errno: %d)
1015
SQLSTATE: HY000
(ER_CANT_LOCK
)
Message: Can't lock file (errno: %d)
1016
SQLSTATE: HY000
(ER_CANT_OPEN_FILE
)
Message: Can't open file: '%s' (errno: %d)
1017
SQLSTATE: HY000
(ER_FILE_NOT_FOUND
)
Message: Can't find file: '%s' (errno: %d)
1018
SQLSTATE: HY000
(ER_CANT_READ_DIR
)
Message: Can't read dir of '%s' (errno: %d)
1019
SQLSTATE: HY000
(ER_CANT_SET_WD
)
Message: Can't change dir to '%s' (errno: %d)
1020
SQLSTATE: HY000
(ER_CHECKREAD
)
Message: Record has changed since last read in table '%s'
1021
SQLSTATE: HY000
(ER_DISK_FULL
)
Message: Disk full (%s); waiting for someone to free some space...
1022
SQLSTATE: 23000
(ER_DUP_KEY
)
Message: Can't write; duplicate key in table '%s'
1023
SQLSTATE: HY000
(ER_ERROR_ON_CLOSE
)
Message: Error on close of '%s' (errno: %d)
1024
SQLSTATE: HY000
(ER_ERROR_ON_READ
)
Message: Error reading file '%s' (errno: %d)
1025
SQLSTATE: HY000
(ER_ERROR_ON_RENAME
)
Message: Error on rename of '%s' to '%s' (errno: %d)
1026
SQLSTATE: HY000
(ER_ERROR_ON_WRITE
)
Message: Error writing file '%s' (errno: %d)
1027
SQLSTATE: HY000
(ER_FILE_USED
)
Message: '%s' is locked against change
1028
SQLSTATE: HY000
(ER_FILSORT_ABORT
)
Message: Sort aborted
1029
SQLSTATE: HY000
(ER_FORM_NOT_FOUND
)
Message: View '%s' doesn't exist for '%s'
1030
SQLSTATE: HY000
(ER_GET_ERRNO
)
Message: Got error %d from storage engine
1031
SQLSTATE: HY000
(ER_ILLEGAL_HA
)
Message: Table storage engine for '%s' doesn't have this option
1032
SQLSTATE: HY000
(ER_KEY_NOT_FOUND
)
Message: Can't find record in '%s'
1033
SQLSTATE: HY000
(ER_NOT_FORM_FILE
)
Message: Incorrect information in file: '%s'
1034
SQLSTATE: HY000
(ER_NOT_KEYFILE
)
Message: Incorrect key file for table '%s'; try to repair it
1035
SQLSTATE: HY000
(ER_OLD_KEYFILE
)
Message: Old key file for table '%s'; repair it!
1036
SQLSTATE: HY000
(ER_OPEN_AS_READONLY
)
Message: Table '%s' is read only
1037
SQLSTATE: HY001
(ER_OUTOFMEMORY
)
Message: Out of memory; restart server and try again (needed %d bytes)
1038
SQLSTATE: HY001
(ER_OUT_OF_SORTMEMORY
)
Message: Out of sort memory; increase server sort buffer size
1039
SQLSTATE: HY000
(ER_UNEXPECTED_EOF
)
Message: Unexpected EOF found when reading file '%s' (errno: %d)
1040
SQLSTATE: 08004
(ER_CON_COUNT_ERROR
)
Message: Too many connections
1041
SQLSTATE: HY000
(ER_OUT_OF_RESOURCES
)
Message: Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space
1042
SQLSTATE: 08S01
(ER_BAD_HOST_ERROR
)
Message: Can't get hostname for your address
1043
SQLSTATE: 08S01
(ER_HANDSHAKE_ERROR
)
Message: Bad handshake
1044
SQLSTATE: 42000
(ER_DBACCESS_DENIED_ERROR
)
Message: Access denied for user '%s'@'%s' to database '%s'
1045
SQLSTATE: 28000
(ER_ACCESS_DENIED_ERROR
)
Message: Access denied for user '%s'@'%s' (using password: %s)
1046
SQLSTATE: 3D000
(ER_NO_DB_ERROR
)
Message: No database selected
1047
SQLSTATE: 08S01
(ER_UNKNOWN_COM_ERROR
)
Message: Unknown command
1048
SQLSTATE: 23000
(ER_BAD_NULL_ERROR
)
Message: Column '%s' cannot be null
1049
SQLSTATE: 42000
(ER_BAD_DB_ERROR
)
Message: Unknown database '%s'
1050
SQLSTATE: 42S01
(ER_TABLE_EXISTS_ERROR
)
Message: Table '%s' already exists
1051
SQLSTATE: 42S02
(ER_BAD_TABLE_ERROR
)
Message: Unknown table '%s'
1052
SQLSTATE: 23000
(ER_NON_UNIQ_ERROR
)
Message: Column '%s' in %s is ambiguous
1053
SQLSTATE: 08S01
(ER_SERVER_SHUTDOWN
)
Message: Server shutdown in progress
1054
SQLSTATE: 42S22
(ER_BAD_FIELD_ERROR
)
Message: Unknown column '%s' in '%s'
1055
SQLSTATE: 42000
(ER_WRONG_FIELD_WITH_GROUP
)
Message: '%s' isn't in GROUP BY
1056
SQLSTATE: 42000
(ER_WRONG_GROUP_FIELD
)
Message: Can't group on '%s'
1057
SQLSTATE: 42000
(ER_WRONG_SUM_SELECT
)
Message: Statement has sum functions and columns in same statement
1058
SQLSTATE: 21S01
(ER_WRONG_VALUE_COUNT
)
Message: Column count doesn't match value count
1059
SQLSTATE: 42000
(ER_TOO_LONG_IDENT
)
Message: Identifier name '%s' is too long
1060
SQLSTATE: 42S21
(ER_DUP_FIELDNAME
)
Message: Duplicate column name '%s'
1061
SQLSTATE: 42000
(ER_DUP_KEYNAME
)
Message: Duplicate key name '%s'
1062
SQLSTATE: 23000
(ER_DUP_ENTRY
)
Message: Duplicate entry '%s' for key %d
1063
SQLSTATE: 42000
(ER_WRONG_FIELD_SPEC
)
Message: Incorrect column specifier for column '%s'
1064
SQLSTATE: 42000
(ER_PARSE_ERROR
)
Message: %s near '%s' at line %d
1065
SQLSTATE: 42000
(ER_EMPTY_QUERY
)
Message: Query was empty
1066
SQLSTATE: 42000
(ER_NONUNIQ_TABLE
)
Message: Not unique table/alias: '%s'
1067
SQLSTATE: 42000
(ER_INVALID_DEFAULT
)
Message: Invalid default value for '%s'
1068
SQLSTATE: 42000
(ER_MULTIPLE_PRI_KEY
)
Message: Multiple primary key defined
1069
SQLSTATE: 42000
(ER_TOO_MANY_KEYS
)
Message: Too many keys specified; max %d keys allowed
1070
SQLSTATE: 42000
(ER_TOO_MANY_KEY_PARTS
)
Message: Too many key parts specified; max %d parts allowed
1071
SQLSTATE: 42000
(ER_TOO_LONG_KEY
)
Message: Specified key was too long; max key length is %d bytes
1072
SQLSTATE: 42000
(ER_KEY_COLUMN_DOES_NOT_EXITS
)
Message: Key column '%s' doesn't exist in table
1073
SQLSTATE: 42000
(ER_BLOB_USED_AS_KEY
)
Message: BLOB column '%s' can't be used in key specification with the used table type
1074
SQLSTATE: 42000
(ER_TOO_BIG_FIELDLENGTH
)
Message: Column length too big for column '%s' (max = %d); use BLOB instead
1075
SQLSTATE: 42000
(ER_WRONG_AUTO_KEY
)
Message: Incorrect table definition; there can be only one auto column and it must be defined as a key
1076
SQLSTATE: HY000
(ER_READY
)
Message: %s: ready for connections. Version: '%s' socket: '%s' port: %d
1077
SQLSTATE: HY000
(ER_NORMAL_SHUTDOWN
)
Message: %s: Normal shutdown
1078
SQLSTATE: HY000
(ER_GOT_SIGNAL
)
Message: %s: Got signal %d. Aborting!
1079
SQLSTATE: HY000
(ER_SHUTDOWN_COMPLETE
)
Message: %s: Shutdown complete
1080
SQLSTATE: 08S01
(ER_FORCING_CLOSE
)
Message: %s: Forcing close of thread %ld user: '%s'
1081
SQLSTATE: 08S01
(ER_IPSOCK_ERROR
)
Message: Can't create IP socket
1082
SQLSTATE: 42S12
(ER_NO_SUCH_INDEX
)
Message: Table '%s' has no index like the one used in CREATE INDEX; recreate the table
1083
SQLSTATE: 42000
(ER_WRONG_FIELD_TERMINATORS
)
Message: Field separator argument is not what is expected; check the manual
1084
SQLSTATE: 42000
(ER_BLOBS_AND_NO_TERMINATED
)
Message: You can't use fixed rowlength with BLOBs; please use 'fields terminated by'
1085
SQLSTATE: HY000
(ER_TEXTFILE_NOT_READABLE
)
Message: The file '%s' must be in the database directory or be readable by all
1086
SQLSTATE: HY000
(ER_FILE_EXISTS_ERROR
)
Message: File '%s' already exists
1087
SQLSTATE: HY000
(ER_LOAD_INFO
)
Message: Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld
1088
SQLSTATE: HY000
(ER_ALTER_INFO
)
Message: Records: %ld Duplicates: %ld
1089
SQLSTATE: HY000
(ER_WRONG_SUB_KEY
)
Message: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys
1090
SQLSTATE: 42000
(ER_CANT_REMOVE_ALL_FIELDS
)
Message: You can't delete all columns with ALTER TABLE; use DROP TABLE instead
1091
SQLSTATE: 42000
(ER_CANT_DROP_FIELD_OR_KEY
)
Message: Can't DROP '%s'; check that column/key exists
1092
SQLSTATE: HY000
(ER_INSERT_INFO
)
Message: Records: %ld Duplicates: %ld Warnings: %ld
1093
SQLSTATE: HY000
(ER_UPDATE_TABLE_USED
)
Message: You can't specify target table '%s' for update in FROM clause
1094
SQLSTATE: HY000
(ER_NO_SUCH_THREAD
)
Message: Unknown thread id: %lu
1095
SQLSTATE: HY000
(ER_KILL_DENIED_ERROR
)
Message: You are not owner of thread %lu
1096
SQLSTATE: HY000
(ER_NO_TABLES_USED
)
Message: No tables used
1097
SQLSTATE: HY000
(ER_TOO_BIG_SET
)
Message: Too many strings for column %s and SET
1098
SQLSTATE: HY000
(ER_NO_UNIQUE_LOGFILE
)
Message: Can't generate a unique log-filename %s.(1-999)
1099
SQLSTATE: HY000
(ER_TABLE_NOT_LOCKED_FOR_WRITE
)
Message: Table '%s' was locked with a READ lock and can't be updated
1100
SQLSTATE: HY000
(ER_TABLE_NOT_LOCKED
)
Message: Table '%s' was not locked with LOCK TABLES
1101
SQLSTATE: 42000
(ER_BLOB_CANT_HAVE_DEFAULT
)
Message: BLOB/TEXT column '%s' can't have a default value
1102
SQLSTATE: 42000
(ER_WRONG_DB_NAME
)
Message: Incorrect database name '%s'
1103
SQLSTATE: 42000
(ER_WRONG_TABLE_NAME
)
Message: Incorrect table name '%s'
1104
SQLSTATE: 42000
(ER_TOO_BIG_SELECT
)
Message: The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
1105
SQLSTATE: HY000
(ER_UNKNOWN_ERROR
)
Message: Unknown error
1106
SQLSTATE: 42000
(ER_UNKNOWN_PROCEDURE
)
Message: Unknown procedure '%s'
1107
SQLSTATE: 42000
(ER_WRONG_PARAMCOUNT_TO_PROCEDURE
)
Message: Incorrect parameter count to procedure '%s'
1108
SQLSTATE: HY000
(ER_WRONG_PARAMETERS_TO_PROCEDURE
)
Message: Incorrect parameters to procedure '%s'
1109
SQLSTATE: 42S02
(ER_UNKNOWN_TABLE
)
Message: Unknown table '%s' in %s
1110
SQLSTATE: 42000
(ER_FIELD_SPECIFIED_TWICE
)
Message: Column '%s' specified twice
1111
SQLSTATE: HY000
(ER_INVALID_GROUP_FUNC_USE
)
Message: Invalid use of group function
1112
SQLSTATE: 42000
(ER_UNSUPPORTED_EXTENSION
)
Message: Table '%s' uses an extension that doesn't exist in this MySQL version
1113
SQLSTATE: 42000
(ER_TABLE_MUST_HAVE_COLUMNS
)
Message: A table must have at least 1 column
1114
SQLSTATE: HY000
(ER_RECORD_FILE_FULL
)
Message: The table '%s' is full
1115
SQLSTATE: 42000
(ER_UNKNOWN_CHARACTER_SET
)
Message: Unknown character set: '%s'
1116
SQLSTATE: HY000
(ER_TOO_MANY_TABLES
)
Message: Too many tables; MySQL can only use %d tables in a join
1117
SQLSTATE: HY000
(ER_TOO_MANY_FIELDS
)
Message: Too many columns
1118
SQLSTATE: 42000
(ER_TOO_BIG_ROWSIZE
)
Message: Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. You have to change some columns to TEXT or BLOBs
1119
SQLSTATE: HY000
(ER_STACK_OVERRUN
)
Message: Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed
1120
SQLSTATE: 42000
(ER_WRONG_OUTER_JOIN
)
Message: Cross dependency found in OUTER JOIN; examine your ON conditions
1121
SQLSTATE: 42000
(ER_NULL_COLUMN_IN_INDEX
)
Message: Column '%s' is used with UNIQUE or INDEX but is not defined as NOT NULL
1122
SQLSTATE: HY000
(ER_CANT_FIND_UDF
)
Message: Can't load function '%s'
1123
SQLSTATE: HY000
(ER_CANT_INITIALIZE_UDF
)
Message: Can't initialize function '%s'; %s
1124
SQLSTATE: HY000
(ER_UDF_NO_PATHS
)
Message: No paths allowed for shared library
1125
SQLSTATE: HY000
(ER_UDF_EXISTS
)
Message: Function '%s' already exists
1126
SQLSTATE: HY000
(ER_CANT_OPEN_LIBRARY
)
Message: Can't open shared library '%s' (errno: %d %s)
1127
SQLSTATE: HY000
(ER_CANT_FIND_DL_ENTRY
)
Message: Can't find function '%s' in library'
1128
SQLSTATE: HY000
(ER_FUNCTION_NOT_DEFINED
)
Message: Function '%s' is not defined
1129
SQLSTATE: HY000
(ER_HOST_IS_BLOCKED
)
Message: Host '%s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
1130
SQLSTATE: HY000
(ER_HOST_NOT_PRIVILEGED
)
Message: Host '%s' is not allowed to connect to this MySQL server
1131
SQLSTATE: 42000
(ER_PASSWORD_ANONYMOUS_USER
)
Message: You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords
1132
SQLSTATE: 42000
(ER_PASSWORD_NOT_ALLOWED
)
Message: You must have privileges to update tables in the mysql database to be able to change passwords for others
1133
SQLSTATE: 42000
(ER_PASSWORD_NO_MATCH
)
Message: Can't find any matching row in the user table
1134
SQLSTATE: HY000
(ER_UPDATE_INFO
)
Message: Rows matched: %ld Changed: %ld Warnings: %ld
1135
SQLSTATE: HY000
(ER_CANT_CREATE_THREAD
)
Message: Can't create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug
1136
SQLSTATE: 21S01
(ER_WRONG_VALUE_COUNT_ON_ROW
)
Message: Column count doesn't match value count at row %ld
1137
SQLSTATE: HY000
(ER_CANT_REOPEN_TABLE
)
Message: Can't reopen table: '%s'
1138
SQLSTATE: 22004
(ER_INVALID_USE_OF_NULL
)
Message: Invalid use of NULL value
1139
SQLSTATE: 42000
(ER_REGEXP_ERROR
)
Message: Got error '%s' from regexp
1140
SQLSTATE: 42000
(ER_MIX_OF_GROUP_FUNC_AND_FIELDS
)
Message: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
1141
SQLSTATE: 42000
(ER_NONEXISTING_GRANT
)
Message: There is no such grant defined for user '%s' on host '%s'
1142
SQLSTATE: 42000
(ER_TABLEACCESS_DENIED_ERROR
)
Message: %s command denied to user '%s'@'%s' for table '%s'
1143
SQLSTATE: 42000
(ER_COLUMNACCESS_DENIED_ERROR
)
Message: %s command denied to user '%s'@'%s' for column '%s' in table '%s'
1144
SQLSTATE: 42000
(ER_ILLEGAL_GRANT_FOR_TABLE
)
Message: Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used
1145
SQLSTATE: 42000
(ER_GRANT_WRONG_HOST_OR_USER
)
Message: The host or user argument to GRANT is too long
1146
SQLSTATE: 42S02
(ER_NO_SUCH_TABLE
)
Message: Table '%s.%s' doesn't exist
1147
SQLSTATE: 42000
(ER_NONEXISTING_TABLE_GRANT
)
Message: There is no such grant defined for user '%s' on host '%s' on table '%s'
1148
SQLSTATE: 42000
(ER_NOT_ALLOWED_COMMAND
)
Message: The used command is not allowed with this MySQL version
1149
SQLSTATE: 42000
(ER_SYNTAX_ERROR
)
Message: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
1150
SQLSTATE: HY000
(ER_DELAYED_CANT_CHANGE_LOCK
)
Message: Delayed insert thread couldn't get requested lock for table %s
1151
SQLSTATE: HY000
(ER_TOO_MANY_DELAYED_THREADS
)
Message: Too many delayed threads in use
1152
SQLSTATE: 08S01
(ER_ABORTING_CONNECTION
)
Message: Aborted connection %ld to db: '%s' user: '%s' (%s)
1153
SQLSTATE: 08S01
(ER_NET_PACKET_TOO_LARGE
)
Message: Got a packet bigger than 'max_allowed_packet' bytes
1154
SQLSTATE: 08S01
(ER_NET_READ_ERROR_FROM_PIPE
)
Message: Got a read error from the connection pipe
1155
SQLSTATE: 08S01
(ER_NET_FCNTL_ERROR
)
Message: Got an error from fcntl()
1156
SQLSTATE: 08S01
(ER_NET_PACKETS_OUT_OF_ORDER
)
Message: Got packets out of order
1157
SQLSTATE: 08S01
(ER_NET_UNCOMPRESS_ERROR
)
Message: Couldn't uncompress communication packet
1158
SQLSTATE: 08S01
(ER_NET_READ_ERROR
)
Message: Got an error reading communication packets
1159
SQLSTATE: 08S01
(ER_NET_READ_INTERRUPTED
)
Message: Got timeout reading communication packets
1160
SQLSTATE: 08S01
(ER_NET_ERROR_ON_WRITE
)
Message: Got an error writing communication packets
1161
SQLSTATE: 08S01
(ER_NET_WRITE_INTERRUPTED
)
Message: Got timeout writing communication packets
1162
SQLSTATE: 42000
(ER_TOO_LONG_STRING
)
Message: Result string is longer than 'max_allowed_packet' bytes
1163
SQLSTATE: 42000
(ER_TABLE_CANT_HANDLE_BLOB
)
Message: The used table type doesn't support BLOB/TEXT columns
1164
SQLSTATE: 42000
(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT
)
Message: The used table type doesn't support AUTO_INCREMENT columns
1165
SQLSTATE: HY000
(ER_DELAYED_INSERT_TABLE_LOCKED
)
Message: INSERT DELAYED can't be used with table '%s' because it is locked with LOCK TABLES
1166
SQLSTATE: 42000
(ER_WRONG_COLUMN_NAME
)
Message: Incorrect column name '%s'
1167
SQLSTATE: 42000
(ER_WRONG_KEY_COLUMN
)
Message: The used storage engine can't index column '%s'
1168
SQLSTATE: HY000
(ER_WRONG_MRG_TABLE
)
Message: All tables in the MERGE table are not identically defined
1169
SQLSTATE: 23000
(ER_DUP_UNIQUE
)
Message: Can't write, because of unique constraint, to table '%s'
1170
SQLSTATE: 42000
(ER_BLOB_KEY_WITHOUT_LENGTH
)
Message: BLOB/TEXT column '%s' used in key specification without a key length
1171
SQLSTATE: 42000
(ER_PRIMARY_CANT_HAVE_NULL
)
Message: All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead
1172
SQLSTATE: 42000
(ER_TOO_MANY_ROWS
)
Message: Result consisted of more than one row
1173
SQLSTATE: 42000
(ER_REQUIRES_PRIMARY_KEY
)
Message: This table type requires a primary key
1174
SQLSTATE: HY000
(ER_NO_RAID_COMPILED
)
Message: This version of MySQL is not compiled with RAID support
1175
SQLSTATE: HY000
(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
)
Message: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
1176
SQLSTATE: HY000
(ER_KEY_DOES_NOT_EXITS
)
Message: Key '%s' doesn't exist in table '%s'
1177
SQLSTATE: 42000
(ER_CHECK_NO_SUCH_TABLE
)
Message: Can't open table
1178
SQLSTATE: 42000
(ER_CHECK_NOT_IMPLEMENTED
)
Message: The storage engine for the table doesn't support %s
1179
SQLSTATE: 25000
(ER_CANT_DO_THIS_DURING_AN_TRANSACTION
)
Message: You are not allowed to execute this command in a transaction
1180
SQLSTATE: HY000
(ER_ERROR_DURING_COMMIT
)
Message: Got error %d during COMMIT
1181
SQLSTATE: HY000
(ER_ERROR_DURING_ROLLBACK
)
Message: Got error %d during ROLLBACK
1182
SQLSTATE: HY000
(ER_ERROR_DURING_FLUSH_LOGS
)
Message: Got error %d during FLUSH_LOGS
1183
SQLSTATE: HY000
(ER_ERROR_DURING_CHECKPOINT
)
Message: Got error %d during CHECKPOINT
1184
SQLSTATE: 08S01
(ER_NEW_ABORTING_CONNECTION
)
Message: Aborted connection %ld to db: '%s' user: '%s' host: `%s' (%s)
1185
SQLSTATE: HY000
(ER_DUMP_NOT_IMPLEMENTED
)
Message: The storage engine for the table does not support binary table dump
1186
SQLSTATE: HY000
(ER_FLUSH_MASTER_BINLOG_CLOSED
)
Message: Binlog closed, cannot RESET MASTER
1187
SQLSTATE: HY000
(ER_INDEX_REBUILD
)
Message: Failed rebuilding the index of dumped table '%s'
1188
SQLSTATE: HY000
(ER_MASTER
)
Message: Error from master: '%s'
1189
SQLSTATE: 08S01
(ER_MASTER_NET_READ
)
Message: Net error reading from master
1190
SQLSTATE: 08S01
(ER_MASTER_NET_WRITE
)
Message: Net error writing to master
1191
SQLSTATE: HY000
(ER_FT_MATCHING_KEY_NOT_FOUND
)
Message: Can't find FULLTEXT index matching the column list
1192
SQLSTATE: HY000
(ER_LOCK_OR_ACTIVE_TRANSACTION
)
Message: Can't execute the given command because you have active locked tables or an active transaction
1193
SQLSTATE: HY000
(ER_UNKNOWN_SYSTEM_VARIABLE
)
Message: Unknown system variable '%s'
1194
SQLSTATE: HY000
(ER_CRASHED_ON_USAGE
)
Message: Table '%s' is marked as crashed and should be repaired
1195
SQLSTATE: HY000
(ER_CRASHED_ON_REPAIR
)
Message: Table '%s' is marked as crashed and last (automatic?) repair failed
1196
SQLSTATE: HY000
(ER_WARNING_NOT_COMPLETE_ROLLBACK
)
Message: Some non-transactional changed tables couldn't be rolled back
1197
SQLSTATE: HY000
(ER_TRANS_CACHE_FULL
)
Message: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
1198
SQLSTATE: HY000
(ER_SLAVE_MUST_STOP
)
Message: This operation cannot be performed with a running slave; run STOP SLAVE first
1199
SQLSTATE: HY000
(ER_SLAVE_NOT_RUNNING
)
Message: This operation requires a running slave; configure slave and do START SLAVE
1200
SQLSTATE: HY000
(ER_BAD_SLAVE
)
Message: The server is not configured as slave; fix in config file or with CHANGE MASTER TO
1201
SQLSTATE: HY000
(ER_MASTER_INFO
)
Message: Could not initialize master info structure; more error messages can be found in the MySQL error log
1202
SQLSTATE: HY000
(ER_SLAVE_THREAD
)
Message: Could not create slave thread; check system resources
1203
SQLSTATE: 42000
(ER_TOO_MANY_USER_CONNECTIONS
)
Message: User %s already has more than 'max_user_connections' active connections
1204
SQLSTATE: HY000
(ER_SET_CONSTANTS_ONLY
)
Message: You may only use constant expressions with SET
1205
SQLSTATE: HY000
(ER_LOCK_WAIT_TIMEOUT
)
Message: Lock wait timeout exceeded; try restarting transaction
1206
SQLSTATE: HY000
(ER_LOCK_TABLE_FULL
)
Message: The total number of locks exceeds the lock table size
1207
SQLSTATE: 25000
(ER_READ_ONLY_TRANSACTION
)
Message: Update locks cannot be acquired during a READ UNCOMMITTED transaction
1208
SQLSTATE: HY000
(ER_DROP_DB_WITH_READ_LOCK
)
Message: DROP DATABASE not allowed while thread is holding global read lock
1209
SQLSTATE: HY000
(ER_CREATE_DB_WITH_READ_LOCK
)
Message: CREATE DATABASE not allowed while thread is holding global read lock
1210
SQLSTATE: HY000
(ER_WRONG_ARGUMENTS
)
Message: Incorrect arguments to %s
1211
SQLSTATE: 42000
(ER_NO_PERMISSION_TO_CREATE_USER
)
Message: '%s'@'%s' is not allowed to create new users
1212
SQLSTATE: HY000
(ER_UNION_TABLES_IN_DIFFERENT_DIR
)
Message: Incorrect table definition; all MERGE tables must be in the same database
1213
SQLSTATE: 40001
(ER_LOCK_DEADLOCK
)
Message: Deadlock found when trying to get lock; try restarting transaction
1214
SQLSTATE: HY000
(ER_TABLE_CANT_HANDLE_FT
)
Message: The used table type doesn't support FULLTEXT indexes
1215
SQLSTATE: HY000
(ER_CANNOT_ADD_FOREIGN
)
Message: Cannot add foreign key constraint
1216
SQLSTATE: 23000
(ER_NO_REFERENCED_ROW
)
Message: Cannot add or update a child row: a foreign key constraint fails
1217
SQLSTATE: 23000
(ER_ROW_IS_REFERENCED
)
Message: Cannot delete or update a parent row: a foreign key constraint fails
1218
SQLSTATE: 08S01
(ER_CONNECT_TO_MASTER
)
Message: Error connecting to master: %s
1219
SQLSTATE: HY000
(ER_QUERY_ON_MASTER
)
Message: Error running query on master: %s
1220
SQLSTATE: HY000
(ER_ERROR_WHEN_EXECUTING_COMMAND
)
Message: Error when executing command %s: %s
1221
SQLSTATE: HY000
(ER_WRONG_USAGE
)
Message: Incorrect usage of %s and %s
1222
SQLSTATE: 21000
(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
)
Message: The used SELECT statements have a different number of columns
1223
SQLSTATE: HY000
(ER_CANT_UPDATE_WITH_READLOCK
)
Message: Can't execute the query because you have a conflicting read lock
1224
SQLSTATE: HY000
(ER_MIXING_NOT_ALLOWED
)
Message: Mixing of transactional and non-transactional tables is disabled
1225
SQLSTATE: HY000
(ER_DUP_ARGUMENT
)
Message: Option '%s' used twice in statement
1226
SQLSTATE: 42000
(ER_USER_LIMIT_REACHED
)
Message: User '%s' has exceeded the '%s' resource (current value: %ld)
1227
SQLSTATE: HY000
(ER_SPECIFIC_ACCESS_DENIED_ERROR
)
Message: Access denied; you need the %s privilege for this operation
1228
SQLSTATE: HY000
(ER_LOCAL_VARIABLE
)
Message: Variable '%s' is a SESSION variable and can't be used with SET GLOBAL
1229
SQLSTATE: HY000
(ER_GLOBAL_VARIABLE
)
Message: Variable '%s' is a GLOBAL variable and should be set with SET GLOBAL
1230
SQLSTATE: 42000
(ER_NO_DEFAULT
)
Message: Variable '%s' doesn't have a default value
1231
SQLSTATE: 42000
(ER_WRONG_VALUE_FOR_VAR
)
Message: Variable '%s' can't be set to the value of '%s'
1232
SQLSTATE: 42000
(ER_WRONG_TYPE_FOR_VAR
)
Message: Incorrect argument type to variable '%s'
1233
SQLSTATE: HY000
(ER_VAR_CANT_BE_READ
)
Message: Variable '%s' can only be set, not read
1234
SQLSTATE: 42000
(ER_CANT_USE_OPTION_HERE
)
Message: Incorrect usage/placement of '%s'
1235
SQLSTATE: 42000
(ER_NOT_SUPPORTED_YET
)
Message: This version of MySQL doesn't yet support '%s'
1236
SQLSTATE: HY000
(ER_MASTER_FATAL_ERROR_READING_BINLOG
)
Message: Got fatal error %d: '%s' from master when reading data from binary log
1237
SQLSTATE: HY000
(ER_SLAVE_IGNORED_TABLE
)
Message: Slave SQL thread ignored the query because of replicate-*-table rules
1238
SQLSTATE: HY000
(ER_INCORRECT_GLOBAL_LOCAL_VAR
)
Message: Variable '%s' is a %s variable
1239
SQLSTATE: 42000
(ER_WRONG_FK_DEF
)
Message: Incorrect foreign key definition for '%s': %s
1240
SQLSTATE: HY000
(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF
)
Message: Key reference and table reference don't match
1241
SQLSTATE: 21000
(ER_OPERAND_COLUMNS
)
Message: Operand should contain %d column(s)
1242
SQLSTATE: 21000
(ER_SUBQUERY_NO_1_ROW
)
Message: Subquery returns more than 1 row
1243
SQLSTATE: HY000
(ER_UNKNOWN_STMT_HANDLER
)
Message: Unknown prepared statement handler (%.*s) given to %s
1244
SQLSTATE: HY000
(ER_CORRUPT_HELP_DB
)
Message: Help database is corrupt or does not exist
1245
SQLSTATE: HY000
(ER_CYCLIC_REFERENCE
)
Message: Cyclic reference on subqueries
1246
SQLSTATE: HY000
(ER_AUTO_CONVERT
)
Message: Converting column '%s' from %s to %s
1247
SQLSTATE: 42S22
(ER_ILLEGAL_REFERENCE
)
Message: Reference '%s' not supported (%s)
1248
SQLSTATE: 42000
(ER_DERIVED_MUST_HAVE_ALIAS
)
Message: Every derived table must have its own alias
1249
SQLSTATE: 01000
(ER_SELECT_REDUCED
)
Message: Select %u was reduced during optimization
1250
SQLSTATE: 42000
(ER_TABLENAME_NOT_ALLOWED_HERE
)
Message: Table '%s' from one of the SELECTs cannot be used in %s
1251
SQLSTATE: 08004
(ER_NOT_SUPPORTED_AUTH_MODE
)
Message: Client does not support authentication protocol requested by server; consider upgrading MySQL client
1252
SQLSTATE: 42000
(ER_SPATIAL_CANT_HAVE_NULL
)
Message: All parts of a SPATIAL index must be NOT NULL
1253
SQLSTATE: 42000
(ER_COLLATION_CHARSET_MISMATCH
)
Message: COLLATION '%s' is not valid for CHARACTER SET '%s'
1254
SQLSTATE: HY000
(ER_SLAVE_WAS_RUNNING
)
Message: Slave is already running
1255
SQLSTATE: HY000
(ER_SLAVE_WAS_NOT_RUNNING
)
Message: Slave already has been stopped
1256
SQLSTATE: HY000
(ER_TOO_BIG_FOR_UNCOMPRESS
)
Message: Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)
1257
SQLSTATE: HY000
(ER_ZLIB_Z_MEM_ERROR
)
Message: ZLIB: Not enough memory
1258
SQLSTATE: HY000
(ER_ZLIB_Z_BUF_ERROR
)
Message: ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)
1259
SQLSTATE: HY000
(ER_ZLIB_Z_DATA_ERROR
)
Message: ZLIB: Input data corrupted
1260
SQLSTATE: HY000
(ER_CUT_VALUE_GROUP_CONCAT
)
Message: %d line(s) were cut by GROUP_CONCAT()
1261
SQLSTATE: 01000
(ER_WARN_TOO_FEW_RECORDS
)
Message: Row %ld doesn't contain data for all columns
1262
SQLSTATE: 01000
(ER_WARN_TOO_MANY_RECORDS
)
Message: Row %ld was truncated; it contained more data than there were input columns
1263
SQLSTATE: 22004
(ER_WARN_NULL_TO_NOTNULL
)
Message: Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld
1264
SQLSTATE: 22003
(ER_WARN_DATA_OUT_OF_RANGE
)
Message: Out of range value adjusted for column '%s' at row %ld
1265
SQLSTATE: 01000
(WARN_DATA_TRUNCATED
)
Message: Data truncated for column '%s' at row %ld
1266
SQLSTATE: HY000
(ER_WARN_USING_OTHER_HANDLER
)
Message: Using storage engine %s for table '%s'
1267
SQLSTATE: HY000
(ER_CANT_AGGREGATE_2COLLATIONS
)
Message: Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'
1268
SQLSTATE: HY000
(ER_DROP_USER
)
Message: Cannot drop one or more of the requested users
1269
SQLSTATE: HY000
(ER_REVOKE_GRANTS
)
Message: Can't revoke all privileges, grant for one or more of the requested users
1270
SQLSTATE: HY000
(ER_CANT_AGGREGATE_3COLLATIONS
)
Message: Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'
1271
SQLSTATE: HY000
(ER_CANT_AGGREGATE_NCOLLATIONS
)
Message: Illegal mix of collations for operation '%s'
1272
SQLSTATE: HY000
(ER_VARIABLE_IS_NOT_STRUCT
)
Message: Variable '%s' is not a variable component (can't be used as XXXX.variable_name)
1273
SQLSTATE: HY000
(ER_UNKNOWN_COLLATION
)
Message: Unknown collation: '%s'
1274
SQLSTATE: HY000
(ER_SLAVE_IGNORED_SSL_PARAMS
)
Message: SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started
1275
SQLSTATE: HY000
(ER_SERVER_IS_IN_SECURE_AUTH_MODE
)
Message: Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format
1276
SQLSTATE: HY000
(ER_WARN_FIELD_RESOLVED
)
Message: Field or reference '%s%s%s%s%s' of SELECT #%d was resolved in SELECT #%d
1277
SQLSTATE: HY000
(ER_BAD_SLAVE_UNTIL_COND
)
Message: Incorrect parameter or combination of parameters for START SLAVE UNTIL
1278
SQLSTATE: HY000
(ER_MISSING_SKIP_SLAVE
)
Message: It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart
1279
SQLSTATE: HY000
(ER_UNTIL_COND_IGNORED
)
Message: SQL thread is not to be started so UNTIL options are ignored
1280
SQLSTATE: 42000
(ER_WRONG_NAME_FOR_INDEX
)
Message: Incorrect index name '%s'
1281
SQLSTATE: 42000
(ER_WRONG_NAME_FOR_CATALOG
)
Message: Incorrect catalog name '%s'
1282
SQLSTATE: HY000
(ER_WARN_QC_RESIZE
)
Message: Query cache failed to set size %lu; new query cache size is %lu
1283
SQLSTATE: HY000
(ER_BAD_FT_COLUMN
)
Message: Column '%s' cannot be part of FULLTEXT index
1284
SQLSTATE: HY000
(ER_UNKNOWN_KEY_CACHE
)
Message: Unknown key cache '%s'
1285
SQLSTATE: HY000
(ER_WARN_HOSTNAME_WONT_WORK
)
Message: MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work
1286
SQLSTATE: 42000
(ER_UNKNOWN_STORAGE_ENGINE
)
Message: Unknown table engine '%s'
1287
SQLSTATE: HY000
(ER_WARN_DEPRECATED_SYNTAX
)
Message: '%s' is deprecated; use '%s' instead
1288
SQLSTATE: HY000
(ER_NON_UPDATABLE_TABLE
)
Message: The target table %s of the %s is not updatable
1289
SQLSTATE: HY000
(ER_FEATURE_DISABLED
)
Message: The '%s' feature is disabled; you need MySQL built with '%s' to have it working
1290
SQLSTATE: HY000
(ER_OPTION_PREVENTS_STATEMENT
)
Message: The MySQL server is running with the %s option so it cannot execute this statement
1291
SQLSTATE: HY000
(ER_DUPLICATED_VALUE_IN_TYPE
)
Message: Column '%s' has duplicated value '%s' in %s
1292
SQLSTATE: 22007
(ER_TRUNCATED_WRONG_VALUE
)
Message: Truncated incorrect %s value: '%s'
1293
SQLSTATE: HY000
(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS
)
Message: Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
1294
SQLSTATE: HY000
(ER_INVALID_ON_UPDATE
)
Message: Invalid ON UPDATE clause for '%s' column
1295
SQLSTATE: HY000
(ER_UNSUPPORTED_PS
)
Message: This command is not supported in the prepared statement protocol yet
1296
SQLSTATE: HY000
(ER_GET_ERRMSG
)
Message: Got error %d '%s' from %s
1297
SQLSTATE: HY000
(ER_GET_TEMPORARY_ERRMSG
)
Message: Got temporary error %d '%s' from %s
1298
SQLSTATE: HY000
(ER_UNKNOWN_TIME_ZONE
)
Message: Unknown or incorrect time zone: '%s'
1299
SQLSTATE: HY000
(ER_WARN_INVALID_TIMESTAMP
)
Message: Invalid TIMESTAMP value in column '%s' at row %ld
1300
SQLSTATE: HY000
(ER_INVALID_CHARACTER_STRING
)
Message: Invalid %s character string: '%s'
1301
SQLSTATE: HY000
(ER_WARN_ALLOWED_PACKET_OVERFLOWED
)
Message: Result of %s() was larger than max_allowed_packet (%ld) - truncated
1302
SQLSTATE: HY000
(ER_CONFLICTING_DECLARATIONS
)
Message: Conflicting declarations: '%s%s' and '%s%s'
1303
SQLSTATE: 2F003
(ER_SP_NO_RECURSIVE_CREATE
)
Message: Can't create a %s from within another stored routine
1304
SQLSTATE: 42000
(ER_SP_ALREADY_EXISTS
)
Message: %s %s already exists
1305
SQLSTATE: 42000
(ER_SP_DOES_NOT_EXIST
)
Message: %s %s does not exist
1306
SQLSTATE: HY000
(ER_SP_DROP_FAILED
)
Message: Failed to DROP %s %s
1307
SQLSTATE: HY000
(ER_SP_STORE_FAILED
)
Message: Failed to CREATE %s %s
1308
SQLSTATE: 42000
(ER_SP_LILABEL_MISMATCH
)
Message: %s with no matching label: %s
1309
SQLSTATE: 42000
(ER_SP_LABEL_REDEFINE
)
Message: Redefining label %s
1310
SQLSTATE: 42000
(ER_SP_LABEL_MISMATCH
)
Message: End-label %s without match
1311
SQLSTATE: 01000
(ER_SP_UNINIT_VAR
)
Message: Referring to uninitialized variable %s
1312
SQLSTATE: 0A000
(ER_SP_BADSELECT
)
Message: SELECT in a stored procedure must have INTO
1313
SQLSTATE: 42000
(ER_SP_BADRETURN
)
Message: RETURN is only allowed in a FUNCTION
1314
SQLSTATE: 0A000
(ER_SP_BADSTATEMENT
)
Message: Statements like SELECT, INSERT, UPDATE (and others) are not allowed in a FUNCTION
1315
SQLSTATE: 42000
(ER_UPDATE_LOG_DEPRECATED_IGNORED
)
Message: The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored
1316
SQLSTATE: 42000
(ER_UPDATE_LOG_DEPRECATED_TRANSLATED
)
Message: The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN
1317
SQLSTATE: 70100
(ER_QUERY_INTERRUPTED
)
Message: Query execution was interrupted
1318
SQLSTATE: 42000
(ER_SP_WRONG_NO_OF_ARGS
)
Message: Incorrect number of arguments for %s %s; expected %u, got %u
1319
SQLSTATE: 42000
(ER_SP_COND_MISMATCH
)
Message: Undefined CONDITION: %s
1320
SQLSTATE: 42000
(ER_SP_NORETURN
)
Message: No RETURN found in FUNCTION %s
1321
SQLSTATE: 2F005
(ER_SP_NORETURNEND
)
Message: FUNCTION %s ended without RETURN
1322
SQLSTATE: 42000
(ER_SP_BAD_CURSOR_QUERY
)
Message: Cursor statement must be a SELECT
1323
SQLSTATE: 42000
(ER_SP_BAD_CURSOR_SELECT
)
Message: Cursor SELECT must not have INTO
1324
SQLSTATE: 42000
(ER_SP_CURSOR_MISMATCH
)
Message: Undefined CURSOR: %s
1325
SQLSTATE: 24000
(ER_SP_CURSOR_ALREADY_OPEN
)
Message: Cursor is already open
1326
SQLSTATE: 24000
(ER_SP_CURSOR_NOT_OPEN
)
Message: Cursor is not open
1327
SQLSTATE: 42000
(ER_SP_UNDECLARED_VAR
)
Message: Undeclared variable: %s
1328
SQLSTATE: HY000
(ER_SP_WRONG_NO_OF_FETCH_ARGS
)
Message: Incorrect number of FETCH variables
1329
SQLSTATE: 02000
(ER_SP_FETCH_NO_DATA
)
Message: No data to FETCH
1330
SQLSTATE: 42000
(ER_SP_DUP_PARAM
)
Message: Duplicate parameter: %s
1331
SQLSTATE: 42000
(ER_SP_DUP_VAR
)
Message: Duplicate variable: %s
1332
SQLSTATE: 42000
(ER_SP_DUP_COND
)
Message: Duplicate condition: %s
1333
SQLSTATE: 42000
(ER_SP_DUP_CURS
)
Message: Duplicate cursor: %s
1334
SQLSTATE: HY000
(ER_SP_CANT_ALTER
)
Message: Failed to ALTER %s %s
1335
SQLSTATE: 0A000
(ER_SP_SUBSELECT_NYI
)
Message: Subselect value not supported
1336
SQLSTATE: 42000
(ER_SP_NO_USE
)
Message: USE is not allowed in a stored procedure
1337
SQLSTATE: 42000
(ER_SP_VARCOND_AFTER_CURSHNDLR
)
Message: Variable or condition declaration after cursor or handler declaration
1338
SQLSTATE: 42000
(ER_SP_CURSOR_AFTER_HANDLER
)
Message: Cursor declaration after handler declaration
1339
SQLSTATE: 20000
(ER_SP_CASE_NOT_FOUND
)
Message: Case not found for CASE statement
1340
SQLSTATE: HY000
(ER_FPARSER_TOO_BIG_FILE
)
Message: Configuration file '%s' is too big
1341
SQLSTATE: HY000
(ER_FPARSER_BAD_HEADER
)
Message: Malformed file type header in file '%s'
1342
SQLSTATE: HY000
(ER_FPARSER_EOF_IN_COMMENT
)
Message: Unexpected end of file while parsing comment '%s'
1343
SQLSTATE: HY000
(ER_FPARSER_ERROR_IN_PARAMETER
)
Message: Error while parsing parameter '%s' (line: '%s')
1344
SQLSTATE: HY000
(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER
)
Message: Unexpected end of file while skipping unknown parameter '%s'
1345
SQLSTATE: HY000
(ER_VIEW_NO_EXPLAIN
)
Message: EXPLAIN/SHOW can not be issued; lacking privileges for underlying table
1346
SQLSTATE: HY000
(ER_FRM_UNKNOWN_TYPE
)
Message: File '%s' has unknown type '%s' in its header
1347
SQLSTATE: HY000
(ER_WRONG_OBJECT
)
Message: '%s.%s' is not %s
1348
SQLSTATE: HY000
(ER_NONUPDATEABLE_COLUMN
)
Message: Column '%s' is not updatable
1349
SQLSTATE: HY000
(ER_VIEW_SELECT_DERIVED
)
Message: View's SELECT contains a subquery in the FROM clause
1350
SQLSTATE: HY000
(ER_VIEW_SELECT_CLAUSE
)
Message: View's SELECT contains a '%s' clause
1351
SQLSTATE: HY000
(ER_VIEW_SELECT_VARIABLE
)
Message: View's SELECT contains a variable or parameter
1352
SQLSTATE: HY000
(ER_VIEW_SELECT_TMPTABLE
)
Message: View's SELECT contains a temporary table '%s'
1353
SQLSTATE: HY000
(ER_VIEW_WRONG_LIST
)
Message: View's SELECT and view's field list have different column counts
1354
SQLSTATE: HY000
(ER_WARN_VIEW_MERGE
)
Message: View merge algorithm can't be used here for now (assumed undefined algorithm)
1355
SQLSTATE: HY000
(ER_WARN_VIEW_WITHOUT_KEY
)
Message: View being updated does not have complete key of underlying table in it
1356
SQLSTATE: HY000
(ER_VIEW_INVALID
)
Message: View '%s.%s' references invalid table(s) or column(s) or function(s)
1357
SQLSTATE: HY000
(ER_SP_NO_DROP_SP
)
Message: Can't drop a %s from within another stored routine
1358
SQLSTATE: HY000
(ER_SP_GOTO_IN_HNDLR
)
Message: GOTO is not allowed in a stored procedure handler
1359
SQLSTATE: HY000
(ER_TRG_ALREADY_EXISTS
)
Message: Trigger already exists
1360
SQLSTATE: HY000
(ER_TRG_DOES_NOT_EXIST
)
Message: Trigger does not exist
1361
SQLSTATE: HY000
(ER_TRG_ON_VIEW_OR_TEMP_TABLE
)
Message: Trigger's '%s' is view or temporary table
1362
SQLSTATE: HY000
(ER_TRG_CANT_CHANGE_ROW
)
Message: Updating of %s row is not allowed in %strigger
1363
SQLSTATE: HY000
(ER_TRG_NO_SUCH_ROW_IN_TRG
)
Message: There is no %s row in %s trigger
1364
SQLSTATE: HY000
(ER_NO_DEFAULT_FOR_FIELD
)
Message: Field '%s' doesn't have a default value
1365
SQLSTATE: 22012
(ER_DIVISION_BY_ZERO
)
Message: Division by 0
1366
SQLSTATE: HY000
(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
)
Message: Incorrect %s value: '%s' for column '%s' at row %ld
1367
SQLSTATE: 22007
(ER_ILLEGAL_VALUE_FOR_TYPE
)
Message: Illegal %s '%s' value found during parsing
1368
SQLSTATE: HY000
(ER_VIEW_NONUPD_CHECK
)
Message: CHECK OPTION on non-updatable view '%s.%s'
1369
SQLSTATE: HY000
(ER_VIEW_CHECK_FAILED
)
Message: CHECK OPTION failed '%s.%s'
1370
SQLSTATE: 42000
(ER_PROCACCESS_DENIED_ERROR
)
Message: %s command denied to user '%s'@'%s' for routine '%s'
1371
SQLSTATE: HY000
(ER_RELAY_LOG_FAIL
)
Message: Failed purging old relay logs: %s
1372
SQLSTATE: HY000
(ER_PASSWD_LENGTH
)
Message: Password hash should be a %d-digit hexadecimal number
1373
SQLSTATE: HY000
(ER_UNKNOWN_TARGET_BINLOG
)
Message: Target log not found in binlog index
1374
SQLSTATE: HY000
(ER_IO_ERR_LOG_INDEX_READ
)
Message: I/O error reading log index file
1375
SQLSTATE: HY000
(ER_BINLOG_PURGE_PROHIBITED
)
Message: Server configuration does not permit binlog purge
1376
SQLSTATE: HY000
(ER_FSEEK_FAIL
)
Message: Failed on fseek()
1377
SQLSTATE: HY000
(ER_BINLOG_PURGE_FATAL_ERR
)
Message: Fatal error during log purge
1378
SQLSTATE: HY000
(ER_LOG_IN_USE
)
Message: A purgeable log is in use, will not purge
1379
SQLSTATE: HY000
(ER_LOG_PURGE_UNKNOWN_ERR
)
Message: Unknown error during log purge
1380
SQLSTATE: HY000
(ER_RELAY_LOG_INIT
)
Message: Failed initializing relay log position: %s
1381
SQLSTATE: HY000
(ER_NO_BINARY_LOGGING
)
Message: You are not using binary logging
1382
SQLSTATE: HY000
(ER_RESERVED_SYNTAX
)
Message: The '%s' syntax is reserved for purposes internal to the MySQL server
1383
SQLSTATE: HY000
(ER_WSAS_FAILED
)
Message: WSAStartup Failed
1384
SQLSTATE: HY000
(ER_DIFF_GROUPS_PROC
)
Message: Can't handle procedures with differents groups yet
1385
SQLSTATE: HY000
(ER_NO_GROUP_FOR_PROC
)
Message: Select must have a group with this procedure
1386
SQLSTATE: HY000
(ER_ORDER_WITH_PROC
)
Message: Can't use ORDER clause with this procedure
1387
SQLSTATE: HY000
(ER_LOGING_PROHIBIT_CHANGING_OF
)
Message: Binary logging and replication forbid changing the global server %s
1388
SQLSTATE: HY000
(ER_NO_FILE_MAPPING
)
Message: Can't map file: %s, errno: %d
1389
SQLSTATE: HY000
(ER_WRONG_MAGIC
)
Message: Wrong magic in %s
1390
SQLSTATE: HY000
(ER_PS_MANY_PARAM
)
Message: Prepared statement contains too many placeholders
1391
SQLSTATE: HY000
(ER_KEY_PART_0
)
Message: Key part '%s' length cannot be 0
1392
SQLSTATE: HY000
(ER_VIEW_CHECKSUM
)
Message: View text checksum failed
1393
SQLSTATE: HY000
(ER_VIEW_MULTIUPDATE
)
Message: Can not modify more than one base table through a join view '%s.%s'
1394
SQLSTATE: HY000
(ER_VIEW_NO_INSERT_FIELD_LIST
)
Message: Can not insert into join view '%s.%s' without fields list
1395
SQLSTATE: HY000
(ER_VIEW_DELETE_MERGE_VIEW
)
Message: Can not delete from join view '%s.%s'
1396
SQLSTATE: HY000
(ER_CANNOT_USER
)
Message: Operation %s failed for %s
1397
SQLSTATE: 42000
(ER_NONEXISTING_PROC_GRANT
)
Message: There is no such grant defined for user '%s' on host '%s' on routine '%s'
1398
SQLSTATE: HY000
(ER_PROC_AUTO_GRANT_FAIL
)
Message: Failed to grant EXECUTE and ALTER ROUTINE privileges
1399
SQLSTATE: HY000
(ER_PROC_AUTO_REVOKE_FAIL
)
Message: Failed to revoke all privileges to dropped routine
1400
SQLSTATE: 22001
(ER_DATA_TOO_LONG
)
Message: Data too long for column '%s' at row %ld
Client error information comes from the following files:
Because updates are frequent, it is possible that these files will contain additional error information not listed here.
2000
(CR_UNKNOWN_ERROR
)
Message: Unknown MySQL error
2001
(CR_SOCKET_CREATE_ERROR
)
Message: Can't create UNIX socket (%d)
2002
(CR_CONNECTION_ERROR
)
Message: Can't connect to local MySQL server through socket '%s' (%d)
2003
(CR_CONN_HOST_ERROR
)
Message: Can't connect to MySQL server on '%s' (%d)
2004
(CR_IPSOCK_ERROR
)
Message: Can't create TCP/IP socket (%d)
2005
(CR_UNKNOWN_HOST
)
Message: Unknown MySQL server host '%s' (%d)
2006
(CR_SERVER_GONE_ERROR
)
Message: MySQL server has gone away
2007
(CR_VERSION_ERROR
)
Message: Protocol mismatch; server version = %d, client version = %d
2008
(CR_OUT_OF_MEMORY
)
Message: MySQL client ran out of memory
2009
(CR_WRONG_HOST_INFO
)
Message: Wrong host info
2010
(CR_LOCALHOST_CONNECTION
)
Message: Localhost via UNIX socket
2011
(CR_TCP_CONNECTION
)
Message: %s via TCP/IP
2012
(CR_SERVER_HANDSHAKE_ERR
)
Message: Error in server handshake
2013
(CR_SERVER_LOST
)
Message: Lost connection to MySQL server during query
2014
(CR_COMMANDS_OUT_OF_SYNC
)
Message: Commands out of sync; you can't run this command now
2015
(CR_NAMEDPIPE_CONNECTION
)
Message: Named pipe: %s
2016
(CR_NAMEDPIPEWAIT_ERROR
)
Message: Can't wait for named pipe to host: %s pipe: %s (%lu)
2017
(CR_NAMEDPIPEOPEN_ERROR
)
Message: Can't open named pipe to host: %s pipe: %s (%lu)
2018
(CR_NAMEDPIPESETSTATE_ERROR
)
Message: Can't set state of named pipe to host: %s pipe: %s (%lu)
2019
(CR_CANT_READ_CHARSET
)
Message: Can't initialize character set %s (path: %s)
2020
(CR_NET_PACKET_TOO_LARGE
)
Message: Got packet bigger than 'max_allowed_packet' bytes
2021
(CR_EMBEDDED_CONNECTION
)
Message: Embedded server
2022
(CR_PROBE_SLAVE_STATUS
)
Message: Error on SHOW SLAVE STATUS:
2023
(CR_PROBE_SLAVE_HOSTS
)
Message: Error on SHOW SLAVE HOSTS:
2024
(CR_PROBE_SLAVE_CONNECT
)
Message: Error connecting to slave:
2025
(CR_PROBE_MASTER_CONNECT
)
Message: Error connecting to master:
2026
(CR_SSL_CONNECTION_ERROR
)
Message: SSL connection error
2027
(CR_MALFORMED_PACKET
)
Message: Malformed packet
2028
(CR_WRONG_LICENSE
)
Message: This client library is licensed only for use with MySQL servers having '%s' license
2029
(CR_NULL_POINTER
)
Message: Invalid use of null pointer
2030
(CR_NO_PREPARE_STMT
)
Message: Statement not prepared
2031
(CR_PARAMS_NOT_BOUND
)
Message: No data supplied for parameters in prepared statement
2032
(CR_DATA_TRUNCATED
)
Message: Data truncated
2033
(CR_NO_PARAMETERS_EXISTS
)
Message: No parameters exist in the statement
2034
(CR_INVALID_PARAMETER_NO
)
Message: Invalid parameter number
2035
(CR_INVALID_BUFFER_USE
)
Message: Can't send long data for non-string/non-binary data types (parameter: %d)
2036
(CR_UNSUPPORTED_PARAM_TYPE
)
Message: Using unsupported buffer type: %d (parameter: %d)
2037
(CR_SHARED_MEMORY_CONNECTION
)
Message: Shared memory: %s
2038
(CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR
)
Message: Can't open shared memory; client could not create request event (%lu)
2039
(CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR
)
Message: Can't open shared memory; no answer event received from server (%lu)
2040
(CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR
)
Message: Can't open shared memory; server could not allocate file mapping (%lu)
2041
(CR_SHARED_MEMORY_CONNECT_MAP_ERROR
)
Message: Can't open shared memory; server could not get pointer to file mapping (%lu)
2042
(CR_SHARED_MEMORY_FILE_MAP_ERROR
)
Message: Can't open shared memory; client could not allocate file mapping (%lu)
2043
(CR_SHARED_MEMORY_MAP_ERROR
)
Message: Can't open shared memory; client could not get pointer to file mapping (%lu)
2044
(CR_SHARED_MEMORY_EVENT_ERROR
)
Message: Can't open shared memory; client could not create %s event (%lu)
2045
(CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR
)
Message: Can't open shared memory; no answer from server (%lu)
2046
(CR_SHARED_MEMORY_CONNECT_SET_ERROR
)
Message: Can't open shared memory; cannot send request event to server (%lu)
2047
(CR_CONN_UNKNOW_PROTOCOL
)
Message: Wrong or unknown protocol
2048
(CR_INVALID_CONN_HANDLE
)
Message: Invalid connection handle
2049
(CR_SECURE_AUTH
)
Message: Connection using old (pre-4.1.1) authentication protocol refused (client option 'secure_auth' enabled)
2050
(CR_FETCH_CANCELED
)
Message: Row retrieval was canceled by mysql_stmt_close() call
2051
(CR_NO_DATA
)
Message: Attempt to read column without prior row fetch
2052
(CR_NO_STMT_METADATA
)
Message: Prepared statement contains no metadata
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.8.3 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.4.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 you want to use the
thr_alarm()
code in your 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
standardized 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
Unix source distributions and binary distributions starting with Version
3.23.29. The tests can be run under Unix, or on Windows in the Cygwin
environment if the server has been compiled under Cygwin. They cannot be
run in a native Windows environment currently.
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, because 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 25.1.2.3 Reporting Bugs in the MySQL Test Suite.
From MySQL 4.1 on,
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.
Before MySQL 4.1, mysql-test-run
does not try to run its own server
by default but tries to use your currently running server. To override this
and cause mysql-test-run
to start its own server, run it with
the --local
option.
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 whether any other tests fail.
You can use the mysqltest
language to write your own test cases.
Unfortunately, we have not yet written full documentation for it.
You can, however, look at our current test cases and use
them as an example. The following points should help you get started:
;
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 recognized 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 the
`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
that the fields are separated by a hard tab, and that there is a hard tab at the end.
You may want to use od -c
to make sure that your text editor has not messed
anything up during edit. We 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.
--error error-number
on the line before the statement.
The error number can be
a list of possible error numbers separated by `,'.
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 use sleep 1.3;
, for example, to sleep 1.3
seconds.
internals
mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
As this list does not accept
attachments, you should ftp all the relevant files to:
ftp://ftp.mysql.com/pub/mysql/upload/
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.4.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://ftp.mysql.com/pub/mysql/upload/
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 whether 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-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.8 MySQL Installation Using a Source Distribution.
There are two ways to add new functions to MySQL:
CREATE FUNCTION
and DROP FUNCTION
statements.
See section 25.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
SyntaxCREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|REAL|INTEGER} SONAME shared_library_name DROP FUNCTION function_name
A user-defined function (UDF) is a way to extend MySQL with a new
function that works like native (built in) MySQL function such as
ABS()
and CONCAT()
.
AGGREGATE
is a new option for MySQL 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 initialization 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-defined functions, see section 25.2.2 Adding a New User-defined Function.
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 you do not
have this table, you should run the script
mysql_fix_privilege_tables
to create it.
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
metaphone
example in `sql/udf_example.cc' that uses
default_charset_info
), you must link the program with
-rdynamic
(see man dlopen
).
If you are using a precompiled version of the server, use MySQL-Max, which supports dynamic loading.
For each function that you want to use in SQL statements, you should define
corresponding C (or C++) functions. In the following discussion, the name
``xxx'' is used for an example function name. To distinguish between SQL and
C/C++ usage, XXX()
(uppercase) indicates an 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 initialization function.
When an SQL statement invokes XXX()
, MySQL calls the
initialization 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 deinitialization functions are not called. Otherwise, the main
function xxx()
is called once for each row. After all rows have been
processed, the deinitialization 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 UDFs, 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 initialization and deinitialization 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 initialization and deinitialization 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 follow. The
initialization 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 65KB or 16MB; 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.
Note that the following function is NOT needed or used by MySQL 4.1.1. You can keep still have define this function if you want to have your code work with both MySQL 4.0 and MySQL 4.1.1
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
(for example by calling xxx_clear()
and then calling
xxx_add()
.
The following function is only required by MySQL 4.1.1 and above:
char *xxx_clear(UDF_INIT *initid, char *is_null, char *error);
This function is called when MySQL needs to reset the summary results.
This will be called at the beginning for each new group but can also be
called to reset the values for a query where there was no matching rows.
is_null
will be set to point to CHAR(0)
before calling
xxx_clear()
.
You can use the error
pointer to store a byte if something went
wrong .
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 25.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 UDFs. See section 25.2.2.3 Argument Processing.
The return value handling in xxx()
should be done identically as
for a normal UDF. See section 25.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_clear()
, 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_clear()
).
error
is never reset.
If is_null
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 initialization
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 initialization 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 initialization 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 initialization function).
The initialization 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 25.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.
The immediately following instructions are for Unix. Instructions for Windows are given later in this section.
The `udf_example.cc' 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 udf_example.cc
If you are using gcc
, you should be able to create
`udf_example.so' with a simpler command:
shell> make udf_example.so
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 the dynamic linker ld
, such as `/usr/lib' or add the
directory in which you placed the shared object to the linker configuration
file (for example, `/etc/ld.so.conf').
On many systems, you can also 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 mysqld_safe
startup scripts and restart
mysqld
.
On some systems, the ldconfig
program that configures the dynamic
linker will not recognize shared objects unless their name begins with
lib
. In this case you should rename a file such as
`udf_example.so' to `libudf_example.so'.
On Windows, you can compile user-defined functions by using the following procedure:
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 previously
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
initialization 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 these
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 whether 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 a row-by-row or GROUP BY
level.
We have created an example procedure in MySQL 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 whether
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 appendix lists some common problems and error messages that you may encounter. It describes how to determine the causes of the problems and what to do to solve them.
When you run into a problem, the first thing you should do is to find out which program or piece of equipment is causing it:
glibc
) are up to date.
It's always good to use a machine with ECC memory to discover
memory problems early.
kbd_mode -a
.
top
, ps
, Task Manager, or some similar program,
to check which program is taking all CPU or is locking the machine.
top
, df
, or a similar program to check whether you are out
of memory, disk space, file descriptors, or some other critical resource.
If after you have examined all other possibilities and you have concluded that the MySQL server or a MySQL client is causing the problem, it's time to create 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 that MySQL is causing the problem. Take into consideration all the situations in this chapter. State any problems exactly how they appear when you examine your system. Use the ``copy and paste'' method for any output and error messages from programs and 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 state only ``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 the following information:
top
. Let
the program run for a while, it may simply be evaluating something
computationally intensive.
mysqld
server is causing problems, can you get any response
from it with mysqladmin -u root ping
or mysqladmin -u root
processlist
?
mysql
, for example.) Does the client jam? Do you get any
output from the program?
When sending a bug report, you should follow the outline described in section 1.4.1.2 Asking Questions or Reporting Bugs.
This section lists some errors that users frequently encounter when running MySQL programs. Although the problems show up when you try to run client programs, the solutions to many of the problems involves changing the configuration of the MySQL server.
Access denied
An Access denied
error can have many causes. Often the problem is
related to the MySQL accounts that the server allows client programs to
use when connecting.
See section 5.5.8 Causes of Access denied
Errors.
See section 5.5.2 How the Privilege System Works.
Can't connect to [local] MySQL server
A MySQL client on Unix can connect to the mysqld
server in two
different ways: By using a Unix socket file to connect through a file in the
filesystem (default `/tmp/mysql.sock'), or by using TCP/IP, which
connects through a port number. A Unix socket file connection is faster
than TCP/IP, but can be used only when connecting to a server on the same
computer. A Unix socket file is used if you don't specify a hostname or if
you specify the special hostname localhost
.
If the MySQL server is running on Windows 9x or Me, you can connect
only via TCP/IP. If the server is running on Windows NT, 2000, XP, or 2003
and is started with the --enable-named-pipe
option, you can also
connect with named pipes if you run the client on the host where the
server is running. The name of the named pipe is MySQL
by default.
If you don't give a hostname when connecting to mysqld
, a MySQL
client first will try to connect to the named pipe. If that 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 is no
MySQL server running on the system or that you are using an incorrect Unix
socket filename or TCP/IP port number when trying to connect to the
server.
Start by checking whether there is a process named mysqld
running on
your server host.
(Use ps xa | grep mysqld
on Unix or the Task Manager on Windows.)
If there is no such process, you should start the server.
See section 2.9.2.3 Starting and Troubleshooting the MySQL Server.
If a mysqld
process is running, you can check it by
trying the following commands. The port number or Unix socket filename
might be different in your setup. host_ip
represents the IP number of
the machine where the server is running.
shell> mysqladmin version shell> mysqladmin variables shell> mysqladmin -h `hostname` version variables shell> mysqladmin -h `hostname` --port=3306 version shell> mysqladmin -h host_ip version shell> mysqladmin --protocol=socket --socket=/tmp/mysql.sock version
Note the use of backticks 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.
If you have no hostname
command or are running on Windows, you can
manually type the hostname of your machine (without backticks) following the
-h
option.
You can also try -h 127.0.0.1
to connect with TCP/IP to the local host.
Here are some reasons the Can't connect to local MySQL server
error might occur:
mysqld
is not running. Check your operating system's process list to
ensure the mysqld
process is present.
mysqld
uses the MIT-pthreads package. See section 2.1.1 Operating Systems Supported by MySQL. However,
not all MIT-pthreads versions support Unix socket files. On a system
without socket file 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
(`/tmp/mysql.sock' by default). For example, you might have a cron
job that
removes old files from the `/tmp' directory. You can always run
mysqladmin version
to check whether the Unix socket file that
mysqladmin
is trying to use really exists. The fix in this case is
to change the cron
job to not remove `mysql.sock' or to place
the socket file 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, but forgotten to tell client
programs the new name of the socket file. If you change the socket
pathname for the server, you must also notify the MySQL clients.
You can do this by providing the same --socket
option when you run
client programs. You also need to ensure that clients have permission to access
the `mysql.sock' file.
To find out where the mysql server socket is, you can do:
shell> netstat -l | grep mysqlSee section A.4.5 How to Protect or Change the MySQL Socket File `/tmp/mysql.sock'.
mysqld
threads (for example, with kill
or with the mysql_zap
script) before you can restart the MySQL
server. See section A.4.2 What to Do If MySQL Keeps Crashing.
mysqld
with a --socket
option that specifies a socket filename
in a directory where the server can create it and where client programs can
access it.
If you get the error message Can't connect to MySQL server on
some_host
, you can try the following things to find out what the
problem is:
telnet
some_host 3306
and pressing the Enter key a couple of times. (3306 is the
default MySQL port number. Change the value if your server is listening to a
different port.) If there is a MySQL server running and listening to the
port, you should get a response that includes the server's version number.
If you get an error such as telnet: Unable to connect to remote host:
Connection refused
, then there is no server running on the given port.
mysqladmin -h
localhost variables
to connect using the Unix socket file. Verify the
TCP/IP port number that the server is configured to listen to (it is the
value of the port
variable.)
mysqld
server was not started with the
--skip-networking
option. If it was, you will not be able to connect
to it using TCP/IP.
Client does not support authentication protocol
MySQL 4.1 and up uses an authentication protocol based on a password hashing algorithm that is incompatible with that used by older clients. If you upgrade the server to 4.1, attempts to connect to it with an older client may fail with the following message:
shell> mysql Client does not support authentication protocol requested by server; consider upgrading MySQL client
To solve this problem, you should use one of the following approaches:
SET PASSWORD
statement and the OLD_PASSWORD()
function:
mysql> SET PASSWORD FOR -> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');Alternatively, use
UPDATE
and FLUSH PRIVILEGES
:
mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd') -> WHERE Host = 'some_host' AND User = 'some_user'; mysql> FLUSH PRIVILEGES;Substitute the password you want to use for ``newpwd'' in the preceding examples. MySQL cannot tell you what the original password was, so you'll need to pick a new one.
mysqld
with the --old-passwords
option.
mysql> SELECT Host, User, Password FROM mysql.user -> WHERE LENGTH(Password) > 16;For each account record displayed by the query, use the
Host
and User
values and assign
a password using the OLD_PASSWORD()
function and either SET PASSWORD
or UPDATE
, as described
earlier.
For additional background on password hashing and authentication, see section 5.5.9 Password Hashing in MySQL 4.1.
MySQL client programs prompt for a password when invoked with a
--password
or -p
option that has no following password value:
shell> mysql -u user_name -p Enter password:
On some systems, you may find that your password works when specified in an
option file or on the command line, but not when you enter it interactively
at the Enter password:
prompt. This occurs when the library provided
by the system to read passwords limits password values to a small number of
characters (typically eight). That is a problem with the system library, not
with MySQL. To work around it, change your MySQL password to
a value that is eight or fewer characters long, or put your password in an
option file.
Host 'host_name' is blocked
If you get the following error, it means that mysqld
has received many
connect requests from the host 'host_name'
that have been
interrupted in the middle:
Host 'host_name' is blocked because of many connection errors. Unblock with 'mysqladmin flush-hosts'
The number of interrupted connect requests allowed is determined by the
value of the max_connect_errors
system variable. After
max_connect_errors
failed requests, mysqld
assumes that
something is wrong (for example, that someone is trying to break in), and
blocks the host from further connections until you execute a
mysqladmin flush-hosts
command or issue a FLUSH HOSTS
statement.
See section 5.2.3 Server System Variables.
By default, mysqld
blocks a host after 10 connection errors.
You can adjust the value by starting the server like this:
shell> mysqld_safe --max_connect_errors=10000 &
If you get this error message for a given host, you should first
verify that there isn't anything wrong with TCP/IP connections from that
host. If you are having network problems, it will do you no good to
increase the value of the max_connect_errors
variable.
Too many connections
If you get a Too many connections
error when you try to connect to the
mysqld
server, this means that all available connections
are in use by other clients.
The number of connections allowed is controlled by the max_connections
system variable. Its default value is 100. If you need to support more
connections, you should restart mysqld
with a larger value for this
variable.
mysqld
actually allows max_connections+1
clients to
connect. The extra connection is reserved for use by accounts that have the
SUPER
privilege. By granting the SUPER
privilege to
administrators and not to normal users (who should not need it), an
administrator can connect to the server and use SHOW PROCESSLIST
to
diagnose problems even if the maximum number of unprivileged clients
are connected.
See section 13.5.4.15 SHOW PROCESSLIST
Syntax.
The maximum number of connections MySQL can support depends on the quality of the thread library 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. Static Linux binaries provided by MySQL AB can support up to 4000 connections.
Out of memory
If you issue a query using the mysql
client program and receive an
error like the following one, it means that mysql
does not
have enough memory to store the entire query result:
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
To remedy the problem, first check whether your query is correct. Is it
reasonable that it should return so many rows? If not, correct the query and
try again. Otherwise, you can invoke mysql
with the --quick
option. This causes it to use the mysql_use_result()
C API function
to retrieve the
result set, which places less of a load on the client (but more on the
server).
MySQL server has gone away
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. In this case,
you normally get one of the following error codes (which one you get is
operating system-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. |
By default, the
server closes the connection after eight hours if nothing has happened. You
can change the time limit by setting the wait_timeout
variable when
you start mysqld
.
See section 5.2.3 Server System Variables.
If you have a script, you just have to issue the query again for the client
to do an automatic reconnection. This assumes that you have automatic
reconnection in the client enabled (which is the default for the mysql
command-line client).
Some other common reasons for the MySQL server has gone away
error are:
KILL
statement or a mysqladmin kill
command.
mysql_options(..., MYSQL_OPT_READ_TIMEOUT,...)
or
mysql_options(..., MYSQL_OPT_WRITE_TIMEOUT,...)
. In this case
increasing the timeout may help solve the problem.
reconnect
flag
in the MYSQL
structure is equal to 0).
wait_timeout
expired) before the command was
issued.
The problem on windows is that in some cases MySQL doesn't get an error
from the OS when writing to the TCP/IP connection to the server, but
instead gets the error when trying to read the answer from connection.
In this case, even if the reconnect
flag in the MYSQL
structure
is equal to 1, MySQL will not automatically reconnect and re-issue the query as
it doesn't know if the server did get the original query or not.
The solution to this is to either do a mysql_ping
on the
connection if there has been a long time since the last query (this is
what MyODBC
does) or set wait_timeout
on the mysqld
server so high that it will in practice never time out.
mysqld
receives 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
setting the server's max_allowed_packet
variable, which has a default
value of 1MB. You may also need to increase the maximum packet size on the
client end. More information on setting the packet size is given in
section A.2.9 Packet too large
.
MySQL server has gone away
error if MySQL
is started with the --skip-networking
option.
You can check whether the MySQL server died and restarted by executing
mysqladmin version
and examining the server's uptime. If the
client connection was broken because mysqld
crashed and restarted,
you should concentrate on finding the reason for the crash. Start by
checking whether issuing the query again kills the server again.
See section A.4.2 What to Do If MySQL Keeps Crashing.
You can get more information about the lost connections by starting
mysqld with the --log-warnings=2
option. This will log some of the
disconnected errors in the hostname.err
file. See section 5.9.1 The Error Log.
If you want to create a bug report regarding this problem, be sure that you include the following information:
mysqld
and the tables involved were
checked with CHECK TABLE
before you ran the query, can you provide a
reproducible test case?
See section E.1.6 Making a Test Case If You Experience Table Corruption.
wait_timeout
system variable in the MySQL
server? (mysqladmin variables
gives you the value of this variable.)
mysqld
with the --log
option to
determine whether the problem query appears in the log?
See also See section A.2.10 Communication Errors and Aborted Connections.
See section 1.4.1.2 Asking Questions or Reporting Bugs.
Packet too large
A communication packet is a single SQL statement sent to the MySQL server or a single row that is sent to the client.
In MySQL 3.23, the largest possible packet is 16MB, due to limits in the client/server protocol. In MySQL 4.0.1 and up, the limit is 1GB.
When a MySQL client or the mysqld
server receives 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 a Lost connection to MySQL server during query
error if the
communication packet is too large.
Both the client and the server have their own
max_allowed_packet
variable, so if you want to handle big packets,
you must increase this variable both in the client and in the server.
If you are using the mysql
client program, its default
max_allowed_packet
variable is 16MB. That is also the maximum value
before MySQL 4.0. To set a larger value from 4.0 on, start mysql
like
this:
mysql> mysql --max_allowed_packet=32M
That sets the packet size to 32MB.
The server's default max_allowed_packet
value is 1MB. You can increase
this if the server needs to handle big queries (for example, if you are
working with big BLOB
columns). For example, to set the variable to
16MB, start the server like this:
mysql> mysqld --max_allowed_packet=16M
Before MySQL 4.0, use this syntax instead:
mysql> mysqld --set-variable=max_allowed_packet=16M
You can also use an option file to set max_allowed_packet
. For
example, to set the size for the server to 16MB, add the following lines in
an option file:
[mysqld] max_allowed_packet=16M
Before MySQL 4.0, use this syntax instead:
[mysqld] set-variable = max_allowed_packet=16M
It's safe to increase the value of this variable because the extra memory is
allocated only when needed. For example, mysqld
allocates more
memory only when you issue a long query or when mysqld
must return a
large result row. The small default value of the variable is a
precaution to catch incorrect packets between the client and server and also
to ensure that you don't run out of memory by using large packets
accidentally.
You can also get strange problems with large packets if you are using large
BLOB
values but have not 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 mysqld_safe
script
and restarting mysqld
.
The server error log can be a useful source of information about connection
problems.
See section 5.9.1 The Error Log.
Starting with MySQL 3.23.40, if you start the server with the
--warnings
option (or --log-warnings
from MySQL 4.0.3 on), you
might find messages like this in your error log:
010301 14:38:23 Aborted connection 854 to db: 'users' user: 'josh'
If Aborted connections
messages appear in the error log, the cause
can be any of the following:
mysql_close()
before exiting.
wait_timeout
or
interactive_timeout
seconds without issuing any requests to the server.
See section 5.2.3 Server System Variables.
When any of these things happen, the server increments the
Aborted_clients
status variable.
The server increments the Aborted_connects
status variable when the
following things happen:
connect_timeout
seconds to get
a connect packet.
See section 5.2.3 Server System Variables.
If these kinds of things happen, it might indicate that someone is trying to break into your server!
Other reasons for problems with aborted clients or aborted connections:
max_allowed_packet
variable value is too small or queries require
more memory than you have allocated for mysqld
.
See section A.2.9 Packet too large
.
See also See section A.2.8 MySQL server has gone away
.
The table is full
There are several ways a full-table error can occur:
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 SQL_BIG_TABLES
before you issue the problematic query.
See section 13.5.3 SET
Syntax.
You can also start mysqld
with the --big-tables
option.
This is exactly the same as using SQL_BIG_TABLES
for all queries.
As of MySQL 3.23, this problem should not occur. If an in-memory temporary
table becomes larger than tmp_table_size
, the server automatically
converts it to a disk-based MyISAM
table.
InnoDB
tables and run out of room in the
InnoDB
tablespace. In this case, the solution is to extend the
InnoDB
tablespace.
See section 15.8 Adding and Removing InnoDB
Data and Log Files.
ISAM
or MyISAM
tables on an operating system
that supports files only up to 2GB in size and you have hit this limit for the
data file or index file.
MyISAM
table and the space required for the table
exceeds what is allowed by the internal pointer size. (If you don't specify
the MAX_ROWS
table option when you create a table, MySQL
uses the myisam_data_pointer_size
system variable. Its default value of
4 bytes is enough to allow only 4GB of data.)
See section 5.2.3 Server System Variables.
You can check the maximum data/index sizes by using this statement:
SHOW TABLE STATUS FROM database LIKE 'tbl_name';You also can use
myisamchk -dv /path/to/table-index-file
.
If the pointer size is too small, you can fix the problem by using ALTER
TABLE
:
ALTER TABLE tbl_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;You have to specify
AVG_ROW_LENGTH
only for tables with BLOB
or TEXT
columns; in this case, MySQL can't optimize the space
required based only on the number of rows.
Can't create/write to file
If you get an error of the following type for some queries, it means that MySQL cannot create a temporary file for the result set in the temporary directory:
Can't create/write to file '\\sqla3fe_0.ism'.
The preceding error is a typical message for Windows; the Unix message is similar.
One fix is to start mysqld
with the --tmpdir
option or to
add the option to the [mysqld]
section of your option file.
For example, to specify a directory of `C:\temp', use these lines:
[mysqld] tmpdir=C:/temp
The `C:\temp' directory must exist and have sufficient space for the MySQL server to write to. See section 4.3.2 Using Option Files.
Another cause of this error can be permissions issues. Make sure that the MySQL
server can write to the tmpdir
directory.
Check also the error code that you get with perror
. One reason
the server cannot write to a table is that the filesystem is full:
shell> perror 28 Error code 28: No space left on device
Commands out of sync
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
calling mysql_use_result()
or mysql_store_result()
in between.
Ignoring user
If you get the following error, it means that when mysqld
was started
or when it reloaded the grant tables, it found an account in the user
table that had an invalid password.
Found wrong password for user 'some_user'@'some_host'; ignoring user
As a result, the account is simply ignored by the permission system.
The following list indicates 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
whether the Password
column 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 account in the user
table to have a new password or
restart mysqld
with the --old-protocol
option.
user
table without using the
PASSWORD()
function. Use mysql
to update the account in the
user
table with a new password, making sure to use the PASSWORD()
function:
mysql> UPDATE user SET Password=PASSWORD('newpwd') -> WHERE User='some_user' AND Host='some_host';
Table 'tbl_name' doesn't exist
If you get either of the following errors, it usually means that no table exists in the current database with the given name:
Table 'tbl_name' doesn't exist Can't find file: 'tbl_name' (errno: 2)
In some cases, it may be that the table does exist but that you are referring to it incorrectly:
You can check which tables are in the current database with
SHOW TABLES
. See section 13.5.4 SHOW
Syntax.
Can't initialize character set
You might see an error like this if you have character set problems:
MySQL Connection Failed: Can't initialize character set charset_name
This error can have any of the following causes:
configure
with the --with-charset=charset_name
or
--with-extra-charsets=charset_name
option.
See section 2.8.2 Typical configure
Options.
All standard MySQL binaries are compiled with
--with-extra-character-sets=complex
, which enables support for
all multi-byte character sets. See section 5.8.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 use one of the following methods to solve the problem:
configure
Options.
--character-sets-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
the MySQL server. You can use the perror
utility to get a
description of what the error number means:
shell> perror 23 Error code 23: File table overflow shell> perror 24 Error code 24: Too many open files shell> perror 11 Error code 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 reducing the value of the table_cache
system
variable (the default value is 64). Reducing the value of
max_connections
also will reduce the number of open files (the
default value is 100).
To change the number of file descriptors available to mysqld
, you can
use the --open-files-limit
option to mysqld_safe
or (as of
MySQL 3.23.30) set the open_files_limit
system variable.
See section 5.2.3 Server System Variables.
The easiest way to set these values is to add an option to your option file.
See section 4.3.2 Using Option Files. If you have an old version of mysqld
that
doesn't support setting the open files limit, you can edit the
mysqld_safe
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 set the number of file
descriptors to be made available to mysqld
.
--open-files-limit
and ulimit
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 be overridden only if you start
mysqld_safe
or mysqld
as root
(just remember that you
also need to start the server with the --user
option in this case so
that it does not continue to run as root
after it starts up).
If you need to increase the operating system limit on the number of file
descriptors available to each process, consult the documentation for your
system.
Note: 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 mysqld_safe
using sh
.
When you are linking an application program to use the MySQL client library,
you might get undefined reference errors for symbols that start with mysql_
,
such as those shown here:
/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 problem by adding -Ldir_path
-lmysqlclient
at the end of your link command, where dir_path
represents the pathname of the directory where the client library is
located. To determine the correct directory, try this command:
shell> mysql_config --libs
The output from mysql_config
might indicate other libraries that
should be specified on the link command as well.
If you get undefined reference
errors for the uncompress
or compress
function, add -lz
to the end of your
link command and try again.
If you get undefined reference
errors for a function that should
exist on your system, such as connect
, check the manual page for the
function in question to determine which libraries you should add to the link
command.
You might get undefined reference
errors such as the following for
functions that don't exist on your system:
mf_format.o(.text+0x201): undefined reference to `__lxstat'
This usually means that your MySQL client library was compiled on a system that is not 100% compatible with yours. In this case, you should download the latest MySQL source distribution and compile MySQL yourself. See section 2.8 MySQL Installation Using a Source Distribution.
You might get undefined reference errors at runtime when you try to execute a
MySQL program. If these errors specify symbols that start with mysql_
or indicate that the mysqlclient
library can't be found, it means
that your system can't find the shared `libmysqlclient.so' library.
The fix for this is to tell your system to search for shared libraries
where the library is located. Use whichever of the following methods is
appropriate for your system:
LD_LIBRARY_PATH
environment variable.
LD_LIBRARY
environment variable.
ldconfig
.
Another way to solve this problem is by linking your program statically with
the -static
option, or by removing the dynamic MySQL libraries
before linking your code. Before trying the second method, you should be
sure that no other programs are using the dynamic libraries.
On Windows, you can run the server as a Windows service using normal user accounts beginning with MySQL 4.0.17 and 4.1.2. (Older MySQL versions required you to have administrator rights. This was a bug introduced in MySQL 3.23.54.)
On Unix, the MySQL server mysqld
can be started and run by any user.
However, you should avoid running the server as the Unix root
user
for security reasons. In order to change mysqld
to run as a normal
unprivileged Unix user user_name, you must do the following:
mysqladmin shutdown
).
root
user):
shell> chown -R user_name /path/to/mysql/datadirIf you do not do this, the server will not be able to access databases or tables when it runs as user_name. If directories or files within the MySQL data directory are symbolic links, you'll also need to follow those links and change the directories and files they point to.
chown -R
might not follow symbolic links for you.
mysqld
as the Unix root
user and use the --user=user_name
option. mysqld
will start up,
then switch
to run as the Unix user user_name before accepting any connections.
user
option 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
If your Unix machine itself isn't secured, you should assign passwords
to the MySQL root
accounts in the grant tables. Otherwise, any
user with a login account on that machine can run the mysql
client with a
--user=root
option and perform any operation. (It is a good idea to
assign passwords to MySQL accounts in any case, but especially so when
other login accounts exist on the server host.)
See section 2.9 Post-Installation Setup and Testing.
If you have problems with file permissions, the UMASK
environment
variable might be set incorrectly when mysqld
starts. For example,
MySQL might issue the following error message when you create a table:
ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)
The default UMASK
value is 0660
. You can change this behavior by
starting mysqld_safe
as follows:
shell> UMASK=384 # = 600 in octal shell> export UMASK shell> mysqld_safe &
By default, MySQL creates database and RAID
directories
with an access permission value of 0700
. You can modify this
behavior by setting the UMASK_DIR
variable. If you set its value, new
directories are created with the combined UMASK
and UMASK_DIR
values. For example, if you want to give group access to all new
directories, you can do this:
shell> UMASK_DIR=504 # = 770 in octal shell> export UMASK_DIR shell> mysqld_safe &
In MySQL 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.
If you have never set a root
password for MySQL, the server will
not require a password at all for connecting as root
. However, it is
recommended to set a password for each account. See section 5.4.1 General Security Guidelines.
If you set a root
password previously, but have forgotten what it
was, you can set a new password. The following procedure is for Windows
systems. The procedure for Unix systems is given later in this section.
The procedure under Windows:
Start Menu -> Control Panel -> Administrative Tools -> ServicesThen find the MySQL service in the list, and stop it. If your server is not running as a service, you may need to use the Task Manager to force it to stop.
Start Menu -> Run -> cmd
C:\> C:\mysql\bin\mysqld-nt --skip-grant-tablesThis starts the server in a special mode that does not check the grant tables to control access.
C:\> C:\mysql\bin\mysqladmin -u root flush-privileges password "newpwd" C:\> C:\mysql\bin\mysqladmin -u root -p shutdownReplace ``newpwd'' with the actual
root
password that you want
to use.
The second command will prompt you to enter the new password for access.
Enter the password that you assigned in the first command.
In a Unix environment, the procedure for resetting the root
password
is as follows:
root
user or as the
same user that the mysqld
server runs as.
kill
(not kill -9
) to the mysqld
process, using the pathname of the
`.pid' file in the following command:
shell> kill `cat /mysql-data-directory/host_name.pid`Note the use of backticks rather than forward quotes with the
cat
command; these cause the output of cat
to be substituted into the kill
command.
--skip-grant-tables
option:
shell> mysqld_safe --skip-grant-tables &
root@localhost
MySQL account:
shell> mysqladmin -u root flush-privileges password "newpwd"Replace ``newpwd'' with the actual
root
password that you want
to use.
Alternatively, on any platform, you can set the new password using the mysql
client:
mysqld
and restart it with the --skip-grant-tables
option as described earlier.
mysqld
server with this command:
shell> mysql -u root
mysql
client:
mysql> UPDATE mysql.user SET Password=PASSWORD('newpwd') -> WHERE User='root'; mysql> FLUSH PRIVILEGES;Replace ``newpwd'' with the actual
root
password that you want
to use.
Each MySQL version is tested on many platforms before it is released. This doesn't mean that there are no bugs in MySQL, but if there are bugs, they should be 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, because you will have a much better chance of getting the problem fixed quickly.
First, you should try to find out whether the problem is that the mysqld
server 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 and
restarted, you may find the reason by looking in the server's error log.
See section 5.9.1 The Error Log.
On some systems, you can find in the error log a stack trace of where
mysqld
died that you can resolve with the resolve_stack_dump
program. See section E.1.4 Using a Stack Trace. Note that the variable values written in
the error log may not always be 100% correct.
Many server crashes are caused by corrupted data files or index files. MySQL
will update the files 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
data files are written but not index files.) This means that data file
contents are safe even
if mysqld
crashes, because the operating system will ensure that the
unflushed data is written to disk. You can force MySQL to flush everything
to disk after every SQL statement by starting mysqld
with the
--flush
option.
The preceding means that normally you should not get corrupted tables unless one of the following happens:
mysqld
that caused it to die in the
middle of an update.
mysqld
without locking the table properly.
mysqld
servers using the same data directory on
a system that doesn't support good filesystem locks (normally handled by the
lockd
lock manager), or you are running multiple servers with the
--skip-external-locking
option.
mysqld
.
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
server with mysqladmin shutdown
, run
myisamchk --silent --force */*.MYI
from the data directory to check
all MyISAM
tables, and restart mysqld
. This will ensure that
you are running from a clean state.
See section 5 Database Administration.
mysqld
with the --log
option and try to determine
from the information written to the log whether some specific query kills
the server. About 95% of all bugs are related to a particular query.
Normally, this will be one of the last queries in the log file just before
the server restarts.
See section 5.9.2 The General Query Log.
If you can repeatedly kill MySQL with a specific query, even
when you have checked all tables just before issuing it, then you
have been able to locate the bug and should submit a bug report for it.
See section 1.4.1.3 How to Report Bugs or Problems.
fork_big.pl
script. (It is located in the `tests'
directory of source distributions.)
--with-debug
or --with-debug=full
option 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 two mysqld
servers on the same
data directory and that you must be careful if you use myisamchk
.
Nevertheless, 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 -u root processlist
usually will 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
in a separate window to produce statistics while you run
your other queries.
mysqld
from gdb
(or another debugger).
See section E.1.3 Debugging mysqld
under gdb
.
gdb
, you can do this with the following commands when 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.
VARCHAR
columns (not BLOB
or TEXT
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 several years
with very few problems, but dynamic-length rows are by nature more prone to
errors, so it may be a good idea to try this strategy to see whether it helps.
This section describes how MySQL responds to disk-full errors (such as ``no space left on device''), and, as of MySQL 4.0.22, to quota-exceeded errors (such as ``write failed'' or ``user block limit reached").
This section is relevant for writes to MyISAM
tables. As of MySQL
4.1.9, it also applies for writes to binary log files and binary log index
file, except that references to ``row'' and ``record'' should be understood
to mean ``event.''
When a disk-full condition occurs, MySQL does the following:
To alleviate the problem, you can take the following actions:
mysqladmin kill
.
The thread will be aborted the next time it checks the disk (in one minute).
Exceptions to the preceding behavior are when you use REPAIR TABLE
or
OPTIMIZE TABLE
or when the indexes are created in a batch after
LOAD DATA INFILE
or after an ALTER TABLE
statement.
All of these statements may create large temporary files that, if left to
themselves, would cause big problems for the rest of the system. If the disk
becomes full while MySQL is doing any of these operations,
it will remove the big temporary files and mark the table as crashed.
The exception is that for ALTER TABLE
, 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', `/var/tmp', or `/usr/tmp'. If the filesystem
containing your temporary file directory is too small, you can use the
--tmpdir
option to mysqld
to specify a directory in a
filesystem where you have enough space.
Starting from MySQL 4.1, the --tmpdir
option can be set to a list
of several paths that are used in round-robin fashion. Paths should be
separated by colon characters (`:') on Unix and semicolon characters
(`;') on Windows, NetWare, and OS/2. Note: To spread the load
effectively, these paths should be located on different
physical disks, not different partitions of the same disk.
If the MySQL server is acting as a replication slave, you should not set
--tmpdir
to point to a directory on a memory-based filesystem or to a
directory that is cleared when the server host restarts. A replication
slave needs some of its temporary files to survive a machine restart so that
it can replicate temporary tables or LOAD DATA INFILE
operations. If
files in the temporary file directory are lost when the server restarts,
replication will fail.
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 required is determined
by the following expression:
(length of what is sorted + sizeof(row pointer)) * number of matched rows * 2
The row pointer size is usually four bytes, 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.
The default location for the Unix socket file that the server uses for communication with local clients is `/tmp/mysql.sock'. This might cause problems, because on some versions of Unix, anyone can delete files in the `/tmp' directory.
On most versions of Unix, you can protect your `/tmp' directory so that
files can be deleted only by their owners or the superuser (root
).
To do this, set the sticky
bit on the `/tmp' directory by
logging in as root
and using the following command:
shell> chmod +t /tmp
You can check whether the sticky
bit is set by executing ls -ld
/tmp
. If the last permission character is t
, the bit is set.
Another approach is to change the place where the server creates the Unix socket file. If you do this, you should also let client programs know the new location of the file. You can specify the file location in several ways:
/etc/my.cnf
:
[mysqld] socket=/path/to/socket [client] socket=/path/to/socketSee section 4.3.2 Using Option Files.
--socket
option on the command line
to mysqld_safe
and when you run client programs.
MYSQL_UNIX_PORT
environment variable to the path of the Unix
socket file.
--with-unix-socket-path
option when you run configure
.
See section 2.8.2 Typical configure
Options.
You can test whether the new socket location works by attempting to connect to the server 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 tell the server your current time zone.
The same applies if UNIX_TIMESTAMP()
returns the wrong value.
This should be done for the environment in which the server runs; for
example, in mysqld_safe
or mysql.server
.
See section F Environment Variables.
You can set the time zone for the server with the
--timezone=timezone_name
option to mysqld_safe
. You can
also set it by setting the TZ
environment variable before you
start mysqld
.
The allowable values for --timezone
or TZ
are
system-dependent. Consult your operating system documentation to see
what values are acceptable.
By default, MySQL searches are not case sensitive (although there are
some character sets that are never case insensitive, such as czech
).
This 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, make sure that one of the operands is a binary string.
You can do this with the BINARY
operator. Write the condition as either
BINARY col_name LIKE 'a%'
or col_name LIKE BINARY 'a%'
.
If you want a column always to be treated in case-sensitive fashion,
declare it as BINARY
. See section 13.2.6 CREATE TABLE
Syntax.
Simple comparison operations (>=, >, =, <, <=
, sorting, and grouping)
are based on each character's ``sort value.'' Characters with the same
sort value (such as `E', `e', and `é') are treated as the
same character.
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. As of MySQL 4.1, you can explicitly declare that a column should
use the big5
character set:
CREATE TABLE t (name CHAR(40) CHARACTER SET big5);
DATE
Columns
The format of a DATE
value is 'YYYY-MM-DD'
. According to
standard 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 >= '2003-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
DATETIME
column. (``Relaxed form'' means that any punctuation character
may be used as the separator between parts. For example, '2004-08-15'
and '2004#08#15'
are equivalent.) MySQL can also convert a
string containing no separators (such as '20040815'
), 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 is automatically converted to NULL
in
MyODBC 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,'20030505')=0;
STRCMP()
is a string function, so it converts idate
to a
string in 'YYYY-MM-DD'
format and performs a string comparison.
It does not convert '20030505'
to the date '2003-05-05'
and perform a date comparison.
If you are using the ALLOW_INVALID_DATES
SQL mode, MySQL allows you to
store dates that are given only limited checking: MySQL ensures only that the
day is in the range from 1 to 31 and the month is in the range from 1 to 12.
This makes MySQL very convenient for Web applications where you obtain year, month, and day in three different fields and you want to store exactly what the user inserted (without date validation).
If you are not using the NO_ZERO_IN_DATE
SQL mode, the day or month
part can be zero. This is convenient if you want to store a birthdate
in a DATE
column and you know only part of the date.
If you are not using the NO_ZERO_DATE
SQL mode, MySQL also allows
you to store '0000-00-00'
as a ``dummy date.'' This is in some cases
more convenient than using NULL
values.
If the date cannot be converted to any reasonable value, a 0
is
stored in the DATE
column, which will be retrieved as
'0000-00-00'
. This is both a speed and a convenience issue. We believe
that the database server's responsibility 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 and not the server to check the dates.
If you want MySQL to check all dates and accept only legal dates
(unless overriden by IGNORE), you should set sql_mode
to
"NO_ZERO_IN_DATE,NO_ZERO_DATE"
.
Date handling in MySQL 5.0.1 and earlier works like MySQL 5.0.2 with the
ALLOW_INVALID_DATES
SQL mode enabled.
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 ``the person is known to have no
phone, and thus no phone number.''
To help with NULL
handling, you can use the IS NULL
and
IS NOT NULL
operators and the IFNULL()
function.
In SQL, the NULL
value is never true 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 an expr = NULL
test. The following statement returns no
rows, because expr = NULL
is never true 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 statements show 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 = '';
You can add an index on a column that can have NULL
values if you are using MySQL 3.23.2 or newer and are using the
MyISAM
, InnoDB
, or BDB
storage engine.
As of MySQL 4.0.2, the MEMORY
storage engine also supports NULL
values in indexes. Otherwise, you must declare an indexed column NOT
NULL
and you cannot insert NULL
into the column.
When reading data with LOAD DATA INFILE
, empty or missing columns
are updated with ''
. If you want a NULL
value in a column,
you should use \N
in the data file. The literal word ``NULL
''
may also be used under some circumstances.
See section 13.1.5 LOAD DATA INFILE
Syntax.
When using DISTINCT
, GROUP BY
, or ORDER BY
, all
NULL
values are regarded as equal.
When using ORDER BY
, NULL
values are presented first, or
last if you specify DESC
to sort in descending order. Exception:
In MySQL 4.0.2 through 4.0.10, NULL
values sort first
regardless of sort order.
Aggregate (summary) functions such as COUNT()
, MIN()
, and
SUM()
ignore NULL
values. The exception to this is
COUNT(*)
, which counts rows and not individual column values.
For example, the following statement produces two counts.
The first is a count of the number of rows in the table, and the second
is a count of the number of non-NULL
values in the age
column:
mysql> SELECT COUNT(*), COUNT(age) FROM person;
For some column types, MySQL handles NULL
values specially. If you
insert NULL
into a TIMESTAMP
column, the
current date and time is inserted. If you insert NULL
into an
integer column that has the AUTO_INCREMENT
attribute, the next
number in the sequence is inserted.
You can use an alias to refer to a column in GROUP BY
,
ORDER BY
, or HAVING
clauses. Aliases can also be used
to give columns better names:
SELECT SQRT(a*b) AS root FROM tbl_name GROUP BY root HAVING root > 0; SELECT id, COUNT(*) AS cnt FROM tbl_name GROUP BY id HAVING cnt > 0; SELECT id AS 'Customer identity' FROM tbl_name;
Standard SQL doesn't allow you to refer to a column 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 tbl_name WHERE cnt > 0 GROUP BY id;
The WHERE
statement is executed to determine which rows should
be included in the GROUP BY
part, whereas HAVING
is used to
decide which rows from the result set should be used.
If you receive the following message when trying to perform a
ROLLBACK
, it means that one or more of the tables you used in the
transaction do not support transactions:
Warning: Some non-transactional changed tables couldn't be rolled back
These non-transactional tables will not be affected by the ROLLBACK
statement.
If you were not deliberately mixing transactional and non-transactional
tables within the transaction, the most likely cause for this message is
that a table you thought was transactional actually is not. This can happen
if you try to create a table using a transactional storage engine that is
not supported by your mysqld
server (or that was disabled with a
startup option). If mysqld
doesn't support a storage engine, it will
instead create the table as a MyISAM
table, which is
non-transactional.
You can check the table type for a table by using either of these statements:
SHOW TABLE STATUS LIKE 'tbl_name'; SHOW CREATE TABLE tbl_name;
See section 13.5.4.17 SHOW TABLE STATUS
Syntax and
section 13.5.4.5 SHOW CREATE TABLE
Syntax.
You can check which storage engines your mysqld
server supports by
using this statement:
SHOW ENGINES;
Before MySQL 4.1.2, SHOW ENGINES
is unavailable. Use the following
statement instead and check the value of the variable that is associated
with the storage engine in which you are interested:
SHOW VARIABLES LIKE 'have_%';
For example, to determine whether the InnoDB
storage engine is
available, check the value of the have_innodb
variable.
See section 13.5.4.8 SHOW ENGINES
Syntax and
section 13.5.4.19 SHOW VARIABLES
Syntax.
MySQL does not support subqueries prior to Version 4.1, or the use of more
than one table in the DELETE
statement prior to Version 4.0. If your
version of MySQL does not support subqueries or multiple-table DELETE
statements, you can use the following approach to delete rows from two
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 length of the DELETE
statement for related_table
is
more than 1MB (the default value of the max_allowed_packet
system
variable), you should split it into smaller parts and execute multiple
DELETE
statements. You will probably get the fastest DELETE
by specifying only 100 to 1,000 related_column
values per statement if the
related_column
is indexed. If the related_column
isn't
indexed, the speed is independent of the number of arguments in the
IN
clause.
If you have a complicated query that uses many tables but that doesn't return any rows, you should use the following procedure to find out what is wrong:
EXPLAIN
to check whether you can find something
that is obviously wrong.
See section 7.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 equality (=
) comparisons. This problem
is common in most computer languages because not all floating-point values
can be stored with exact precision. In some cases, changing the
FLOAT
to a DOUBLE
will fix this.
See section A.5.8 Problems with Floating-Point Comparisons.
mysql test < query.sql
that shows your problems. You can
create a test file by dumping the tables with mysqldump --quick
db_name tbl_name_1 ... tbl_name_n > query.sql
. Open the file in an editor,
remove some insert lines (if there are more than needed to demonstrate
the problem), and add your SELECT
statement at the end of the file.
Verify that the test file demonstrates the problem by executing these
commands:
shell> mysqladmin create test2 shell> mysql test2 < query.sqlPost the test file using
mysqlbug
to the general MySQL mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
Floating-point numbers sometimes cause confusion because they
are not stored as exact values inside computer architecture. What you
can see on the screen usually is not the exact value of the number.
The column types FLOAT
, DOUBLE
, and DECIMAL
are such.
DECIMAL
columns store values with exact precision because they are
represented as strings, but calculations on DECIMAL
values may be done
using floating-point operations.
The following example demonstrate the problem. It shows that even for the
DECIMAL
column type, calculations that are done using floating-point
operations are subject to floating-point error.
mysql> CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2)); mysql> 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 (the values of a
and b
do
not appear to be different), they may do so because the difference between
the numbers shows up around the tenth decimal or so, depending on computer
architecture.
The problem cannot be solved by using ROUND()
or similar functions,
because the result is still a floating-point number:
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 when displayed with more
decimal places:
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 your computer architecture, you may or may not see similar results. Different CPUs may evaluate floating-point numbers differently. For example, on some machines you may get the ``correct'' results by multiplying both arguments by 1, as the following example shows.
Warning: Never use this method in your applications. It is not an example of a trustworthy 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 that the preceding example seems to work is that on the particular machine where the test was done, CPU floating-point arithmetic happens to round the numbers to the same value. However, there is no rule that any CPU should do so, so this method cannot be trusted.
The correct way to do floating-point number comparison is to first decide on an acceptable tolerance for differences between the numbers and then do the comparison against the tolerance value. For example, if we agree that floating-point numbers should be regarded the same if they are same within a precision of one in ten thousand (0.0001), the comparison should be written to find differences larger than the tolerance value:
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)
Conversely, to get rows where the numbers are the same, the test should find differences within the tolerance value:
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 | +------+-------+-------+
MySQL uses a cost-based optimizer to determine the best way to resolve a query. In many cases, MySQL can calculate the best possible query plan, but sometimes MySQL doesn't have enough information about the data at hand and has to make ``educated'' guesses about the data.
For the cases when MySQL does not do the "right" thing, tools that you have available to help MySQL are:
EXPLAIN
statement to get information about how MySQL will
process a query. To use it, just add the keyword EXPLAIN
to the
front of your SELECT
statement:
mysql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.i = t2.i;
EXPLAIN
is discussed in more detail in section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
).
ANALYZE TABLE tbl_name
to update the key distributions for the
scanned table. See section 13.5.2.1 ANALYZE TABLE
Syntax.
FORCE INDEX
for the scanned table to tell MySQL that table
scans are very expensive compared to using the given index.
See section 13.1.7 SELECT
Syntax.
SELECT * FROM t1, t2 FORCE INDEX (index_for_column) WHERE t1.col_name=t2.col_name;
USE INDEX
and IGNORE INDEX
may also be useful.
STRAIGHT_JOIN
. See section 13.1.7 SELECT
Syntax.
mysqld
with the --max-seeks-for-key=1000
option or use
SET max_seeks_for_key=1000
to tell the optimizer to assume that no
key scan will cause more than 1,000 key seeks.
See section 5.2.3 Server System Variables.
ALTER TABLE
ALTER TABLE
changes a table to the current character set.
If you get a duplicate-key error during ALTER TABLE
, the cause
is either that the new character sets maps two keys to the same value
or that the table is corrupted. In the latter case, you should run
REPAIR TABLE
on the table.
If ALTER TABLE
dies with the following error, the problem may be that
MySQL crashed during an earlier ALTER TABLE
operation and there is an
old table named `A-xxx' or `B-xxx' lying around:
Error on rename of './database/name.frm' to './database/B-xxx.frm' (Errcode: 17)
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 in the following way:
If something goes wrong with the renaming operation, MySQL tries to undo the changes. If something goes seriously wrong (although this shouldn't happen), MySQL may leave the old table as `B-xxx'. A simple rename of the table files at the system level should get your data back.
If you use ALTER TABLE
on a transactional table or if you are using
Windows or OS/2, ALTER TABLE
will UNLOCK
the table if you had
done a LOCK TABLE
on it. This is because InnoDB
and these
operating systems cannot drop a table that is in use.
First, consider whether you really need to change the column order in a table. The whole point of SQL is to abstract the application from the data storage format. You should always specify the order in which you wish to retrieve your data. The first of the following statements returns columns in the order col_name1, col_name2, col_name3, whereas the second returns them in the order col_name1, col_name3, col_name2:
mysql> SELECT col_name1, col_name2, col_name3 FROM tbl_name; mysql> SELECT col_name1, col_name3, col_name2 FROM tbl_name;
If you decide to change the order of table columns anyway, you can do so as follows:
mysql> INSERT INTO new_table -> SELECT columns-in-new-order FROM old_table;
old_table
.
mysql> ALTER TABLE new_table RENAME old_table;
SELECT *
is quite suitable for testing queries. However, in an
application, you should never rely on using SELECT *
and
retrieving the columns based on their position. The order and position
in which columns are returned will not remain the same if you add, move,
or delete columns. A simple change to your table structure will cause
your application to fail.
TEMPORARY TABLE
Problems
The following list indicates limitations on the use of TEMPORARY
tables:
TEMPORARY
table can only be of type HEAP
, ISAM
,
MyISAM
, MERGE
, or InnoDB
.
TEMPORARY
table more than once in the same query.
For example, the following does not work:
mysql> SELECT * FROM temp_table, temp_table AS t2; ERROR 1137: Can't reopen table: 'temp_table'
SHOW TABLES
statement does not list TEMPORARY
tables.
RENAME
to rename a TEMPORARY
table. However,
you can use ALTER TABLE
instead:
mysql> ALTER TABLE orig_name RENAME new_name;
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!).
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.
MySQL
version 4.0.
DECIMAL
.
mysql_tableinfo
.
While MySQL AB owns all copyrights in the MySQL server
and the MySQL manual
, we wish to recognize 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 an 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.)
mysqldump
(previously msqldump
, but ported and enhanced by
Monty).
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.
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_setpermission
script.
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.
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 mailing lists:
DBD::mysql
questions.
xmysql
-related questions and basic installation questions.
mysqlbug
.
DBD
, Linux, some SQL syntax questions.
The following people has helped us with writing the MySQL documentation and translating the documentation or error messages in MySQL.
DBI
/DBD
section in the manual.
The following is a list of the creators of the libraries we have included with the MySQL server source to make it easy to compile and install MySQL. We are very thankfully to all individuals that have created these and it has made our life much easier.
WHERE column REGEXP regexp
.
--debug
.
readline
library (used by the mysql
command-line client).
libedit
package (optionally used by the mysql
command-line
client).
The following is a list of creators/maintainers of some of the most important API/packages/applications that a lot of people use with MySQL.
We can't list every possible package here because the list would then be way to hard to maintain. For other packages, please refer to the software portal at http://solutions.mysql.com/software/.
DBD
(Perl) interface.
DBD::mysql
module.
mysqli
extension (API) for use with MySQL 4.1 and up.
The following is a list of some of the tools we have used to create MySQL. We use this to express our thanks to those that has created them as without these we could not have made MySQL what it is today.
gcc
), an excellent
debugger (gdb
and the libc
library (from which we have
borrowed `strto.c' to get some code working in Linux).
valgrind
, an excellent memory checker tool that has helped
us find a lot of otherwise hard to find bugs in MySQL.
DDD
(The Data Display Debugger) which is an excellent
graphical frontend to gdb
).
While MySQL AB owns all copyrights in the MySQL server
and the MySQL manual
, we wish to recognize 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 section summarizes the features that we plan to implement in MySQL Server. The items are ordered by release series. Within a list, items are shown in approximately the order they will be done.
Note: If you are an enterprise-level user with an urgent need for a particular feature, please contact sales@mysql.com to discuss sponsoring options. Targeted financing by sponsor companies allows us to allocate additional resources for specific purposes. One example of a feature sponsored in the past is replication.
The following features are planned for inclusion into MySQL 5.0. Some of the features such as stored procedures are complete and are included in MySQL 5.0 alpha. Others such as cursors are only partially available. Expect these and other features to mature and be fully supported in upcoming releases.
Note that because we have many developers that are working on different projects, there will also be many additional features. There is also a small chance that some of these features will be added to MySQL 4.1. For a list what is done in MySQL 4.1, see section 1.3.2.1 Features Available in MySQL 4.1.
For those wishing to take a look at the bleeding edge of MySQL development, we make our BitKeeper repository for MySQL version 5.0 publicly available. See section 2.8.3 Installing from the Development Source Tree.
CREATE VIEW
Syntax.
MyISAM
tables that an index
should be created as an RTREE
index. (In MySQL 4.1, RTREE
indexes
are used internally for geometrical data that use GIS data types, but cannot be
created on request.)
MEMORY
tables.
INFORMATION_SCHEMA
.
See section 21 The INFORMATION_SCHEMA
Information Database.
VARCHAR
support (column lengths longer than 255, and
no stripping of trailing whitespace).
There is support for this in the MyISAM
storage engine,
but it is not available at the user level.
SHOW COLUMNS FROM tbl_name
(used by the mysql
client to allow
expansions of column names) should not open the table, only the
definition file. This will require less memory and be much faster.
DELETE
on MyISAM
tables to use the record cache.
To do this, we need to update the threads record cache when we update
the `.MYD' file.
MEMORY
tables:
RENAME TABLE
on a table used in an active
MERGE
table possibly corrupting the table.
The news section of this manual includes a more in-depth list of features. See section D.1 Changes in release 5.0.x (Development).
FOREIGN KEY
support for all table types, not just InnoDB
.
BIT
type to take one bit. (BIT
takes one byte;
it is treated as a synonym for TINYINT
.)
RENAME DATABASE
. To make this safe for all storage engines,
it should work as follows:
RENAME
command.
CONNECT BY PRIOR
to search tree-like (hierarchical)
structures.
SUM(DISTINCT)
.
INSERT SQL_CONCURRENT
and mysqld --concurrent-insert
to do
a concurrent insert at the end of a table if the table is read-locked.
UPDATE
statements. For example:
UPDATE foo SET @a:=a+b,a=@a, b=@a+c
.
GROUP BY
, as in the following statement:
SELECT id, @a:=COUNT(*), SUM(sum_col)/@a FROM tbl_name GROUP BY id
.
IMAGE
option to LOAD DATA INFILE
to not update
TIMESTAMP
and AUTO_INCREMENT
columns.
LOAD DATA INFILE ... UPDATE
syntax that works like this:
LOAD DATA INFILE ... REPLACE INTO
.
LOAD DATA INFILE
understand syntax like this:
LOAD DATA INFILE 'file_name.txt' INTO TABLE tbl_name TEXT_FIELDS (text_col1, text_col2, text_col3) SET table_col1=CONCAT(text_col1, text_col2), table_col3=23 IGNORE text_col3This can be used to skip over extra columns in the text file, or update columns based on expressions of the read data.
SET
type columns:
ADD_TO_SET(value,set)
REMOVE_FROM_SET(value,set)
mysql
in the middle of a query, you should open
another connection and kill the old running query.
Alternatively, an attempt should be made to detect this in the server.
SHOW INFO FROM tbl_name
for basic table information
should be implemented.
SELECT a FROM tbl_name1 LEFT JOIN tbl_name2 USING (a)
; in this
case a
is assumed to come from tbl_name1.
DELETE
and REPLACE
options to the UPDATE
statement
(this will delete rows when a duplicate-key error occurs while updating).
DATETIME
to store fractions of seconds.
regexp
library instead of the current
one (the new library should be much faster than the current one).
ANY()
, EVERY()
, and SOME()
group functions. In
standard SQL, these work only on boolean columns, but we can extend these to
work on any columns or expressions by treating a value of zero as FALSE and
non-zero values as TRUE.
MAX(column)
to be the same as the column type:
mysql> CREATE TABLE t1 (a DATE); mysql> INSERT INTO t1 VALUES (NOW()); mysql> CREATE TABLE t2 SELECT MAX(a) FROM t1; mysql> SHOW COLUMNS FROM t2;
MyISAM
recovery at the same time.
INSERT INTO ... SELECT
to optionally use concurrent inserts.
SELECT MIN(column) ... GROUP BY
.
long_query_time
with a granularity
in microseconds.
myisampack
code into the server so that it can perform
PACK
or COMPRESS
operations.
INSERT/DELETE/UPDATE
so that we
can gracefully recover if the index file gets full.
ALTER TABLE
on a table that is symlinked to another
disk, create temporary tables on that disk.
DATE/DATETIME
type that handles time zone information
properly, to make dealing with dates in different time zones easier.
configure
so that all libraries (like MyISAM
)
can be compiled without threads.
LIMIT
arguments; for example,
LIMIT @a,@b
.
mysql
to a Web browser.
LOCK DATABASES
(with various options).
SHOW STATUS
. Record reads and
updates. Selects on a single table and selects with joins. Mean number of
tables in selects. Number of ORDER BY
and GROUP BY
queries.
mysqladmin copy database new-database
; this requires a COPY
operation to be added to mysqld
.
SHOW HOSTS
for printing information about the hostname cache.
NULL
for calculated columns.
Item_copy_string
on numerical values to avoid
number-to-string-to-number conversion in case of
SELECT COUNT(*)*(id+0) FROM tbl_name GROUP BY id
.
ALTER TABLE
doesn't abort clients
that execute INSERT DELAYED
.
UPDATE
clause,
they contain the old values from before the update started.
get_changed_tables(timeout,table1,table2,...)
.
mmap()
when possible. Only
compressed tables use mmap()
.
SET TIMESTAMP=val;
.
n
, replace other
occurrences of col_name within the expression with n
.
Currently, this is done only for some simple cases.
MINUS
, INTERSECT
, and FULL OUTER JOIN
.
(Currently UNION
and LEFT|RIGHT OUTER JOIN
are supported.)
SQL_OPTION MAX_SELECT_TIME=val
, for placing a time limit on a query.
LIMIT
to allow retrieval of data from the end of a result set.
mysqld_safe
: According to FSSTND (which
Debian tries to follow), PID files should go into `/var/run/<progname>.pid'
and log files into `/var/log'. It would be nice if you could put the
"DATADIR" in the first declaration of "pidfile" and "log" so that the
placement of these files can be changed with a single statement.
LOAD DATA INFILE
statement
to read files that have been compressed with gzip
.
BLOB
columns (partly solved).
JOIN
with parentheses.
GET_LOCK()
to obtain more than one lock. When doing this, it is
also necessary to handle the possible deadlocks this change will introduce.
We aim toward full compliance with ANSI/ISO SQL. There are no features we plan not to implement.
This appendix lists the changes from version to version in the MySQL source code.
We are working actively on MySQL 4.1 and 5.0, and will provide only critical bugfixes 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 MySQL 4.1 and 5.0. See section C 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 recent version of MySQL listed here that you can't find on our download page (http://dev.mysql.com/downloads/), it means that the version has not yet been released.
The date mentioned with a release version is the date of the last BitKeeper ChangeSet on which the release was based, not the date when the packages were made available. The binaries are usually made available a few days after the date of the tagged ChangeSet, because building and testing all packages takes some time.
The following changelog shows what has been done in the 5.0 tree:
CREATE VIEW
Syntax.
SELECT INTO list_of_vars
, which can be of mixed
(that is, global and local) types.
See section 19.1.6.3 SELECT ... INTO
Statement.
--log-update
, it will be
translated to --log-bin
(or ignored if the server is explicitly
started with --log-bin
), and a warning message will be written to
the error log. Setting SQL_LOG_UPDATE
will silently set
SQL_LOG_BIN
instead (or do nothing if the server is explicitly
started with --log-bin
).
SET
@a=10;
then SELECT @A;
will now return 10
.
Case sensitivity of a variable's value depends on the collation of the value.
VARCHAR
fields remembers end space. A VARCHAR()
field can
contain up to 65535 bytes.
MEMORY
(HEAP
) tables can have VARCHAR()
fields.
CREATE ... SELECT
, MySQL creates the result field based
on the max_length of the string/expression:
max_length | Column type |
= 0 | CHAR(0)
|
< 512 | VARCHAR(max_length)
|
>= 512 | TEXT
|
For a full list of changes, please refer to the changelog sections for each individual 5.0.x release.
Functionality added or changed:
mysql_library_init()
and mysql_library_end()
as
synonyms for the mysql_server_init()
and mysql_server_end()
C API functions. mysql_library_init()
and mysql_library_end()
are #define
symbols, but the names more clearly indicate that they
should be called when beginning and ending use of a MySQL C API
library no matter whether the application uses libmysqlclient
or libmysqld
. (Bug #6149)
SHOW COLUMNS
now displays NO
rather than blank in the
Null
output column if the corresponding table column cannot be
NULL
.
mysql
from
<col_name>col_value</col_name>
to
<field name="col_name">col_value</field>
to allow for
proper encoding of column names that are not legal as element names.
(Bug #7811)
--innodb-checksums
and --innodb-doublewrite
options for
mysqld
.
--large-pages
option for mysqld
.
multi_read_range
system variable.
SHOW DATABASES
, SHOW TABLES
, SHOW COLUMNS
, and so forth
display information about the INFORMATION_SCHEMA
database. Also,
several SHOW
statements now accept a WHERE
clause specifying
which output rows to display.
See section 21 The INFORMATION_SCHEMA
Information Database.
CREATE ROUTINE
and ALTER ROUTINE
privileges, and made
the EXECUTE
privilege operational.
ROW_FORMAT=COMPACT
tables that caused corruption. (Bug #7973) There may still be bugs in the
crash recovery, especially in COMPACT
tables.
MyISAM
storage engine detects corruption of a MyISAM
table, a message describing the problem now is written to the error log.
fcntl()
file flush method on Mac OS X versions 10.3 and later.
Apple had disabled fsync()
in Mac OS X for internal disk
drives, which caused corruption at power outages.
TRUNCATE TABLE
. The old approach
(deleting rows one by one) may be used if the table is being
referenced by foreign keys. (Bug #7150)
cp932
(SJIS for Windows Japanese) and
eucjpms
(UJIS for Windows Japanese) character sets.
InnoDB
status variables.
See section 5.2.4 Server Status Variables.
FEDERATED
storage engine.
See section 14.6 The FEDERATED
Storage Engine.
SHOW CREATE TABLE
now uses USING index_type
rather than
TYPE index_type
to specify an index type. (Bug #7233)
TRUNCATE TABLE
. One visible change from this
is that auto-increment values for this table are reset on TRUNCATE
.
error
member to the MYSQL_BIND
data structure that
is used in the C API for prepared statements. This member is used for
reporting data truncation errors. Truncation reporting is enabled via the
new MYSQL_REPORT_DATA_TRUNCATION
option for the mysql_options()
C API function.
reconnect
flag in the MYSQL
structure is now set
to 0 by mysql_real_connect()
. Only those client programs which didn't
explicitely set this flag to 0 or 1 after mysql_real_connect()
will
experience a change. Having automatic reconnection enabled by default was
considered too dangerous (after reconnection, table locks, temporary tables,
user and session variables are lost).
FLUSH TABLES WITH READ LOCK
is now killable while it's waiting for
running COMMIT
statements to finish.
MEMORY
(HEAP
) can have VARCHAR()
fields.
VARCHAR
columns now remember end space. A VARCHAR()
column can
now contain up to 65535 bytes. For more details, see section D.1 Changes in release 5.0.x (Development).
If the table handler doesn't support the new VARCHAR
type, then
it's converted to a CHAR
column. Currently this happens for NDB
and InnoDB
tables.
ROW_FORMAT=REDUNDANT
.
The new format (ROW_FORMAT=COMPACT
) is the default.
AUTO_INCREMENT
value for the table
using CREATE TABLE...AUTO_INCREMENT =
works now also for the
InnoDB
table.
Seconds_Behind_Master
will be NULL
(which means ``unknown'') if
the slave SQL thread is not running, or if the slave I/O thread is not running
or not connected to master. It will be zero if SQL thread has caught up on I/O
thread. It no longer grows indefinitely if the master is idle.
--log-bin
option but cannot initialize the
binary log at startup (that is, an error occurs when writing to the binary
log file or binary log index file).
MyISAM
tables when there is a ``disk full'' or ``quota exceeded''
error.
See section A.4.3 How MySQL Handles a Full Disk.
--log-bin-index
and without --log-bin
, and when started with
--log-slave-updates
and without --log-bin
.
--log-bin
and
without --log-bin-index
, thus not providing a name for the binary log
index file, a warning will be issued because MySQL will fall back to
using the hostname for that name, and this is prone to replication issues if
the server's hostname's gets changed later. See section 1.5.7.3 Open Bugs and Design Deficiencies in MySQL.
MAX_USER_CONNECTIONS
limit, which allows you to
specify the maximum number of concurrent connections for the account. Also,
all limited resources now are counted per account (instead of being counted per
user + host pair as it was before). Use the --old-style-user-limits
option to get the old behavior.
LOCK_REC_NOT_GAP
) is now taken for a
matching record in the foreign key check because inserts can be
allowed into gaps.
InnoDB
uses consistent read in these cases for a selected table.
Bugs fixed:
LOAD INDEX
statement to actually load index in memory. (Bug #8452)
--replicate-*-table
options had been specified.
(Bug #7011)
CREATE TABLE ... LIKE
Windows when the source or
destination table was located in a symlinked database directory. (Bug #6607)
lower_case_table_names
set to 1, mysqldump
on Windows
could write the same table name in different lettercase for different SQL
statements. Fixed so that consistent lettercase is used. (Bug #5185)
mysqld_safe
now understands the --help
option.
Previously, it ignored the option and attempted to start the server
anyway. (Bug #7931)
NO_BACKSLASH_ESCAPES
SQL mode for strings that
contained both the string quoting character and backslash. (Bug #6368)
SUM(DISTINCT...)
.
OUTER JOIN
.
CONV()
function returning unsigned BIGINT
number (third argument is positive, and return value does not fit in
32 bits). (Bug #7751)
IN()
operator to return correct result if all
values in the list were constants and some of them were using substring
functions, for example, LEFT()
, RIGHT()
, or MID()
.
(Bug #7716)
CONVERT_TZ()
function when its second or third argument
was from a const
table (see section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
)). (Bug #7705)
SELECT DISTINCT
combined with a
subquery and GROUP BY
. (Bug #7946)
row(1,(2,3))
) with a subquery. (Bug #8022)
ALTER TABLE
improperly would accept an index on a
TIMESTAMP
column that CREATE TABLE
would reject. (Bug #7884)
SHOW CREATE TABLE
now reports ENGINE=MEMORY
rather than
ENGINE=HEAP
for a MEMORY
table (unless the MYSQL323
SQL
mode is enabled). (Bug #6659)
GROUP_CONCAT()
with HAVING
caused a server crash. (Bug #7769)
-not
and trunc*
operators of
full-text search. Using more than one truncated negative search term, was
causing empty result set.
ucs2
character set. (Bug #7350)
tmpfile()
function on Netware. All InnoDB
temporary files will be created under sys:\tmp
. Previously,
InnoDB temporary files were never deleted on Netware.
max_heap_table_size
handling, that resulted in
Table is full
error when the table was still smaller than the limit.
(Bug #7791).
mysqlaccess
script.
Reported by Javier Fernandez-Sanguino Pena
and Debian Security Audit Team.
( CAN-2005-0004)
CONVERT_TZ()
function with constant arguments was prepared. (Bug #6849)
CREATE TABLE .. SELECT
query to the binary log when the
insertion of new records partially failed. (Bug #6682)
mysqld
a SIGHUP
caused it to crash.
CREATE/ALTER/DROP DATABASE
statements so
that replication of CREATE DATABASE
is possible when using
--binlog-do-db
and --binlog-ignore-db
. (Bug #6391)
BEGIN
(or SET AUTOCOMMIT=0
), FLUSH TABLES
WITH READ LOCK
, transactional update, COMMIT
, FLUSH
TABLES WITH READ LOCK
could hang the connection forever and possibly the MySQL
server itself. This happened for example when running the innobackup
script several times. (Bug #6732)
mysqlbinlog
did not print SET PSEUDO_THREAD_ID
statements in
front of LOAD DATA INFILE
statements inserting into temporary tables,
thus causing potential problems when rolling forward these statements after
restoring a backup. (Bug #6671)
InnoDB
now supports ALTER
TABLE...AUTO_INCREMENT = x
query to set auto increment value for a
table.
SHOW CREATE DATABASE
even if the
connection has an open transaction or locked tables; refusing it made
mysqldump --single-transaction
sometimes fail to print a complete
CREATE DATABASE
statement for some dumped databases. (Bug #7358)
MyISAM
sometimes didn't sleep and retry the write, thus
resulting in a corrupted table. (Bug #7714)
--expire-log-days
was not honored if using only transactions.
(Bug #7236)
ANALYZE
TABLE
, OPTIMIZE TABLE
, or REPAIR TABLE
statements from the
master. (Bug #6461, Bug #7658)
mysqlbinlog
forgot to add backquotes around the collation of user
variables (causing later parsing problems as BINARY
is a reserved
word). (Bug #7793)
mysqldump --single-transaction
sets its transaction
isolation level to REPEATABLE READ
before proceeding (otherwise if the
MySQL server was configured to run with a default isolation level lower than
REPEATABLE READ
it could give an inconsistent dump). (Bug #7850)
RPAD()
function (or any function adding spaces
to the right) in a query that had to be resolved by using a temporary table,
all resulting strings had rightmost spaces removed (i.e. RPAD()
did not
work) (Bug #4048)
SELECT
@@unknown_var
hangs them -- which was fixed in MySQL 3.23.50). (Bug #7965)
InnoDB
now takes an exclusive lock when INSERT
ON DUPLICATE KEY UPDATE
is checking duplicate keys.
Functionality added or changed:
INFORMATION_SCHEMA
``information database'' that
provides database metadata.
See section 21 The INFORMATION_SCHEMA
Information Database.
HAVING
clause in a SELECT
statement now can refer to columns
in the GROUP BY
clause, as required by standard SQL.
CREATE USER
and RENAME USER
statements.
DROP USER
so that it drops the account, including all its
privileges. Formerly, it removed the account record only for an account that
had had all privileges revoked.
NOT
operator has changed so that expressions such as
NOT a BETWEEN b AND c
are parsed correctly as
NOT (a BETWEEN b AND c)
rather than as
(NOT a) BETWEEN b AND c
.
The pre-5.0 higher-precedence behavior can be obtained by enabling the new
HIGH_NOT_PRECEDENCE
SQL mode.
IS [NOT] boolean_value
syntax, where boolean_value is
TRUE
, FALSE
, or UNKNOWN
.
InnoDB
status variables.
See section 5.2.4 Server Status Variables.
WITH CHECK OPTION
clause for CREATE VIEW
.
CHECK TABLE
now works for views.
SCHEMA
and SCHEMAS
keywords are now accepted as synonyms
for DATABASE
and DATABASES
.
CREATE TRIGGER
and
DROP TRIGGER
statements).
mysqldump --single-transaction --master-data
is now able to take an
online (non-blocking) dump of InnoDB and report the corresponding binary log
coordinates, which makes a backup suitable for point-in-time recovery,
roll-forward or replication slave creation. See section 8.8 The mysqldump
Database Backup Program.
--start-datetime
, --stop-datetime
,
--start-position
, --stop-position
options to
mysqlbinlog
(makes point-in-time recovery easier).
SIGHUP
and SIGQUIT
on
Mac OS X 10.3. This is needed because under this OS, the MySQL server receives
lots of these signals (reported as Bug #2030).
--auto-increment-increment
and --auto-increment-offset
startup options. These allow you to set up a server to generate
auto-increment values that don't conflict with another server.
ALLOW_INVALID_DATES
SQL mode.
STRICT_TRANS_TABLES
, STRICT_ALL_TABLES
,
NO_ZERO_IN_DATE
, NO_ZERO_DATE
,
ERROR_FOR_DIVISION_BY_ZERO
, and TRADITIONAL
SQL modes.
The TRADITIONAL
mode is shorthand for all the preceding modes.
When using mode TRADITIONAL
, MySQL generates an error if you try
to insert a wrong value in a column. It does not adjust the value to the
closest possible legal value.
STRICT_TRANS_TABLES
/STRICT_ALL_TABLES
mode, you now get
an error if you do an INSERT
without specifying all columns that
don't have a default value. A side effect of this is that when you do
SHOW CREATE
for a new table, you will no longer see a DEFAULT
value for a column for which you didn't specify a default value.
DONT_USE_DEFAULT_FIELDS
was removed because you
can get the same behavior by setting the sql_mode
system variable to
STRICT_TRANS_TABLES
.
NO_AUTO_CREATE_USER
SQL mode to prevent GRANT
from automatically creating new users if it would otherwise do so,
unless a password also is specified.
sql_updatable_view_key
system variable to
updatable_views_with_limit
. This variable now can have only two values:
1
or YES
: Don't issue an error message (warning only) if a
VIEW without presence of a key in the underlying table is used in queries
with a LIMIT
clause for updating. (This is the default value.)
0
or NO
: Prohibit update of a VIEW, which does not contain a
key in the underlying table and the query uses a LIMIT
clause (usually
get from GUI tools).
SHOW TABLES
to old pre-5.0.1 format that did
not include a table type column. To get the additional column that lists the
table type, use SHOW FULL TABLES
now.
mysql_fix_privilege_tables
script now initializes the global
CREATE VIEW
and SHOW VIEW
privileges in the user
table to the value of the CREATE
privilege in that table.
user
table has not been upgraded to
include the view-related privilege columns, it treats each account as having
view privileges that are the same as its CREATE
privilege.
innodb_locks_unsafe_for_binlog
in `my.cnf', InnoDB in an UPDATE
or a DELETE
only
locks the rows that it updates or deletes. This greatly reduces the
probability of deadlocks.
State
column of SHOW PROCESSLIST
.
mysqlbinlog
now prints an informative commented line (thread id,
timestamp, server id, etc) before each LOAD DATA INFILE
, like it
does for other queries; unless --short-form
is used.
Bugs fixed:
mysqlbinlog --read-from-remote-server
sometimes
couldn't accept two binary logfiles on the command line. (Bug #4507)
mysqlbinlog --position --read-from-remote-server
had incorrect # at
lines. (Bug #4506)
CREATE TABLE ... TYPE=HEAP ... AS SELECT...
caused
replication slave to stop. (Bug #4971)
mysql_options(...,MYSQL_OPT_LOCAL_INFILE,...)
failed to
disable LOAD DATA LOCAL INFILE
. (Bug #5038)
disable-local-infile
option had no effect if client read it
from a configuration file using
mysql_options(...,MYSQL_READ_DEFAULT,...)
. (Bug #5073)
SET GLOBAL SYNC_BINLOG
did not work on some platforms (Mac OS
X). (Bug #5064)
mysql-test-run
failed on the rpl_trunc_binlog
test if
running test from the installed (the target of 'make install') directory. (Bug
#5050)
mysql-test-run
failed on the grant_cache
test when run
as Unix user 'root'. (Bug #4678)
KILL
. (Bug
#4810)
KILL
ed while it was doing
START SLAVE
. (Bug #4827)
FLUSH TABLES WITH READ LOCK
block COMMIT
if server is
running with binary logging; this ensures that the binary log position can be
trusted when doing a full backup of tables and the binary log. (Bug #4953)
auto_increment
column was not reset by
TRUNCATE TABLE
is the table was a temporary one. (Bug #5033)
SET COLLATION_SERVER...
statements it
replicates don't advance its position (so that if it gets interrupted before
the actual update query, it will later redo the SET
). (Bug #5705)
FLUSH TABLES WITH READ LOCK
, then COMMIT
,
would cause replication slaves to stop (complaining about error 1223). Bug
surfaced when using the InnoDB innobackup
script. (Bug #5949)
OPTIMIZE TABLE
, REPAIR TABLE
, and ANALYZE TABLE
are now
replicated without any error code in the binary log. (Bug #5551)
SELECT FOR UPDATE
then executed a non-transactional update, that update automatically committed
the transaction (thus releasing InnoDB's row-level locks etc). (Bug #5714)
BEGIN
and ROLLBACK
binary
log events; that caused superfluous slave stops. (Bug #6522)
mysqlbinlog
from being able to read
from stdin
, for example, when piping the output from zcat
to
mysqlbinlog
. (Bug #7853)
Note: This build passes our test suite and fixes a lot of reported bugs found in the previous 5.0.0 release. However, please be aware that this is not a ``standard MYSQL build'' in the sense that there are still some open critical bugs in our bugs database at http://bugs.mysql.com/ that affect this release as well. We are actively fixing these and will make a new release where these are fixed as soon as possible. However, this binary should be a good candidate for testing new MySQL 5.0 features for future products.
Functionality added or changed:
SELECT
is slow, but even using
EXPLAIN
for it takes a noticeable amount of time.) Two new system
variables, optimizer_search_depth
and optimizer_prune_level
, can
be used to fine-tune optimizer behavior.
mysql_shutdown()
now requires a second argument.
This is a source-level incompatibility that affects how you compile client
programs; it does not affect the ability of compiled clients to communicate
with older servers.
See section 22.2.3.54 mysql_shutdown()
.
db.p()
USE db_name
is
in effect.
USE db_name
statements no longer are allowed in a
stored procedure.
SHOW TABLES
output field name and values according to standard.
Field name changed from Type
to table_type
, values are
BASE TABLE
, VIEW
and ERROR
. (Bug #4603)
sql_updatable_view_key
system variable.
--replicate-same-server-id
server option.
Last_query_cost
status variable that reports optimizer cost
for last compiled query.
--to-last-log
option to mysqlbinlog
, for use
in conjunction with --read-from-remote-server
.
--innodb-safe-binlog
server option, which adds consistency
guarantees between the content of InnoDB
tables and the binary log.
See section 5.9.4 The Binary Log.
OPTIMIZE TABLE
for InnoDB
tables is now mapped to ALTER
TABLE
instead of ANALYZE TABLE
.
sync_frm
is now a settable global variable (not only a startup option).
MEMORY
(HEAP
) tables: Made the master
automatically write a DELETE FROM
statement to its binary log when a
MEMORY
table is opened for the first time since master's startup.
This is for the case where the slave has replicated a non-empty
MEMORY
table, then the master is shut down and restarted: the table
is now empty on master; the DELETE FROM
empties it on slave too. Note
that even with this fix, between the master's restart and the first use of
the table on master, the slave still has out-of-date data in the table. But
if you use the --init-file
option to populate the MEMORY
table
on the master at startup, it ensures that the failing time interval is zero.
(Bug #2477)
DROP TEMPORARY TABLE IF
EXISTS
instead of DROP TEMPORARY TABLE
, for more robustness.
SET SQL_LOG_BIN
is issued by a
user without the SUPER
privilege (in previous versions it just silently
ignored the statement in this case).
--log-bin
option was used), then no transaction binary log cache
is allocated for connections. This should save binlog_cache_size
bytes of memory (32KB by default) for every connection.
sync_binlog=N
global variable and startup option, which makes
the MySQL server synchronize its binary log to disk (fdatasync()
) after
every Nth write to the binary log.
slave-skip-errors
).
DROP DATABASE IF EXISTS
, DROP TABLE IF EXISTS
, single-table
DELETE
, and single-table UPDATE
now are written to the binary log
even if they changed nothing on the master (for example, even if a
DELETE
matched no rows). The old behavior sometimes caused bad surprises
in replication setups.
mysqlbinlog
now have better support for the case that
the session character set and collation variables are changed within a given
session.
See section 6.7 Replication Features and Known Problems.
CHECK TABLE
statement does not result in the table being
marked as ``corrupted'' any more; the table remains as if CHECK TABLE
had not even started.
See section 13.5.5.3 KILL
Syntax.
Bugs fixed:
ALTER DATABASE
caused the client to hang if the database did not
exist. (Bug #2333)
SLAVE START
(which is a deprecated syntax, START SLAVE
should be
used instead) could crash the slave. (Bug #2516)
DELETE
statements were never replicated by the slave if
there were any --replicate-*-table
options. (Bug #2527)
mysql_real_query()
or mysql_stmt_prepare()
) was terminated
by garbage characters. This can happen if you pass a wrong length
parameter to these functions. The result was that the
garbage characters were written into the binary log. (Bug #2703)
OPTIMIZE TABLE
or REPAIR
TABLE
), this could sometimes stop the slave SQL thread. This does not lead
to any corruption, but you must use START SLAVE
to get replication
going again. (Bug #1858)
--read-only
option. (Bug #2757)
--replicate-wild-*-table
rules apply to ALTER DATABASE
when the table pattern is %
, as is the case for CREATE
DATABASE
and DROP DATABASE
. (Bug #3000)
Rotate
event is found by the slave SQL thread in the
middle of a transaction, the value of Relay_Log_Pos
in SHOW SLAVE
STATUS
remains correct. (Bug #3017)
InnoDB
reports when it is doing a
crash recovery on a slave server. (Bug #3015)
Seconds_Behind_Master
in SHOW SLAVE STATUS
to
never show a value of -1. (Bug #2826)
DROP TEMPORARY TABLE
statement is automatically
written to the binary log when a session ends, the statement is recorded with an
error code of value zero (this ensures that killing a SELECT
on the
master does not result in a superfluous error on the slave). (Bug #3063)
INSERT DELAYED
(also known as a
delayed_insert
thread) is killed, its statements are recorded with an
error code of value zero (killing such a thread does not endanger
replication, so we thus avoid a superfluous error on the slave). (Bug #3081)
START SLAVE
commands were run at the same
time. (Bug #2921)
--replicate-*
options. The bug was that if the
statement had been killed on the master, the slave would stop. (Bug #2983)
--local-load
option of mysqlbinlog
now requires an argument.
LOAD DATA FROM MASTER
after
RESET SLAVE
. (Bug #2922)
mysqlbinlog --read-from-remote-server
read all binary logs following the
one that was requested. It now stops at the end of the requested file, the
same as it does when reading a local binary log. There is an option
--to-last-log
to get the old behavior. (Bug #3204)
mysqlbinlog --read-from-remote-server
to print the exact
positions of events in the "at #" lines. (Bug #3214)
Binlog has bad magic number
and stop when it
was not necessary to do so. (Bug #3401)
mysqlbinlog
not to forget to print a USE
statement
under rare circumstances where the binary log contained a LOAD DATA
INFILE
statement. (Bug #3415)
LOAD DATA INFILE
when the
master had version 3.23. (Bug #3422)
DELETE
statements were always replicated by the slave if
there were some --replicate-*-ignore-table
options and no
--replicate-*-do-table
options. (Bug #3461)
--with-debug
and replicating itself. (Bug #3568)
server-id
was not set using startup options but with SET
GLOBAL
, the replication slave still complained that it was not set.
(Bug #3829)
mysql_fix_privilege_tables
didn't correctly handle the argument of its
--password=#
option. (Bug #4240)
mysql_real_connect()
(which
required a compromised DNS server and certain operating systems). (Bug #4017)
mysqld
was run as the root
system user, and if you had
--log-bin=<somewhere_out_of_var_lib_mysql>
it created binary log
files owned by root
in this directory, which remained owned by
root
after the installation. This is now fixed by starting
mysqld
as the mysql
system user instead. (Bug #4038)
DROP DATABASE
honor the value of
lower_case_table_names
. (Bug #4066)
INSERT ... SELECT
if it
examined more than 4 billion rows. (Bug #3871)
mysqlbinlog
didn't escape the string content of user variables, and did
not deal well when these variables were in non-ASCII character sets; this is
now fixed by always printing the string content of user variables in
hexadecimal. The character set and collation of the string is now also
printed. (Bug #3875)
AND
/OR
expressions if query was ignored (either by a
replication server because of --replicate-*-table
rules, or by any MySQL
server because of a syntax error). (Bug #3969, Bug #4494)
CREATE TEMPORARY TABLE t SELECT
failed while loading the data, the
temporary table was not dropped. (Bug #4551)
DROP TABLE
failed to drop a table on
the master server, the error code was not written to the binary log.
(Bug #4553)
LOAD DATA INFILE
statement, it didn't show the statement in the output of SHOW
PROCESSLIST
. (Bug #4326)
Functionality added or changed:
KILL
statement now takes CONNECTION
and QUERY
modifiers. The first is the same as KILL
with no modifier (it
kills a given connection thread). The second kills only the statement
currently being executed by the connection.
TIMESTAMPADD()
and TIMESTAMPDIFF()
functions.
WEEK
and QUARTER
values as INTERVAL
arguments
for the DATE_ADD()
and DATE_SUB()
functions.
sql_mode
, SQL_AUTO_IS_NULL
, FOREIGN_KEY_CHECKS
(which was replicated since 4.0.14, but here it's done more
efficiently and takes less space in the binary logs), UNIQUE_CHECKS
.
Other variables (like character sets, SQL_SELECT_LIMIT
, ...) will be
replicated in upcoming 5.0.x releases.
OR
clauses.
See section 7.2.6 Index Merge Optimization.
SELECT INTO list_of_vars
, which can be of mixed
(that is, global and local) types.
See section 19.1.6.3 SELECT ... INTO
Statement.
InnoDB
is not aware of multiple tablespaces.
Bugs fixed:
Version 4.1 of the MySQL server includes many enhancements and new features. Binaries for this version are available for download at http://dev.mysql.com/downloads/mysql-4.1.html.
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 13.1.4 INSERT
Syntax.
GROUP_CONCAT()
aggregate function.
See section 12.9 Functions and Modifiers for Use with GROUP BY
Clauses.
UTF8
. This makes MySQL
more flexible, but might cause some problems upgrading if you have table
or column names that use characters outside of the standard 7-bit US-ASCII
range.
See section 2.10.2 Upgrading from Version 4.0 to 4.1.
MyISAM
tables with many tunable parameters. You can
have multiple key caches, preload index into caches for batches...
BTREE
index on HEAP
tables.
SHOW WARNINGS
shows warnings for the last command.
See section 13.5.4.20 SHOW WARNINGS
Syntax.
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table2 LIKE
table1
.
HELP
command that can be used in the mysql
command-line client (and other clients) to get help for SQL statements.
For a full list of changes, please refer to the changelog sections for each individual 4.1.x release.
Functionality added or changed:
mysql_library_init()
and mysql_library_end()
as
synonyms for the mysql_server_init()
and mysql_server_end()
C API functions. mysql_library_init()
and mysql_library_end()
are #define
symbols, but the names more clearly indicate that they
should be called when beginning and ending use of a MySQL C API
library no matter whether the application uses libmysqlclient
or libmysqld
. (Bug #6149)
lower_case_table_names=2
and the
data directory is on a case-sensitive filesystem, just as when
lower_case_table_names=0
on a case-insensitive filesystem.
(Bug #7887)
fcntl()
file flush method on Mac OS X versions 10.3 and later.
Apple had disabled fsync()
in Mac OS X for internal disk
drives, which caused corruption at power outages.
LOCK_REC_NOT_GAP
) is now taken for a
matching record in the foreign key check because inserts can be
allowed into gaps.
InnoDB
uses consistent read in these cases for a selected table.
Bugs fixed:
LOAD INDEX
statement to actually load index in memory. (Bug #8452)
YEAR
column were being stored as
2000
rather than as 0000
. (Bug #6067)
--replicate-*-table
options had been specified.
(Bug #7011)
mysql_stmt_close()
C API function was not clearing an error indicator
when a previous prepare call failed, causing subsequent invocations of
error-retrieving calls to indicate spurious error values. (Bug #7990)
CREATE TABLE ... LIKE
Windows when the source or
destination table was located in a symlinked database directory. (Bug #6607)
lower_case_table_names
set to 1, mysqldump
on Windows
could write the same table name in different lettercase for different SQL
statements. Fixed so that consistent lettercase is used. (Bug #5185)
HAVING
that referred to RAND()
or a user-defined function in
the SELECT
part through an alias could cause a crash or wrong value.
(Bug #8216)
CONVERT_TZ()
function in SELECT
, which in its turn
was used in CREATE TABLE
statements, then system time
zone tables were added to list of tables joined in SELECT and thus erroneous
result was produced. (Bug #7899)
CONV()
function returning unsigned BIGINT
number (third argument is positive, and return value does not fit in
32 bits). (Bug #7751)
IN()
operator to return correct result if all
values in the list were constants and some of them were using substring
functions, for example, LEFT()
, RIGHT()
, or MID()
.
SHOW INDEX
reporting Sub_part
values in bytes
rather than characters for columns with a multi-byte character set.
(Bug #7943)
CONVERT_TZ()
function when its second or third argument
was from a const
table (see section 7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
)). (Bug #7705)
mysql_config
, which was failing to produce
proper zlib
option for linking under some circumstances. (Bug #6273)
SELECT DISTINCT
combined with a
subquery and GROUP BY
. (Bug #7946)
row(1,(2,3))
) with a subquery. (Bug #8022)
--default-character-set
option. (Bug #8159)
CHAR(31)
were considered equal to the empty string. (Bug #8134)
debug
command to mysqladmin
help output.
(Bug #8207)
perror.exe
was always returning ``Unknown error'' on Windows.
See section 8.12 perror
, Explaining Error Codes.
(Bug #7390)
SET
statements produced by mysqldump
to write quoted
strings using single quotes rather than double quotes. This avoids problems if
the dump file is reloaded while the ANSI_QUOTES
SQL mode is in effect.
(Bug #8148)
ALTER TABLE
improperly would accept an index on a
TIMESTAMP
column that CREATE TABLE
would reject. (Bug #7884)
UPDATE
statements that
could cause spurious Table '#sql_....' is full
errors if the number
of rows to update is big enough. (Bug #7788)
SHOW INDEX
on a MERGE
table could crash a
debugging version of the server. (Bug #7377)
ORDER BY
clause for an indexed column
would cause a SELECT
to return an empty result. (Bug #7311)
ALTER TABLE
on a TEMPORARY
table with a
mixed-lettercase name could cause the table to disappear when
lower_case_table_names
was set to 2. (Bug #7261)
SIGHUP
signal. (Bug #4285)
mysql_stmt_prepare()
to be very slow when
used in client programs on Windows. (Bug #5787)
SHOW CREATE TABLE
now displays the index type even if it
is the default, for storage engines that support multiple index types.
(Bug #7235)
GROUP_CONCAT()
with HAVING
caused a server crash. (Bug #7769)
TIMEDIFF()
function to return wrong results
if one of its arguments had non-zero microsecond part (Bug #7586).
TIMESTAMP
columns with display width
specified to be not identical to DATETIME
columns when server
was run in MAXDB
mode (Bug #7418).
UNION
statements that resulted in the wrong number of the
examined rows reported in the slow query log.
-not
and trunc*
operators of
full-text search. Using more than one truncated negative search term, was
causing empty result set.
innodb_file_per_table
. mysqld
would stop
and complain about Windows error number 87 in a file operation.
(See the Bugs database or the 4.1.9 change notes about a workaround for that
bug in 4.1.9). (Bug #8021)
ucs2
character set. (Bug #7350)
tmpfile()
function on Netware. All InnoDB
temporary files will be created under sys:\tmp
. Previously,
InnoDB temporary files were never deleted on Netware.
max_heap_table_size
handling, that resulted in
Table is full
error when the table was still smaller than the limit.
(Bug #7791).
mysqlaccess
script.
Reported by Javier Fernandez-Sanguino Pena
and Debian Security Audit Team.
( CAN-2005-0004)
mysqlbinlog
forgot to add backquotes around the collation of user
variables (causing later parsing problems as BINARY
is a reserved
word). (Bug #7793)
mysqldump --single-transaction
sets its transaction
isolation level to REPEATABLE READ
before proceeding (otherwise if the
MySQL server was configured to run with a default isolation level lower than
REPEATABLE READ
it could give an inconsistent dump). (Bug #7850)
mysql
client so that including \p
as part of a
prompt command will use the name of the shared memory connection when the
connection is using shared memory. (Bug #7922)
SELECT
@@unknown_var
hangs them -- which was fixed in MySQL 3.23.50). (Bug #7965)
Functionality added or changed:
mysqld_safe
no longer tests for the presence of the data
directory when using a relatively-located server binary. It just assumes
the directory is there, and will fail to start up if it is not. This allows
the data directory location to be specified on the command line, and avoids
running a server binary that was not intended. (Bug #7249)
-win
to -win32
-noinstall
and -essential
have been
moved in front of the version number
Seconds_Behind_Master
will be NULL
(which means ``unknown'') if
the slave SQL thread is not running, or if the slave I/O thread is not running
or not connected to master. It will be zero if the SQL thread has caught up
with the I/O thread. It no longer grows indefinitely if the master is idle.
InnoDB
table lock in LOCK
TABLES
if AUTOCOMMIT=1
. This helps in porting old MyISAM
applications to InnoDB
. InnoDB
table locks in that case
caused deadlocks very easily.
InnoDB
if the size of `ibdata' files is smaller than what is stored in the
tablespace header; innodb_force_recovery
overrides this.
--log-bin
option but cannot initialize the
binary log at startup (that is, an error occurs when writing to the binary
log file or binary log index file).
MyISAM
when there is a "disk full" or "quota exceeded" error. See section A.4.3 How MySQL Handles a Full Disk.
Bugs fixed:
mysql_fix_privilege_tables
could result
in grant table columns with too-short lengths if the server character set had
been set to a multi-byte character set first. (Bug #7539)
innodb_file_per_table
in `my.cnf'.
If you shut down mysqld
, records could disappear from
the secondary indexes of a table. Unfortunately, on Windows a new Bug #8021
was introduced. Windows users of innodb_file_per_table
should put a line innodb_flush_method=unbuffered
to their
`my.cnf' or `my.ini' to work around 8021. (Bug #7496)
mysqld
binaries built on HP-UX-11 did
not work with InnoDB
files greater than 2 GB in size. (Bug #6189)
DISCARD TABLESPACE
if it fails because the table is referenced by a FOREIGN KEY
.
InnoDB
failed to drop a table in the background
drop queue if the table was referenced by a FOREIGN KEY
constraint.
INSERT
was waiting
for a lock to check a FOREIGN KEY
constraint, then an assertion would
fail in lock_reset_all_on_table()
.
NULL
value from a wrong field in the index; this has probably
caused no bugs visible to the user. It caused only some extra space to be
used in some rare cases.
fcntl()
file flush method on Mac OS X versions 10.3
and up. Apple had disabled fsync()
in Mac OS X for internal disk
drives, which caused corruption at power outages.
mysqladmin password
now checks whether the server has
--old-passwords
turned on or predates 4.1 and uses the old-format
password if so. (Bug #7451)
--default-character-set
option to mysqladmin
to avoid
problems when the default character set is not latin1
. (Bug #7524)
FLOAT
values. (Bug #7361)
PROCEDURE ANALYSE()
, which did not quote some
ENUM
values properly. (Bug #2813)
TIME
or DATE
values.
(Bug #6914)
mysql_config --lib_r
.
(Bug #7021)
mysql_config
not producing all relevant
flags from CFLAGS
. (Bug #6964)
mysqld_safe
not properly capturing
output from ps
. (Bug #5878)
INSERT DELAYED
with prepared
statements.
STR_TO_DATE
function, if there is some other specifier in
the format string following %f
. (Bug #7458)
SHOW CREATE DATABASE
even if the
connection has an open transaction or locked tables. Refusing it made
mysqldump --single-transaction
sometimes fail to print a complete
CREATE DATABASE
statement for some dumped databases. (Bug #7358)
MyISAM
sometimes didn't sleep and retry the write, thus
resulting in a corrupted table. (Bug #7714)
--expire-log-days
was not honored if using only transactions.
(Bug #7236)
ANALYZE
TABLE
, OPTIMIZE TABLE
, or REPAIR TABLE
statements from the
master. (Bug #6461, Bug #7658)
Note: Due to a libtool-related bug in the source distribution,
the creation of shared libmysqlclient
libraries was not possible
(the resulting files were missing the .so
file name extension).
The file `ltmain.sh' was updated to fix this problem and the resulting
source distribution was released as `mysql-4.1.8a.tar.gz'. This
modification did not affect the binary packages. (Bug #7401)
Functionality added or changed:
ALTER DATABASE
, the database name now can be omitted to apply the
change to the default database.
WITH CONSISTENT SNAPSHOT
clause to START TRANSACTION
to
begin a transaction with a consistent read.
--order-by-primary
to mysqldump
,
to sort each table's data in a dump file.
This may be useful when dumping a MyISAM table which
will be loaded into an InnoDB table.
Dumping a MyISAM table with this option is considerably
slower than without.
SHOW INNODB STATUS
information
to a temporary file unless the configuration option
innodb_status_file=1
is set.
ALTER TABLE
. This makes it much faster to recover from an
aborted ALTER TABLE
or OPTIMIZE TABLE
.
FULLTEXT
index block size is changed to be 1024 instead of 2048.
--disable-log-bin
option to mysqlbinlog
. Using
this option you can disable binary logging for the statements produced
by mysqlbinlog
. That is, mysqlbinlog --disable-log-bin
<file_name> | mysql
won't write any statements to the MySQL server
binary log.
--master-data
option for mysqldump
now takes an optional
argument of 1 or 2 to produce a non-commented or commented CHANGE MASTER
TO
statement. The default is 1 for backward compatibility.
mysqldump --single-transaction --master-data
now is able to take an
online (non-blocking) dump of InnoDB and report the corresponding binary log
coordinates. This makes a backup suitable for point-in-time recovery,
roll-forward or replication slave creation. See section 8.8 The mysqldump
Database Backup Program.
--lock-all-tables
to mysqldump
to lock all tables by
acquiring a global read lock.
--hex-blob
option to mysqldump
for dumping binary
string columns using hexadecimal notation.
mysql_hex_string()
C API function that hex-encodes a string.
Binlog Dump
requests.
[mysql_cluster]
section to `my.cnf' file for configuration
settings specific to MySQL Cluster. ndb-connectstring
variable moved here.
State
column of SHOW PROCESSLIST
.
mysqlbinlog
now prints an informative commented line (thread id,
timestamp, server id, etc) before each LOAD DATA INFILE
, like it
does for other queries; unless --short-form
is used.
Bugs fixed:
WHERE
clause. (Bug #7079)
LEFT
, when this function
is part of the expression which is used as GROUP BY
field.
(Bug #7101)
time_zone
variable or used CONVERT_TZ()
function) in case
when some table-level or column-level privileges existed. (Bug #6765)
mysql_stmt_data_seek(stmt,0)
will now rewind a counter and enable
that buffered rows can be re-fetched on the client side.
(Bug #6996)
SHOW CREATE TABLE
command. (Bug #7043)
MATCH ... AGAINST
on columns that use multi-byte character sets.
(Bug #6269)
CREATE TABLE .. SELECT
query to the binary log when the
insertion of new records partially failed. (Bug #6682)
INSERT ... SELECT
no longer reports spurious "column truncated" warnings
(Bug #6284)
HEAP
tables that contain only one row.
(Bug #6748)
mysqld_safe
was in many cases ignoring any
--no-defaults
, --defaults-file
, or
--defaults-extra-file
arguments. Those arguments
are now honored, and this may change what options are
passed to mysqld
in some installations.
CHAR BINARY
and VARCHAR BINARY
columns from 4.0 tables as having the BINARY
and VARBINARY
data types. Now they are interpreted as CHAR
and VARCHAR
columns that have the binary collation of the column's character set. (This
is the same way that CHAR BINARY
and VARCHAR BINARY
are
handled for new tables created in 4.1.)
REPLACE
or
INSERT ... ON DUPLICATE KEY UPDATE
statements performing multiple-row
insert in the table that had unique and fulltext indexes.
(Bug #6784)
SET
and DO
statements
which caused wrong results to be returned from subsequent queries.
(Bug #6462)
MYSQL_TIME
structure as for datetime values passed as strings.
(Bug #6266)
INSERT
for a table with FULLTEXT
indexes.
Under rare circumstances, this could result in a corrupted table if words of
different lengths may be considered equal. This is possible in some
collations, for example, in utf8_general_ci
or latin1_german2_ci
.
(Bug #6265)
FOREIGN KEY
parser to remove the latin1
character 0xA0
from the end of an unquoted identifier. The EMS MySQL
Manager in ALTER TABLE
adds that character after a table name, which
caused error 121 when we tried to add a new constraint.
rewind()
when displaying
SHOW INNODB STATUS
information on stderr
.
INSERT IGNORE
to insert several rows at a time,
and the first inserts were ignored because of a duplicate key collision,
then InnoDB in a replication slave assigned AUTO_INCREMENT
values 1
bigger than in the master. This broke the MySQL replication. (Bug #6287)
innodb_data_file_path
the
max
specification in :autoextend:max:2000M
.
This bug was introduced in 4.1.1.
innodb_locks_unsafe_for_binlog
still uses
next-key locking (Bug #6747). InnoDB used next-key locking when
record matched completely to search tuple. This unnecessary
next-key locking is now removed when innodb_locks_unsafe_for_binlog
option is used.
FOREIGN KEY
constraints treated table and
database names as case-insensitive. RENAME TABLE t TO T
would hang
in an endless loop if t
had a foreign key constraint defined on it.
Fix also a hang over the dictionary mutex that would occur if one tried
in ALTER TABLE
or RENAME TABLE
to create a foreign key
constraint name that collided with another existing name. (Bug #3478)
STMT_ATTR_UPDATE_MAX_LENGTH
is set for a prepared statement,
mysql_stmt_store_result()
will update field->max_length
for numeric columns as well. (Bug#6096)
ZEROFILL
when converting integer
to string
.
mysql_stmt_store_result()
occurred without
a preceding call to mysql_stmt_bind_result()
.
SELECT * FROM t1 NATURAL JOIN t2...
.
SELECT ... PROCEDURE
.
GROUP_CONCAT(...ORDER BY)
when used with prepared statements gave
wrong sorting order.
CREATE TABLE created_table
didn't signal when table was created.
This could cause a DROP TABLE created_table
in another thread
to wait "forever".
OPTIMIZE TABLE
, REPAIR TABLE
, and ANALYZE TABLE
are now replicated
without any error code in the binary log. (Bug #5551)
LOAD DATA INFILE
now works with option replicate-rewrite-db.
(Bug #6353)
CREATE/ALTER/DROP DATABASE
statements so
that replication of CREATE DATABASE
is possible when using
--binlog-do-db
and --binlog-ignore-db
. (Bug #6391)
SELECT FOR UPDATE
then executed a non-transactional update, that update automatically committed
the transaction (thus releasing InnoDB's row-level locks etc). (Bug #5714)
BEGIN
and ROLLBACK
binary
log events; that caused superfluous slave stops. (Bug #6522)
BEGIN
(or SET AUTOCOMMIT=0
), FLUSH TABLES
WITH READ LOCK
, transactional update, COMMIT
, FLUSH
TABLES WITH READ LOCK
could hang the connection forever and possibly the MySQL
server itself. This happened for example when running the innobackup
script several times. (Bug #6732)
mysqlbinlog
did not print SET PSEUDO_THREAD_ID
statements in
front of LOAD DATA INFILE
statements inserting into temporary tables,
thus causing potential problems when rolling forward these statements after
restoring a backup. (Bug #6671)
Functionality added or changed:
MOD()
no longer rounds arguments with a fractional part to integers.
Now it returns exact remainder after division. (Bug #6138)
innodb_table_locks
for making LOCK TABLE
acquire also InnoDB
locks.
The default value is 1, which means that
LOCK TABLES
causes also InnoDB internally to take a table lock.
In applications using AUTOCOMMIT=1
and LOCK TABLES
, InnoDB's
internal table locks that were added in 4.0.20 and 4.1.2
can cause deadlocks. You can set
innodb_table_locks=0
in `my.cnf' to remove that problem.
(Bug #3299, Bug #5998)
InnoDB
Tables. (Bug #3299, Bug #5998)
InnoDB: SHOW TABLE STATUS
now shows the creation time of the table
for InnoDB. Note that this timestamp might not be the correct time because,
e.g., ALTER TABLE
changes this timestamp.
innodb_thread_concurrency
would be exceeded, let a thread
sleep 10 ms before entering the FIFO queue; previously, the value was 50 ms.
Bugs fixed:
FOUND_ROWS()
used together with LIMIT
clause
in prepared statements. (Bug#6088)
NATURAL JOIN
in prepared statements. (Bug#6046).
time_zone
variable or use CONVERT_TZ()
function)
does not require any privileges. (Bug #6116)
libmysqlclient
function mysql_create_db()
was called. (Bug #6081)
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user
so that all
privileges are revoked correctly. (Bug #5831). This corrects a case that
the fix in 4.1.6 could miss.
HEAP
table with key_column IS
NOT NULL
. This could also cause a crash if not all index parts where used.
(Bug #6082)
MyISAM
index corruption when key values
start with character codes below BLANK
. This was caused by the
new key sort order in 4.1. (Bug #6151)
LOAD DATA INFILE…REPLACE
printing duplicate key error when executing the same
load query several times. (Bug #5835)
SELECT
statements not returning a result set (such
as SELECT ... INTO OUTFILE
). (Bug #6059)
libmysqlclient
with wrong conversion of negative time
values to strings. (Bug #6049).
libmysqlclient
with wrong conversion of zero date
values (0000-00-00
) to strings. (Bug #6058)
RAND(?)
. (Bug #5985)
DATE
, TIME
, and DATETIME
columns in the binary protocol. The problem is compiler-specific and could
have been observed on HP-UX, AIX, Solaris9, when compiling with native
compiler. (Bug #6025)
TINYINT
columns in the binary protocol.
The problem is specific to platforms where the C compiler has the char
data type unsigned by default. (Bug #6024)
FLUSH TABLES WITH READ LOCK
,
then COMMIT
, would cause replication slaves to stop (complaining
about error 1223). Bug surfaced when using the InnoDB innobackup
script. (Bug #5949)
FOREIGN KEY
operation, so that we do not starve other users doing CREATE TABLE
or other DDL operation. This caused a notorious 'Long semaphore wait' message
to be printed to the `.err' log. (Bug #5961)
Functionality added or changed:
--sigint-ignore
to the mysql
command line client
to make it ignore SIGINT
signals (typically the result of the user
pressing Control-C).
innodb_max_purge_lag
for delaying INSERT
, UPDATE
and DELETE
operations when the purge operations are lagging.
The default value of this parameter is zero, meaning that there will
not be any delays. See section 15.13 Implementation of Multi-Versioning.
innodb_autoextend_increment
startup option that was
introduced in release 4.1.5 was made a settable global variable. (Bug #5736)
DROP TABLE
is invoked on an InnoDB table for which the
.ibd
file is missing, print to error log that the table was removed
from the InnoDB
data dictionary, and allow MySQL to delete the
.frm
file. Maybe DROP TABLE
should issue a warning in this
case.
TIMESTAMP
columns now can store NULL
values. To create such
a column, you must explicitly specify the NULL
attribute in the column
specification. (Unlike all other column types, TIMESTAMP
columns
are NOT NULL
by default.)
ALTER TABLE
converts one AUTO_INCREMENT
column to
another AUTO_INCREMENT
column it will preserve zero values (this
includes the case that we don't change such column at all).
ALTER TABLE
converts some column to TIMESTAMP NOT NULL
column it will convert NULL
values to current timestamp value (One can
still get old behavior by setting system TIMESTAMP
variable to zero).
Bugs fixed:
FOREIGN KEY
parser that prevented
ALTER TABLE
of tables containing `#' in their names. (Bug #5856)
ALTER TABLE t DISCARD TABLESPACE
from working. (Bug #5851)
SHOW CREATE TABLE
now obeys the SET SQL_MODE=ANSI
and SET SQL_QUOTE_SHOW_CREATE=0
settings. (Bug #5292)
CREATE TEMPORARY TABLE ... ENGINE=InnoDB
to terminate
mysqld
when running in innodb_file_per_table
mode.
Per-table tablespaces for temporary tables will from now on be
created in the temporary directory of mysqld
. (Bug #5137)
TEXT
or BLOB
) value, then
ANOTHER externally stored column would show up as 512 bytes of good
data + 20 bytes of garbage in a consistent read that fetched the old
version of the row. (Bug #5960)
HA_ERR_ROW_IS_REFERENCED
if we cannot
DROP
a parent table referenced by a FOREIGN KEY
constraint;
this error number is less misleading than the previous number
HA_ERR_CANNOT_ADD_FOREIGN
, but misleading still.
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user
so that all privileges are revoked correctly. (Bug #5831)
'abc' LIKE CONVERT('abc' as utf8)
. (Bug #5688)
mysql_change_user()
C API function now frees all prepared statements
associated with the connection. (Bug #5315)
NULL
into an AUTO_INCREMENT
column
failed, when using prepared statements. (Bug #5510)
SET COLLATION_SERVER...
statements it
replicates don't advance its position (so that if it gets interrupted before
the actual update query, it will later redo the SET
). (Bug #5705)
MyISAM
table fails because of a full disk or
an exceeded disk quota, it prints a message to the error log every 10 minutes,
and waits until disk space becomes available. (Bug #3248)
FROM
clause when it resolves GROUP BY
clause (e.g. SELECT t1.a AS
c FROM t1, t2 ORDER BY a
will produce an error if both t1
and
t2
tables contain a
column). (Bug #4302)
ALTER TABLE
converting column containing NULL
values to AUTO_INCREMENT
column is no longer affected by
NO_AUTO_VALUE_ON_ZERO
mode. (Bug #5915).
Functionality added or changed:
InnoDB
: Added configuration option innodb_autoextend_increment
for setting the size in megabytes by which InnoDB
tablespaces are
extended when they become full. The default value is 8, corresponding to
the fixed increment of 8MB in previous versions of MySQL.
InnoDB
: The new Windows installation wizard of MySQL makes InnoDB as
the MySQL default table type on Windows, unless explicitly specified
otherwise. Note that it places the `my.ini' file in the
installation directory of the MySQL server.
Bugs fixed:
BETWEEN ? AND ?
and a datetime column.
(Bug #5748)
max_sort_length
, sql_mode
, and
group_concat_max_len
system variables now are stored in the query cache
with other query information to avoid returning an incorrect result from the
query cache. (Bug #5394)
(Bug #5515)
sql_mode=IGNORE_SPACE
. It happened
to take phrases like default .07
as
identifier.identifier
. (Bug #5318)
SELECT @var_name
.
(Bug #4788)
LIKE
used with arguments
in different character sets crashed server on first execute. (Bug #4368)
OPTIMIZE TABLE
that could cause table corruption
on FULLTEXT
indexes. (Bug #5327)
Note: To fix a compile problem on systems that do not have
automake
1.7 installed, an updated 4.1.4a source tarball has been
published. In addition to resolving this automake
dependency (Bug
#5319), it also fixes some reported libedit
compile errors when using
a non-gcc
compiler (Bug #5353).
Functionality added or changed:
CSV
storage engine.
TIMESTAMP
values in InnoDB
in
4.1 to be the same as in 4.0. This difference resulted in incorrect datetime
values in TIMESTAMP
columns in InnoDB
tables after an upgrade
from 4.0 to 4.1. (Bug #4492)
Warning: extra steps during upgrade required!
Unfortunately this means that if you are upgrading from 4.1.x,
where x <= 3, to 4.1.4
you should use mysqldump
for saving and then restoring your
InnoDB
tables with TIMESTAMP
columns.
mysqld-opt
Windows server was renamed to mysqld
.
This completes the Windows server renaming begun in MySQL 4.1.2.
See section 2.3.9 Selecting a MySQL Server type.
ucs2
and utf8
Unicode
character sets. These are called ucs2_roman_ci
and
utf8_roman_ci
.
MySQLCOM
in MySQL 4.1.2).
Thanks to Bryan McCormack for reporting this.
--start-datetime
, --stop-datetime
, --start-position
,
and --stop-position
options to mysqlbinlog
. These make
point-in-time recovery easier.
CHECK TABLE
statement does not result in the table being
marked as ``corrupted'' any more; the table remains as if CHECK TABLE
had not even started.
See section 13.5.5.3 KILL
Syntax.
SIGHUP
and SIGQUIT
on Mac OS X 10.3.
This is needed because under this OS, the MySQL server receives lots of these
signals (reported as Bug #2030).
ORDER BY
and GROUP BY
was dropped. For example the following
query SELECT a AS b FROM t1 ORDER BY t1.b
is not allowed. One should
use SELECT a AS b FROM t1 ORDER BY t1.a
or SELECT a AS b FROM
t1 ORDER BY b
instead. This was non-standard (since aliases are defined on
query level not on table level) and caused problems with some queries.
Bugs fixed:
MEDIUMINT
column. (Bug #5126)
SELECT ... INTO @var
for a second time.
(Bug #5034)
IN
subqueries that use compound
indexes. (Bug #4435)
SLAVE STOP
if the IO thread was in a special
state. (Bug #4629)
MERGE
tables
(even one MERGE
table and MyISAM
tables), that could have
resulted in a crash or hang of the server. (Bug #2408)
NOT
in WHERE
or ON
clauses. (Bug #4912)
MATCH ... AGAINST
now works in a subquery. (Bug #4769)
--log-error
) when the hostname contained a domain name.
The domain name is now replaced by the extension. (Bug #4997)
myisamchk
. (Bug #4901)
CONVERT_TZ()
function with time zone described in database as parameter and this time
zone was not used before. (Bug #4508)
%T, %r, %V, %v
and %X, %x
format specifiers was
added to STR_TO_DATE()
function. (Bug #4756)
NATURAL JOIN
where joined table had
no common column. (Bug #4807)
UNHEX(NULL)
. (Bug #4441)
mysql_fix_privilege_tables
didn't correctly handle the argument of its
--password=#
option. (Bug #4240, Bug #4543)
mysqlbinlog --read-from-remote-server
sometimes
couldn't accept 2 binary logs on command line. (Bug #4507)
mysqlbinlog --position --read-from-remote-server
had wrong # at
lines. (Bug #4506)
CREATE TEMPORARY TABLE t SELECT
failed while loading the data, the
temporary table was not dropped. (Bug #4551)
DROP TABLE
failed to drop a table on
the master server, the error code was not written to the binary log.
(Bug #4553)
LOAD DATA INFILE
statement, it didn't show the statement in the output of SHOW
PROCESSLIST
. (Bug #4326)
CREATE TABLE ... TYPE=HEAP ... AS SELECT...
caused
replication slave to stop. (Bug #4971)
mysql_options(...,MYSQL_OPT_LOCAL_INFILE,...)
failed to
disable LOAD DATA LOCAL INFILE
. (Bug #5038)
disable-local-infile
option had no effect if client read it
from a configuration file using
mysql_options(...,MYSQL_READ_DEFAULT,...)
. (Bug #5073)
SET GLOBAL SYNC_BINLOG
did not work on some platforms (Mac OS
X). (Bug #5064)
mysql-test-run
failed on the rpl_trunc_binlog
test
if running test from the installed (the target of 'make install') directory.
(Bug #5050)
mysql-test-run
failed on the grant_cache
test when
run as Unix user 'root'. (Bug #4678)
KILL
.
(Bug #4810)
KILL
ed while it was doing
START SLAVE
. (Bug #4827)
FLUSH TABLES WITH READ LOCK
block COMMIT
if server is
running with binary logging; this ensures that the binary log position is
trustable when doing a full backup of tables and the binary log. (Bug #4953)
auto_increment
column was not reset by
TRUNCATE TABLE
if the table was a temporary table. (Bug #5033)
ORDER BY
clause was present in two tables participating in SELECT
even if the
second instance of column in select list was renamed. (Bug #4302)
Note: The initial release of MySQL 4.1.3 for Windows accidentally was not compiled with support for the Spatial Extensions (OpenGIS). This was fixed by rebuilding from the same 4.1 code snapshot with the missing option and releasing those packages as version 4.1.3a.
To enable compiling the newly released PHP 5 against MySQL 4.1.3 on Windows, the Windows packages had to be rebuilt once more to add a few missing symbols to the MySQL client library. These packages were released as MySQL 4.1.3b.
Functionality added or changed:
ARCHIVE
storage engine.
ucs2
and utf8
Unicode character sets: Icelandic, Latvian, Romanian, Slovenian, Polish,
Estonian, Swedish, Turkish, Czech, Danish, Lithuanian, Slovak, Spanish,
Traditional Spanish.
@@time_zone
system
variable to a value such as '+10:00'
or 'Europe/Moscow'
(where
'Europe/Moscow'
is the name of one of the time zones described in the
system tables). Functions like CURRENT_TIMESTAMP
,
UNIX_TIMESTAMP
, and so forth honor this time zone. Values of
TIMESTAMP
type are also interpreted as values in this time zone. So
now our TIMESTAMP
type behaves similar to Oracle's TIMESTAMP
WITH LOCAL TIME ZONE
. That is, values stored in such a column are
normalized toward UTC and converted back to the current connection time
zone when they are retrieved from such a column.
To set up the tables that store time zone information, see
section 2.9 Post-Installation Setup and Testing.
timezone
system variable has been removed and replaced by
system_time_zone
.
See section 5.2.3 Server System Variables.
CONVERT_TZ()
was
added. It assumes that its first argument is a datetime value in the time zone
specified by its second argument and returns the equivalent datetime value in
the time zone specified by its third argument.
CHECK TABLE
now can be killed. It will then mark the table as corrupted.
See section 13.5.5.3 KILL
Syntax.
mysql_shutdown()
now requires a second argument.
This is a source-level incompatibility that affects how you compile client
programs; it does not affect the ability of compiled clients to communicate
with older servers.
See section 22.2.3.54 mysql_shutdown()
.
OPTIMIZE TABLE
for InnoDB
tables is now mapped to ALTER
TABLE
instead of ANALYZE TABLE
.
sync_frm
is now a settable global variable (not only a startup option).
sync_binlog=N
global variable and startup option, which makes
the MySQL server synchronize its binary log to disk (fdatasync()
) after
every Nth write to the binary log.
slave-skip-errors
).
DROP DATABASE IF EXISTS
, DROP TABLE IF EXISTS
, single-table
DELETE
and single-table UPDATE
are now written to the binary log
even if they changed nothing on the master (for example, even if the
DELETE
matched no row). The old behavior sometimes caused bad surprises
in replication setups.
mysqlbinlog
now have better support for the case that
the session character set and collation variables are changed within a given
session.
See section 6.7 Replication Features and Known Problems.
--innodb-safe-binlog
server option, which adds consistency
guarantees between the content of InnoDB
tables and the binary log.
See section 5.9.4 The Binary Log.
LIKE
now supports the use of a prepared statement parameter or
delimited constant expression as the argument to ESCAPE
(Bug #4200).
Bugs fixed:
CREATE DATABASE IF NOT EXISTS
for Win32 which caused an
error if database existed. (Bug #4378)
root
account to Windows version of mysqld
.
(Bug #4242)
EXPLAIN
statement which led to server crash.
(Bug #4271)
MERGE
tables created with INSERT_METHOD=LAST
, that
were not able to report a key number that caused ``Duplicate entry''
error for UNIQUE
key in INSERT
. As a result, error message was
not precise enough (error 1022 instead of error 1062) and
INSERT ... ON DUPLICATE KEY UPDATE
did not work.
(Bug #4008)
DELETE
from a table with FULLTEXT
indexes
which under rare circumstances could result in a corrupted table, if words of
different lengths may be considered equal (which is possible in some
collations, for example, in utf8_general_ci
or latin1_german2_ci
.)
(Bug #3808)
HAVING
clause. (Bug #3984)
mysqldump
when it didn't return an error if
the output device was filled (Bug #1851)
MYSQL_TIME
application buffer (prepared statements API). (Bug #4030)
DATETIME
or TIMESTAMP
column. (Bug #2336)
IN()
queries on
different key parts. (Bug #4157)
NULL
and derived tables. (Bug #4097)
UNION
results if display length of fields for numeric
types was set less then real length of values in them. (Bug #4067)
mysql_stmt_close()
, which hung up when attempting
to close statement after failed mysql_stmt_fetch()
. (Bug #4079)
COUNT(*)
, MAX()
and
MIN()
functions in prepared statements. (Bug #2687)
COUNT(DISTINCT)
performance degradation in cases
like COUNT(DISTINCT a TEXT, b CHAR(1))
(no index used). (Bug #3904)
MATCH ... AGAINST(... IN BOOLEAN MODE)
that
under rare circumstances could cause wrong results
if in the data's collation one byte could match many
(like in utf8_general_ci
or latin1_german2_ci
.)
(Bug #3964)
MYSQL_TYPE_TIME
/MYSQL_TYPE_DATETIME
columns was not sent to
the client. (Bug #4026)
--with-charset
with configure
didn't
affect the MySQL client library. (Bug #3990)
CONCAT(?, col_name)
in prepared
statements. (Bug #3796)
mysql_real_connect()
(which
required a compromised DNS server and certain operating systems). (Bug #4017)
mysqld
was run as the root
system user, and if you had
--log-bin=file_name
, where the file was located somewhere
outside of the data directory, it created binary log files owned by
root
in this directory that remained owned by root
after the
installation. This is now fixed by starting mysqld
as the
mysql
system user instead. (Bug #4038)
DROP DATABASE
honor the value of
lower_case_table_names
. (Bug #4066)
INSERT ... SELECT
if it
examined more than 4 billion rows. (Bug #3871)
mysqlbinlog
didn't escape the string content of user variables, and did
not deal well when these variables were in non-ASCII character sets; this is
now fixed by always printing the string content of user variables in
hexadecimal. The character set and collation of the string is now also
printed. (Bug #3875)
AND
/OR
expressions if query was ignored (either by a
replication server because of --replicate-*-table
rules, or by any MySQL
server because of a syntax error). (Bug #3969, Bug #4494)
Functionality added or changed:
EXAMPLE
storage engine.
mysqld
Windows server was renamed to mysqld-debug
.
See section 2.3.9 Selecting a MySQL Server type.
Handler_discover
status variable.
MYSQL_TYPE_BLOB
type
code in prepared statement protocol.
SELECT
of UNION
in output of
EXPLAIN SELECT
statement.
mysql
command-line client now supports multiple -e
options.
(Bug #591)
myisam_data_pointer_size
system variable.
See section 5.2.3 Server System Variables.
--log-warnings
server option now is enabled by default.
Disable with --skip-log-warnings
.
--defaults-file=file_name
option now requires that the filename
must exist (safety fix). (Bug #3413)
mysqld_multi
now creates the log in the directory named by
datadir
(from the [mysqld]
section in `my.cnf' or
compiled in), not in `/tmp' (vulnerability ID CAN-2004-0388). Thanks to
Christian Hammers from Debian Security Team for reporting this.
'a' = 'a '
then from it must follow that 'a' > 'a\t'
.
(The latter was not the case before MySQL 4.1.2.) To implement it, we had to
change how storage engines compare strings internally. As a side effect, if
you have a table where a CHAR
or VARCHAR
column in some row
has a value with the last character less than ASCII(32)
, you will have
to repair this table. CHECK TABLES
will tell you if this problem
exists. (Bug #3152)
DEFAULT CURRENT_TIMESTAMP
and for ON UPDATE
CURRENT_TIMESTAMP
specifications for TIMESTAMP
columns. Now you can
explicitly say that a TIMESTAMP
column should be set automatically
to the current timestamp for INSERT
and/or UPDATE
statements, or
even prevent the column from updating automatically. Only one column with such
an auto-set
feature per table is supported. TIMESTAMP
columns created with earlier
versions of MySQL behave as before. Behavior of TIMESTAMP
columns that
were created without explicit specification of default/on as earlier
depends on its position in table: If it is the first TIMESTAMP
column, it will
be treated as having been specified as TIMESTAMP DEFAULT
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
.
In other cases, it would be treated as a TIMESTAMP DEFAULT 0
column.
NOW
is supported as an alias for CURRENT_TIMESTAMP
.
Warning: Incompatible change! Unlike in previous versions, explicit
specification of default values for TIMESTAMP
column is never ignored
and turns off the auto-set feature (unless you have CURRENT_TIMESTAMP
as
the default).
Old Name | New Name |
mysql_bind_param() | mysql_stmt_bind_param()
|
mysql_bind_result() | mysql_stmt_bind_result()
|
mysql_prepare() | mysql_stmt_prepare()
|
mysql_execute() | mysql_stmt_execute()
|
mysql_fetch() | mysql_stmt_fetch()
|
mysql_fetch_column() | mysql_stmt_fetch_column()
|
mysql_param_count() | mysql_stmt_param_count()
|
mysql_param_result() | mysql_stmt_param_metadata()
|
mysql_get_metadata() | mysql_stmt_result_metadata()
|
mysql_send_long_data() | mysql_stmt_send_long_data()
|
MYSQL_STMT
structure begin with
the prefix mysql_stmt_
.
mysql_stmt_prepare()
function was changed to
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
unsigned long length)
.
To create a MYSQL_STMT
handle, you
should use the mysql_stmt_init()
function, not
mysql_stmt_prepare()
.
SHOW GRANTS
with no FOR
clause or with FOR
CURRENT_USER()
shows the privileges for the current session.
MyISAM
and HEAP
storage engines is now available for
InnoDB
as well.
PRIMARY KEY
if the table has one.)
(Bug #856)
SET
or ENUM
column with
duplicate values in the list is created. (Bug #1427)
SQL_SELECT_LIMIT
variable has no influence on subqueries.
(Bug #2600)
UNHEX()
function implemented.
See section 12.3 String Functions.
mysql
command-line client no longer stores in the history file
multiple copies of identical queries that are run consecutively.
mysql
command-line client now are stored
in the history file as a single line.
UUID()
function implemented. Note that it does not work with replication
yet.
See section 12.8.4 Miscellaneous Functions.
MyISAM
tables now support keys up to 1000 bytes long.
MyISAM
and InnoDB
tables now support index prefix lengths up
to 1000 bytes long.
ft_boolean_syntax
variable now can be changed while the server is
running.
See section 5.2.3 Server System Variables.
REVOKE ALL PRIVILEGES, GRANT FROM user_list
is changed to a more consistent
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_list
. (Bug #2642)
'0x10'+0
will not work anymore.
(Actually, it worked only on some systems before, such as Linux. It
did not work on others, such as FreeBSD or Solaris. Making these queries
OS-independent was the goal of this change.) Use CONV()
to convert
hexadecimal numbers to decimal. E.g. CONV(MID('0x10',3),16,10)+0
.
mysqlhotcopy
now works on NetWare.
ALTER TABLE DROP PRIMARY KEY
no longer drops the first UNIQUE
index if there is no primary index. (Bug #2361)
latin1_spanish_ci
(Modern Spanish) collation for the latin1
character set.
ENGINE
table option as a synonym for the TYPE
option
for CREATE TABLE
and ALTER TABLE
.
--default-storage-engine
server option as a synonym for
--default-table-type
.
storage_engine
system variable as a synonym for
table_type
.
Type
output column for SHOW TABLE STATUS
now is labeled
Engine
.
init_connect
and init_slave
system variables.
The values should be SQL statements to be executed when each client
connects or each time a slave's SQL thread starts, respectively.
SERVER_QUERY_NO_INDEX_USED
and
SERVER_QUERY_NO_GOOD_INDEX_USED
flags are now set
in the server_status
field of the MYSQL
structure.
It is these flags that make the query to be logged as slow
if mysqld
was started with --log-slow-queries
--log-queries-not-using-indexes
.
MEMORY
(HEAP
) tables: Made the master
automatically write a DELETE FROM
statement to its binary log when a
MEMORY
table is opened for the first time since master's startup.
This is for the case where the slave has replicated a non-empty
MEMORY
table, then the master is shut down and restarted: the table
is now empty on master; the DELETE FROM
empties it on slave too. Note
that even with this fix, between the master's restart and the first use of
the table on master, the slave still has out-of-date data in the table. But
if you use the init-file
option to populate the MEMORY
table
on the master at startup, it ensures that the failing time interval is zero.
(Bug #2477)
DROP TEMPORARY TABLE IF
EXISTS
instead of DROP TEMPORARY TABLE
, for more robustness.
SET SQL_LOG_BIN
or SET
SQL_LOG_UPDATE
is issued by a user without the SUPER
privilege (in
previous versions it just silently ignored the statement in this case).
--log-bin
option was used), then no transaction binary log cache
is allocated for connections. This should save binlog_cache_size
bytes of memory (32KB by default) for every connection.
Binlog_cache_use
and Binlog_cache_disk_use
status
variables that count the number of transactions that used transaction binary
log and that had to flush this temporary binary log to disk instead of using
only the in-memory buffer. They can be used for tuning the
binlog_cache_size
system variable.
--replicate-same-server-id
.
--to-last-log
to mysqlbinlog
, for use in conjunction
with --read-from-remote-server
.
Bugs fixed:
EXPLAIN
of UNION
. (Bug #3639)
DISTINCT
and ORDER BY
by column's real name, while the column had an alias, specified in
SELECT
clause. (Bug #3681)
mysqld
could crash when a table was altered and used at the same time.
This was a 4.1.2-specific bug. (Bug #3643).
WHERE
with PROCEDURE ANALYSE()
.
(Bug #2238).
GRANT
accounts until FLUSH PRIVILEGES
was executed.
(Bug #3404)
GROUP_CONCAT()
on expression with ORDER BY
and external ORDER BY
in a query. (Bug #3752)
ALL
/SOME
subqueries in case of optimization (key
field present in subquery). (Bug #3646)
SHOW GRANTS
and EXPLAIN SELECT
character
set conversion. (Bug #3403)
ORDER BY
list.
UNION
statements did not consult SQL_SELECT_LIMIT
value when
set. This is now fixed properly, which means that this limit is applied
to the top level query, unless LIMIT
for entire UNION
is
used.
UPDATE
statements that resulted in an
error when one of the tables was not updated but was used in the nested query,
contained therein.
mysql_stmt_send_long_data()
behavior on second execution of
prepared statement and in case when long data had zero length. (Bug #1664)
UNION
.
(Bug #3577)
mysql_stmt_attr_set(..., STMT_ATTR_UPDATE_MAX_LENGTH)
to tell the client library to update MYSQL_FIELD->max_length
when
doing mysql_stmt_store_result()
. (Bug #1647).
FROM
clause with parameter used. (Bug #3020)
DELETE
statement in prepared statements. (Bug #3411)
UPDATE
privilege for tables which will not be updated in
multiple-table UPDATE
statement in prepared statements.
INSERT
, REPLACE
,
CREATE
, DELETE
, SELECT
, DO
, SET
and
SHOW
. All other commands are prohibited via prepared statement
interface. (Bug #3398, Bug #3406, Bug #2811)
GROUP_CONCAT()
. (Bug #2695, Bug #3381, Bug #3319)
character_set_results
variable to NULL
.
(Bug #3296)
ANALYZE TABLE
on a BDB
table inside a transaction
that hangs server thread. (Bug #2342)
myisamchk -p
, myisam_repair_threads
);
sometimes the repair process failed to repair a table. (Bug #1334)
UNION [DISTINCT]
and UNION ALL
now works correctly. (Bug #1428)
LONGBLOB
columns. (Bug #2821)
CONCAT_WS()
makes the server die in case of illegal mix of collations. (Bug #3087)
DROP DATABASE
to report number of tables deleted.
mysql_stmt_close
after
mysql_close
). (Bug #3073)
OR
and AND
functions. (Bug #2838)
--lower_case_table_names
option. (Bug #2880)
NULL
if index built on column where NULL
is impossible in IN
subquery optimization. (Bug #2393)
FROM
clause. (Bug #2421)
RAND()
in subqueries with static tables. (bug #2645)
mysqldump
for
various values of sql_mode
of server. (Bug #2591)
DOUBLE
and
FLOAT
columns.
(Bug #2082)
--with-pstack
with binutils 2.13.90. (Bug #1661)
GRANT
system. When a password was assigned to an
account at the global level and then privileges were granted at the database
level (without specifying any password), the existing password was replaced
temporarily in memory until the next FLUSH PRIVILEGES
operation or
the server was restarted. (Bug #2953)
Max_used_connections
to be less than
the actual maximum number of connections in use simultaneously.
Index_length
in HEAP
table status for
BTREE
indexes. (Bug #2719)
mysql_stmt_affected_rows()
call to always return number of rows
affected by given statement. (Bug #2247)
MATCH ... AGAINST()
on a phrase search operator with
a missing closing double quote. (Bug #2708)
mysqldump --tab
. (Bug #2705)
UNION
operations that prevented proper handling of
NULL
columns. This happened only if a column in the first
SELECT
node was NOT NULL
. (Bug #2508)
UNION
operations with InnoDB
storage engine,
when some columns from one table were used in one SELECT
statement and
some were used in another SELECT
statement. (Bug #2552)
SHOW CREATE TABLE ...
which didn't properly double
quotes. (Bug #2593)
FROM
clause locks all tables at once for now.
This also fixed bugs in EXPLAIN
of subqueries
in FROM
output. (Bug #2120)
mysqldump
not quoting ``tricky'' names correctly.
(Bug #2592)
CREATE TABLE ... LIKE ...
that resulted
in a statement not being written to the binary log. (Bug #2557)
INSERT ... ON DUPLICATE KEY UPDATE ...
.
(Bug #2438)
CONVERT(expr,type)
legal again.
INET_ATON()
. (Bug #2310)
CREATE ... SELECT
that sometimes caused a
string column with a multi-byte character set (such as utf8
) to have
insufficient length to hold the data.
INSERT
, REPLACE
,
UPDATE
, etc. but not DELETE
) to a FULLTEXT
index.
(Bug #2417)
MySQL-client
RPM package against libreadline
instead
of libedit
. (Bug #2289)
vio_timeout()
virtual function for all protocols. This bug occurred on
Windows. (Bug #2025)
mysql
client program to erroneously
cache the value of the current database. (Bug #2025)
mysql_set_server_option()
or
mysql_get_server_option()
were invoked.
(Bug #2207)
CAST()
was
applied on NULL
to signed or unsigned integer column.
(Bug #2219)
mysql
client program when
database name was longer then expected.
(Bug #2221)
CHECK TABLE
that sometimes
resulted in a spurious error Found key at page ... that points to record
outside datafile
for a table with a FULLTEXT
index. (Bug #2190)
GRANT
with table-level privilege handling. (Bug #2178)
ORDER BY
on a small column. (Bug #2147)
INTERVAL()
function when 8 or more
comparison arguments are provided. (Bug #1561)
postinstall
script
(mysql_install_db
was called with an obsolete argument).
MySQL-server-4.1.1-0
to MySQL-server-4.1.1-1
. The
other RPMs were not affected by this change.
myisamchk
and CHECK TABLE
that sometimes
resulted in a spurious error Found key at page ... that points to record
outside datafile
for a table with a FULLTEXT
index. (Bug #1977)
utf8
) charsets. (Bug #2065)
OPTIMIZE TABLE
or REPAIR
TABLE
), this could sometimes stop the slave SQL thread. This does not lead
to any corruption, but you must use START SLAVE
to get replication
going again. (Bug #1858)
UPDATE
could produce an
incorrect complaint that some record was not found in one table, if the
UPDATE
was preceded by a INSERT ... SELECT
. (Bug #1701)
MyISAM
table first receives "no space left on device" but is able to finally
complete, see section A.4.3 How MySQL Handles a Full Disk); the bug was that the master forgot to reset the
error code to 0 after success, so the error code got into its binary log, thus
making the slave giving false alarms like "did not get the same error as on
master". (Bug #2083)
ALTER DATABASE
caused the client to hang if the database did not
exist. (Bug #2333)
DELETE
statements were never replicated by the slave if
there were any --replicate-*-table
options. (Bug #2527)
ALTER TABLE RENAME
, when rename to the table with
the same name in another database silently dropped destination table if
it existed. (Bug #2628)
mysql_real_query()
or mysql_stmt_prepare()
) was terminated
by garbage characters. This can happen if you pass a wrong length
parameter to these functions. The result was that the
garbage characters were written into the binary log. (Bug #2703)
mysql_stmt_fetch
and
mysql_stmt_store_result()
to hang if they were called without
prior call of mysql_stmt_execute()
. Now they give an error instead.
(Bug #2248)
--read-only
option. (Bug #2757)
--replicate-wild-*-table
rules apply to ALTER DATABASE
when the table pattern is %
, as is the case for CREATE
DATABASE
and DROP DATABASE
. (Bug #3000)
Rotate
event is found by the slave SQL thread in the
middle of a transaction, the value of Relay_Log_Pos
in SHOW SLAVE
STATUS
remains correct. (Bug #3017)
InnoDB
reports when it is doing a
crash recovery on a slave server. (Bug #3015)
Seconds_Behind_Master
in SHOW SLAVE STATUS
to
never show a value of -1. (Bug #2826)
DROP TEMPORARY TABLE
statement is automatically
written to the binary log when a session ends, the statement is recorded with an
error code of value zero (this ensures that killing a SELECT
on the
master does not result in a superfluous error on the slave). (Bug #3063)
INSERT DELAYED
(also known as a
delayed_insert
thread) is killed, its statements are recorded with an
error code of value zero (killing such a thread does not endanger
replication, so we thus avoid a superfluous error on the slave). (Bug #3081)
START SLAVE
commands were run at the same
time. (Bug #2921)
--replicate-*
options. The bug was that if the
statement had been killed on the master, the slave would stop. (Bug #2983)
--local-load
option of mysqlbinlog
now requires an argument.
LOAD DATA FROM MASTER
after
RESET SLAVE
. (Bug #2922)
mysqlbinlog --read-from-remote-server
read all binary logs following the
one that was requested. It now stops at the end of the requested file, the
same as it does when reading a local binary log. There is an option
--to-last-log
to get the old behavior. (Bug #3204)
mysqlbinlog --read-from-remote-server
to print the exact
positions of events in the "at #" lines. (Bug #3214)
Binlog has bad magic number
and stop when it
was not necessary to do so. (Bug #3401)
Exec_master_log_pos
column and its disk image in the
`relay-log.info' file to be correct if the master had version 3.23. (The
value was too big by six bytes.) This bug does not exist in MySQL 5.0.
(Bug #3400)
mysqlbinlog
not to forget to print a USE
statement
under rare circumstances where the binary log contained a LOAD DATA
INFILE
statement. (Bug #3415)
LOAD DATA INFILE
when the
master had version 3.23. Some smaller problems remain in this setup,
See section 6.7 Replication Features and Known Problems. (Bug #3422)
DELETE
statements were always replicated by the slave if
there were some --replicate-*-ignore-table
options and no
--replicate-*-do-table
options. (Bug #3461)
--with-debug
and replicating itself. (Bug #3568)
REPAIR TABLE
that resulted sometimes in a corrupted
table, if the table contained FULLTEXT
indexes and many words
of different lengths that are considered equal (which is possible in
certain collations, such as latin1_german2_ci
or utf8_general_ci
).
(Bug #3835)
mysqld
that was started with binary
logging disabled, but with a non-zero value for the expire_logs_days
system variable.
(Bug #3807)
server-id
was not set using startup options but with SET
GLOBAL
, the replication slave still complained that it was not set. (Bug
#3829)
This release includes all fixes in MySQL 4.0.16 and most of the fixes in MySQL 4.0.17.
Functionality added or changed:
lower_case_table_names
is
non-zero.
--old-protocol
option for mysqld
is no longer supported
and has been removed.
bdb_version
system variable to version_bdb
.
CHECKSUM TABLE
statement for reporting table checksum values.
character_set_client
, character_set_connection
,
character_set_database
, character_set_results
,
character_set_server
, character_set_system
,
collation_connection
, collation_database
, and
collation_server
system variables to provide information about
character sets and collations.
CACHE INDEX
Syntax.
See section 13.5.5.4 LOAD INDEX INTO CACHE
Syntax.
Structured system
variables are introduced as a means of grouping related key cache parameters.
See section 9.4.1 Structured System Variables.
preload_buffer_size
system variable.
COERCIBILITY()
function to return the collation coercibility of a
string.
--quote-names
option for mysqldump
now is enabled
by default.
mysqldump
now includes a statement in the dump output to set
FOREIGN_KEY_CHECKS
to 0 to avoid problems with tables having to be
reloaded in a particular order when the dump is reloaded. The existing
FOREIGN_KEY_CHECKS
value is saved and restored.
InnoDB
-4.1.1 or higher,
you cannot downgrade to a version lower than 4.1.1
any more! That is because earlier versions of InnoDB
are not aware of
multiple tablespaces.
REVOKE ALL PRIVILEGES, GRANT FROM user_list
.
IGNORE
option for DELETE
statement.
mysql_set_server_option()
C API client function to allow multiple
statement handling in the server to be enabled or disabled.
mysql_next_result()
C API function now returns -1
if there
are no more result sets.
CLIENT_MULTI_QUERIES
connect option flag to
CLIENT_MULTI_STATEMENTS
. To allow for a transition period, the old
option will continue to be recognized for a while.
DEFAULT
before table and database default character set.
This enables us to use ALTER TABLE tbl_name ... CHARACTER SET=...
to change the character set for all CHAR
, VARCHAR
, and
TEXT
columns in a table.
MATCH ... AGAINST( ... WITH QUERY EXPANSION)
and the
ft_query_expansion_limit
system variable.
ft_max_word_len_for_sort
system variable.
ft_max_word_len_for_sort
variable from myisamchk
.
utf8
character set. (The Unicode ucs2
character set is not
yet supported.)
MATCH ... AGAINST ( ... IN BOOLEAN MODE)
no longer
matches partial words.
BIT_XOR()
for bitwise XOR operations.
START SLAVE
statement now supports an UNTIL
clause for
specifying that the slave SQL thread should be started but run only until it
reaches a given position in the master's binary logs or in the slave's relay logs.
INSERT
statements, not just for
multiple-row INSERT
statements. Previously, it was necessary to set
SQL_WARNINGS=1
to generate warnings for single-row statements.
delimiter
(\d
) command to the mysql
command-line
client for changing the statement delimiter (terminator).
The default delimiter is semicolon.
CHAR
, VARCHAR
, and TEXT
columns now have lengths measured
in characters rather than in bytes.
The character size depends on the column's character set.
This means, for example, that a CHAR(n)
column
for a multi-byte character set will take more storage than before.
Similarly, index values on such columns are measured in characters, not bytes.
LIMIT
no longer accepts negative arguments
(they used to be treated as very big positive numbers before).
DATABASE()
function now returns NULL
rather than the empty
string if there is no database selected.
--sql-mode=NO_AUTO_VALUE_ON_ZERO
option to suppress the usual
behavior of generating the next sequence number when zero is stored in
an AUTO_INCREMENT
column. With this mode enabled, zero is stored as
zero; only storing NULL
generates a sequence number.
user
table, not 45-byte passwords as in 4.1.0.
Any 45-byte passwords created for 4.1.0 must be reset after running the
mysql_fix_privilege_tables
script.
secure_auth
global server system variable and --secure-auth
server option that disallow authentication for accounts that have old
(pre-4.1.1) passwords.
--secure-auth
option to mysql
command-line client. If this
option is set, the client refuses to send passwords in old (pre-4.1.1) format.
mysql_prepare_result()
function to
mysql_get_metadata()
as the old name was confusing.
DROP USER 'user_name'@'host_name'
statement to drop an account
that has no privileges.
xxx_clear()
function for each aggregate function XXX()
.
ADDTIME()
, DATE()
, DATEDIFF()
, LAST_DAY()
,
MAKEDATE()
, MAKETIME()
, MICROSECOND()
, SUBTIME()
,
TIME()
, TIMEDIFF()
, TIMESTAMP()
, UTC_DATE()
,
UTC_TIME()
, UTC_TIMESTAMP()
, and WEEKOFYEAR()
functions.
ADDDATE()
and SUBDATE()
.
The second argument now may be a number representing the number of days to
be added to or subtracted from the first date argument.
type
values DAY_MICROSECOND
,
HOUR_MICROSECOND
, MINUTE_MICROSECOND
,
SECOND_MICROSECOND
, and MICROSECOND
for DATE_ADD()
, DATE_SUB()
, and EXTRACT()
.
%f
microseconds format specifier for DATE_FORMAT()
and
TIME_FORMAT()
.
SELECT
does not use indexes properly
now are written to the slow query log when long log format is used.
MERGE
table from MyISAM
tables in
different databases. Formerly, all the MyISAM
tables had to be in the
same database, and the MERGE
table had to be created in that database
as well.
COMPRESS()
, UNCOMPRESS()
, and
UNCOMPRESSED_LENGTH()
functions.
SET sql_mode='mode'
for a complex mode (like ANSI
), we
now update the sql_mode
variable to include all the individual options
implied by the complex mode.
ROLLUP
, which
provides summary rows for each GROUP BY
level.
SQLSTATE
codes for all server errors.
mysql_sqlstate()
and mysql_stmt_sqlstate()
C API client
functions that return the SQLSTATE
error code for the last error.
TIME
columns with hour values greater than 24 were returned incorrectly
to the client.
ANALYZE TABLE
, OPTIMIZE TABLE
, REPAIR TABLE
, and FLUSH
statements
are now stored in the binary log and thus replicated to slaves.
This logging does not occur if the optional NO_WRITE_TO_BINLOG
keyword
(or its alias LOCAL
) is given. Exceptions are that
FLUSH LOGS
, FLUSH MASTER
, FLUSH SLAVE
, and
FLUSH TABLES WITH READ LOCK
are not logged in any case.
For a syntax example, see section 13.5.5.2 FLUSH
Syntax.
relay_log_purge
to enable or disable automatic
relay log purging.
LOAD DATA
now produces warnings that can be fetched with
SHOW WARNINGS
.
CREATE TABLE table2 (LIKE table1)
that creates an empty table table2
with a definition that is
exactly the same as table1
, including any indexes.
CREATE TABLE tbl_name (...) TYPE=storage_engine
now generates a
warning if the named storage engine is not available. The table is still
created as a MyISAM
table, as before.
PURGE BINARY LOGS
as an alias for PURGE MASTER LOGS
.
PURGE LOGS
statement that was added in version 4.1.0.
The statement now should be issued as PURGE MASTER LOGS
or
PURGE BINARY LOGS
.
SHOW BDB LOGS
as an alias for SHOW LOGS
.
SHOW MASTER LOGS
as an alias for SHOW BINARY LOGS
.
(In 4.1.0, SHOW MASTER LOGS
was renamed to SHOW BINARY LOGS
.
Now you can use either one.)
Slave_IO_State
and Seconds_Behind_Master
columns
to the output of SHOW SLAVE STATUS
.
Slave_IO_State
indicates the state of the slave I/O thread, and
Seconds_Behind_Master
indicates the number of seconds by
which the slave is late compared to the master.
--lower-case-table-names=1
server option now also makes aliases case
insensitive. (Bug #534)
Bugs fixed:
mysql
parser not to erroneously interpret `;' character
within /* ... */
comment as statement terminator.
UNION
operations. The types and lengths now are determined taking into
account values for all SELECT
statements in the UNION
,
not just the first SELECT
.
[CREATE | REPLACE| INSERT] ... SELECT
statements.
HASH
, BTREE
, RTREE
, ERRORS
, and
WARNINGS
no longer are reserved words. (Bug #724)
ROLLUP
when all tables were const
tables.
(Bug #714)
UNION
that prohibited NULL
values from being
inserted into result set columns where the first SELECT
of the
UNION
retrieved NOT NULL
columns. The type and max_length
of the result column is now defined based on all UNION
parts.
WHERE
clause
bigger than outer query WHERE
clause. (Bug #726)
MyISAM
tables with FULLTEXT
indexes
created in 4.0.x to be unreadable in 4.1.x.
REPAIR TABLE ... USE_FRM
when used
with tables
that contained TIMESTAMP
columns and were created in 4.0.x.
ORDER BY
/GROUP BY
clauses. (Bug #442)
INSERT
/REPLACE
statements. (Bug #446)
CREATE FULLTEXT INDEX
syntax illegal.
SELECT
that required a temporary table
(marked by Using temporary
in EXPLAIN
output)
was used as a derived table in EXPLAIN
command. (Bug #251)
DELETE
from a big table with
a new (created by MySQL-4.1) full-text index.
LAST_INSERT_ID()
now returns 0 if the last INSERT
statement
didn't insert any rows.
BEGIN
, in the
first relay log.) (Bug #53)
CONNECTION_ID()
now is properly replicated. (Bug #177)
PASSWORD()
function in 4.1 is now properly replicated.
(Bug #344)
UNION
operations that involved temporary tables.
DERIVED TABLES
when EXPLAIN
is
used on a DERIVED TABLES
with a join.
DELETE
with ORDER BY
and
LIMIT
caused by an uninitialized array of reference pointers.
USER()
function caused by an error in the size of
the allocated string.
UNION
caused by the empty select list and
a non-existent column being used in some of the individual SELECT
statements.
FLUSH LOGS
was
issued on the master. (Bug #254)
REQUIRE SSL
option specified for
their accounts.
INSERT INTO t VALUES(@a)
, where @a
had never
been set by this connection before), the slave could replicate the
query incorrectly if a previous transaction on the master used a user
variable of the same name. (Bug #1331)
?
prepared statement
parameter as the argument to certain functions or statement clauses caused
a server crash when mysql_prepare()
was invoked. (Bug #1500)
SLAVE START
(which is a deprecated syntax, START SLAVE
should be
used instead) could crash the slave. (Bug #2516)
ALTER TABLE RENAME
, when rename to the table with
the same name in another database silently dropped destination table if
it existed. (Bug #2628)
SET PASSWORD FOR user
it's now
defaulted to %
instead of the current host.
Functionality added or changed:
SHOW MASTER LOGS
statement to SHOW BINARY LOGS
.
DEFAULT(col_name)
in expressions; it produces the
column's default value.
--compatible
option to mysqldump
for producing output that
is compatible with other database systems or with older MySQL servers.
--opt
option for mysqldump
now is enabled by default,
as are all the options implied by --opt
.
CHARSET()
and COLLATION()
functions to return the character
set and collation of a string.
USING type_name
syntax in index definition.
IS_USED_LOCK()
for determining the connection identifier
of the client that holds a given advisory lock.
user
table.
old-password
command to mysqladmin
for changing
password but storing it using the old password-hashing format.
CRC32()
function to compute cyclic redundancy check value.
localhost
.
REPAIR TABLE
of MyISAM
tables now uses less temporary disk space when
sorting char columns.
DATE
/DATETIME
checking is now a bit stricter to support the
ability to automatically distinguish between date, datetime, and time
with microseconds. For example, dates of type YYYYMMDD HHMMDD
are no
longer supported; you 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()
C API client function.
libmysqlclient
that fetched column defaults.
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 13.5.5.3 KILL
Syntax.
REPAIR TABLE
and OPTIMIZE TABLE
now can be killed. See section 13.5.5.3 KILL
Syntax.
USE INDEX
,
IGNORE INDEX
, and FORCE INDEX
.
DROP TEMPORARY TABLE
now drops only temporary tables and doesn't
end transactions.
UNION
in derived tables.
TIMESTAMP
is now returned as a string of type
'YYYY-MM-DD HH:MM:SS'
and different timestamp lengths are not supported.
This change was necessary for SQL standards compliance. In a future
version, a further change will be made (backward compatible with this
change), allowing the timestamp length to indicate the desired number
of digits of fractions of a second.
MYSQL_FIELD
structure.
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 UNSIGNED 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
.
DIV
is now a reserved word.
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;
CONVERT(... USING ...)
syntax for converting string values between
character sets.
BTREE
index on MEMORY
(HEAP
) tables.
CREATE TABLE
.
SHOW FULL COLUMNS FROM tbl_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)
function returns the variance of expr
CREATE
[TEMPORARY] TABLE [IF NOT EXISTS] table (LIKE table)
. The table can
be either normal or temporary.
--reconnect
and --skip-reconnect
for the
mysql
client, to reconnect automatically or not if the
connection is lost.
START SLAVE
(STOP SLAVE
) no longer returns an error
if the slave is started (stopped); it returns a
warning instead.
SLAVE START
and SLAVE STOP
are no longer accepted by the query
parser; use START SLAVE
and STOP SLAVE
instead.
Version 4.0 of the MySQL server includes many enhancements and new features:
InnoDB
storage engine is now included in the standard binaries,
adding transactions, row-level locking, and foreign keys.
See section 15 The InnoDB
Storage Engine.
MERGE
tables, now supporting INSERT
statements and
AUTO_INCREMENT
.
See section 14.2 The MERGE
Storage Engine.
UNION
syntax in SELECT
.
See section 13.1.7.2 UNION
Syntax.
DELETE
statements.
See section 13.1.1 DELETE
Syntax.
libmysqld
, the embedded server library.
See section 22.2.16 libmysqld, the Embedded MySQL Server Library.
GRANT
privilege options for even tighter control and
security.
See section 13.5.1.3 GRANT
and REVOKE
Syntax.
GRANT
system, particularly
useful for ISPs and other hosting providers.
See section 5.6.4 Limiting Account 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:
InnoDB
: Added configuration option and settable global variable
innodb_autoextend_increment
for setting the size in megabytes by
which InnoDB
tablespaces are extended when they become full. The
default value is 8, corresponding to the fixed increment of 8MB in
previous versions of MySQL.
InnoDB
table lock in LOCK
TABLES
if AUTOCOMMIT=1
. This helps in porting old MyISAM
applications to InnoDB
. InnoDB
table locks in that case
caused deadlocks very easily.
Bugs fixed:
--replicate-*-table
options had been specified.
(Bug #7011)
set_bit()
and clear_bit()
functions in source code
to avoid a conflict with functions of the same names in Linux kernel
header files. (Bug #7971)
QUOTE()
function returning bad results.
(Bug #8248)
INSERT INTO ...SELECT
failed when the source and
target table were the same. (Bug #6034)
tmpfile()
function on Netware. All InnoDB
temporary files will be created under sys:\tmp
. Previously,
InnoDB temporary files were never deleted on Netware.
mysqlaccess
script.
Reported by Javier Fernandez-Sanguino Pena
and Debian Security Audit Team.
( CAN-2005-0004)
mysql_list_fields()
, which was
accidentally broken in 4.0.22 (Bug#6761)
query_cache_wlock_invalidate
system variable visible in
SHOW VARIABLES
output. (Bug #7594)
FROM_UNIXTIME()
function to return
NULL
for zero argument instead of the Epoch. (Bug #7515)
QUOTE
function when used in conjunction with some
other string functions. This lead to severe buffer overflow and server
crashing. (Bug #7495)
mysqld
binaries built on HP-UX-11 did
not work with InnoDB
files greater than 2 GB in size. (Bug #6189)
MyISAM
sometimes didn't sleep and retry the write, thus
resulting in a corrupted table. (Bug #7714)
ANALYZE
TABLE
, OPTIMIZE TABLE
, or REPAIR TABLE
statements from the
master. (Bug #6461, Bug #7658)
Note: Due to a libtool-related bug in the source distribution,
the creation of shared libmysqlclient
libraries was not possible
(the resulting files were missing the .so
file name extension).
The file `ltmain.sh' was updated to fix this problem and the resulting
source distribution was released as `mysql-4.0.23a.tar.gz'. This
modification did not affect the binary packages. (Bug #7401)
Functionality added or changed:
--hex-blob
option to mysqldump
for dumping binary
string columns using hexadecimal notation.
mysql_hex_string()
C API function that hex-encodes a string.
SHOW INNODB STATUS
information
to a temporary file unless the configuration option
innodb_status_file=1
is set.
mysqlbinlog
now prints an informative commented line (thread id,
timestamp, server id, etc) before each LOAD DATA INFILE
, like it
does for other queries; unless --short-form
is used.
Bugs fixed:
mysql.user
table in Windows distributions
that had been created with a Host
value of build
rather than
%
. (Bug #6000)
CREATE TABLE .. SELECT
query to the binary log when the
insertion of new records partially failed. (Bug #6682)
FROM_UNIXTIME()
function to return wrong result
if the argument was too big. (Bug #6439)
TIMESTAMP
columns and give wrong results for UNIX_TIMESTAMP()
function if it
was run in time zone with leap seconds. (Bug #6387)
LOAD DATA INFILE…REPLACE
printing duplicate key error when executing the same
load query several times. (Bug #5835)
rewind()
when displaying
SHOW INNODB STATUS
information on stderr
.
INSERT IGNORE
to insert several rows at a time,
and the first inserts were ignored because of a duplicate key collision,
then InnoDB in a replication slave assigned AUTO_INCREMENT
values 1
bigger than in the master. This broke the MySQL replication. (Bug #6287)
FOREIGN KEY
constraints treated table and
database names as case-insensitive. RENAME TABLE t TO T
would hang
in an endless loop if t
had a foreign key constraint defined on it.
Fix also a hang over the dictionary mutex that would occur if one tried
in ALTER TABLE
or RENAME TABLE
to create a foreign key
constraint name that collided with another existing name. (Bug #3478)
0xA0
as space in InnoDB's
FOREIGN KEY
parser if MySQL treats it as space in
the default charset. EMS MySQL Manager inserts character
0xA0
after the table name in an ALTER
, which
confused InnoDB's parser.
SELECT FOR UPDATE
then executed a non-transactional update, that update automatically committed
the transaction (thus releasing InnoDB's row-level locks etc). (Bug #5714)
BEGIN
and ROLLBACK
binary
log events; that caused superfluous slave stops. (Bug #6522)
BEGIN
(or SET AUTOCOMMIT=0
), FLUSH TABLES
WITH READ LOCK
, transactional update, COMMIT
, FLUSH
TABLES WITH READ LOCK
could hang the connection forever and possibly the MySQL
server itself. This happened for example when running the innobackup
script several times. (Bug #6732)
Functionality added or changed:
--with-openssl
option for configure
now accepts a path
prefix as an argument. --with-openssl-includes
and
--with-openssl-libs
are still supported, but are needed only to
override the default values. (Bug #5494)
--without-man
option to configure
to suppress
building/installing the manual pages. (Bug #5379)
mysqld
option --innodb-table-locks
and session
variable innodb_table_locks
(on by default).
In applications using AUTOCOMMIT=1
and MySQL's LOCK TABLES
command, InnoDB's internal table locks that were added in 4.0.20
can cause deadlocks. You can set
innodb_table_locks=0
in `my.cnf' to remove that problem.
See section 15.17 Restrictions on InnoDB
Tables.
(Bug #3299, Bug #5998)
innodb_max_purge_lag
for delaying INSERT
, UPDATE
and DELETE
operations when the purge operations are lagging.
The default value of this parameter is zero, meaning that there will
not be any delays. See section 15.13 Implementation of Multi-Versioning.
HA_ERR_ROW_IS_REFERENCED
if we cannot
DROP
a parent table because it is referenced by a
FOREIGN KEY
constraint.
Bugs fixed:
libmysqlclient
functions mysql_create_db(), mysql_rm_db()
were called and were going to return error. (Bug #6081)
ENABLE KEYS
, which failed if tmpdir
ran out of
space. Now, a full repair is done in this case. (Bug #5625)
FOREIGN KEY
constraint. (Bug #5784)
FLUSH TABLE(S)
to close HANDLER
tables. HANDLER
tables are now reopened after a FLUSH
TABLE(S)
the next time they are used. However, they lose their file position
if this happens. (Bug #4286)
HANDLER
tables with the same alias to be
opened multiple times. HANDLER
aliases must now be unique, even though
it is syntactically correct in versions below 4.1, to qualify them with their
base table's database name (e.g. test_db.handler_tbl, but this will now
conflict with e.g. another_db.handler_tbl). (Bug #4335)
mysqlimport
now reads input files locally from the client host only
if the --local
option is given. Previously, it assumed incorrectly
in some cases that files were local even without --local
.
(Bug #5829)
FOREIGN KEY
parser that prevented
ALTER TABLE
of tables containing `#' in their names. (Bug #5856)
FLUSH TABLES WITH READ LOCK
, then COMMIT
,
would cause replication slaves to stop (complaining about error 1223).
Bug surfaced
when using the InnoDB innobackup
script. (Bug #5949)
TEXT
or BLOB
) value, then
ANOTHER externally stored column would show up as 512 bytes of good
data + 20 bytes of garbage in a consistent read that fetched the old
version of the row. (Bug #5960)
FOREIGN KEY
operation, so that we do not starve other users doing CREATE TABLE
or other DDL operations. This caused a notorious 'Long semaphore wait' message
to be printed to the `.err' log. (Bug #5961)
LOCK TABLES
,
also over plain consistent read SELECT
s.
mysqldump
with the option -l
or --opt
,
or if one used LOCK TABLES ... LOCAL
. (Workaround in 4.0.21: use
--quick
and --single-transaction
. (Bug #5538)
UNION
s. This value is printed in the slow query log.
(Bug #5879)
read_rnd_buffer_size
(Bug #5492)
TIMESTAMP
fields if --new
mode was enabled. (Bug #4131)
mysqladmin
now returns a status of 0 even when the server denies
access; such an error means the server is running. (Bug #3120)
SHOW
DATABASES
even if the database name doesn't match the given wildcard (Bug #5539)
Functionality added or changed:
./configure --comment
during
compilation) when starting the server. E.g.:
Version: '4.0.21-debug' socket: '/tmp/mysql.sock' port: 0 Official MySQL Binary
SIGHUP
and SIGQUIT
on
Mac OS X 10.3. This is needed because under this OS, the MySQL server receives
lots of these signals (reported as Bug #2030).
mysqld-nt
and mysqld-max-nt
servers now
write error messages to the Windows event log in addition to the MySQL error
log.
Bugs fixed:
MERGE
tables
(even one MERGE
table and MyISAM
tables), that could've
resulted in a crash or hang of the server. (Bug #2408)
GROUP BY
queries
with expression in HAVING
clause that refers to a BLOB
(TEXT
, TINYBLOB
, etc) fields. (Bug #4358)
HEAP
table is
dropped.
It could only happen on Windows when a symlink file (.sym) is used and
if that symlink file contained double backslashes (\\). (Bug #4973)
TIMESTAMP(19)
fields from being created.
(Bug #4491)
NULL
values in BLOB
(TINYBLOB
, TEXT
,
TINYTEXT
, etc) columns of MyISAM
tables. (Bug #4816)
ROUND()
reporting incorrect metadata
(number of digits after the decimal point). It can be seen, for example,
in CREATE TABLE t1 SELECT ROUND(1, 34)
. (Bug #4393)
SQRT()
and LOG()
. (Bug #4356)
LOAD DATA
with the LOCAL
option. The problem occurs when an error happens during the LOAD DATA
operation. Previously, the connection was broken. Now the error message
is returned and connection stays open.
col IN (val)
the same way it does
for col = val
.
net_buffer_length
when building the
DBD::mysql
Perl module. (Bug #4206)
lower_case_table_names=2
(keep case for table names) was not honored
with ALTER TABLE
and CREATE/DROP INDEX
. (Bug #3109)
DECIMAL(0,...)
column. (Bug #4046)
IF()
function incorrectly determining the result type
if aggregate functions were involved. (Bug #3987)
MATCH ... AGAINST()
on a phrase search operator with
a missing closing double quote. (Bug #3870)
server-id
was not set using startup options but with SET
GLOBAL
, the replication slave still complained that it was not set.
(Bug #3829)
mysql_real_connect()
(which
required a compromised DNS server and certain operating systems). (Bug #4017)
mysqld
was run as the root
system user, and if you had
--log-bin=<somewhere_out_of_var_lib_mysql>
it created binary log
files owned by root
in this directory, which remained owned by
root
after the installation. This is now fixed by starting
mysqld
as the mysql
system user instead. (Bug #4038)
DROP DATABASE
honor the value of
lower_case_table_names
. (Bug #4066)
INSERT ... SELECT
if it
examined more than 4 billion rows. (Bug #3871)
AND
/OR
expressions if query was ignored (either by a
replication server because of --replicate-*-table
rules, or by any MySQL
server because of a syntax error). (Bug #3969, Bug #4494)
mysqlbinlog --position --read-from-remote-server
had wrong # at
lines. (Bug #4506)
CREATE TEMPORARY TABLE t SELECT
failed while loading the data, the
temporary table was not dropped. (Bug #4551)
DROP TABLE
failed to drop a table on
the master server, the error code was not written to the binary log.
(Bug #4553)
LOAD DATA INFILE
statement, it didn't show the statement in the output of SHOW
PROCESSLIST
. (Bug #4326)
CREATE TABLE ... TYPE=HEAP ... AS SELECT...
caused
replication slave to stop. (Bug #4971)
disable-local-infile
option had no effect if client read it
from a configuration file using
mysql_options(...,MYSQL_READ_DEFAULT,...)
. (Bug #5073)
mysql-test-run
failed on the rpl_trunc_binlog
test if
running test from the installed (the target of 'make install') directory. (Bug
#5050)
KILL
. (Bug
#4810)
KILL
ed while it was doing
START SLAVE
. (Bug #4827)
FLUSH TABLES WITH READ LOCK
block COMMIT
if server is
running with binary logging; this ensures that the binary log position is
trustable when doing a full backup of tables and the binary log. (Bug #4953)
auto_increment
column was not reset by
TRUNCATE TABLE
is the table was a temporary one. (Bug #5033)
database.table.column
) when
lower_case_table_names=1
. (Bug #4792)
SET CHARACTER SET
was not replicated correctly. MySQL 4.1
does not have that bug. (Bug #4500)
Note: The windows packages had to be repackaged and re-released several times to resolve packaging issues (such as missing files). This did not affect the binaries included (they have not been recompiled), therefore the installation packages are of version 4.0.20d, while the binaries included still identify themselves as version 4.0.20b.
Functionality added or changed:
MATCH ... AGAINST ( ... IN BOOLEAN MODE)
no longer
matches partial words.
Bugs fixed:
/
reporting incorrect metadata
(number of digits after the decimal point). It can be seen, for example,
in CREATE TABLE t1 SELECT "0.01"/"3"
. (Bug #3612)
DROP DATABASE
on some configurations
(in particular, Linux 2.6.5 with ext3 are known to expose this bug).
(Bug #3594)
Note: The MySQL 4.0.19 binaries were uploaded to the download mirrors on May, 10th. However, a potential crashing bug was found just before the 4.0.19 release was publicly announced and published from the 4.0 download pages at http://dev.mysql.com/.
A fix for the bug was pushed into the MySQL source tree shortly after it could be reproduced and is included in MySQL 4.0.20. Users upgrading from MySQL 4.0.18 should upgrade directly to MySQL 4.0.20 or later.
See (Bug #3596) for details (it was reported against MySQL-4.1, but was confirmed to affect 4.0.19 as well).
Functionality added or changed:
"YYYY-MM-DD HH:MM:SS
. This is done to make it easier
to use tables created in MySQL 4.1 to be used in MySQL 4.0.
RAID_CHUNKS
with a value > 255 it will be set to 255.
This was made to ensure that all raid directories are always 2 hex bytes.
(Bug #3182)
FORCE INDEX
clause as a candidate to resolve ORDER BY
as well.
--log-warnings
server option now is enabled by default.
Disable with --skip-log-warnings
.
SELECT ... UNION SELECT ... ORDER BY ...
, it was possible
to qualify a column name in the ORDER BY
clause with a table name. This
is no longer possible. Column names in ORDER BY
should refer to names
established in the first SELECT
of the UNION
. (Bug #3064)
max_insert_delayed_threads
system variable as a synonym for
max_delayed_threads
.
query_cache_wlock_invalidate
system variable. It allows
emulation of MyISAM
table write-locking behavior, even for queries
in the query cache. (Bug #2693)
MASTER_SERVER_ID
is not reserved anymore.
InnoDB
in this case always stores filenames in lower case:
You can now force lower_case_table_names
to 0 from the command
line or a configuration file. This is useful with case-insensitive filesystems
when you have previously not used
lower_case_table_names=1
or lower_case_table_names=2
and
you have created InnoDB
tables. With
lower_case_table_names=0
, InnoDB
tables were stored in mixed case
while setting lower_case_table_names to a non-zero value now will force it to
lower case (to make the table names case insensitive).
Because it's possible to crash MyISAM
tables by referring to them with
different case on a case-insensitive filesystem, we recommend that you
use lower_case_table_names
or lower_case_table_names=2
on
such filesystems.
The easiest way to convert to use lower_case_table_names=2
is to
dump all your InnoDB
tables with mysqldump
, drop them and then
restore them.
DROP TEMPORARY TABLE IF
EXISTS
instead of DROP TEMPORARY TABLE
, for more robustness.
--replicate-same-server-id
.
Bugs fixed:
ft_stopword_file
to myisamchk
.
','
at the end of field specifications. (Bug #3481)
INTERVAL
now can handle big values for seconds, minutes and hours.
(Bug #3498)
'%'
. (Bug #3473)
SOUNDEX()
to ignore non-alphabetic characters also
in the beginning of the string. (Bug #3556)
MATCH ... AGAINST()
searches when another thread was
doing concurrent inserts into the MyISAM
table in question. The first
--- full-text search -- query could return incorrect results in this case
(for example, ``phantom'' rows or not all matching rows, even an empty result set).
The easiest way to check whether you are affected is to start mysqld
with --skip-concurrent-insert
switch and see if it helps.
DROP DATABASE
on a directory containing non-
MySQL files. Now a proper error message is returned.
ANALYZE TABLE
on a BDB
table inside a transaction
that hangs server thread. (Bug #2342)
SELECT DISTINCT
where all selected parts
where constants and there were hidden columns in the created temporary table.
(Bug #3203)
COUNT(DISTINCT)
when there was a lot of
values and one had a big value for max_heap_table_size
.
RAID
tables. (Bug #2882)
max_relay_log_size
and the slave thread did a
flush_io_cache()
at the same time.
SLAVE START
from different
threads at the same time. (Bug #2921)
DROP DATABASE
with lower_case_table_names=2
.
UNION
when using lower_case_table_names=2
.
(Bug #2858)
DELETE
and UPDATE
statements if thread is killed.
(Bug #2422)
INSERT DELAYED
statement is written at
once if binary logging is enabled. (Bug #2491).
myisamchk -p
, myisam_repair_threads
) -
sometimes repair process failed to repair a table. (Bug #1334)
UPDATE
statements involving at least one constant
table. Bug was exhibited in allowing non matching row to be updated.
(Bug #2996).
--set-character-set
and --character-sets-dir
options in
myisamchk
now work.
mysqlbinlog
that caused one pointer to be free'd twice
in some cases.
+
operator (for example,
MATCH ... AGAINST('+(+(word1 word2)) +word3*' IN BOOLEAN MODE)
.
DELETE
that was caused by foreign key
constraints. If the order of the tables established by MySQL optimizer
did not match parent-child order, no rows were deleted and no error
message was provided. (Bug #2799)
OPTIMIZE TABLE
or REPAIR
TABLE
), this could sometimes stop the slave SQL thread. This does not lead
to any corruption, but you must use START SLAVE
to get replication
going again. (Bug #1858)
The bug was accidentally not fixed in 4.0.17 as it was unfortunately
earlier said.
Rotate
event is found by the slave SQL thread in the
middle of a transaction, the value of Relay_Log_Pos
in SHOW SLAVE
STATUS
remains correct. (Bug #3017)
InnoDB
reports when it is doing a
crash recovery on a slave server. (Bug #3015)
DROP TEMPORARY TABLE
statement is automatically
written to the binary log when a session ends, the statement is recorded with an
error code of value zero (this ensures that killing a SELECT
on the
master does not result in a superfluous error on the slave). (Bug #3063)
INSERT DELAYED
(also known as a
delayed_insert
thread) is killed, its statements are recorded with an
error code of value zero (killing such a thread does not endanger
replication, so we thus avoid a superfluous error on the slave). (Bug #3081)
START SLAVE
commands were run at the same
time. (Bug #2921)
--replicate-*
options. The bug was that if the
statement had been killed on the master, the slave would stop. (Bug #2983)
--local-load
option of mysqlbinlog
now requires an argument.
LOAD DATA FROM MASTER
after
RESET SLAVE
. (Bug #2922)
Binlog has bad magic number
and stop when it
was not necessary to do so. (Bug #3401)
Exec_master_log_pos
(and its disk image in the
relay-log.info
file) to be correct if the master had version 3.23 (it
was too big by 6 bytes). This bug does not exist in the 5.0 version.
(Bug #3400)
mysqlbinlog
does not forget to print a USE
command
under rare circumstances where the binary log contained a LOAD DATA
INFILE
command. (Bug #3415)
LOAD DATA INFILE
when the
master had version 3.23. Some smaller problems remain in this setup,
See section 6.7 Replication Features and Known Problems. (Bug #3422)
DELETE
statements were always replicated by the slave if
there were some --replicate-*-ignore-table
options and no
--replicate-*-do-table
options. (Bug #3461)
--with-debug
and replicating itself. (Bug #3568)
Functionality added or changed:
LOAD DATA
by mysqlbinlog
in remote mode.
(Bug #1378)
ENGINE
is now a synonym for the TYPE
option for
CREATE TABLE
and ALTER TABLE
.
lower_case_table_names
system variable now can take a value of
2
, to store table names in mixed case on case-insensitive filesystems.
It's forced to 2 if the database directory is located on a case-insensitive
filesystem.
MEMORY
(HEAP
) tables: Made the master
automatically write a DELETE FROM
statement to its binary log when a
MEMORY
table is opened for the first time since master's startup.
This is for the case where the slave has replicated a non-empty
MEMORY
table, then the master is shut down and restarted: the table
is now empty on master; the DELETE FROM
empties it on slave too. Note
that even with this fix, between the master's restart and the first use of
the table on master, the slave still has out-of-date data in the table. But
if you use the init-file
option to populate the MEMORY
table
on the master at startup, it ensures that the failing time interval is zero.
(Bug #2477)
--old-rpl-compat
server option, which was a
holdover from the very first 4.0.x versions. (Bug #2428)
--sync-frm
. It's on by default, to
instruct MySQL to sync to disk each time `.frm' file is created.
Use --disable-sync-frm
to disable.
Bugs fixed:
mysqlhotcopy
now works on NetWare.
DROP DATABASE
could not drop databases with RAID tables that had
more than nine RAID_CHUNKS
. (Bug #2627)
wait_timeout
to 2147483 on Windows (OS limit). (Bug #2400)
--init-file
crashes MySQL if it contains a large
SELECT
. (Bug #2526)
SHOW KEYS
now shows NULL
in the Sub_part
column for
FULLTEXT
indexes.
mysqld
to run on Debian/IA-64 with a TLS-enabled glibc
. (Bug #2599)
SELECT
privilege is needed for tables that are only read in
multiple-table UPDATE
statements. (Bug #2377)
LOCK TABLES ... ; INSERT
... SELECT
and one used the same table in the INSERT
and SELECT
part. (Bug #2296)
SELECT INTO ... DUMPFILE
now deletes the generated file on error.
BDB
tables. The
symptom was that data could be returned in the wrong lettercase. (Bug #2509)
TEXT
columns if these columns happened to contain
values having trailing spaces. This bug was introduced in 4.0.17.
indexed_TEXT_column = expr
was present and the column contained values having trailing spaces.
This bug was introduced in 4.0.17.
TEXT
columns
that happened to contain values having trailing spaces. This bug was
introduced in 4.0.17. (Bug #2295)
MyISAM
tables for BLOB
values longer
than 16MB. (Bug #2159)
mysqld_safe
when running multiple instances of
MySQL. (Bug #2114)
HANDLER
statement with tables not
from a current database. (Bug #2304)
UPDATE
statements did not check that there was only one table
to be updated. (Bug #2103)
BLOB
column
type index size being calculated incorrectly in MIN()
and MAX()
optimizations.
(Bug #2189)
LOCK TABLES
in
mysqldump
. (Bug #2242)
mysqld_safe
that caused mysqld
to generate a
warning about duplicate user=xxx
options if this option was specified in
the [mysqld]
or [server]
sections of `my.cnf'.
(Bug #2163)
INSERT DELAYED ... SELECT ...
could cause table corruption because
tables were not locked properly. This is now fixed by ignoring DELAYED
in this context. (Bug #1983)
MyISAM
table may first receive ``no space left
on device,'' but later complete when disk space becomes available.
See section A.4.3 How MySQL Handles a Full Disk.) The bug was that the master forgot to reset the error
code to 0 after success, so the error code got into its binary log, thus
causing the slave to issue false alarms such as ``did not get the same
error as on master.'' (Bug #2083)
LOAD DATA INFILE
for an empty file from a 3.23 master to a
4.0 slave caused the slave to print an error. (Bug #2452)
lower_case_table_names
to 1 if the file
system was case insensitive, mysqld
could crash. This bug existed only
in MySQL 4.0.17. (Bug #2481)
TIMESTAMP
columns
that was erroneously disabled in previous release. (Bug #2539) Fixed
SHOW CREATE TABLE
to reflect these values. (Bug #1885) Note
that because of the auto-update feature for the first TIMESTAMP
column in a table, it makes no sense to specify a default value for
the column. Any such default will be silently ignored (unless another
TIMESTAMP
column is added before this one). Also fixed the meaning
of the DEFAULT
keyword when it is used to specify the value to be
inserted into a TIMESTAMP
column other than the first. (Bug #2464)
UNIX_TIMESTAMP()
to produce incorrect results or that caused
non-zero values to be inserted into TIMESTAMP
columns. (Bug #2523)
Also, current time zone now is taken into account when checking if datetime
values satisfy both range boundaries for TIMESTAMP
columns. The
range allowed for a TIMESTAMP
column is time zone-dependent and
equivalent to a range of 1970-01-01 00:00:01
UTC to 2037-12-31
23:59:59
UTC.
DELETE
statements were never replicated by the slave if
there were any --replicate-*-table
options. (Bug #2527)
query_prealloc_size
,
query_alloc_block_size
, trans_prealloc_size
,
trans_alloc_block_size
now
have an effect. (Bug #1948)
ALTER TABLE RENAME
, when rename to the table with
the same name in another database silently dropped destination table if
it existed. (Bug #2628)
Functionality added or changed:
mysqldump
no longer dumps data for MERGE
tables. (Bug #1846)
lower_case_table_names
is now forced to 1 if the database directory
is located on a case-insensitive filesystem. (Bug #1812)
realpath()
doesn't
work. (Before one could use CREATE TABLE .. DATA DIRECTORY=..
even if
HAVE_BROKEN_REALPATH
was defined. This is now disabled to avoid
problems when running ALTER TABLE
).
AUTO_INCREMENT
value in a MyISAM
table
no longer updates the AUTO_INCREMENT
counter to a big unsigned value.
(Bug #1366)
WEEK(..., mode)
function.
See section 12.5 Date and Time Functions.
(Bug #1178)
UNION DISTINCT
syntax.
mysql_server_init()
now returns 1 if it can't initialize the
environment. (Previously mysql_server_init()
called exit(1)
if it could not create a key with pthread_key_create()
. (Bug #2062)
mysqld
from MySql
to MySQL
.
This should not affect usage, because service names are not case sensitive.
mysqld
as a service on Windows systems, mysqld
will read startup options in option files from the option group with the same
name as the service name.
(Except when the service name is MySQL
).
Bugs fixed:
SIGHUP
to mysqld
crashed the server if it was running with
--log-bin
. (Bug #2045)
ON
clauses
when lower_case_table_names
is set. (Bug #1736)
IGNORE ... LINES
option to LOAD DATA INFILE
didn't work
when used with fixed length rows. (Bug #1704)
UNIX_TIMESTAMP()
for timestamps close to 0.
(Bug #1998)
QUOTE()
function. (Bug #1868)
TEXT
with endspace. (Bug #1651)
ENUM
column that is set to the
empty string (for example, with REPLACE()
). (Bug #2023)
mysql
client program now correctly prints connection identifier
returned by mysql_thread_id()
as unsigned integer rather than as signed
integer. (Bug #1951)
FOUND_ROWS()
could return incorrect number of rows after a query
with an impossible WHERE
condition. (Bug #1468)
SHOW DATABASES
no longer shows .sym
files (on Windows) that
do not point to a valid directory. (Bug #1385)
libmysql.so
library. (from pthread_key_create()
). (Bug #2061)
UNION
statement with alias *
. (Bug #1249)
DELETE ... ORDER BY ... LIMIT
where the rows where not
deleted in the proper order. (Bug #1024, Bug #1697).
DECIMAL
. (Bug #2128)
EXPLAIN
if query contained an
ORDER BY NULL
clause. (Bug #1335)
DROP DATABASE
. (Bug #1898)
AND
/OR
queries. (Bug #1828)
ORDER BY
when ordering by expression and identifier.
(Bug #1945)
HANDLER
when an ALTER TABLE
was
executed in a different connection. (Bug #1826)
trunc*
operator of full-text search which
sometimes caused MySQL not to find all matched rows.
DECIMAL
column values.
REF
access plan was
preferred to more efficient RANGE
on another column.
mysqld --install mysql --defaults-file=path-to-file.
(Bug #1643)
const
tables
(such as one-row tables) and non-constant expression
(such as RAND()
). (Bug #1271)
SQL_CALC_FOUND_ROWS
into
account if LIMIT
clause was present. (Bug #1274)
mysqlbinlog
now asks for a password at the console when the -p
or --password
option is used with no argument. This is consistent with
the way that other clients such mysqladmin
and mysqldump
behave. Note: A consequence of this change is that it is no
longer possible to invoke mysqlbinlog
as mysqlbinlog -p
pass_val
(with a space between the -p
option and the following
password value).
(Bug #1595)
STOP SLAVE
was
issued.
A->B->C
, if 2 sessions on A
updated temporary tables of the same name at the same time, the binary log
of B
became incorrect, resulting in C
becoming confused.
(Bug #1686)
A->B->C
, if STOP SLAVE
was issued on B
while it was replicating a temporary table from
A
, then when START SLAVE
was issued on B
, the binary log
of B
became incorrect, resulting in C
becoming confused.
(Bug #1240)
MASTER_LOG_FILE
and MASTER_LOG_POS
were not
specified, CHANGE MASTER
used the coordinates of the slave I/O
thread to set up replication, which broke replication if the slave SQL
thread lagged behind the slave I/O thread. This caused the slave
SQL thread to lose some events. The new behavior is to use the
coordinates of the slave SQL thread instead.
See section 13.6.2.1 CHANGE MASTER TO
Syntax.
(Bug #1870)
TIMESTAMP
or
DATETIME
value checks of year, month, day, hour, minute
and second ranges are performed and numbers representing illegal
timestamps are converted to 0 value. This behavior is consistent
with manual and with behavior of string to
TIMESTAMP
/DATETIME
conversion. (Bug #1448)
BIT_AND()
and BIT_OR()
group functions
returned incorrect value if SELECT
used a temporary table and
no rows were found. (Bug #1790).
BIT_AND()
is now unsigned in all contexts. This means that it will
now return 18446744073709551615 (= 0xffffffffffffffff) instead of -1 if
there were no rows in the result.
BIT_AND()
still returning signed value for an
empty set in some cases. (Bug #1972)
^
(XOR) and >>
(bit shift) still returning
signed value in some cases. (Bug #1993)
UPDATE
could produce a
wrong complain that some record was not found in one table, if the
UPDATE
was preceded by a INSERT ... SELECT
. (Bug #1701)
SHOW TABLE STATUS
to be
very slow when a database contained a large number of tables, even if a single
particular table were specified. (Bug #1952)
Functionality added or changed:
mysqladmin debug
. This works only on systems that support the
mallinfo()
call (like newer Linux systems).
range_alloc_block_size
, query_alloc_block_size
,
query_prealloc_size
, transaction_alloc_block_size
, and
transaction_prealloc_size
.
mysqlbinlog
now reads option files. To make this work, you must now
specify --read-from-remote-server
when reading binary logs from
a MySQL server. (Note that using a remote server is deprecated and may
disappear in future mysqlbinlog
versions).
SIGPIPE
signals also for non-threaded programs. The blocking is moved
from mysql_init()
to mysql_server_init()
, which is
automatically called on the first call to mysql_init()
.
--libs_r
and --include
options to mysql_config
.
`>
prompt for mysql
. This prompt is similar to the
'>
and ">
prompts, but indicates that an identifier
quoted with backticks was begun on an earlier line and the closing backtick
has not yet been seen.
mysql_install_db
to be able to use the local machine's IP
address instead of the hostname when building the initial grant tables if
skip-name-resolve
has been specified. This
option can be helpful on FreeBSD to avoid thread-safety problems with the
FreeBSD resolver libraries. (Thanks to Jeremy Zawodny for the patch.)
--slave-load-tmpdir
option. All these files are
needed when the slave resumes replication after you restore the slave's data.
Bugs fixed:
ERROR 14: Can't change size of file (Errcode: 2)
on Windows in DELETE FROM tbl_name
without a WHERE
clause or
TRUNCATE TABLE tbl_name
, when tbl_name is a MyISAM
table. (Bug #1397)
thr_alarm queue is full
warnings after
increasing the max_connections
variable with SET GLOBAL
.
(Bug #1435)
LOCK TABLES
to work when Lock_tables_priv
is granted on the
database level and Select_priv
is granted on the table level.
FLUSH QUERY CACHE
on queries that use same table
several times (Bug #988).
SQL_WARNINGS
) to NULL
.
ERROR 2013: Lost connection
to MySQL server during query
for queries that lasted longer than 30 seconds,
if the client didn't specify a limit with mysql_options()
. Users of
4.0.15 on Windows should upgrade to avoid this problem.
SELECT
statement. (Bug #1194).
BLOB
values with compressed tables.
This was a bug introduced in 4.0.14. It caused MySQL to regard some
correct tables containing BLOB
values as corrupted.
(Bug #770, Bug #1304, and maybe Bug #1295)
SHOW GRANTS
showed USAGE
instead of the real column-level
privileges when no table-level privileges were given.
LOAD DATA FROM
MASTER
dropped the corresponding database on the slave, thus erroneously
dropping tables that had no counterpart on the master and tables that
may have been excluded from replication using --replicate-*-table
rules. Now LOAD DATA FROM MASTER
no longer drops the database.
Instead, it drops only the tables that have a counterpart on the master
and that match the --replicate-*-table
rules. --replicate-*-db
rules can still be used to include or exclude a
database as a whole from LOAD DATA FROM MASTER
. A database will
also be included or excluded as a whole if there are some rules like
--replicate-wild-do-table=db1.%
or
--replicate-wild-ignore-table=db1.%
, as is the case for
CREATE DATABASE
and DROP DATABASE
in replication. (Bug
#1248)
mysqlbinlog
crashed with a segmentation fault when used with the
-h
or --host
option. (Bug #1258)
mysqlbinlog
crashed with a segmentation fault
when used on a binary log containing only final events for LOAD
DATA
. (Bug #1340)
mysqlbinlog
will not reuse temporary filenames from previous runs.
Previously mysqlbinlog
failed if was used several times on the same
binary log file that contained a LOAD DATA
command.
OPENSSL_DISABLE_OLD_DES_SUPPORT
option was enabled).
LOAD DATA INFILE
command from its master.
The bug was that one slave MySQL server sometimes
deleted the `SQL_LOAD-*' files (used for replication of
LOAD DATA INFILE
and located in the slave-load-tmpdir
directory,
which defaults to tmpdir
) belonging to the other slave MySQL server of
this machine, if these slaves had the same slave-load-tmpdir
directory.
When that happened, the other slave could not replicate
LOAD DATA INFILE
and complained about not being able to open some
SQL_LOAD-*
file. (Bug #1357)
LOAD DATA INFILE
failed for a small file, the master forgot to
write a marker (a Delete_file
event) in its binary log, so the slave
could not delete 2 files (`SQL_LOAD-*.info' and
`SQL_LOAD-*.data' from its tmpdir
. (Bug #1391)
SQL_LOAD-*.info
file from tmpdir
after successfully replicating a LOAD DATA
INFILE
command. (Bug #1392)
DROP TEMPORARY TABLE
statements to the binary log for all temporary tables which the
connection had not explicitly dropped. MySQL forgot to use backticks to quote
the database and table names in the statement. (Bug #1345)
IMPORTANT:
If you are using this release on Windows, you should upgrade at least your
clients (any program that uses libmysql.lib
) to 4.0.16 or above. This
is because the 4.0.15 release had a bug in the Windows client library that
causes Windows clients using the library to die with a Lost connection
to MySQL server during query
error for queries that take more than 30
seconds. This problem is specific to Windows; clients on other platforms are
unaffected.
Functionality added or changed:
mysqldump
now correctly quotes all identifiers when communicating
with the server. This assures that during the dump process, mysqldump
will never send queries to the server that result in a syntax error.
This problem is not related to the
mysqldump
program's output, which was not changed. (Bug #1148)
MIN()
and MAX()
report that they can return NULL
(this is true because an
empty set will return NULL
). (Bug #324)
mysqld
server is
started on the same TCP/IP port as a running mysqld
server.
mysqld
system variables wait_timeout
,
net_read_timeout
, and net_write_timeout
now work on Windows.
One can now also set timeouts for read and writes in Windows clients with
mysql_options()
.
--sql-mode=NO_DIR_IN_CREATE
to make it possible for
slaves to ignore INDEX DIRECTORY
and
DATA DIRECTORY
options given to CREATE TABLE
.
When this is mode is on, SHOW CREATE TABLE
will not show the
given directories.
SHOW CREATE TABLE
now shows the INDEX DIRECTORY
and
DATA DIRECTORY
options, if they were specified when the table was
created.
open_files_limit
system variable now shows the real open files limit.
MATCH ... AGAINST()
in natural language mode
now treats words that are present
in more than 2,000,000 rows as stopwords.
.tar.gz
) has been moved into a subdirectory docs
.
See section 2.1.5 Installation Layouts.
info
file in the binary
distributions. (Bug #1019)
libmysqld.a
) by default. Due to a linking problem with non-gcc
compilers, it was not included in all packages of the initial 4.0.15
release. The affected packages were rebuilt and released as 4.0.15a.
See section 1.3.1.2 The Embedded MySQL Server.
BETWEEN
with
non-constant limits. (Bug #991)
binlog-do-db
and binlog-ignore-db
options are tested
against the database on the master (see section 5.9.4 The Binary Log), and a
paragraph about how --replicate-do-db
, --replicate-do-table
and analogous options are tested against the database and tables on the
slave (see section 6.8 Replication Startup Options).
SET PASSWORD
if it is configured to exclude the mysql
database from
replication (using for example
--replicate-wild-ignore-table=mysql.%
). This was the
case for GRANT
and REVOKE
since version 4.0.13 (although
there was Bug #980 in 4.0.13 & 4.0.14, which has been fixed in
4.0.15).
State
column of SHOW
PROCESSLIST
for replication threads and for MASTER_POS_WAIT()
and added the most common states for these threads to the
documentation, see section 6.3 Replication Implementation Details.
GRANT
command that creates an anonymous user
(that is, an account with an empty username) no longer requires
FLUSH PRIVILEGES
for the account to be recognized by the server.
(Bug #473)
CHANGE MASTER
now flushes `relay-log.info'. Previously
this was deferred to the next run of START SLAVE
, so if
mysqld
was shutdown on the slave after CHANGE MASTER
without having run START SLAVE
, the relay log's name and
position were lost. At restart they were reloaded from
`relay-log.info', thus reverting to their old (incorrect) values from
before CHANGE MASTER
and leading to error messages
(as the old relay log did not exist any more) and the slave threads
refusing to start. (Bug #858)
Bugs fixed:
ALTER
privilege on the
mysql.user
table to execute random code or to gain shell access with
the UID of the mysqld
process (thanks to Jedi/Sector One for spotting and
reporting this bug).
FORCE INDEX
in a query that contained
"Range checked for each record" in the EXPLAIN
output. (Bug #1172)
MYISAM
introduced in 4.0.3 where the index file header
was not updated directly after an UPDATE
of split dynamic rows.
The symptom was that the table had a corrupted delete-link if mysqld
was shut down or the table was checked directly after the update.
Can't unlock file
error when running
myisamchk --sort-index
on Windows. (Bug #1119)
key_buffer_size
while
the key cache was actively used. (Bug #1088)
MyISAM
and ISAM
when a row is updated
in a table with a large number of columns and at least one BLOB/TEXT
column.
UNION
and LIMIT #,#
when
braces were not used around the SELECT
parts.
UNION
and ORDER BY .. LIMIT #
when one didn't use braces around the SELECT
parts.
SELECT SQL_CALC_FOUND_ROWS ... UNION ALL ... LIMIT #
where FOUND_ROWS()
returned incorrect number of rows.
1+1-1+1-1...
in certain combinations. (Bug #871)
FULLTEXT
index
from being marked as "analyzed".
SHOW CREATE TABLE
is always larger than the data length.
The only known application that was affected by the old behavior was
Borland dbExpress, which truncated the output from the command.
(Bug #1064)
tis620
character
set. (Bug #1116)
ISAM
bug in MAX()
optimization.
myisamchk --sort-records=N
no longer marks table as crashed if
sorting failed because of an inappropriate key. (Bug #892)
MyISAM
compressed table handling that sometimes
made it impossible to repair compressed table in "Repair by sort" mode.
"Repair with keycache" (myisamchk --safe-recover
) worked, though.
(Bug #1015)
PRIMARY
key declared for a column
that is not explicitly marked NOT NULL
was sorted after a
UNIQUE
key for a NOT NULL
column).
INTERVAL
when applied to a DATE
value.
(Bug #792)
XOR
evaluation in WHERE
clause. (Bug #992)
LEFT JOIN
)
when ON
condition is always false, and range search in used.
(Bug #926)
MATCH ... AGAINST()
in some
joins. (Bug #942)
MERGE
tables do not ignore Using index
(from EXPLAIN
output)
anymore.
myisamchk --sort-records
crash when used on compressed table.
ALTER TABLE
and related commands such as CREATE INDEX
.
(Bug #712)
LOAD DATA FROM MASTER
when
the master was running without the --log-bin
option. (Bug #934)
REQUIRE SSL
option specified for
their accounts.
GRANT
or REVOKE
queries even if it was configured to exclude the
mysql
database from replication (for example, using
--replicate-wild-ignore-table=mysql.%
). (Bug #980)
Last_Errno
and Last_Error
fields in the output of
SHOW SLAVE STATUS
are now cleared by CHANGE MASTER
and
when the slave SQL thread starts. (Bug #986)
RESET SLAVE
does not change
connection information (master host, port, user, and
password), whereas it does. The statement resets these to the startup options
(master-host
etc) if there were some. (Bug #985)
SHOW SLAVE STATUS
now shows correct information (master host,
port, user, and password) after RESET SLAVE
(that is, it shows the new values, which are copied from the startup
options if there were some). (Bug #985)
Exec_Master_Log_Pos
and problems
with MASTER_POS_WAIT()
in A->B->C replication setup. (Bug #1086)
mysqlbinlog
when
--position=x
was used with x
being between a
Create_file
event and its fellow Append_block
,
Exec_load
or Delete_file
events. (Bug #1091)
mysqlbinlog
printed superfluous warnings when using
--database
, which caused syntax errors when piped to
mysql
. (Bug #1092)
mysqlbinlog --database
filter LOAD DATA INFILE
too
(previously, it filtered all queries except LOAD DATA
INFILE
). (Bug #1093)
mysqlbinlog
in some cases forgot to put a leading '#'
in
front of the original LOAD DATA INFILE
(this command is
displayed only for information, not to be run; it is later reworked to
LOAD DATA LOCAL
with a different filename, for execution by
mysql
). (Bug #1096)
binlog-do-db
and binlog-ignore-db
incorrectly filtered
LOAD DATA INFILE
(it was half-written to the binary log). This
resulted in a corrupted binary log, which could cause the slave to
stop with an error. (Bug #1100)
InnoDB
table)
was updated, and later in the same transaction a
non-transactional table (such as a MyISAM
table) was
updated using the updated content of the transactional table
(with INSERT ... SELECT
for example), the queries were written
to the binary log in an incorrect order. (Bug #873)
INSERT ... SELECT
updated a
non-transactional table, and ROLLBACK
was issued, no error was
returned to the client. Now the client is warned that some changes
could not be rolled back, as this was the case for normal
INSERT
. (Bug #1113)
STOP SLAVE
was run while the slave
SQL thread was in the middle of a transaction, and then CHANGE
MASTER
was used to point the slave to some non-transactional
statement, the slave SQL thread could get confused (because it would
still think, from the past, that it was in a transaction).
Functionality added or changed:
default_week_format
system variable. The value is used as the
default mode for the WEEK()
function.
mysqld
now reads an additional option file group having a name
corresponding to the server's release series:
[mysqld-4.0]
for 4.0.x servers, [mysqld-4.1]
for 4.1.x servers,
and so forth. This allows options to be specified on a series-specific basis.
CONCAT_WS()
function no longer skips empty strings. (Bug #586).
InnoDB
now supports indexing a prefix of a column. This means, in
particular, that BLOB
and TEXT
columns can be indexed in
InnoDB
tables, which was not possible before.
INTERVAL(NULL, ...)
returns -1
.
INSERT
from SELECT
when the table into which the records
are inserted is also a table listed in the SELECT
.
CREATE TABLE
and INSERT
from any UNION
.
SQL_CALC_FOUND_ROWS
option now always returns the total number
of rows for any UNION
.
--table
option from mysqlbinlog
to avoid repeating mysqldump
functionality.
basedir=c:\mysql # installation directory
).
max_seeks_for_key
variable that can
be used to force the optimizer to use keys instead of table scans
even if the cardinality of the index is low.
LEFT JOIN
to normal join in
some cases.
CHANGE MASTER
command. See section 13.6.2.1 CHANGE MASTER TO
Syntax.
--nice
option to mysqld_safe
to allow setting the
niceness of the mysqld
process. (Thanks to Christian Hammers for
providing the initial patch.) (Bug #627)
--read-only
option to cause mysqld
to allow no updates
except from slave threads or from users with the SUPER
privilege.
(Original patch from Markus Benning).
SHOW BINLOG EVENTS FROM x
where x
is less than 4 now
silently converts x
to 4 instead of printing an error. The same change
was done for CHANGE MASTER TO MASTER_LOG_POS=x
and
CHANGE MASTER TO RELAY_LOG_POS=x
.
mysqld
now only adds an interrupt handler for the SIGINT
signal
if you start it with the new --gdb
option. This is because some
MySQL users encountered strange problems when they accidentally sent SIGINT
to
mysqld
threads.
RESET SLAVE
now clears the Last_Errno
and
Last_Error
fields in the output of SHOW SLAVE STATUS
.
max_relay_log_size
variable; the relay log will be rotated
automatically when its size exceeds max_relay_log_size
. But if
max_relay_log_size
is 0 (the default), max_binlog_size
will be used (as in older versions). max_binlog_size
still
applies to binary logs in any case.
FLUSH LOGS
now rotates relay logs in addition to the other types of
logs it rotates.
Bugs fixed:
latin1_de
character set was rewritten.
The old algorithm could not handle cases like "sä" > "ßa"
.
See section 5.8.1.1 Using the German Character Set. In rare cases it resulted in table
corruption.
ALTER TABLE ... UNION=(...)
for MERGE
table is now allowed
even if some underlying MyISAM
tables are read-only. (Bug #702)
CREATE TABLE t1 SELECT x'41'
. (Bug #801)
REPAIR TABLE
on a table with a
multiple-part auto_increment key where one part was a packed CHAR
.
INSERT
statements not being replicated in the
event of a FLUSH LOGS
command or when the binary log exceeds
max_binlog_size
. (Bug #791)
INTERVAL
and GROUP BY
or
DISTINCT
. (Bug #807)
mysqlhotcopy
so it actually aborts for unsuccessful
table copying operations. Fixed another bug so that it succeeds
when there are thousands of tables to copy. (Bug #812)
mysqlhotcopy
failing to read options from option
files. (Bug #808)
FULLTEXT
indexes even though it was possible (for example, in
SELECT * FROM t1 WHERE MATCH a,b AGAINST("index") > 0
).
UNION
operations.
SHOW TABLES
and
similar commands.
max_user_connections
.
HANDLER
without an index now works properly when a table has deleted
rows. (Bug #787)
LOAD DATA
in mysqlbinlog
. (Bug #670)
SET CHARACTER SET DEFAULT
works. (Bug #462)
MERGE
table behavior in ORDER BY ... DESC
queries.
(Bug #515)
PURGE MASTER LOGS
or SHOW MASTER LOGS
when the binary log is off. (Bug #733)
DATETIME
column and an integer
constant. (Bug #504)
mysqlbinlog
. (Bug #672)
ERROR 1105: Unknown error
that occurred for some SELECT
queries, where a column that was declared as NOT NULL
was compared
with an expression that took NULL
value.
mysql_real_connect()
to use poll()
instead of
select()
to work around problem with many open files in the client.
MATCH ... AGAINST
used with a
LEFT JOIN
query.
mysqld
variables
to 4294967295 when they are specified on the command line.
HANDLER ... READ
statements, when a table is referenced
via an alias.
safe_malloc
, which caused MySQL to
give "Freeing wrong aligned pointer" errors on SCO 3.2.
ALTER TABLE ... ENABLE/DISABLE KEYS
could cause a core dump when
done after an INSERT DELAYED
statement on the same table.
mysqld
. (Bug #549)
INSERT ... SELECT
into an AUTO_INCREMENT
column
not replicate well. This bug is in the master, not in the slave.
(Bug #490)
INSERT ... SELECT
statement inserted rows into a
non-transactional table, but failed at some point (for example, due to
a ``Duplicate key'' error), the query was not written to the binary log.
Now it is written to the binary log, with its error code, as all other
queries are. About the slave-skip-errors
option for how to
handle partially completed queries in the slave, see section 6.8 Replication Startup Options. (Bug #491)
SET FOREIGN_KEY_CHECKS=0
was not replicated properly.
The fix probably will not be backported to 3.23.
LOAD DATA INFILE
which had no IGNORE
or
REPLACE
clause on the master, was replicated with IGNORE
.
While this is not a problem if the master and slave data are identical
(a LOAD
that produces no duplicate conflicts on the master will
produce none on the slave anyway), which is true in normal operation, it
is better for debugging not to silently add the IGNORE
. That way,
you can get an error message on the slave and discover that for some
reason, the data on master and slave are different and investigate why.
(Bug #571)
LOAD DATA INFILE
printed an incomplete ``Duplicate entry
'%-.64s' for key %d''' message (the key name and value were not mentioned)
in case of duplicate conflict (which does not happen in normal operation).
(Bug #573)
--debug
, CHANGE MASTER
TO RELAY_LOG_POS
could cause a debug assertion failure. (Bug #576)
LOCK TABLES WRITE
on an InnoDB
table, commit could
not happen, if the query was not written to the binary log (for example, if
--log-bin
was not used, or binlog-ignore-db
was
used). (Bug #578)
DROP TABLE
statements to its binary log, then the 4.0.13
slave would not notice the temporary tables have to be dropped, until the
slave mysqld
server is restarted. This minor inconvenience is
fixed in 3.23.57 and 4.0.14 (meaning the master must be upgraded to
3.23.57 and the slave to 4.0.14 to remove the inconvenience). (Bug #254)
MASTER_POS_WAIT()
was waiting, and the slave was idle, and
the slave SQL thread terminated, MASTER_POS_WAIT()
would wait
forever. Now when the slave SQL thread terminates,
MASTER_POS_WAIT()
immediately returns NULL
(``slave
stopped''). (Bug #651)
RESET SLAVE; START SLAVE;
, the Relay_Log_Space
value
displayed by SHOW SLAVE STATUS
was too big by four bytes. (Bug #763)
--replicate-ignore-table
and other similar rules), the slave
still checked if the query got the same error code (0, no error) as on
the master. So if the master had an error on the query (for example,
``Duplicate entry'' in a multiple-row insert), then the slave stopped
and warned that the error codes didn't match. (Bug #797)
Functionality added or changed:
PRIMARY KEY
now implies NOT NULL
. (Bug #390)
--enable-local-infile
to match the Unix build configuration.
mysql-test-run
. time
does not
accept all required parameters on many platforms (for example, QNX) and timing
the tests is not really required (it's not a benchmark anyway).
SHOW MASTER STATUS
and SHOW SLAVE STATUS
required the
SUPER
privilege; now they accept REPLICATION CLIENT
as well.
(Bug #343)
MyISAM
repair optimization and
myisam_repair_threads
variable to enable it.
See section 5.2.3 Server System Variables.
innodb_max_dirty_pages_pct
variable which controls amount of
dirty pages allowed in InnoDB
buffer pool.
CURRENT_USER()
and Access denied
error messages now report the
hostname exactly as it was specified in the GRANT
command.
InnoDB
tables now support ANALYZE TABLE
.
--new
now changes binary items (0xFFDF
) to be
treated as binary strings instead of numbers by default. This fixes some
problems with character sets where it's convenient to input the string
as a binary item. After this change you have to convert the binary
string to INTEGER
with a CAST
if you want to compare two
binary items with each other and know which one is bigger than the other.
SELECT CAST(0xfeff AS UNSIGNED) < CAST(0xff AS UNSIGNED)
.
This will be the default behavior in MySQL 4.1. (Bug #152)
delayed_insert_timeout
on Linux (most modern glibc
libraries have a fixed pthread_cond_timedwait()
). (Bug #211)
max_delayed_threads
. (Bug #211)
UPDATE ... LIMIT
to apply the limit to rows that were matched,
whether or not they actually were changed. Previously the limit was applied
as a restriction on the number of rows changed.
BIT_AND()
and BIT_OR()
now return an unsigned 64-bit value.
--log-warnings
).
--skip-symlink
and --use-symbolic-links
and
replaced these with --symbolic-links
.
innodb_flush_log_at_trx_commit
was changed
from 0 to 1 to make InnoDB
tables ACID by default.
See section 15.5 InnoDB
Startup Options.
SHOW KEYS
to display keys that are disabled by
ALTER TABLE DISABLE KEYS
command.
CREATE TABLE
, first
try if the default table type exists before falling back to MyISAM
.
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
no longer silently deletes the binary logs when invoked with
the --master-data
or --first-slave
option;
while this behavior was convenient for some
users, others may suffer from it. Now you must explicitly ask for binary
logs to be deleted by using 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:
Access denied
error message had incorrect Using password
value. (Bug #398)
NATURAL LEFT JOIN
, NATURAL RIGHT JOIN
and
RIGHT JOIN
when using many joined tables. The problem was that
the JOIN
method was not always associated with the tables
surrounding the JOIN
method. If you have a query that uses many
RIGHT JOIN
or NATURAL ... JOINS
you should verify that they
work as you expected after upgrading MySQL to this version. (Bug #291)
mysql
parser not to erroneously interpret `'' or `"'
characters within /* ... */
comment as beginning a quoted string.
mysql
command-line client no longer looks for \*
commands
inside backtick-quoted strings.
Unknown error
when using UPDATE ... LIMIT
. (Bug #373)
GROUP BY
with constants. (Bug #387)
UNION
and OUTER JOIN
. (Bug #386)
UPDATE
and the query required a
temporary table bigger than tmp_table_size
. (Bug #286)
mysql_install_db
with the -IN-RPM
option for the Mac OS X
installation to not fail on systems with improperly configured hostname
configurations.
LOAD DATA INFILE
will now read 000000
as a zero date instead as
"2000-00-00"
.
DELETE FROM table WHERE const_expression
always to delete the whole table (even if expression result was false).
(Bug #355)
FORMAT('nan',#)
. (Bug #284)
HAVING ... COUNT(DISTINCT ...)
.
*
) in
MATCH ... AGAINST()
in some complex joins.
REPAIR ... USE_FRM
command, when used on read-only,
nonexisting table or a table with a crashed index file.
mysql
monitor program. It occurred if
program was started with --no-defaults
, with a prompt that contained
the hostname and a connection to a non-existent database was requested.
LEFT
, RIGHT
and MID
when used with
multi-byte character sets and some GROUP BY
queries. (Bug #314)
ORDER BY
being discarded for some
DISTINCT
queries. (Bug #275)
SET SQL_BIG_SELECTS=1
works as documented (This corrects
a new bug introduced in 4.0)
UPDATE ... ORDER BY
. (Bug #241)
WHERE
clause with constant
expression like in WHERE 1 AND (a=1 AND b=1)
.
SET SQL_BIG_SELECTS=1
works again.
SHOW GRANTS
.
FULLTEXT
index stopped working after ALTER TABLE
that converts TEXT
column to CHAR
. (Bug #283)
SELECT
and wildcarded select list,
when user only had partial column SELECT
privileges on the table.
MyISAM
table as "analyzed" only when all the keys are indeed
analyzed.
SET PASSWORD
.
NATURAL JOIN
s in the query.
SUM()
didn't return NULL
when there was no rows in result
or when all values was NULL
.
--open-files-limit
in
mysqld_safe
. (Bug #264)
SHOW PROCESSLIST
.
NAN
in FORMAT(...)
function ...
ALTER TABLE ENABLE / DISABLE KEYS
which failed to
force a refresh of table data in the cache.
LOAD DATA INFILE
for custom parameters
(ENCLOSED
, TERMINATED
and so on) and temporary tables.
(Bug #183, Bug #222)
FLUSH LOGS
was
issued on the master. (Bug #254)
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 columns and at least one BLOB/TEXT
column. Bug was caused
by incorrect calculation of the needed buffer to pack data.
SELECT
@nonexistent_variable caused the
error in client - server protocol 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 used only
current thread information instead of information from the linked list of threads.
InnoDB
tables as well.
mysqldump
when it was called with
--master-data
: the CHANGE MASTER TO
commands appended to
the SQL dump had incorrect 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:
mysqld
no longer reads options from world-writable config files.
SHOW PROCESSLIST
will now include the client TCP port after the
hostname to make it easier to know from which client the request
originated.
--new
option can be used to make a 4.0 server return
TIMESTAMP
as a string in 'YYYY-MM-DD HH:MM:SS'
format, the way that 4.1 servers do.
Bugs fixed:
mysqld
crash on extremely small values of
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)
InnoDB
tables. This bug occurred as, in many cases, InnoDB
tables cannot
be updated ``on the fly,'' but offsets to the records have to be stored in
a temporary table.
mysql_secure_installation
to the server
RPM subpackage. (Bug #141)
myisamchk
) crash on artificially
corrupted .MYI
files.
BACKUP TABLE
to overwrite existing files.
UPDATE
statements when user had all privileges
on the database where tables are located and there were any entries in
tables_priv
table, that is, 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 okay.
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 (although they were, but only
internally). (Bug #70)
LOAD DATA
.
ANALYZE
procedure with error.
CHAR(0)
columns that could cause incorrect
results from the query.
AUTO_INCREMENT
column,
as a secondary column in a multi-column key (see section 3.6.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 (for example, HP-UX and
Tru64) due to different return values of the atof()
function.
rpl_rotate_logs
test to not fail on certain platforms (such as
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 MySQL 4.0.2). This change was required to comply
with the SQL standard. (The original change was made because we thought
that standard SQL required NULL
to be always sorted at the same position,
but this was incorrect).
START TRANSACTION
(standard SQL 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:
InnoDB
tables.
BLOB NOT NULL
columns used with IS NULL
.
InnoDB
storage engine.
BLOB
columns with long strings.
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 incorrect values when used in OUTER JOIN
.
MIN(key_column)
and MAX(key_column)
could return incorrect
values if one of the tables was empty.
MyISAM
tables with blobs.
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.
mysqld
server should now compile on NetWare.
GROUP BY ... ORDER BY NULL
then result is not sorted.
--ft-stopword-file
command-line option for mysqld
to
replace/disable the built-in stopword list that is used in full-text searches.
See section 5.2.3 Server System Variables.
glibc
that requires a
stack size larger than 128K
for 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
column and also
uses LAST_INSERT_ID()
.
ORDER BY constant_expression
.
myisamchk
parallel repair mode.
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 an AUTO_INCREMENT
column 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
columns then the slave data is corrupted and you
should reinitialize the affected tables from the master.
BLOB
value larger than 16M
to the client.
NOT NULL
column 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
optimizing 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.
MyISAM
after each query. This will reduce
memory in the case you have a lot of big blobs in a table.
Bugs fixed:
mysqld
server to die if the remote
hostname can't be resolved. This is now 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 read by
mysql_options(MYSQL_READ_DEFAULT_FILE)
.
for clients.
InnoDB
tables now also support 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.
NULL
values 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
).
mysql.server
startup script in the RPM packages from
`/etc/rc.d/init.d/mysql' to `/etc/init.d/mysql'
(which almost all current Linux distributions support for LSB compliance).
Qcache_lowmem_prunes
status variable (number of queries that were
deleted from the cache because of low memory).
mysqlcheck
so it can deal with table names containing dashes.
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 12.8.3 Information Functions.
CHECK
constraints to be compatible with standard SQL. This made
CHECK
a reserved word. (Checking of CHECK
constraints is
still not implemented).
CAST(... as CHAR)
.
LIMIT
syntax:
SELECT ... LIMIT row_count OFFSET 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..)
CHANGE MASTER
and RESET SLAVE
now require that slave
threads both be stopped; these commands will return an error
if at least one of these two threads is running.
Bugs fixed:
multi table updates
--lower-case-table-names
default on Mac OS X as the default
filesystem (HFS+) is case insensitive.
See section 9.2.2 Identifier Case Sensitivity.
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 also solved problems with LEFT JOIN
.
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 multiple-table-update and
multiple-table-delete.
--replicate-do=xxx
didn't work for UPDATE
commands.
(Bug introduced in 4.0.0)
InnoDB
bugs in REPLACE, AUTO_INCREMENT,
INSERT INTO ... SELECT ...
were fixed. See the InnoDB
changelog
in the InnoDB
section of the manual.
RESET SLAVE
caused a crash if the slave threads were running.
Functionality added or changed:
SHOW PROCESSLIST
command
WEEK()
so that you can get
week number according to the ISO 8601 specification.
(Old code should still work).
INSERT DELAYED
threads don't hang on Waiting for
INSERT
when one sends a SIGHUP
to mysqld
.
AND
works according to standard SQL when it comes to
NULL
handling. In practice, this affects only 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 TABLE
, it gets the table structure from the `.frm' file, so the
table can be repaired even if the .MYI
header is corrupted.
MAX()
optimization when used with JOIN
and
ON
expressions.
BETWEEN
behavior changed (see section 12.1.3 Comparison Functions and 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 no longer used.
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.
InnoDB
now supports also isolation levels
READ UNCOMMITTED
and READ COMMITTED
.
For a detailed InnoDB
changelog, see section D.9 InnoDB
Change History
in this manual.
Bugs fixed:
MAX()
optimization 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 TABLE
or REPAIR TABLE
.
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 columns.
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 row_count
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 re-create 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. You 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 reworked in a future release.
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).
my_getopt()
; --set-variable
syntax didn't work for
those options that didn't have a valid variable in the my_option
struct.
This affected at least the default-table-type
option.
REPAIR TABLE
and
myisamchk --recover
to fail on tables with duplicates in a unique
key.
CREATE TABLE tbl_name
SELECT expression(),...
SELECT * FROM table-list GROUP BY ...
and
SELECT DISTINCT * FROM ...
.
--slow-log
when logging an administrator command
(like FLUSH TABLES
).
OPTIMIZE TABLE
of locked and modified table,
reported table corruption.
my_getopt()
in handling of special prefixes
(--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
.
--lower-case-table-names
,
--lower-case-table-names=1
,
-O lower-case-table-names=1
,
--set-variable=lower-case-table-names=1
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 initialized.
MyISAM
index file on update if not strictly necessary.
SELECT DISTINCT ... FROM many_tables ORDER BY
not-used-column
.
BIGINT
values 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 enumeration to allow it to be
set 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 columns 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 initialization 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.tbl_name.col_name=''
.
DROP DATABASE
SET [GLOBAL | SESSION]
syntax to change thread-specific and global
system 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 read_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 12.4.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
tbl_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 applies to 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 12.8.2 Encryption Functions.
AES_ENCRYPT()
and AES_DECRYPT()
functions to perform
encryption according to AES standard (Rijndael).
See section 12.8.2 Encryption Functions.
--single-transaction
option to mysqldump
, allowing a
consistent dump of InnoDB
tables.
See section 8.8 The mysqldump
Database Backup Program.
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 optimizer uses only indexes.
ALTER TABLE tbl_name RENAME new_tbl_name
is as fast
as RENAME TABLE
.
GROUP BY
with two or more columns, where at least one
column 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 UNION
. 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.
const
tables.
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
optimization.
... 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 like 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 12.7 Cast Functions and Operators.
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 5.6.4 Limiting Account Resources.
mysql_secure_installation
to the `scripts/' directory.
system
command to mysql
.
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(str)
now returns the characters in str 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.
myisam/ft_dump
utility for low-level inspection
of FULLTEXT
indexes.
DELETE ... WHERE ... MATCH ...
.
MATCH ... AGAINST(... IN BOOLEAN MODE)
.
Note: You must rebuild your tables with
ALTER TABLE tbl_name 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()
initialization so that RAND(N)
and
RAND(N+1)
are more distinct.
UPDATE ... ORDER BY
.
INSERT INTO ... SELECT
always had IGNORE
enabled.
Now MySQL will stop (and possibly roll back) by default in case of an error
unless you specify IGNORE
.
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
system variables.
ft_min_word_len
, ft_max_word_len
, and
ft_max_word_len_for_sort
variables to myisamchk
.
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 behavior 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(date,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 row_count
.
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 ...
.
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
optimization.
--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.10.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
ISAM
library which is tuned for SQL and supports large files.
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 bugfixes 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 preceding remarks don'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.
MERGE
tables
(even one MERGE
table and MyISAM
tables), that could've
resulted in a crash or hang of the server. (Bug #2408)
AND
/OR
expressions if query was ignored (either by a
replication server because of --replicate-*-table
rules, or by any MySQL
server because of a syntax error). (Bug #3969, Bug #4494)
ALTER TABLE RENAME
. (Bug #3270)
ACOS()
, ASIN()
(Bug #2338)
and in FLOOR()
(Bug #3051).
The cause of the problem is an overly strong optimization done by gcc
in this case.
INSERT ... SELECT
statements where, if a NOT NULL
column is assigned a value of NULL
, the following columns in the row
might be assigned a value of zero. (Bug #2012)
--replicate-ignore-table
and other similar rules), the slave
still checked if the query got the same error code (0, no error) as on
the master. So if the master had an error on the query (for example,
``Duplicate entry'' in a multiple-row insert), then the slave stopped
and warned that the error codes didn't match. This is a backport of the
fix for MySQL 4.0. (Bug #797)
mysqlbinlog
now asks for a password at console when the
-p/--password
option is used with no argument. This is how the
other clients (mysqladmin
, mysqldump
..)
behave. Note that one now has to use mysqlbinlog -p<my_password>
;
mysqlbinlog -p <my_password>
will not work anymore (in other
words, put no space after -p
). (Bug #1595)
ALTER TABLE RENAME
, when rename to the table with
the same name in another database silently dropped destination table if
it existed. (Bug #2628)
mysql_real_connect()
(which
required a compromised DNS server and certain operating systems). (Bug #4017)
ALTER
privilege on the
mysql.user
table to execute random code or to gain shell access with
the UID of the mysqld
process (thanks to Jedi/Sector One for spotting and
reporting this bug).
mysqldump
now correctly quotes all identifiers when communicating
with the server. This assures that during the dump process, mysqldump
will never send queries to the server that result in a syntax error. This
problem is not related to the mysqldump
program's output,
which was not changed. (Bug #1148)
MyISAM
and ISAM
when a row is updated
in a table with a large number of columns and at least one BLOB/TEXT
column.
SHOW CREATE TABLE
is always larger than the data length.
The only known application that was affected by the old behavior was
Borland dbExpress, which truncated the output from the command.
(Bug #1064)
ISAM
bug in MAX()
optimization.
Unknown error
when doing ORDER BY
on reference table which
was used with NULL
value on NOT NULL
column. (Bug #479)
mysqld
(option file group name and
service name).
kill pid-of-mysqld
to work on Mac OS X.
SHOW TABLE STATUS
displayed incorrect Row_format
value for
tables that have been compressed with myisampack
.
(Bug #427)
SHOW VARIABLES LIKE 'innodb_data_file_path'
displayed only the
name of the first data file. (Bug #468)
mysqld
didn't allow one to UPDATE
rows in a table even if one had a global UPDATE
privilege and a
database SELECT
privilege.
SELECT
and wildcarded select list,
when user only had partial column SELECT
privileges on the table.
WHERE
clause with a constant
expression such as in WHERE 1 AND (a=1 AND b=1)
.
mysqlbinlog
to fail.
innodb_flush_log_at_trx_commit
was changed
from 0 to 1 to make InnoDB
tables ACID by default.
See section 15.5 InnoDB
Startup Options.
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 columns and at least one BLOB/TEXT
column. Bug was caused
by incorrect calculation of the needed buffer to pack data.
TRUNCATE tbl_name
or
DELETE FROM tbl_name
statements, which could cause an INSERT
to
tbl_name to be written to the log before the
TRUNCATE
or DELETE
statements.
UPDATE
of InnoDB
tables where one row could be
updated multiple times.
PROCEDURE ANALYSE()
to report DATE
instead of
NEWDATE
.
PROCEDURE ANALYSE(#)
to restrict the number of values in an
ENUM
column to #
also for string values.
mysqldump
no longer silently deletes the binary logs when invoked with
the --master-data
or --first-slave
option;
while this behavior was convenient for some
users, others may suffer from it. Now you must explicitly ask for binary
logs to be deleted by using the new --delete-master-logs
option.
mysqldump
when it was invoked with the
--master-data
option: The CHANGE MASTER TO
statements that were
appended to the SQL dump had incorrect coordinates. (Bug #159)
mysqld
crash on extremely small values of
sort_buffer
variable.
GRANT UPDATE
on the column level.
HAVING
with GROUP BY
.
WHERE
clause. (Bug #142)
myisamchk
) crash on artificially
corrupted `.MYI' files.
mysqld
no longer reads options from world-writable config files.
mysqld
and safe_mysqld
now use only the first --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 incorrect
results from the query.
SHOW VARIABLES
on 64-bit platforms. The bug was
caused by incorrect 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 (such as
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=1
(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 you must log in 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.
NULL
values in CASE ... WHEN ...
.
--chroot
(see section D.4.6 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 default
filesystem (HFS+) 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 col_name = key_col_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 uppercase letters.
--skip-show-database
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 lowercase.
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 TABLE
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).
InnoDB
.
BEGIN
/COMMIT
around transaction in the binary log.
This makes replication honor transactions.
user.db
table.
RAND()
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()
to return 0 for Duplicates
value 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.
datadir
parameter to mysqld
.
<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.
mysqld
to die in free()
.
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.
mysqld
with
--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
.
MERGE
table, DELETE FROM merge_table
used without a
WHERE
clause no longer clears the mapping for the table by emptying
the `.MRG' file. Instead, it deletes records from the mapped tables.
mysqldump --disable-keys
to work.
NULL
.
LOAD DATA LOCAL INFILE
more secure.
glibc
library,
which has serious problems under high load and Red Hat 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 optimizer 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 binary log name and the offset InnoDB
was able to recover
to. This is useful, for example, when resynchronizing 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 expr[,expr]...
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 TABLE
, REPAIR TABLE
, 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 data files and raw disk partitions bigger
than 4GB on those operating systems that have big files.
InnoDB
calculates better table cardinality estimates for the
MySQL optimizer.
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 delayed thread could be
hanging on upgrading locks
for 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 TABLE
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_table_names
also works on Unix.
--sql-mode=value[,value[,value]]
option to mysqld
.
See section 5.2.1 mysqld
Command-Line Options.
shutdown
on Solaris where the
`.pid' file wasn't deleted.
InnoDB
now supports < 4GB 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 whether 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 (larger than 4GB)
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
TABLE
, REPAIR TABLE
, OPTIMIZE TABLE
.
InnoDB
.
SELECT * FROM tbl_name, tbl_name2 ... ORDER BY key_part1 LIMIT row_count
will use an 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 in use). 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 TABLE
) 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
would 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 4MB.
=
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 multiple-part key where a key part may be NULL
.
MAX()
optimization 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
.
ASC
and DESC
with GROUP BY
columns
to specify a sort order.
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 multiple-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 behavior, Linux seems to "leak"
memory, as it's being allocated to the directory entry cache instead of
the disk cache.
BACKUP TABLE
, RESTORE TABLE
, CHECK TABLE
, REPAIR TABLE
, 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()
function.
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 4GB.
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 optimized 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 multiple-part keys where you
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.
server-id
value to 1 for masters and 2 for slaves
to make it easier to use the binary log.
bdb_lock_max
variable to bdb_max_lock
.
AUTO_INCREMENT
on sub-fields for BDB
tables.
ANALYZE TABLE
of BDB
tables.
BDB
tables, we now store the number of rows; this helps to optimize
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 are 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 5.1.5 The mysqld_multi
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
TABLE
/OPTIMIZE TABLE
.
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 8.3 mysql
, the Command-Line Tool, mysql --help
and the interactive help for more information.
MyISAM
table failed.
SELECT
, UPDATE
and INSERT
statements
constantly were 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 row_count
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 Red Hat 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 65KB 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 tbl_name
as a synonym for
DELETE FROM tbl_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
statement to display a list of binary log files.
--safemalloc-mem-limit
option to mysqld
to simulate memory
shortage when compiled with the --with-debug=full
option.
SHOW SLAVE STATUS
was using an uninitialized 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 binary log.
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 data file 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 TABLE
and
REPAIR TABLE
. Allow CHECK TABLE
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 used only 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 initialized 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 TABLE
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 multiple-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 (as in Solaris).
HEAP
tables didn't use keys properly. (Bug from 3.23.23.)
MERGE
tables (keys, mapping, creation,
documentation...). See section 14.2 The MERGE
Storage Engine.
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 TABLE
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 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 these statements 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 TABLE
. Note that this is a new feature and tables
will not be marked to be analyzed 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 TABLE
, ANALYZE
TABLE
,
REPAIR TABLE
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
(IA-64) 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 64MB.
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 as required by standard SQL.
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 data files.
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 standard 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 TABLE
and to REPAIR TABLE
.
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 TABLE
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 7.4.5 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)
.
mysqlbinlog
program for displaying binary log files in text
format.
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
statement.
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_col 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.
HIGH_PRIORITY
option to INSERT
. This overrides the
effect of the --low-priority-updates
server option and will not
perform concurrent inserts.
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
no longer allows 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.12.1 Linux Notes.
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
standard 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 tbl_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 tbl_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 for 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).
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, the account
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 standard 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()
function.
SELECT * FROM tbl_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 optimizer bug (when using BLOB
values) 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 14.1 The MyISAM
Storage Engine.
HEAP
tables which are extremely fast for
lookups.
LOAD_FILE(filename)
to get the contents of a file as a
string value.
<=>
operator that acts as =
but returns 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 'é'
is now true. (If the line doesn't
display correctly, the latter 'e' is a French 'e' with an acute accent 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 tbl_name (col INT NOT NULL UNIQUE)
CREATE TABLE tbl_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 standard 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 3.22
is that the output of DISTINCT
is no longer sorted.
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
options
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.10.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 standard 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 tbl_name WHERE key_part1 >= const AND (key_part2 = const
OR key_part2 = const)
.
ISAM
.
DATA
is no longer a reserved word.
LOCK TABLES tbl_name READ; FLUSH TABLES;
isamchk
should now work on Windows.
libtool
1.3.2.
configure
.
--defaults-file=file_name
to option file handling to force
use of only one specific option file.
CREATE
syntax to ignore MySQL 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 no longer reserved words.
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 optimized 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' optimization 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 no lonher crash
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
(single-row) 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.
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 make the configuration process 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, you need 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_IDs 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 > 16MB.
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' filenames.
COUNT()
, STD()
and AVG()
are extended to handle more than
4GB 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
value.
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 two arguments.
const
reference tables from 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 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.
--user
option to mysqld
, to allow it to run
as another Unix user (if it is started as the Unix root
user).
mysqladmin password "newpwd"
. 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 optimizer
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!
MySQL 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
dumped core 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
dumped core 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
host_name.err
instead
of host_name.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 with an accent).
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 (Organization,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
optimization 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 recognize binary strings. Now BETWEEN
is
case-sensitive.
--skip-thread-priority
option to mysqld
, for systems
where mysqld
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:SS'
) as argument.
OR
operators of key parts
inside AND
expressions.
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 standard SQL but may break
old applications that are ported from mSQL
.)
You can get the old behavior 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 2GB to 4GB.
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.
BLOB
values 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 standard 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
tbl_name.col_name!)
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 an 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 INT
values before sorting.
key_col=constant
.
DOUBLE
values sorted on integer results instead.
mysql
no longer requires a database argument.
HAVING
should be. According to the SQL standards, it should
be after GROUP BY
but before ORDER BY
. MySQL 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 standard 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 standard SQL standard. This will
make mysqldump
with NOT NULL
and default values incompatible with
MySQL 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 BLOB
types, 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 data 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 optimizer (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:SS'
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
these 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 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 SQL
syntax instead: expr BETWEEN expr AND expr
.
SUM()
functions.
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. Standard 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
optimizer 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 use only
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;
MySQL 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
(standard 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 64KB for
the server and 512KB 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 unoptimizable 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
optimizer 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 SELECT
statements 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
for standard SQL compliance.
--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 BLOB
values.
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
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 multiple-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 behavior, 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 optimizer 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 whether 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.
'_'
.
MySQL 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 information 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.
InnoDB
Change HistoryStarting from 4.0.22 and 4.1.5, all InnoDB changes are included in the MySQL Change History, and this manual section is no longer separately maintained.
Functionality added or changed:
innodb_status_file
system variable to mysqld
to control whether output from SHOW INNODB STATUS
is written
to a `innodb_status.<pid>' file in the data directory.
By default, the file is not created. To create it, start mysqld
with the --innodb_status_file=1
option.
`mysqld'
server process.
Bugs fixed:
ON DELETE CASCADE
and ON UPDATE CASCADE
foreign key constraints: long chains of cascaded operations would cause
a stack overflow and crash the server. Cascaded operations are now limited
to 15 levels. (Bug #4446)
LOCK TABLES
introduced in
MySQL/InnoDB-4.0.19: The count of tables explicitly locked by a
transaction was incremented only after the locks were granted, but
decremented when the lock structures were destroyed.
UNLOCK TABLES
in AUTOCOMMIT=0
mode,
introduced in MySQL/InnoDB-4.0.19: The memory allocated for some locks
acquired by the transaction could be deallocated before those locks were
released. The bug can lead to crashes and memory corruption of the
buffer pool when the transaction acquires a large number of locks (table
locks or row-level locks).
CHECK TABLE
. A
long-running CHECK TABLE
would cause InnoDB to
complain about a 'long semaphore wait', and crash the server,
if a query had to wait more than 600 seconds behind that
CHECK TABLE
operation.
(Bug #2694)
innodb_additional_mem_pool_size
so small that InnoDB
memory allocation spills over from it, then every 4 billionth spill may
cause memory corruption. A symptom is a printout like below in the
`.err' log.
The workaround is to make
innodb_additional_mem_pool_size
big enough to hold all memory
allocation.
Use SHOW INNODB STATUS
to determine that there is plenty of free space
available in the additional mem pool, and the total allocated memory stays
rather constant.
InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the InnoDB: previous allocated area! InnoDB: Apparent memory corruption: mem dump len 500; hex
innodb_monitor
,
innodb_lock_monitor
, innodb_tablespace_monitor
,
innodb_table_monitor
, and innodb_validate
in
CREATE TABLE
and DROP TABLE
statements was accidentally
removed in MySQL/InnoDB-4.0.19. The diagnostic functions attached
to these special table names (see section 15.12.1 SHOW INNODB STATUS
and the InnoDB
Monitors) are accessible
again in MySQL/InnoDB-4.0.21.
mem_realloc()
, whose implementation was incorrect. As a
result, InnoDB can incorrectly parse column and table names as the
empty string. The InnoDB realloc()
implementation has been
corrected in MySQL/InnoDB-4.0.21.
SHOW TABLE STATUS
InnoDB systematically overestimated the row count by 1 if the
table fit on a single 16 kB data page.
tmpfile()
.
On Windows, the files would be created in the root directory of the current
file system. To correct this behavior, the invocations of tmpfile()
were replaced with code that uses the function create_temp_file()
in
the MySQL portability layer. (Bug #3998)
ALTER TABLE ... DROP FOREIGN KEY ...
fails because of a wrong
constraint name, return a table handler error number 150 instead of 152.
RENAME
d a table, InnoDB forgot to load the FOREIGN KEY
constraints that reference the new table name, and forgot to check that
they are compatible with the table.
Functionality added or changed:
TIMESTAMP
values in InnoDB
in
4.1 to be the same as in 4.0. This difference resulted in incorrect datetime
values in TIMESTAMP
columns in InnoDB
tables after an upgrade
from 4.0 to 4.1. (Bug #4492)
Warning: extra steps during upgrade required!
This means that if you are upgrading from 4.1.x,
where x <= 3, to 4.1.4
you should use mysqldump
for saving and then restoring your
InnoDB
tables with TIMESTAMP
columns. No conversion
is needed if you upgrade from 3.23 or 4.0 to 4.1.4 or later.
innodb_locks_unsafe_for_binlog
. This
option forces InnoDB
not to use next-key locking in searches and
index scans.
innodb_status_file
system variable to mysqld
to control whether output from SHOW INNODB STATUS
is written
to a `innodb_status.<pid>' file in the data directory.
By default, the file is not created. To create it, start mysqld
with the --innodb_status_file=1
option.
mysqld
server process.
LOCK_INSERT_INTENTION
flag do not need to wait for
anything. This is because different users can have conflicting lock types
on gaps. This change reduces unnecessary deadlocks.
Bugs fixed:
ON DELETE CASCADE
and ON UPDATE CASCADE
foreign key constraints: long chains of cascaded operations would cause
a stack overflow and crash the server. Cascaded operations are now limited
to 15 levels. (Bug #4446)
CHECK TABLE
. (Bug #2694)
innodb_additional_mem_pool_size
so small that InnoDB
memory allocation spills over from it, then every 4 billionth spill may
cause memory corruption. A symptom is a printout like below in the
`.err' log.
InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the InnoDB: previous allocated area! InnoDB: Apparent memory corruption: mem dump len 500; hex
SHOW TABLE STATUS
InnoDB systematically overestimated the row count by 1 if the
table fit on a single 16 kB data page.
tmpfile()
.
On Windows, the files would be created in the root directory of the current
file system. To correct this behavior, the invocations of tmpfile()
were replaced with code that uses the function create_temp_file()
in
the MySQL portability layer. (Bug #3998)
RENAME
d a table, InnoDB forgot to load the foreign key
constraints that reference the new table name, and forgot to check
that they are compatible with the table.
mysqld
.
Functionality added or changed:
InnoDB
uses the same character
set comparison functions as MySQL for non-latin1_swedish_ci
character strings that are not BINARY
. This changes the sorting
order of space and characters < ASCII(32) in those character sets.
For latin1_swedish_ci
character strings and BINARY
strings,
InnoDB
uses its own pad-spaces-at-end comparison method, which stays
unchanged. If you have an InnoDB
table created with MySQL 4.1.2 or
earlier, with an index on a non-latin1
character set (in the case
of 4.1.0 and 4.1.1 with any character set) CHAR
/VARCHAR
/or
TEXT
column that is not BINARY
but may contain characters <
ASCII(32), then you should do ALTER TABLE
or OPTIMIZE
table on
it to regenerate the index, after upgrading to MySQL 4.1.3 or later.
OPTIMIZE TABLE
for InnoDB
tables is now mapped to ALTER
TABLE
rather than to ANALYZE TABLE
.
Bugs fixed:
innodb_file_per_table
on Unix) has been fixed.
The bug was a combination of two bugs. Crash recovery ignored the files,
because the attempt to lock them in the wrong mode failed. From now on,
locks will only be obtained for regular files opened in read/write mode,
and crash recovery will stop if an `.ibd' file for a table exists
in a database directory but is unaccessible.
select_lock_type
inside LOCK TABLES
.
(Bug #4047)
innodb_monitor
,
innodb_lock_monitor
, innodb_tablespace_monitor
,
innodb_table_monitor
, and innodb_validate
in
CREATE TABLE
and DROP TABLE
statements was accidentally
removed in MySQL/InnoDB-4.1.2. The diagnostic functions attached
to these special table names (see section 15.12.1 SHOW INNODB STATUS
and the InnoDB
Monitors) are accessible
again in MySQL/InnoDB-4.1.3.
mem_realloc()
, whose implementation was incorrect. As a
result, InnoDB can incorrectly parse column and table names as the
empty string. The InnoDB realloc()
implementation has been
corrected in MySQL/InnoDB-4.1.3.
ON UPDATE CASCADE
or
ON DELETE CASCADE
constraints.
LIKE 'abc%'
, the '%'
did not match
the empty string if the character set was not
latin1_swedish_ci
. This bug was fixed by changing the sorting
order in these character sets. See the above note about data conversion
in 4.1.3.
NOTE: CRITICAL BUG in 4.1.2 if you specify
innodb_file_per_table
in `my.cnf' on Unix. In crash recovery
InnoDB will skip the crash recovery for all `.ibd' files and those
tables become CORRUPT! The symptom is a message Unable to lock ...ibd
with lock 1, error: 9: fcntl: Bad file descriptor
in the `.err'
log in crash recovery.
Functionality added or changed:
latin1_swedish_ci
cannot be accessed in
MySQL/InnoDB 4.0.
FOREIGN KEY
, if the user does
not create one. Removes most of the cases of Error 1005 (errno 150)
in table creation.
ib_logfiles
are
too small for innodb_thread_concurrency
. Instead, print
instructions how to adjust `my.cnf' and call exit(1)
.
SELECT
from an InnoDB table without setting
any table locks, print a descriptive error message and assert; some
subquery bugs were of this type.
Bugs fixed:
innodb_additional_mem_pool_size
so small that InnoDB
memory allocation spills over from it, then every 4 billionth spill may
cause memory corruption. A symptom is a printout like below in the
`.err' log.
InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the InnoDB: previous allocated area! InnoDB: Apparent memory corruption: mem dump len 500; hex
PRIMARY KEY
) to calculate an
ORDER BY
. (Bug #1942)
SHOW INNODB STATUS
;
reported by Jocelyn Fournier.
Bugs fixed:
InnoDB
parser and can be used within quoted table and column identifiers in
FOREIGN KEY
clauses.
LOCK TABLE
aware of InnoDB
row-level locks and
InnoDB
aware of locks set with LOCK TABLE
. (Bug #3299)
SHOW INNODB STATUS
. (Bug #3596)
Functionality added or changed:
pread()
and pwrite()
calls if there is a long semaphore wait.
SHOW INNODB STATUS
will be written
to a file `<datadir>/innodb.status.<pid>' every 15
seconds.
Bugs fixed:
DROP DATABASE
did not work if FOREIGN KEY
references were defined within the database. (Bug #3058)
FOREIGN KEY
, ON UPDATE CASCADE
was not triggered if the update changed a string to another value
identical in alphabetical ordering, for example, `abc' -> `aBc'.
SHOW
INNODB STATUS
print garbage characters after the error info.
CONSTRAINT FOREIGN KEY
correctly. (Bug #3332)
srv0srv.c
, whether the bug shows itself. 4
bytes were overwritten with a pointer to a statically allocated
string `get windows aio return value'.
read_key
fails
with a lock wait timeout error 146.
UNIV_SYNC_DEBUG
to be disabled while
UNIV_DEBUG
is enabled.
FOREIGN KEY
constraint, unless the user does SET FOREIGN_KEY_CHECKS=0
.
The error message here is somewhat misleading
``Cannot delete or update a parent row...'', and must be changed in a
future version 4.1.x.
InnoDB
to remember the CONSTRAINT
name given by a user for
a FOREIGN KEY
.
FOREIGN KEY
constraints spanning
multiple databases to `db_name`.`tbl_name`
. But when
parsing them, we must also accept `db_name.tbl_name`
,
because that was the output format in < 4.0.18.
AUTOCOMMIT=1
, then we do not
need to make a plain SELECT
set shared locks even on the
SERIALIZABLE
isolation level, because we know that the
transaction is read-only. A read-only transaction can always be
performed on the REPEATABLE READ
level, and that does not
endanger the serializability.
REPLACE
to internally
perform an UPDATE
if the table is referenced by a
FOREIGN KEY
. The MySQL manual states that REPLACE
must
resolve a duplicate-key error semantically with
DELETE
(s) + INSERT
, and not by an UPDATE
.
In versions < 4.0.18 and < 4.1.2, MySQL could resolve a duplicate key
conflict in REPLACE
by doing an UPDATE
on the existing
row, and FOREIGN KEY
checks could behave in a semantically
wrong way. (Bug #2418)
FOREIGN KEY
constraint identifiers
locally for each table, in the form
db_name/tbl_name_ibfk_number. If the user gives the
constraint name explicitly, then remember it. These changes should
ensure that foreign key id's in a slave are the same as in the master,
and DROP FOREIGN KEY
does not break replication. (Bug #2167)
FOREIGN KEY
definitions with a backtick (`) and a double quote
("). You can now use also spaces in table and column names, if you
quote the identifiers. (Bug #1725, Bug #2424)
FOREIGN KEY ... ON UPDATE/DELETE NO ACTION
must
check the foreign key constraint, not ignore it. Since we do not have
deferred constraints in InnoDB
, this bugfix makes InnoDB
to check
NO ACTION
constraints immediately, like it checks
RESTRICT
constraints.
InnoDB
crashed in RENAME TABLE
if
db_name.tbl_name is shorter than 5 characters.
(Bug #2689)
SHOW TABLE STATUS
, InnoDB
row count and index
cardinality estimates wrapped around at 512 million in 32-bit
computers. Note that unless MySQL is compiled with the
BIG_TABLES
option, they will still wrap around at 4 billion.
UNIQUE
secondary index, and
NULL
values in that unique index, then with the
IS NULL
predicate, InnoDB
returned only the first matching row,
though there can be many.
This bug was introduced in 4.0.16. (Bug #2483)
InnoDB
is not aware of multiple tablespaces.
InnoDB
in 5.0.0 is essentially the same as InnoDB-4.1.1 with the
bugfixes of InnoDB-4.0.17 included.
InnoDB
would
assert in `row0upd.c', line 713. The same assertion failed if you
updated a column in an ordinary secondary index so that the new value was
alphabetically equivalent, but had a different length. This could happen,
for example, in the UTF8 character set if you updated a letter to its
accented or umlaut form.
InnoDB
could think that a secondary index record was not
locked though it had been updated to an alphabetically equivalent value,
for example, 'abc' -> 'aBc'.
InnoDB
failed to restore
the field in the secondary index to its original value.
InnoDB
is not aware of multiple tablespaces.
InnoDB
. You can store each
InnoDB
type table and its indexes into a separate `.ibd' file into a
MySQL database directory, into the same directory where the
`.frm' file is stored.
InnoDB
tables also if
AUTOCOMMIT=0
, or the statements are enclosed inside
BEGIN ... COMMIT
.
InnoDB
memory consumption by a few megabytes if one sets the buffer
pool size < 8MB.
InnoDB
set two record locks if a unique exact match search
condition was used on a multi-column unique key. For a single column
unique key it worked right.
#sql... -> rsql...
to recover a temporary table, InnoDB
asserted in
row_mysql_lock_data_dictionary()
.
InnoDB
could make the index page directory corrupt in the
first B-tree page splits after mysqld
startup. A symptom would be
an assertion failure in `page0page.c', in function
page_dir_find_slot()
.
InnoDB
could in rare cases return an extraneous row if a
rollback, purge, and a SELECT
coincided.
SELECT
was used inside LOCK TABLES
.
DELETE
statement first managed to delete
some rows and then failed in a FOREIGN KEY
error or a
Table is full
error, MySQL did not roll back the whole SQL statement
as it should.
BLOB
and TEXT
) was exceeded, InnoDB
simply removed
the record from the clustered index. In a similar insert, InnoDB
would
leak reserved file space extents, which would only be freed at the next
mysqld
startup.
BLOB
values, and your log files were
relatively small, InnoDB
could in a big BLOB
operation temporarily
write over the log produced after the latest checkpoint. If InnoDB
would crash at that moment, then the crash recovery would fail,
because InnoDB
would not be able to scan the log even up to the
latest checkpoint. Starting from this version, InnoDB
tries to ensure
the latest checkpoint is young enough. If that is not possible,
InnoDB
prints a warning to the `.err' log of MySQL and advises
you to make the log files bigger.
innodb_fast_shutdown=0
had no effect.
CREATE TABLE
ended in a
comment, that could cause a memory overrun.
InnoDB
printed Operating system error number .. in
a file operation
to the `.err' log in Windows, the error number
explanation was wrong. Workaround: look at section 13.2 of
http://www.innodb.com/ibman.php about Windows
error numbers.
PRIMARY KEY
like in t(a CHAR(200), PRIMARY KEY (a(10)))
on a fixed-length CHAR
column, InnoDB
would crash even in a
simple SELECT
. A CHECK TABLE
would report the table as
corrupt, also in the case where the created key was not PRIMARY
.
InnoDB
now supports the SAVEPOINT
and ROLLBACK TO SAVEPOINT
SQL statements. See http://www.innodb.com/ibman.php#Savepoints for
the syntax.
CREATE TABLE t (a BLOB, INDEX (a(10)))
.
O_DIRECT
as the innodb_flush_method
on the
latest versions of Linux and FreeBSD. Beware of possible bugs in those
operating systems, though.
InnoDB
will print warnings:
InnoDB: Warning: An inconsistent page in the doublewrite buffer InnoDB: space id 2552202359 page number 8245, 127'th page in dblwr buf.but that is not dangerous and can be ignored.
InnoDB
log files are very small compared to the buffer pool size.
SHOW INNODB STATUS
to print detailed info
on the latest UNIQUE KEY
error, but storing that information could
slow down REPLACE
significantly. We no longer store or print
the info.
SET FOREIGN_KEY_CHECKS=0
was not replicated properly
in the MySQL replication. The fix will not be backported to 3.23.
innodb_max_dirty_pages_pct
forgot to
take into account the free pages in the buffer pool. This could lead
to excessive flushing even though there were lots of free pages in
the buffer pool. Workaround: SET GLOBAL
innodb_max_dirty_pages_pct = 100
.
InnoDB
could assert because of a very long semaphore wait.
AUTOCOMMIT=1
then inside LOCK TABLES
MySQL
failed to do the commit after an updating SQL statement if binary logging was
not on, and for SELECT
statements did not commit regardless of binary logging state.
InnoDB
could make the index page directory corrupt in the
first B-tree page splits after a mysqld
startup. A symptom would be an
assertion in page0page.c, in function page_dir_find_slot().
FOREIGN KEY
with an UPDATE CASCADE
clause the parent column was of a different internal storage length
than the child column, then a cascaded update would make the column
length wrong in the child table and corrupt the child table. Because
of MySQL's 'silent column specification changes' a fixed-length
CHAR
column can change internally to a VARCHAR
and cause
this error.
latin1
character set was used and if in a
FOREIGN KEY
the parent column was of a different internal storage
length than the child column, then all inserts to the child table would
fail in a foreign key error.
InnoDB
could complain that it cannot find the clustered
index record, or in rare cases return an extraneous row if a rollback,
purge, and a SELECT
coincided.
SELECT
was used
inside LOCK TABLES
.
DELETE
statement first managed to delete
some rows and then failed in a FOREIGN KEY
error or a
Table is full
error, MySQL did not roll back the whole SQL statement
as it should, and also wrote the failed statement to the binary log, reporting
there a non-zero error_code.
InnoDB
did not check that limit in CREATE TABLE
, and a subsequent
INSERT
or SELECT
from that table could cause an assertion.
innodb_flush_log_at_trx_commit
from 0
to 1. If you have not specified it explicitly in your `my.cnf', and
your application runs much slower with this new release, it is because the
value 1 causes a log flush to disk at each transaction commit.
InnoDB
forgot to call pthread_mutex_destroy() when a table was
dropped. That could cause memory leakage on FreeBSD and other non-Linux
Unixes.
InnoDB
estimated
an index range size to 0 records though the range was not empty; MySQL also
failed to do the next-key locking in the case of an empty index range.
GROUP BY
and DISTINCT
could treat NULL values
inequal.
InnoDB
now supports ALTER TABLE DROP FOREIGN KEY
. You have to use
SHOW CREATE TABLE
to find the internally generated foreign key ID
when you want to drop a foreign key.
SHOW INNODB STATUS
now prints detailed information of the latest
detected FOREIGN KEY
and UNIQUE KEY
errors. If you do not understand
why InnoDB
gives the error 150 from a CREATE TABLE
, you can use
this statement to study the reason.
ANALYZE TABLE
now works also for InnoDB
type tables. It makes 10
random dives to each of the index trees and updates index cardinality
estimates accordingly. Note that because these are only estimates,
repeated runs of ANALYZE TABLE
may produce different numbers. MySQL
uses index cardinality estimates only in join optimization. If some
join is not optimized in the right way, you may try using ANALYZE TABLE
.
InnoDB
group commit capability now works also when MySQL
binary logging is switched on. There have to be > 2 client threads
for the group commit to become active.
innodb_flush_log_at_trx_commit
from
0 to 1. If you have not specified it explicitly in your `my.cnf',
and your application runs much slower with this new release, it
is because the value 1 causes a log flush to disk at each transaction
commit.
innodb_max_dirty_pages_pct
. It is an integer in the range 0 - 100.
The default is 90. The main thread in InnoDB
tries to flush pages
from the buffer pool so that at most this many percents are not yet
flushed at any time.
innodb_force_recovery=6
, do not let InnoDB
do repair of corrupt
pages based on the doublewrite buffer.
InnoDB
startup now happens faster because it does not set the
memory in the buffer pool to zero.
InnoDB
parser for FOREIGN KEY
definitions was
confused by the keywords 'foreign key' inside MySQL comments.
FOREIGN
KEY
reference, and later created the same table with non-matching
column types, InnoDB
could assert in `dict0load.c', in function
dict_load_table()
.
GROUP BY
and DISTINCT
could treat NULL
values as not equal.
MySQL also failed to do the next-key locking in the case of an
empty index range.
MyISAM
table is updated; this also makes CREATE TABLE
not to commit an
InnoDB
transaction, even when binary logging is enabled.
ON DELETE SET NULL
to modify the same
table where the delete was made; we can allow it because that cannot
produce infinite loops in cascaded operations.
HANDLER PREV
and NEXT
also after positioning
the cursor with a unique search on the primary key.
MIN()
or MAX()
resulted in a deadlock or a lock
wait timeout, MySQL did not return an error, but returned NULL
as the
function value.
InnoDB
forgot to call pthread_mutex_destroy()
when
a table was dropped. That could cause memory leakage on FreeBSD
and other non-Linux Unix systems.
InnoDB
now supports up to 64GB of buffer pool memory in a
Windows 32-bit Intel computer. This is possible because InnoDB
can use the AWE extension of Windows to address memory over
the 4GB limit of a 32-bit process. A new startup variable
innodb_buffer_pool_awe_mem_mb
enables AWE and sets the size
of the buffer pool in megabytes.
InnoDB
uses
2 % less memory.
InnoDB
query optimization: queries of type
SELECT ... WHERE indexcolumn < x and SELECT ... WHERE
indexcolumn > x could cause a table scan even if the selectivity
would have been very good.
InnoDB
now prints the progress in percents of a
transaction rollback.
mysqld
releases the S-latch whenever it
passes data from a SELECT to the client.
InnoDB
estimated an index range size to 0 records though
the range was not empty; MySQL also failed to do the next-key
locking in the case of an empty index range.
InnoDB
query optimization: queries of type
SELECT ... WHERE indexcolumn < x and SELECT ... WHERE
indexcolumn > x could cause a table scan even if the
selectivity would have been very good.
InnoDB
HANDLER commands on a fresh handle
crashed mysqld
in ha_innobase::change_active_index()
.
InnoDB
could hang on the adaptive hash index latch in btr0sea.c.
InnoDB
could report table corruption and assert
in page_dir_find_owner_slot() if an adaptive hash index search
coincided with purge or an insert.
InnoDB
file write to fail with error 33 ERROR_LOCK_VIOLATION.
In synchronous writes InnoDB
now retries the write 100 times at 1
second intervals.
InnoDB
log files was >= 2GB
in a 32-bit computer, InnoDB
would write log in a wrong
position. That could make crash recovery and InnoDB Hot Backup
to fail in log scan.
InnoDB
could hang on the adaptive hash index latch in btr0sea.c.
InnoDB
could report table corruption and assert in
page_dir_find_owner_slot() if an adaptive hash index search
coincided with purge or an insert.
InnoDB
file write to fail with error 33 ERROR_LOCK_VIOLATION.
In synchronous writes InnoDB
now retries the write 100 times
at 1 second intervals.
InnoDB
`page0cur.c' file in function page_cur_search_with_match
which caused InnoDB
to remain on the same page forever.
This bug is evident only in tables with more than one page.
InnoDB
log files was >= 2GB in a
32-bit computer, InnoDB
would write log in a wrong position. That could
make crash recovery and InnoDB Hot Backup
to fail.
InnoDB
now supports also FOREIGN KEY (...) REFERENCES ...(...)
[ON UPDATE CASCADE | ON UPDATE SET NULL | ON UPDATE RESTRICT
| ON UPDATE NO ACTION].
InnoDB
prevents creation of such indexes.
InnoDB
in 4.0.7 is essentially the same as in 4.0.6.
InnoDB
.
InnoDB
to hang on a semaphore created in btr0sea.c, line 128.
Workaround: switch binary logging on.
InnoDB
range estimator greatly exaggerated
the size of a short index range if the paths to the endpoints of
the range in the index tree happened to branch in the root.
This could cause unnecessary table scans in SQL queries.
InnoDB
could erroneously return the NEXT record.
InnoDB
prevents creation of such indexes.
InnoDB
now supports also transaction isolation levels READ COMMITTED
and READ UNCOMMITTED. READ COMMITTED more closely emulates Oracle
and makes porting of applications from Oracle to MySQL easier.
InnoDB
does a consistency check to most index pages
before writing them to a data file.
innodb_force_recovery
> 0, InnoDB
tries to
jump over corrupt index records and pages when doing
SELECT * FROM table. This helps in dumping.
InnoDB
now again uses asynchronous unbuffered I/O in
Windows 2000 and XP; only unbuffered simulated async
I/O in NT, 95/98/ME.
InnoDB
range estimator greatly exaggerated
the size of a short index range if the paths to the
endpoints of the range in the index tree happened
to branch in the root. This could cause
unnecessary table scans in SQL queries.
The fix will also be backported to 3.23.54.
InnoDB
startup could take very long or even
crash on some Windows 95/98/ME computers.
InnoDB
would hang, printing to the error
log many waits for a mutex created at srv0srv.c, line 1621.
InnoDB
now
does ORDER BY ... DESC like MyISAM
.
InnoDB
could return the NEXT record.
InnoDB
startup
could take very long or even crash on some Windows 95/98/ME computers.
InnoDB
would hang, printing to the error
log many waits for a mutex created at srv0srv.c, line 1621.
InnoDB
tables from 500 to 1024 bytes.
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.
InnoDB
could assert on line 155 of pars0sym.c.
InnoDB
produced a bus error
at startup.
InnoDB
Monitor to the client. The InnoDB
Monitor now prints detailed
information on
the latest detected deadlock.
InnoDB
made the SQL query optimizer to avoid too much index-only
range scans and choose full table scans instead. This is now fixed.
BEGIN
and COMMIT
are now added in the binary log around transactions.
The MySQL replication now respects transaction borders:
a user will no longer see half transactions in replication slaves.
innodb_flush_log_at_trx_commit=2
makes InnoDB
to write
the log to the operating system file cache at each commit. This is
almost as fast as the setting innodb_flush_log_at_trx_commit=0, and
the setting 2 also has the nice feature that in a crash where the
operating system does not crash, no committed transaction is lost.
If the operating system crashes or there is a power outage, then
the setting 2 is no safer than the setting 0.
InnoDB
if you have UNIQUE constraints on secondary indexes.
This flag should be used only if you are certain that the input records
contain no UNIQUE constraint violations.
InnoDB
type table, it now
checks also the adaptive hash index for all tables.
InnoDB
deleted or updated
the child row. This is now changed to conform to standard SQL: you get
the error 'Cannot delete parent row'.
InnoDB
causes InnoDB
to roll back the whole transaction, but MySQL could still
write the earlier SQL statements to the binary log, even though
InnoDB
rolled them back. This could, for example, cause replicated
databases to get out-of-sync.
InnoDB
would assert in buf0buf.ic line 214.
InnoDB
code.
InnoDB
produced a bus error
at startup.
InnoDB
is essentially the same as InnoDB-3.23.51.
InnoDB
at the database creation
now creates a 10MB auto-extending data file ibdata1 to the datadir
of MySQL. In 4.0.1 the file was 64MB and not auto-extending.
InnoDB
to attempt the deletion of the same row twice because of
a cascading delete, then you got an assertion failure.
InnoDB
may assert in ha_innobase.cc, line 302.
InnoDB
now supports an auto-extending last data file. You do not need
to preallocate the whole data file at the database startup.
InnoDB Hot Backup
tool. It is a separate non-free tool you can use to take online backups
of your database without shutting down the server or setting
any locks.
InnoDB Hot Backup
tool on an auto-extending
data file you have to upgrade it to version ibbackup-0.35.
InnoDB
data files.
InnoDB
tables: If a transaction is defined as SERIALIZABLE
then InnoDB
conceptually adds LOCK IN SHARE MODE
to all consistent reads. If a transaction is defined to have any other
isolation level, then InnoDB
obeys its default locking strategy
which is REPEATABLE READ.
DROP
DATABASE
to work. Fixed in 3.23.49: case no longer matters
on Windows. On Unix, the database name remains case sensitive.
InnoDB
now prints after crash recovery the latest MySQL binary log
file name and the position in that file (= byte offset)
InnoDB
was able to recover to. This is useful, for example,
when resynchronizing a master and a slave database in replication.
InnoDB
tablespace.
InnoDB
now prevents a FOREIGN KEY declaration where the signedness
is not the same in the referencing and referenced integer columns.
mysqld
to crash.
Especially at risk was mysqldump, because it calls frequently
SHOW CREATE TABLE.
InnoDB
table and
simultaneously did queries to it, mysqld
could crash with an assertion
failure in row0row.c, line 474.
InnoDB
asserted in lock0lock.c.
InnoDB
shutdown
to finish.
InnoDB
allows now several similar key values in a UNIQUE secondary index
if those values contain SQL NULLs. Thus the convention is now the same as in
MyISAM
tables.
InnoDB
gives a better row count estimate for a table which contains BLOBs.
InnoDB
is now case-insensitive to column
names, and in Windows also to table names.
InnoDB
allows a FOREIGN KEY column of CHAR type to refer to a column of
VARCHAR type, and vice versa. MySQL silently changes the type of some
columns between CHAR and VARCHAR, and these silent changes do not hinder
FOREIGN KEY declaration any more.
InnoDB
table is done through the
primary key. This will save a sort in some ORDER BY queries.
InnoDB
tables is again restricted to 500 bytes.
The MySQL interpreter is not able to handle longer keys.
InnoDB
is the same as in 3.23.47.
InnoDB
now flushes stdout and stderr every 10 seconds: If these
are redirected to files, the file contents can be better viewed with
an editor.
InnoDB
.
InnoDB
could go into an infinite loop
constantly printing
a warning message that it cannot find free blocks from the buffer pool.
InnoDB
type, and then
used ALTER TABLE to it, the MySQL server could crash.
InnoDB
type.
InnoDB
tables. An example: FOREIGN KEY (col1) REFERENCES table2(col2).
InnoDB
monitors, including a new innodb_table_monitor
which allows you to print the contents of the InnoDB
internal data
dictionary.
InnoDB
tables.
InnoDB
will calculate better table cardinality
estimates.
InnoDB
does a full purge
and an insert buffer merge at shutdown.
InnoDB
Monitors: innodb_monitor,
innodb_lock_monitor, and innodb_tablespace_monitor.
innodb_monitor now prints also buffer pool hit rate and the total
number of rows inserted, updated, deleted, read.
InnoDB
Monitor.
ORDER BY
bug (``Sort aborted'') fixed.
CHECK TABLE
now works for InnoDB
tables.
innodb_unix_file_flush_method
introduced. It can be used to tune disk write performance.
SELECT ... LOCK IN SHARE MODE
is introduced.
InnoDB
now calls fsync()
after every disk write and calculates
a checksum
for every database page it writes or reads, which will reveal disk defects.
MySQL Cluster
Change HistoryFunctionality added or changed:
Bugs fixed:
Functionality added or changed:
ndb-shm
and
ndb-optimized-node-selection
.
Bugs fixed:
Functionality added or changed:
ndb_mgmd
was changed to 1186 (from 2200) as
this port number was officially assigned to MySQL Cluster by IANA.
ndb_mgm
, PURGE STALE SESSIONS, as a workaround
for cases where nodes fail to allocate a node id even if it is free
to use.
ndb_mgm
, CONNECT.
[ndbd]
, [ndb_mgmd]
,
[ndb_mgm]
, [ndb_restore]
etc.
[ndbd] ndb-connectstring=myhost.domain.com:1234 [ndb_mgm] ndb-connectstring=myhost.domain.com:1234
[mysql_cluster]
in `my.cnf'. All cluster
executables, including mysqld, parse this section. Convenient place to
put e.g. ndb-connectstring
so that it only needs to be specified once.
ndb-connectstring|connect-string=myhost1,myhost2,myhost3
is
a valid connectstring and connect will occur on default port 1186.
SHOW WARNINGS
after
an error has occured which relates to the ndb storage engine.
ndb_force_send
and
ndb_use_exact_count
. Do show variables like 'ndb%';
in mysql
client for listing. Use set
command to alter variables.
ndb_use_transactions
and
ndb_autoincrement_prefetch_sz
.
Bugs fixed:
Functionality added or changed:
Bugs fixed:
Functionality added or changed:
Char set | Collation |
big5 | big5_chinese_ci |
big5_bin | |
binary | binary |
euckr | euckr_korean_ci |
euckr_bin | |
gb2312 | gb2312_chinese_ci |
gb2312_bin | |
gbk | gbk_chinese_ci |
gbk_bin | |
latin1 | latin1_swedish_ci |
latin1_bin | |
sjis | sjis_japanese_ci |
sjis_bin | |
tis620 | tis620_bin |
ucs2 | ucs2_general_ci |
ucs2_bin | |
ujis | ujis_japanese_ci |
ujis_bin | |
utf8 | utf8_general_ci |
utf8_bin |
SHOW TABLES
now directly shows ndb tables created on a different mysql server,
i.e. without a prior table access.
SHOW WARNINGS
after
an error has occured which relates to the ndb storage engine.
Bugs fixed:
Functionality added or changed:
ScanBatchSize
is likely to change.
MaxNoOfOrderedIndexes
, MaxNoOfUniqueHashIndexes
Configuration variables no longer used:
MaxNoOfIndexes
(split into the two above).
ALTER TABLE
, TRUNCATE TABLE
, and LOAD
DATA
were performed as one big transaction. In this version, all those
statements will be automatically separated into a number of transactions.
This removes the limitation that one could not change very large tables
due to the MaxNoOfConcurrentOperations
parameter.
NULL
in indexes. This
is now possible in all indexes.
AUTO_INCREMENT
features work as for
other table handlers. Autoincrements as a partial key is still only
supported by MyISAM
.
mysqld
would crash if the cluster wasn't
started and the --ndbcluster
option was used. Now mysqld
will handle cluster crashes and not started without crashing.
-i
option for initial startup has been removed from
ndbd
. Initial startup still can be specified by using the
--initial
option. The reason is to ensure that it is clearer what
takes place when using the --initial
option. This option completely
removes all data from the disk and should only be used at initial start, in
certain software upgrade cases, and in some cases when node restarts don't
work as a workaround.
ndb_mgm
) now has more commands and more
information is printed in some commands such as show
.
ndb_mgmd
and
ndbd
. Yn particular, they are now started as daemons by default.
The -n
option was removed since it could confusion as to whether its
meaning is nostart or nodaemon.
[NDBD]
as an alias for
[DB]
, [MYSQLD]
as an alias for [API]
, and
[NDB_MGMD]
as an alias for [MGM]
.
MaxNoOfOrderedIndexes : 128
and
MaxNoOfOrderedIndexes = 128
are equivalent.
MaxNoOfOrderedIndexes: 128
is equivalent to
MAXNOOFORDEREDINDEXES = 128
.
FileSystemPath
by using the BackupDir
config variable.
Log files and trace files can now be put in any directory by setting
the DataDir
configuration variable.
FileSystemPath
is no longer mandatory and defaults to DataDir
.
Bugs fixed:
Functionality added or changed:
ndbd
and
ndb_mgmd
processes have changed.
BLOB
data types was introduced in this version.
Bugs fixed:
Functionality added or changed:
Bugs fixed:
Functionality added or changed:
Bugs fixed:
This appendix will help you port MySQL to other operating systems. Do check the list of currently supported operating systems first. See section 2.1.1 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 is not good enough), 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/).
Up to MySQL 4.0.2, the MySQL distribution included a patched version of Chris Provenzano's Pthreads from MIT (see the MIT Pthreads Web page at http://www.mit.edu/afs/sipb/project/pthreads/ and a programming introduction at http://www.mit.edu:8001/people/proven/IAP_2000/). These can be used for some operating systems that do not have POSIX threads. See section 2.8.5 MIT-pthreads Notes.
It is also possible to use another user level thread package named FSU Pthreads (see http://moss.csc.ncsu.edu/~mueller/pthreads/). 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
on many platforms. Other compilers that are known to work are SPARCworks,
Sun Forte, Irix cc
, HP-UX aCC
, IBM AIX xlC_r
), Intel
ecc/icc
and Compaq cxx
).
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 will also need GNU Automake and Autoconf. See section 2.8.3 Installing from the Development Source Tree.
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 optimization that may cause problems.
See section A.4.2 What to Do If MySQL Keeps Crashing.
If mysqld
doesn't want to start, you should verify 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 optimize the table with OPTIMIZE TABLE
or
myisamchk
. See section 5 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.12 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. However, running with SAFEMALLOC
is
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 probably have 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
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 is to
send mail to a MySQL mailing list and ask for help.
See section 1.4.1.1 The MySQL Mailing Lists.
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 it
to crash quickly, you can try to create a trace file to find the problem.
To do this, you must have a mysqld
that has been compiled with
debugging support.
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'
on Unix or `C:\mysqld.trace' on Windows:
shell> mysqld --debug
On Windows, you should also use the --standalone
flag to not start
mysqld
as a service. In a console window, use this command:
C:\> mysqld --debug --standalone
After this, you can use the mysql.exe
command-line tool in a
second console window to reproduce the problem. You can stop the
mysqld
server with mysqladmin shutdown
.
Note that the trace file will become very big! If you want to generate a smaller trace file, you can use debugging options something like this:
mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace
This only prints information with the most interesting tags to the trace file.
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://ftp.mysql.com/pub/mysql/upload/ 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.
mysqld
under gdb
On most systems you can also start mysqld
from gdb
to get
more information if mysqld
crashes.
With some older gdb
versions on Linux you must use run
--one-thread
if you want to be able to debug mysqld
threads. In
this case, you can only have one thread active at a time. We recommend you
to upgrade to gdb 5.1 ASAP as thread debugging works much better with this
version!
NTPL threads (the new thread library on Linux) may cause problems while
running mysqld
under gdb
. Some symptoms are:
mysqld
hangs during startup (before it writes
ready for connections
).
mysqld
crashes during a
pthread_mutex_lock()
or pthread_mutex_unlock()
call.
In this case you should set the following environment variable
in the shell before starting gdb
:
LD_ASSUME_KERNEL=2.4.1 export LD_ASSUME_KERNEL
When running mysqld
under gdb
, you should disable
the stack trace with --skip-stack-trace
to be able to catch
segfaults within gdb
.
In MySQL 4.0.14 and above you should use the --gdb
option to
mysqld. This will install an interrupt handler for SIGINT
(needed
to stop mysqld
with ^C
to set breakpoints) and disable stack
tracing and core file handling.
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.2 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 the general MySQL mailing list.
See section 1.4.1.1 The MySQL Mailing Lists.
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.
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 5.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 Attempting 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 most MySQL binary distributions (except for the "debug" packages, where this information is included inside of the binaries themselves) ship with the above file, named
mysqld.sym.gz
.
In this case, you can simply unpack it 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.4.1.3 How to Report Bugs or Problems.
mysqld
Note that before starting mysqld
with --log
you should
check all your tables with myisamchk
.
See section 5 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 `host_name.log' In most cases it is 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 7.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 5.9.5 The Slow Query Log.
If you find the text mysqld restarted
in the error log file
(normally named `hostname.err') you probably have found a query
that causes mysqld
to fail. If this happens, you should check all
your tables with myisamchk
(see section 5 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 a MySQL
mailing list.
The mailing lists are described at
http://lists.mysql.com/, which also has links to online
list archives.
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 5.2.1 mysqld
Command-Line Options.
It's 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 whether 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 5.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://ftp.mysql.com/pub/mysql/upload/ and enter it into
our bugs system at http://bugs.mysql.com/.
If you are a support customer, you can use the MySQL Customer Support Center
https://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.8.2 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 that 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.4.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 created by Fred Fish. When you have 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.
This section summaries the argument values that you can specify in debug options on the command line for MySQL programs that have been built with debugging support. For more information about programming with the DBUG package, see the DBUG manual in the `dbug' directory of MySQL source distributions. It's best to use a recent distribution for MySQL 5.0 to get the most updated DBUG manual.
You use the debug package by invoking a program with the
--debug="..."
or the -#...
option.
Most MySQL programs have a default debug string that will be
used if you don't specify an option to --debug
. The default
trace file is usually /tmp/program_name.trace
on Unix and
\program_name.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 recognized 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. For example, -#D,20 specifies a delay of two seconds.
|
f | Limit debugging and/or tracing, and profiling to the list of named functions. Note that a null list disables 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 debug output. |
o | Redirect the debugger output stream to the specified file. The default output is stderr .
|
O | Like 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 that 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
.
I have tried to use the RTS thread packages with MySQL but stumbled on the following problems:
They use old versions of many 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 currently 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.''
This appendix lists 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 take precedence over values specified in option files and environment variables, and values in option files take precedence over values in environment variables.
In many cases, it's preferable to use an option file instead of environment variables to modify the behavior of MySQL. See section 4.3.2 Using Option Files.
Variable | Description |
CXX | The name of your C++ compiler (for running configure ).
|
CC | The name of your C compiler (for running configure ).
|
CFLAGS | Flags for your C compiler (for running configure ).
|
CXXFLAGS | Flags for your C++ compiler (for running configure ).
|
DBI_USER | The default username for Perl DBI. |
DBI_TRACE | Trace options for 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 located. |
MYSQL_DEBUG | Debug trace options when debugging. |
MYSQL_HISTFILE | The path to the mysql history file. If this variable is set, its value overrides the default of `$HOME/.mysql_history'.
|
MYSQL_HOST | The default hostname used by the mysql command-line client.
|
MYSQL_PS1 | The command prompt to use in the mysql command-line client.
|
MYSQL_PWD | The default password when connecting to mysqld . Note that use of this is insecure! See section 5.6.6 Keeping Your Password Secure.
|
MYSQL_TCP_PORT | The default TCP/IP port number. |
MYSQL_UNIX_PORT | The default Unix socket filename; used for connections to localhost .
|
PATH | Used by the shell to find MySQL programs. |
TMPDIR | The directory where temporary 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 username on Windows and NetWare to use when
connecting to mysqld .
|
A regular expression is a powerful way of specifying a pattern for a complex search.
MySQL uses Henry Spencer's implementation of regular expressions, which is
aimed at conformance with POSIX 1003.2.
See section B Credits.
MySQL uses the extended version to support pattern-matching operations
performed with the REGEXP
operator in SQL statements.
See section 3.3.4.7 Pattern Matching.
This appendix is a summary, with examples, of the special characters and
constructs that can be used in MySQL for REGEXP
operations.
It does not contain all the details that can be found in
Henry Spencer's regex(7)
manual page. That manual page is
included in MySQL source distributions, in the `regex.7' file under the
`regex' directory.
A regular expression describes a set of strings. The simplest regular
expression is one that has no special characters in it. For example, the
regular expression 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 regular expression
hello|word
matches either the string hello
or the string
word
.
As a more complex example, the regular expression 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 for the REGEXP
operator may use any of the
following special characters and 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\r\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}
{n}
or {m,n}
notation provides
a more general way of writing regular expressions that match many
occurrences of the previous atom (or ``piece'') of the pattern.
m
and n
are integers.
a*
a{0,}
.
a+
a{1,}
.
a?
a{0,1}
.
a{n}
matches exactly n
instances of
a
.
a{n,}
matches n
or more instances of a
.
a{m,n}
matches m
through n
instances of a
,
inclusive.
m
and n
must be in the range from 0
to
RE_DUP_MAX
(default 255), inclusive. If both m
and n
are given, m
must be less than or equal to n
.
mysql> SELECT 'abcde' REGEXP 'a[bcd]{2}e'; -> 0 mysql> SELECT 'abcde' REGEXP 'a[bcd]{3}e'; -> 1 mysql> SELECT 'abcde' REGEXP 'a[bcd]{1,10}e'; -> 1
[a-dX]
[^a-dX]
a
,
b
, c
, d
or X
. A -
character between two other
characters forms a range that matches all characters from the first
character to the second. For example, [0-9]
matches any decimal
digit. To include a literal ]
character, it must immediately follow
the opening bracket [
. To include a literal -
character, it
must be written first or last. Any character that does not have a defined
special meaning inside a []
pair 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.]
[
and ]
),
matches the sequence of characters of that collating element. characters
is either a single character or a character name like newline
.
You can find the full list of character names in the `regexp/cname.h'
file.
mysql> SELECT '~' REGEXP '[[.~.]]'; -> 1 mysql> SELECT '~' REGEXP '[[.tilde.]]'; -> 1
[=character_class=]
[
and ]
),
[=character_class=]
represents
an equivalence class. It matches all characters with the same collation
value, including itself.
For example, if o
and (+)
are the members of an
equivalence class, then [[=o=]]
, [[=(+)=]]
, and
[o(+)]
are all synonymous.
An equivalence class may not be used as an endpoint of a range.
[:character_class:]
[
and ]
),
[:character_class:]
represents a character class that matches all
characters belonging to that class. The standard class names are:
alnum | Alphanumeric characters |
alpha | Alphabetic characters |
blank | Whitespace characters |
cntrl | Control characters |
digit | Digit characters |
graph | Graphic characters |
lower | Lowercase alphabetic characters |
print | Graphic or space characters |
punct | Punctuation characters |
space | Space, tab, newline, and carriage return |
upper | Uppercase alphabetic characters |
xdigit | Hexadecimal digit characters |
ctype(3)
manual
page. A particular locale may provide other class names.
A character class may not be used as an endpoint of a range.
mysql> SELECT 'justalnums' REGEXP '[[:alnum:]]+'; -> 1 mysql> SELECT '!!' REGEXP '[[:alnum:]]+'; -> 0
[[:<:]]
[[:>:]]
alnum
class or an underscore
(_
).
mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]'; -> 1 mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; -> 0
To use a literal instance of a special character in a regular expression,
precede it by two backslash (\) characters. The MySQL parser
interprets one of the backslashes, and the regular expression library
interprets the other. For example, to match the string 1+2
that
contains the special +
character, only the last of the following
regular expressions is the correct one:
mysql> SELECT '1+2' REGEXP '1+2'; -> 0 mysql> SELECT '1+2' REGEXP '1\+2'; -> 0 mysql> SELECT '1+2' REGEXP '1\\+2'; -> 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.
25.6 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 0.3, 10 February 2005
The MySQL AB Exception for Free/Libre and Open Source Software-only Applications Using MySQL Client Libraries (the ``FLOSS Exception'').
We want specified Free/Libre and Open Source Software (``FLOSS'') applications to be able to use specified GPL-licensed MySQL client libraries (the ``Program'') despite the fact that not all FLOSS licenses are compatible with version 2 of the GNU General Public License (the ``GPL'').
As a special exception to the terms and conditions of version 2.0 of the GPL:
License name | Version(s)/Copyright Date |
Academic Free License | 2.0 |
Apache Software License | 1.0/1.1/2.0 |
Apple Public Source License | 2.0 |
Artistic license | From Perl 5.8.0 |
BSD license | "July 22 1999" |
Common Public License | 1.0 |
GNU Library or "Lesser" General Public License (LGPL) | 2.0/2.1 |
Jabber Open Source License | 1.0 |
MIT license | - |
Mozilla Public License (MPL) | 1.0/1.1 |
Open Software License | 2.0 |
OpenSSL license (with original SSLeay license) | "2003" ("1998") |
PHP License | 3.0 |
Python license (CNRI Python License) | - |
Python Software Foundation License | 2.1.1 |
Sleepycat License | "1999" |
W3C License | "2001" |
X11 License | "2001" |
Zlib/libpng License | - |
Zope Public License | 2.0 |
CC
environment variable
CXX
environment variable
CC
CXX
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_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_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_client_version()
mysql_get_host_info()
mysql_get_proto_info()
mysql_get_server_info()
mysql_get_server_version()
mysql_hex_string()
MYSQL_HISTFILE
environment variable
MYSQL_HOST
environment variable
mysql_info()
mysql_init()
mysql_insert_id()
mysql_kill()
mysql_library_end()
mysql_library_init()
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_ping()
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_server_end()
mysql_server_init()
mysql_set_sever_option()
mysql_shutdown()
mysql_sqlstate()
mysql_ssl_set()
mysql_stat()
mysql_stmt_affected_rows()
mysql_stmt_attr_get()
mysql_stmt_attr_set()
mysql_stmt_bind_param()
mysql_stmt_bind_result()
mysql_stmt_close()
mysql_stmt_data_seek()
mysql_stmt_errno()
mysql_stmt_error()
.
mysql_stmt_execute()
mysql_stmt_fetch()
mysql_stmt_fetch_column()
mysql_stmt_field_count()
mysql_stmt_free_result()
mysql_stmt_init()
mysql_stmt_insert_id()
mysql_stmt_num_rows()
mysql_stmt_param_count()
mysql_stmt_param_metadata()
mysql_stmt_prepare()
mysql_stmt_reset()
mysql_stmt_result_metadata
.
mysql_stmt_row_seek()
mysql_stmt_row_tell()
mysql_stmt_send_long_data()
.
mysql_stmt_sqlstate()
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()
mysql_warning_count()
.
USER
environment variable
--with-raid
link errors
ACID
GROUP BY
clauses
ORDER BY
clauses
ARCHIVE
storage engine, ARCHIVE
storage engine
ARCHIVE
table type, ARCHIVE
table type
AUTO_INCREMENT
, and NULL
values
batch
, mysql
option
BDB
storage engine, BDB
storage engine
BDB
table type, BDB
table type
BDB
tables
BerkeleyDB
storage engine, BerkeleyDB
storage engine
BerkeleyDB
table type, BerkeleyDB
table type
BLOB
columns, default values
BLOB
columns, indexing, BLOB
columns, indexing
BLOB
, inserting binary data
BLOB
, size
blocking_queries
, mysqlcc
option
mysqld
server
gcc
cc1plus
problems
character-sets-dir
, mysql
option
mysql
mysqladmin
mysqlcc
gcc
compress
, mysql
option
compress
, mysqlcc
option
config-file
, mysqld_multi
option
config.cache
file
configure
script
configure
, running after prior invocation
connect_timeout
variable, connect_timeout
variable, connect_timeout
variable
connection_name
, mysqlcc
option
CSV
storage engine, CSV
storage engine
CSV
table type, CSV
table type
database
, mysql
option
database
, mysqlcc
option
db
table, sorting
DBI
interface
DBI/DBD
interface
debug-info
, mysql
option
debug
, mysql
option
decode_bits
myisamchk
variable
BLOB
and TEXT
columns
default-character-set
, mysql
option
mysql.sock
SHOW
, displaying, information, SHOW
, displaying, information, SHOW
, displaying, information, SHOW
EXAMPLE
storage engine, EXAMPLE
storage engine
EXAMPLE
table type, EXAMPLE
table type
example
, mysqld_multi
option
myisamchk
output
execute
, mysql
option
FALSE
, testing for
fatal signal 11
FEDERATED
storage engine, FEDERATED
storage engine
FEDERATED
table type, FEDERATED
table type
config.cache
tmp
force
, mysql
option
ft_max_word_len
myisamchk
variable
ft_min_word_len
myisamchk
variable
ft_stopword_file
myisamchk
variable
SELECT
and WHERE
clauses
gcc
GROUP BY
, aliases in
GROUP BY
, extensions to standard SQL, GROUP BY
, extensions to standard SQL
HEAP
storage engine, HEAP
storage engine
HEAP
table type, HEAP
table type
help
, mysql
option
help
, mysqlcc
option
help
, mysqld_multi
option
history_size
, mysqlcc
option
host
table
host
table, sorting
host
, mysql
option
host
, mysqlcc
option
html
, mysql
option
ignore-space
, mysql
option
BLOB
columns, indexes, and BLOB
columns
IS NULL
LIKE
NULL
values
TEXT
columns, indexes, and TEXT
columns
InnoDB
storage engine, InnoDB
storage engine
InnoDB
table type, InnoDB
table type
InnoDB
tables
ISAM
storage engine, ISAM
storage engine
ISAM
table type, ISAM
table type
key_buffer_size
myisamchk
variable
mysqlclient
mysqld
local-infile
, mysql
option
local-infile
, mysqlcc
option
log
, mysqld_multi
option
make_binary_distribution
max_allowed_packet
variable, max_allowed_packet
variable
max_join_size
variable, max_join_size
variable
MEMORY
storage engine, MEMORY
storage engine
MEMORY
table type, MEMORY
table type
MERGE
storage engine, MERGE
storage engine
MERGE
table type, MERGE
table type
msql2mysql
MyISAM
storage engine, MyISAM
storage engine
MyISAM
table type, MyISAM
table type
myisam_block_size
myisamchk
variable
myisamchk
, myisamchk
myisamchk
, example output
myisamchk
, options
myisampack
, myisampack
, myisampack
, myisampack
mysql
, mysql
mysql
command-line options
mysql.server
mysql.sock
, protection
mysql_config
mysql_fix_privilege_tables
, mysql_fix_privilege_tables
mysql_install_db
mysql_install_db
script
mysqlaccess
mysqladmin
, mysqladmin
, mysqladmin
, mysqladmin
, mysqladmin
, mysqladmin
, mysqladmin
, mysqladmin
mysqladmin
command-line options
mysqladmin
, mysqld_multi
option
mysqlbinlog
, mysqlbinlog
mysqlbug
mysqlbug
script
mysqlbug
script, location
mysqlcc
, mysqlcc
mysqlcc
command-line options
mysqlcheck
mysqlclient
library
mysqld
mysqld
library
mysqld
options
mysqld
server, buffer sizes
mysqld
, starting
mysqld-max
, mysqld-max
mysqld
, mysqld_multi
option
mysqld_multi
, mysqld_multi
mysqld_safe
, mysqld_safe
mysqldump
, mysqldump
, mysqldump
mysqlhotcopy
mysqlimport
, mysqlimport
, mysqlimport
, mysqlimport
mysqlshow
named-commands
, mysql
option
net_buffer_length
variable, net_buffer_length
variable
mysql.user
table
no-auto-rehash
, mysql
option
no-beep
, mysql
option
no-log
, mysqld_multi
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_files_limit
variable
mysql
mysqladmin
mysqlcc
configure
myisamchk
ORDER BY
, aliases in
pack_isam
pager
, mysql
option
password
, mysql
option
password
, mysqlcc
option
password
, mysqld_multi
option
perror
plugins_path
, mysqlcc
option
port
, mysql
option
port
, mysqlcc
option
DATE
columns
prompt
, mysql
option
protocol
, mysql
option
query
, mysqlcc
option
quick
, mysql
option
raw
, mysql
option
read_buffer_size
myisamchk
variable
reconnect
, mysql
option
register
, mysqlcc
option
replace
configure
after prior invocation
safe-updates
option
safe-updates
, mysql
option
safe_mysqld
mysql_install_db
mysqlbug
SELECT
, Query Cache
select_limit
variable, select_limit
variable
server
, mysqlcc
option
shutdown_timeout
variable
sigint-ignore
, mysql
option
silent
, mysql
option
silent
, mysqld_multi
option
skip-column-names
, mysql
option
skip-line-numbers
, mysql
option
socket
, mysql
option
socket
, mysqlcc
option
sort_buffer_size
myisamchk
variable
sort_key_blocks
myisamchk
variable
sql_yacc.cc
problems
mysqld
mysql
mysqladmin
mysqlcc
syntax
, mysqlcc
option
syntax_file
, mysqlcc
option
table
, mysql
option
BDB
Berkeley DB
HEAP
host
InnoDB
MEMORY
MERGE
MyISAM
tcp-ip
, mysqld_multi
option
tee
, mysql
option
TEXT
columns, default values
TEXT
columns, indexing, TEXT
columns, indexing
TEXT
, size
connect_timeout
variable, timeout, connect_timeout
variable, timeout, connect_timeout
variable
shutdown_timeout
variable
TIMESTAMP
, and NULL
values
translations_path
, mysqlcc
option
TRUE
, testing for
unbuffered
, mysql
option
UNKNOWN
, testing for
user
table, sorting
user
, mysql
option
user
, mysqlcc
option
user
, mysqld_multi
option
VARCHAR
, size
mysqld
verbose
, mysql
option
verbose
, mysqld_multi
option
version
, mysql
option
version
, mysqlcc
option
version
, mysqld_multi
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
write_buffer_size
myisamchk
variable
xml
, mysql
option