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 already
are used 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
already 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 already 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;
Go to the first, previous, next, last section, table of contents.