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.
ps, Task Manager, or some similar program, to check which program is taking all CPU or is locking the machine.
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.
mysqldserver is causing problems, can you get any response from it with
mysqladmin -u root pingor
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 126.96.36.199 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 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
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
Start by checking whether there is a process named
mysqld running on
your server host.
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 188.8.131.52 Starting and Troubleshooting the MySQL Server.
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
command; these cause the output of
hostname (that is, the current
hostname) to be substituted into the
If you have no
hostname command or are running on Windows, you can
manually type the hostname of your machine (without backticks) following the
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:
mysqldis not running. Check your operating system's process list to ensure the
mysqldprocess is present.
mysqlduses 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
mysqlduses (`/tmp/mysql.sock' by default). For example, you might have a
cronjob that removes old files from the `/tmp' directory. You can always run
mysqladmin versionto check whether the Unix socket file that
mysqladminis trying to use really exists. The fix in this case is to change the
cronjob 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'.
mysqldserver with the
--socket=/path/to/socketoption, 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
--socketoption 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'.
mysqldthreads (for example, with
killor with the
mysql_zapscript) before you can restart the MySQL server. See section A.4.2 What to Do If MySQL Keeps Crashing.
--socketoption 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
telnet some_host 3306and 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 variablesto 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
mysqldserver was not started with the
--skip-networkingoption. 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 PASSWORDstatement and the
mysql> SET PASSWORD FOR -> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');Alternatively, use
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.
mysql> SELECT Host, User, Password FROM mysql.user -> WHERE LENGTH(Password) > 16;For each account record displayed by the query, use the
Uservalues and assign a password using the
OLD_PASSWORD()function and either
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
-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
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
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
See section 5.2.3 Server System Variables.
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
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
system variable. Its default value is 100. If you need to support more
connections, you should restart
mysqld with a larger value for this
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 184.108.40.206
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
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
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
|The client couldn't send a question to the server.|
|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
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
Some other common reasons for the
MySQL server has gone away error are:
KILLstatement or a
mysql_options(..., MYSQL_OPT_WRITE_TIMEOUT,...). In this case increasing the timeout may help solve the problem.
reconnectflag in the
MYSQLstructure is equal to 0).
wait_timeoutexpired) 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
reconnectflag in the
MYSQLstructure 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_pingon the connection if there has been a long time since the last query (this is what
MyODBCdoes) or set
mysqldserver so high that it will in practice never time out.
mysqldreceives 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
BLOBcolumns), you can increase the query limit by setting the server's
max_allowed_packetvariable, 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 awayerror if MySQL is started with the
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:
mysqldand the tables involved were checked with
CHECK TABLEbefore 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_timeoutsystem variable in the MySQL server? (
mysqladmin variablesgives you the value of this variable.)
--logoption to determine whether the problem query appears in the log?
See also See section A.2.10 Communication Errors and Aborted Connections.
See section 220.127.116.11 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
max_allowed_packet bytes, it issues a
large error and closes the connection. With some clients, you may also
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> 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
example, to set the size for the server to 16MB, add the following lines in
an option file:
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
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
The server error log can be a useful source of information about connection
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'
Aborted connections messages appear in the error log, the cause
can be any of the following:
interactive_timeoutseconds 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_timeoutseconds 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_packetvariable 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_sizebytes. To avoid this problem, you can use the
-O tmp_table_size=#option to make
mysqldincrease the temporary table size or use the SQL option
SQL_BIG_TABLESbefore you issue the problematic query. See section 13.5.3
SETSyntax. You can also start
--big-tablesoption. This is exactly the same as using
SQL_BIG_TABLESfor 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
InnoDBtables and run out of room in the
InnoDBtablespace. In this case, the solution is to extend the
InnoDBtablespace. See section 15.8 Adding and Removing
InnoDBData and Log Files.
MyISAMtables 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.
MyISAMtable and the space required for the table exceeds what is allowed by the internal pointer size. (If you don't specify the
MAX_ROWStable option when you create a table, MySQL uses the
myisam_data_pointer_sizesystem 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 tbl_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;You have to specify
AVG_ROW_LENGTHonly for tables with
TEXTcolumns; 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:
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
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
try to execute a new query before you have called
It can also happen if you try to execute two queries that return data without
mysql_store_result() in between.
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
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:
mysqldwith an old
usertable. You can check this by executing
mysqlshow mysql userto see whether the
Passwordcolumn is shorter than 16 characters. If so, you can correct this condition by running the
--old-protocoloption. Update the account in the
usertable to have a new password or restart
usertable without using the
mysqlto update the account in the
usertable with a new password, making sure to use the
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
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:
--with-extra-charsets=charset_nameoption. See section 2.8.2 Typical
configureOptions. 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:
If you get
ERROR '...' not found (errno: 23),
Can't open file:
... (errno: 24), or any other error with
errno 23 or
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
mysqld to keep open fewer files at a time, you can make the
table cache smaller by reducing the value of the
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
--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
doesn't support setting the open files limit, you can edit the
mysqld_safe script. There is a commented-out line
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
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
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
Note: If you run the
ulimit will not work!
tcsh will also report incorrect values when you ask for the current
limits. In this case, you should start
When you are linking an application program to use the MySQL client library,
you might get undefined reference errors for symbols that start with
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
-lmysqlclient at the end of your link command, where
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
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
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
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:
Another way to solve this problem is by linking your program statically with
-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
for security reasons. In order to change
mysqld to run as a normal
unprivileged Unix user user_name, you must do the following:
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 -Rmight not follow symbolic links for you.
mysqldas the Unix
rootuser and use the
mysqldwill start up, then switch to run as the Unix user user_name before accepting any connections.
useroption 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:
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
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)
UMASK value is
0660. You can change this behavior by
mysqld_safe as follows:
shell> UMASK=384 # = 600 in octal shell> export UMASK shell> mysqld_safe &
By default, MySQL creates database and
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
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
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
rootpassword 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
is as follows:
rootuser or as the same user that the
mysqldserver runs as.
kill -9) to the
mysqldprocess, 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
catcommand; these cause the output of
catto be substituted into the
shell> mysqld_safe --skip-grant-tables &
[email protected]MySQL account:
shell> mysqladmin -u root flush-privileges password "newpwd"Replace ``newpwd'' with the actual
rootpassword that you want to use.
Alternatively, on any platform, you can set the new password using the
mysqldand restart it with the
--skip-grant-tablesoption as described earlier.
mysqldserver with this command:
shell> mysql -u root
mysql> UPDATE mysql.user SET Password=PASSWORD('newpwd') -> WHERE User='root'; mysql> FLUSH PRIVILEGES;Replace ``newpwd'' with the actual
rootpassword 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
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
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
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
The preceding means that normally you should not get corrupted tables unless one of the following happens:
mysqldthat caused it to die in the middle of an update.
mysqldwithout locking the table properly.
mysqldservers using the same data directory on a system that doesn't support good filesystem locks (normally handled by the
lockdlock manager), or you are running multiple servers with the
ALTER TABLEon 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:
mysqladmin shutdown, run
myisamchk --silent --force */*.MYIfrom the data directory to check all
MyISAMtables, and restart
mysqld. This will ensure that you are running from a clean state. See section 5 Database Administration.
--logoption 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 18.104.22.168 How to Report Bugs or Problems.
fork_big.plscript. (It is located in the `tests' directory of source distributions.)
configureand then recompile. See section E.1 Debugging a MySQL Server.
mysqld. On some systems, the
lockdlock manager does not work properly; the
mysqldnot to use external locking. (This means that you cannot run two
mysqldservers 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 processlistwhen
mysqldappears to be running but not responding? Sometimes
mysqldis 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 processlistusually 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 statusor
mysqladmin -i 5 -r statusin a separate window to produce statistics while you run your other queries.
gdb(or another debugger). See section E.1.3 Debugging
gdb, you can do this with the following commands when
mysqldhas crashed inside
backtrace info local up info local up info localWith
gdb, you can also examine which threads exist with
info threadsand switch to a specific thread with
thread #, where
#is the thread ID.
TEXTcolumns), you can try to change all
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
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
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
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.
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 (
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
/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:
[mysqld] socket=/path/to/socket [client] socket=/path/to/socketSee section 4.3.2 Using Option Files.
--socketoption on the command line to
mysqld_safeand when you run client programs.
MYSQL_UNIX_PORTenvironment variable to the path of the Unix socket file.
--with-unix-socket-pathoption when you run
configure. See section 2.8.2 Typical
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
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
The allowable values for
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
This means that if you search with
col_name LIKE 'a%', you will get all
column values that start with
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
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
big5 character set:
CREATE TABLE t (name CHAR(40) CHARACTER SET big5);
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
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
clause that compares a date to a
DATETIME column. (``Relaxed form'' means that any punctuation character
may be used as the separator between parts. For example,
'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
MyODBC 2.50.12 and above, because ODBC can't handle this kind of
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
'YYYY-MM-DD' format and performs a string comparison.
It does not convert
'20030505' to the date
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
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
If the date cannot be converted to any reasonable value, a
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
Date handling in MySQL 5.0.1 and earlier works like MySQL 5.0.2 with the
ALLOW_INVALID_DATES SQL mode enabled.
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
''. 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
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
In SQL, the
NULL value is never true in comparison to any
other value, even
NULL. An expression that contains
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
mysql> SELECT NULL, 1+NULL, CONCAT('Invisible',NULL);
If you want to search for column values that are
cannot use an
expr = NULL test. The following statement returns no
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
values if you are using MySQL 3.23.2 or newer and are using the
BDB storage engine.
As of MySQL 4.0.2, the
MEMORY storage engine also supports
values in indexes. Otherwise, you must declare an indexed column
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 ``
may also be used under some circumstances.
See section 13.1.5
LOAD DATA INFILE Syntax.
GROUP BY, or
ORDER BY, all
NULL values are regarded as equal.
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
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
mysql> SELECT COUNT(*), COUNT(age) FROM person;
For some column types, MySQL handles
NULL values specially. If you
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
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;
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
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
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 22.214.171.124
SHOW TABLE STATUS Syntax and
SHOW CREATE TABLE Syntax.
You can check which storage engines your
mysqld server supports by
using this statement:
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
See section 126.96.36.199
SHOW ENGINES Syntax and
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
statements, you can use the following approach to delete rows from two
SELECTthe rows based on some
WHEREcondition in the main table.
DELETEthe 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
more than 1MB (the default value of the
variable), you should split it into smaller parts and execute multiple
DELETE statements. You will probably get the fastest
by specifying only 100 to 1,000
related_column values per statement if the
related_column is indexed. If the
indexed, the speed is independent of the number of arguments in the
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:
EXPLAINto check whether you can find something that is obviously wrong. See section 7.2.1
EXPLAINSyntax (Get Information About a
LIMIT 10with the query.
SELECTfor the column that should have matched a row against the table that was last removed from the query.
DOUBLEcolumns 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
DOUBLEwill fix this. See section A.5.8 Problems with Floating-Point Comparisons.
mysql test < query.sqlthat 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
SELECTstatement 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
mysqlbugto the general MySQL mailing list. See section 188.8.131.52 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
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
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
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
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:
EXPLAINstatement to get information about how MySQL will process a query. To use it, just add the keyword
EXPLAINto the front of your
mysql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.i = t2.i;
EXPLAINis discussed in more detail in section 7.2.1
EXPLAINSyntax (Get Information About a
ANALYZE TABLE tbl_nameto update the key distributions for the scanned table. See section 184.108.40.206
FORCE INDEXfor the scanned table to tell MySQL that table scans are very expensive compared to using the given index. See section 13.1.7
SELECT * FROM t1, t2 FORCE INDEX (index_for_column) WHERE t1.col_name=t2.col_name;
IGNORE INDEXmay also be useful.
STRAIGHT_JOIN. See section 13.1.7
--max-seeks-for-key=1000option or use
SET max_seeks_for_key=1000to 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 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.
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
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
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;
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.
The following list indicates limitations on the use of
TEMPORARYtable can only be of type
TEMPORARYtable 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 TABLESstatement does not list
RENAMEto rename a
TEMPORARYtable. However, you can use
mysql> ALTER TABLE orig_name RENAME new_name;
Go to the first, previous, next, last section, table of contents.