Apéndice A. Problemas y errores comunes
Anterior |  | Siguiente

## Apéndice A. Problemas y errores comunes

Este apéndice enumera algunos problemas comunes y mensajes de error que usted podría encontrarse. Explica como determinar los motivos de los problemas y qué hacer para resolverlos.

## A.1. Cómo determinar a qué es debido un problema

Cuando se encuentre un problema, la primera cosa que debe hacer es determinar qué programa o pieza de hardware lo está causando:

- Si tiene uno de los siguientes síntomas, entonces es probable que sea un problema de hardware (como memória, placa madre, CPU, o disco duro), o un problema del núcleo del sistema operativo:

  - El teclado no funciona. Esta anomalía puede comprobarse normalmente pulsando la tecla Bloq Mayus (Caps Lock). Si la luz de bloqueo de mayúsculas no se enciende, debería cambiar su teclado. (Antes de hacer esto, debería intentar reiniciar la máquina y comprobar todo el cableado del teclado).

  - El puntero del ratón no se mueve.

  - La máquina no responde a pings de máquinas remotas.

  - Otros programas que no están relacionados con MySQL no se comportan correctamente.

  - El sistema se reinició inesperadamente. (Un programa de nivel de usuario defectuoso nunca debería ser capaz de hacer caer el sistema.)

  En este caso, debería comenzar por comprobar todos los cables y ejecutar alguna herramienta de diagnóstico para comprobar el hardware. Debería también comprobar si hay algún parche, actualización, o paquetes de servicio para su sistema operativo que podría resolver su problema. Compruebe también que todas las librerías (tales como `glibc`) están actualizadas.

  Siempre es bueno utilizar una máquina con memoria ECC para descubrir los problemas de memoria lo antes posible.

- Si el teclado está bloqueado, debería ser capaz de recuperarlo conectándose a su máquina desde otra y ejecutando `kbd_mode -a`.

- Por favor, examine su archivo de registro del sistema (`/var/log/messages` o similar) para encontrar motivos de su problema. Si piensa que el problema está en MySQL, también debería revisar los archivos de registro de MySQL. Consulte Sección 5.10, “Los ficheros de registro (log) de MySQL”.

- Si no cree que tenga problemas de hardware, debería intentar encontrar el programa que le está casuando problemas. Intente utilizar los programas top, ps, el Administrador de Tareas, o algún programa similar, para comprobar cual de los procesos que se están ejecutando está monopolizando la CPU o bloqueando la máquina.

- Utilice top, df, o un programa similar para comprobar si se está quedando sin memoria, espacio en disco, descriptores de archivo, o algún otro recurso crítico.

- Si el problema es algún proceso desbocado, siempre puede intentar matarlo. Si no quiere morir, probablemente exista algún error en el sistema operativo.

Si tras haber examinado el resto de posibilidades y llega a la conclusión de que el servidor o el cliente MySQL puedan estar causando el problema, es el momento de crear un informe de fallos para nuestra lista de correos o equipo de soporte. En el informe, intente dar una descripción muy detallada de como el sistema se está comportando y qué es lo que usted cree que está sucediendo. También debería explicar por qué cree que MySQL está causando el problema. Tenga en cuenta todas los puntos de este capítulo. Explique cualqiuer problema de la maenra exacta como aparecen cuando usted examina su sistema. Utilice el método de “copiar y pegar” para enviar cualquier salida o mensaje de error de los programas o archivos de registro.

Intente explicar con detalle qué programa no está funcionando y los síntomas que usted ve. En el pasado, hemos recibido muchos informes de error que únicamente decían “el sistema no funciona.” Esto no nos da mucha información sobre cual pueda ser el problema.

Si un programa falla, siempre es útil saber lo siguiente:

- ¿Ha hecho el programa en cuestión un fallo de segmentación?

- ¿El programa está ocupando todo el tiempo disponible de CPU? Compruébelo con top. Deje el programa ejecutarse durante unos instantes, podría ser simplemente que está haciendo algunos cálculos intensivos.

- If the mysqld server is causing problems, can you get any response from it with mysqladmin -u root ping or mysqladmin -u root processlist?

- What does a client program say when you try to connect to the MySQL server? (Try with 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 Sección 1.6.1.2, “Hacer preguntas y reportar bugs”.

## A.2. Errores comunes al usar programas MySQL

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.

### A.2.1. `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 Sección 5.6.8, “Causas de errores `Access denied`”. See Sección 5.6.2, “Cómo funciona el sistema de privilegios”.

### A.2.2. `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 tries to connect to the named pipe. If that doesn't work, it connects 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 Sección 2.9.2.3, “Arrancar y resolver problemas del servidor MySQL”.

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.

- You are running on a system that uses MIT-pthreads. If you are running on a system that doesn't have native threads, mysqld uses the MIT-pthreads package. See Sección 2.1.1, “Sistemas operativos que MySQL soporta”. 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

- Someone has removed the Unix socket file that 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 Sección A.4.5, “Cómo proteger o cambiar el fichero socket de MySQL `/tmp/mysql.sock`”.

- You have started the 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 socket file is, you can do:

      shell> netstat -ln | grep mysql

  See Sección A.4.5, “Cómo proteger o cambiar el fichero socket de MySQL `/tmp/mysql.sock`”.

- You are using Linux and one server thread has died (dumped core). In this case, you must kill the other mysqld threads (for example, with `kill` or with the `mysql_zap` script) before you can restart the MySQL server. See Sección A.4.2, “Qué hacer si MySQL sigue fallando (crashing)”.

- The server or client program might not have the proper access privileges for the directory that holds the Unix socket file or the socket file itself. In this case, you must either change the access privileges for the directory or socket file so that the server and clients can access them, or restart 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:

- Check whether the server is running on that host by executing `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.

- If the server is running on the local host, try using 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.)

- Make sure that your mysqld server was not started with the `--skip-networking` option. If it was, you cannot connect to it using TCP/IP.

- Check to make sure that there is no firewall blocking access to MySQL. Applications such as ZoneAlarm and the Windows XP personal firewall may need to be configured to allow external access to a MySQL server.

### A.2.3. `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:

- Upgrade all client programs to use a 4.1.1 or newer client library.

- When connecting to the server with a pre-4.1 client program, use an account that still has a pre-4.1-style password.

- Reset the password to pre-4.1 style for each user that needs to use a pre-4.1 client program. This can be done using the `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.

- Tell the server to use the older password hashing algorithm:

  1. Start mysqld with the `--old-passwords` option.

  2. Assign an old-format password to each account that has had its password updated to the longer 4.1 format. You can identify these accounts with the following query:

         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.

Note: In PHP, the `mysql` extension does not support the new authentication protocol in MySQL 4.1.1 and higher. This is true regardless of the PHP version being used. If you wish to use the `mysql` extension with MySQL 4.1 or newer, you will need to follow one of the options discussed above for configuring MySQL to work with old clients. The `mysqli` extension (stands for "MySQL, Improved"; new in PHP 5) is compatible with the improved password hashing employed in MySQL 4.1 and higher, and no special configuration of MySQL need be done in order to use this newer MySQL client library for PHP. For more information about the `mysqli` extension, see http://php.net/mysqli.

For additional background on password hashing and authentication, see Sección 5.6.9, “Hashing de contraseñas en MySQL 4.1”.

### A.2.4. La contraseña falla cuando se introduce interactivamente

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.

### A.2.5. `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 Sección 5.3.3, “Variables de sistema del servidor”.

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 does you no good to increase the value of the `max_connect_errors` variable.

### A.2.6. `Too many connections`

If you get a `Too many connections` error when you try to connect to the mysqld server, this means that all available connections are in use by other clients.

The number of connections allowed is controlled by the `max_connections` system variable. Its default value is 100. If you need to support more connections, you should restart mysqld with a larger value for this variable.

mysqld actually allows `max_connections+1` clients to connect. The extra connection is reserved for use by accounts that have the `SUPER` privilege. By granting the `SUPER` privilege to administrators and not to normal users (who should not need it), an administrator can connect to the server and use `SHOW PROCESSLIST` to diagnose problems even if the maximum number of unprivileged clients are connected. See Sección 13.5.4.16, “Sintaxis de `SHOW PROCESSLIST`”.

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.

### A.2.7. `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).

### A.2.8. `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 Sección 5.3.3, “Variables de sistema del servidor”.

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:

- You (or the db administrator) has killed the running thread with a `KILL` statement or a mysqladmin kill command.

- You tried to run a query after closing the connection to the server. This indicates a logic error in the application that should be corrected.

- You got a timeout from the TCP/IP connection on the client side. This may happens if you have been using the commands: `mysql_options(..., MYSQL_OPT_READ_TIMEOUT,...)` or `mysql_options(..., MYSQL_OPT_WRITE_TIMEOUT,...)`. In this case increasing the timeout may help solve the problem.

- You have encountered a timeout on the server side and the automatic reconnection in the client is disabled (the `reconnect` flag in the `MYSQL` structure is equal to 0).

- You are using a windows client and the server had dropped the connection (probably because `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 does 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 in practice never times out.

- You can also get these errors if you send a query to the server that is incorrect or too large. If 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 Sección A.2.9, “`Packet too large`”.

- You also get a lost connection if you are sending a packet 16MB or larger if your client is older than 4.0.8 and your server is 4.0.8 and above, or the other way around.

- You may also see the `MySQL server has gone away` error if MySQL is started with the `--skip-networking` option.

- You have encountered a bug where the server died while executing the query.

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 Sección A.4.2, “Qué hacer si MySQL sigue fallando (crashing)”.

You can get more information about the lost connections by starting mysqld with the `--log-warnings=2` option. This logs some of the disconnected errors in the `hostname.err` file. See Sección 5.10.1, “El registro de errroes (Error Log)”.

If you want to create a bug report regarding this problem, be sure that you include the following information:

- Indicate whether or not the MySQL server died. You can find information about this in the server error log. See Sección A.4.2, “Qué hacer si MySQL sigue fallando (crashing)”.

- If a specific query kills mysqld and the tables involved were checked with `CHECK TABLE` before you ran the query, can you provide a reproducible test case? See Sección D.1.6, “Crear un caso de prueba tras haber encontrado una tabla corrupta”.

- What is the value of the `wait_timeout` system variable in the MySQL server? (mysqladmin variables gives you the value of this variable.)

- Have you tried to run mysqld with the `--log` option to determine whether the problem query appears in the log?

See also See Sección A.2.10, “Errores de comunicación y conexiones abortadas”.

See Sección 1.6.1.2, “Hacer preguntas y reportar bugs”.

### A.2.9. `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.

### A.2.10. Errores de comunicación y conexiones abortadas

The server error log can be a useful source of information about connection problems. See Sección 5.10.1, “El registro de errroes (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:

- The client program did not call `mysql_close()` before exiting.

- The client had been sleeping more than `wait_timeout` or `interactive_timeout` seconds without issuing any requests to the server. See Sección 5.3.3, “Variables de sistema del servidor”.

- The client program ended abruptly in the middle of a data transfer.

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:

- A client doesn't have privileges to connect to a database.

- A client uses an incorrect password.

- A connection packet doesn't contain the right information.

- It takes more than `connect_timeout` seconds to get a connect packet. See Sección 5.3.3, “Variables de sistema del servidor”.

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:

- Use of Ethernet protocol with Linux, both half and full duplex. Many Linux Ethernet drivers have this bug. You should test for this bug by transferring a huge file via FTP between the client and server machines. If a transfer goes in burst-pause-burst-pause mode, you are experiencing a Linux duplex syndrome. The only solution is switching the duplex mode for both your network card and hub/switch to either full duplex or to half duplex and testing the results to determine the best setting.

- Some problem with the thread library that causes interrupts on reads.

- Badly configured TCP/IP.

- Faulty Ethernets, hubs, switches, cables, and so forth. This can be diagnosed properly only by replacing hardware.

- The `max_allowed_packet` variable value is too small or queries require more memory than you have allocated for mysqld. See Sección A.2.9, “`Packet too large`”.

See also See Sección A.2.8, “`MySQL server has gone away`”.

### A.2.11. `The table is full`

There are several ways a full-table error can occur:

- You are using a MySQL server older than 3.23 and an in-memory temporary table becomes larger than `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 Sección 13.5.3, “Sintaxis de `SET`”.

  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.

- You are using `InnoDB` tables and run out of room in the `InnoDB` tablespace. In this case, the solution is to extend the `InnoDB` tablespace. See Sección 15.7, “Añadir y suprimir registros y ficheros de datos `InnoDB`”.

- You are using `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.

- You are using a `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. From MySQL 5.0.6 on, the default value is 6 bytes, which is enough to allow 65,536TB of data. Before MySQL 5.0.6, the default value is 4 bytes, which is enough to allow only 4GB of data. See Sección 5.3.3, “Variables de sistema del servidor”.

  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.

### A.2.12. `Can't create/write to file`

If you get an error of the following type for some queries, it means that MySQL cannot create a temporary file for the result set in the temporary directory:

    Can't create/write to file '\\sqla3fe_0.ism'.

The preceding error is a typical message for Windows; the Unix message is similar.

One fix is to start mysqld with the `--tmpdir` option or to add the option to the `[mysqld]` section of your option file. For example, to specify a directory of `C:\temp`, use these lines:

    [mysqld]
    tmpdir=C:/temp

The `C:\temp` directory must exist and have sufficient space for the MySQL server to write to. See Sección 4.3.2, “Usar ficheros de opciones”.

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

### A.2.13. `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.

### A.2.14. `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:

- You may be running a new version of 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.

- The account has an old password (eight characters long) and you didn't start 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.

- You have specified a password in the `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';

### A.2.15. `Table '`nombre_de_tabla`' 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:

- Because MySQL uses directories and files to store databases and tables, database and table names are case sensitive if they are located on a filesystem that has case-sensitive filenames.

- Even for filesystems that are not case sensitive, such as on Windows, all references to a given table within a query must use the same lettercase.

You can check which tables are in the current database with `SHOW TABLES`. See Sección 13.5.4, “Sintaxis de `SHOW`”.

### A.2.16. `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:

- The character set is a multi-byte character set and you have no support for the character set in the client. In this case, you need to recompile the client by running configure with the `--with-charset=`charset_name`` or `--with-extra-charsets=`charset_name`` option. See Sección 2.8.2, “Opciones típicas de configure”.

  All standard MySQL binaries are compiled with `--with-extra-character-sets=complex`, which enables support for all multi-byte character sets. See Sección 5.9.1, “El conjunto de caracteres utilizado para datos y ordenación”.

- The character set is a simple character set that is not compiled into 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:

  - Recompile the client with support for the character set. See Sección 2.8.2, “Opciones típicas de configure”.

  - Specify to the client the directory where the character set definition files are located. For many clients, you can do this with the `--character-sets-dir` option.

  - Copy the character definition files to the path where the client expects them to be.

### A.2.17. No se encontró el fichero

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 reduces 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 Sección 5.3.3, “Variables de sistema del servidor”. The easiest way to set these values is to add an option to your option file. See Sección 4.3.2, “Usar ficheros de opciones”. 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 does not work! tcsh also reports incorrect values when you ask for the current limits. In this case, you should start mysqld_safe using sh.

## A.3. Problemas relacionados con la instalación

### A.3.1. Problemas al enlazar a la biblioteca de clientes MySQL

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 Sección 2.8, “Instalación de MySQL usando una distribución de código fuente”.

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:

- Add the path to the directory where `libmysqlclient.so` is located to the `LD_LIBRARY_PATH` environment variable.

- Add the path to the directory where `libmysqlclient.so` is located to the `LD_LIBRARY` environment variable.

- Copy `libmysqlclient.so` to some directory that is searched by your system, such as `/lib`, and update the shared library information by executing `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.

### A.3.2. Cómo correr MySQL como usuario normal

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:

1. Stop the server if it's running (use mysqladmin shutdown).

2. Change the database directories and files so that `user_name` has privileges to read and write files in them (you might need to do this as the Unix `root` user):

       shell> chown -R user_name /path/to/mysql/datadir

   If you do not do this, the server is not 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.

3. Start the server as user `user_name`. If you are using MySQL 3.22 or later, another alternative is to start mysqld as the Unix `root` user and use the `--user=`user_name`` option. mysqld starts up, then switches to run as the Unix user `user_name` before accepting any connections.

4. To start the server as the given user automatically at system startup time, specify the username by adding a `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 Sección 2.9, “Puesta en marcha y comprobación después de la instalación”.

### A.3.3. Problemas con permisos de ficheros

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 Apéndice E, Variables de entorno.

## A.4. Cuestiones relacionadas con la administración

### A.4.1. Cómo reiniciar la contraseña de root

If you have never set a `root` password for MySQL, the server does not require a password at all for connecting as `root`. However, it is recommended to set a password for each account. See Sección 5.5.1, “Guía de seguridad general”.

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:

1. Log on to your system as Administrator.

2. Stop the MySQL server if it is running. For a server that is running as a Windows service, go to the Services manager:

       Start Menu -> Control Panel -> Administrative Tools -> Services

   Then 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.

3. Create a text file and place the following command within it on a single line:

       SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');

   Save the file with any name. For this example the file will be `C:\mysql-init.txt`.

4. Open a console window to get to the DOS command prompt:

       Start Menu -> Run -> cmd

5. We are assuming that you installed MySQL to `C:\mysql`. If you installed MySQL to another location, adjust the following commands accordingly.

   At the DOS command prompt, execute this command:

       C:\> C:\mysql\bin\mysqld-nt --init-file=C:\mysql-init.txt

   The contents of the file named by the `--init-file` option are executed at server startup, changing the `root` password. After the server has started successfully, you should delete `C:\mysql-init.txt`.

   Users of MySQL 4.1 and higher who install MySQL using the MySQL Installation Wizard may need to specify a `--defaults-file` option:

       C:\> C:\Program Files\MySQL\MySQL Server 5.0\bin\mysqld-nt.exe
                --defaults-file="C:\Program Files\MySQL\MySQL Server 5.0\my.ini"
                --init-file=C:\mysql-init.txt

   The appropriate `--defaults-file` setting can be found using the Services Manager:

       Start Menu -> Control Panel -> Administrative Tools -> Services

   Find the MySQL service in the list, right-click on it, and choose the `Properties` option. The `Path to executable` field contains the `--defaults-file` setting.

6. Stop the MySQL server, then restart it in normal mode again. If you run the server as a service, start it from the Windows Services window. If you start the server manually, use whatever command you normally use.

7. You should be able to connect using the new password.

In a Unix environment, the procedure for resetting the `root` password is as follows:

1. Log on to your system as either the Unix `root` user or as the same user that the mysqld server runs as.

2. Locate the `.pid` file that contains the server's process ID. The exact location and name of this file depend on your distribution, hostname, and configuration. Common locations are `/var/lib/mysql/`, `/var/run/mysqld/`, and `/usr/local/mysql/data/`. Generally, the filename has the extension of `.pid` and begins with either `mysqld` or your system's hostname.

   You can stop the MySQL server by sending a normal `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.

3. Create a text file and place the following command within it on a single line:

       SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');

   Save the file with any name. For this example the file will be `~/mysql-init`.

4. Restart the MySQL server with the special `--init-file=~/mysql-init` option:

       shell> mysqld_safe --init-file=~/mysql-init &

   The contents of the init-file are executed at server startup, changing the root password. After the server has started successfully you should delete `~/mysql-init`.

5. You should be able to connect using the new password.

Alternatively, on any platform, you can set the new password using the mysql client(but this approach is less secure):

1. Stop mysqld and restart it with the `--skip-grant-tables --user=root` option (Windows users omit the `--user=root` portion).

2. Connect to the mysqld server with this command:

       shell> mysql -u root

3. Issue the following statements in the 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.

4. You should be able to connect using the new password.

### A.4.2. Qué hacer si MySQL sigue fallando (crashing)

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 always helps if you try to find out exactly what crashes your system, because you 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 Sección 5.10.1, “El registro de errroes (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 Sección D.1.4, “Usar 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 updates 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 ensures 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:

- The MySQL server or the server host was killed in the middle of an update.

- You have found a bug in mysqld that caused it to die in the middle of an update.

- Some external program is manipulating data files or index files at the same time as mysqld without locking the table properly.

- You are running many 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.

- You have a crashed data file or index file that contains very corrupt data that confused mysqld.

- You have found a bug in the data storage code. This isn't likely, but it's at least possible. In this case, you can try to change the table type to another storage engine by using `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:

- Stop the mysqld server with mysqladmin shutdown, run myisamchk --silent --force */*.MYI from the data directory to check all `MyISAM` tables, and restart mysqld. This ensures that you are running from a clean state. See Capítulo 5, Administración de bases de datos.

- Start 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 is one of the last queries in the log file just before the server restarts. See Sección 5.10.2, “El registro general de consultas”. 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 Sección 1.6.1.3, “Cómo informar de bugs y problemas”.

- Try to make a test case that we can use to repeat the problem. See Sección D.1.6, “Crear un caso de prueba tras haber encontrado una tabla corrupta”.

- Try running the tests in the `mysql-test` directory and the MySQL benchmarks. See Sección 27.1.2, “El paquete de pruebas MySQL Test”. They should test MySQL rather well. You can also add code to the benchmarks that simulates your application. The benchmarks can be found in the `sql-bench` directory in a source distribution or, for a binary distribution, in the `sql-bench` directory under your MySQL installation directory.

- Try the `fork_big.pl` script. (It is located in the `tests` directory of source distributions.)

- If you configure MySQL for debugging, it is much easier to gather information about possible errors if something goes wrong. Configuring MySQL for debugging causes a safe memory allocator to be included that can find some errors. It also provides a lot of output about what is happening. Reconfigure MySQL with the `--with-debug` or `--with-debug=full` option to configure and then recompile. See Sección D.1, “Depurar un servidor MySQL”.

- Make sure that you have applied the latest patches for your operating system.

- Use the `--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.)

- Have you tried 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 is able to make a connection even in these cases, and can provide useful information about the current number of connections and their status.

- Run the command mysqladmin -i 5 status or mysqladmin -i 5 -r status in a separate window to produce statistics while you run your other queries.

- Try the following:

  1. Start mysqld from gdb (or another debugger). See Sección D.1.3, “Depurar mysqld con gdb”.

  2. Run your test scripts.

  3. Print the backtrace and the local variables at the three lowest levels. In gdb, you can do this with the following commands when mysqld has crashed inside gdb:

         backtrace
         info local
         up
         info local
         up
         info local

     With gdb, you can also examine which threads exist with `info threads` and switch to a specific thread with `thread #`, where `#` is the thread ID.

- Try to simulate your application with a Perl script to force MySQL to crash or misbehave.

- Send a normal bug report. See Sección 1.6.1.3, “Cómo informar de bugs y problemas”. Be even more detailed than usual. Because MySQL works for many people, it may be that the crash results from something that exists only on your computer (for example, an error that is related to your particular system libraries).

- If you have a problem with tables containing dynamic-length rows and you are using only `VARCHAR` columns (not `BLOB` or `TEXT` columns), you can try to change all `VARCHAR` to `CHAR` with `ALTER TABLE`. This forces 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.

- Do not rule out your server hardware when diagnosing problems. Defective hardware can be the cause of data corruption. Particular attention should be paid to both RAMS and hard-drives when troubleshooting hardware.

### A.4.3. Cómo se comporta MySQL ante un disco lleno

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:

- It checks once every minute to see whether there is enough space to write the current row. If there is enough space, it continues as if nothing had happened.

- Every 10 minutes it writes an entry to the log file, warning about the disk-full condition.

To alleviate the problem, you can take the following actions:

- To continue, you only have to free enough disk space to insert all records.

- To abort the thread, you must use mysqladmin kill. The thread is aborted the next time it checks the disk (in one minute).

- Other threads might be waiting for the table that caused the disk-full condition. If you have several “locked” threads, killing the one thread that is waiting on the disk-full condition allows the other threads to continue.

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 removes the big temporary files and mark the table as crashed. The exception is that for `ALTER TABLE`, the old table is left unchanged.

### A.4.4. Dónde almacena MySQL los archivos temporales

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 fails.

MySQL creates all temporary files as hidden files. This ensures that the temporary files are removed if mysqld is terminated. The disadvantage of using hidden files is that you do 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.

### A.4.5. Cómo proteger o cambiar el fichero socket de MySQL `/tmp/mysql.sock`

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:

- Specify the path in a global or local option file. For example, put the following lines in `/etc/my.cnf`:

      [mysqld]
      socket=/path/to/socket

      [client]
      socket=/path/to/socket

  See Sección 4.3.2, “Usar ficheros de opciones”.

- Specify a `--socket` option on the command line to mysqld_safe and when you run client programs.

- Set the `MYSQL_UNIX_PORT` environment variable to the path of the Unix socket file.

- Recompile MySQL from source to use a different default Unix socket file location. Define the path to the file with the `--with-unix-socket-path` option when you run configure. See Sección 2.8.2, “Opciones típicas de configure”.

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

### A.4.6. Problemas con las franjas horarias

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 Apéndice E, Variables de entorno.

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.

## A.5. Problemas relacionados con consultas

### A.5.1. Sensibilidad a mayúsculas en búsquedas

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 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 has a case sensitive or binary collation. For example, if you are comparing a column and a string that both have the `latin1` character set, you can use the `COLLATE` operator to cause either operand to have the `latin1_general_cs` or `latin1_bin` collation. For example:

    col_name COLLATE latin1_general_cs LIKE 'a%'
    col_name LIKE 'a%' COLLATE latin1_general_cs
    col_name COLLATE latin1_bin LIKE 'a%'
    col_name LIKE 'a%' COLLATE latin1_bin

If you want a column always to be treated in case-sensitive fashion, declare it with a case sensitive or binary collation. See Sección 13.1.5, “Sintaxis de `CREATE TABLE`”.

Before MySQL 4.1, `COLLATE` is unavailable. Use the `BINARY` operator in expressions to treat a string as a binary string: `BINARY `col_name` LIKE 'a%'` or ``col_name` LIKE BINARY 'a%'`. In column declarations, use the `BINARY` attribute.

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.

### A.5.2. Problemas en el uso de columnas `DATE`

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.

When you compare a `DATE`, `TIME`, `DATETIME`, or `TIMESTAMP` to a constant string with the `<`, `<=`, `=`, `>=`, `>`, or `BETWEEN` operators, MySQL normally converts the string to an internal long integer for faster comparision (and also for a bit more “relaxed” string checking). However, this conversion is subject to the following exceptions:

- When you compare two columns

- When you compare a `DATE`, `TIME`, `DATETIME`, or `TIMESTAMP` column to an expression

- When you use any other comparison method than those just listed, such as `IN` or `STRCMP()`.

For these exceptional cases, the comparison is done by converting the objects to strings and performing a string comparison.

To keep things safe, assume that strings are compared as strings and use the appropriate string functions if you want to compare a temporal value to a string.

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 does 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 is 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.

### A.5.3. Problemas con valores `NULL`

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 Sección 13.2.5, “Sintaxis de `LOAD DATA INFILE`”.

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.

### A.5.4. Problemas con alias de columnas

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.

### A.5.5. Fallo en la cancelación de una transacción con tablas no transaccionales

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 are not 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 instead creates 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 Sección 13.5.4.18, “Sintaxis de `SHOW TABLE STATUS`” and Sección 13.5.4.5, “Sintaxis de `SHOW CREATE TABLE`”.

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 Sección 13.5.4.8, “Sintaxis de `SHOW ENGINES`” and Sección 13.5.4.21, “Sintaxis de `SHOW VARIABLES`”.

### A.5.6. Borrar registros de tablas relacionadas

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:

1. `SELECT` the rows based on some `WHERE` condition in the main table.

2. `DELETE` the rows in the main table based on the same condition.

3. `DELETE FROM related_table WHERE related_column IN (selected_rows)`.

If the total 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 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.

### A.5.7. Resolver problemas con registros que no salen

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:

1. Test the query with `EXPLAIN` to check whether you can find something that is obviously wrong. See Sección 7.2.1, “Sintaxis de `EXPLAIN` (Obtener información acerca de un `SELECT`)”.

2. Select only those columns that are used in the `WHERE` clause.

3. Remove one table at a time from the query until it returns some rows. If the tables are large, it's a good idea to use `LIMIT 10` with the query.

4. Issue a `SELECT` for the column that should have matched a row against the table that was last removed from the query.

5. If you are comparing `FLOAT` or `DOUBLE` columns with numbers that have decimals, you can't use 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` fixes this. See Sección A.5.8, “Problemas con comparaciones en Floating-Point”.

6. If you still can't figure out what's wrong, create a minimal test that can be run with `mysql test < query.sql` that shows your problems. You can create a test file 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.sql

   Post the test file using mysqlbug to the general MySQL mailing list. See Sección 1.6.1.1, “Las listas de correo de MySQL”.

### A.5.8. Problemas con comparaciones en Floating-Point

Note that the following section is relevant primarily for versions of MySQL older than 5.0.3. As of version 5.0.3, MySQL performs `DECIMAL` operations with a precision of 64 decimal digits, which should solve most common inaccuracy problems when it comes to `DECIMAL` columns. For `DOUBLE` and `FLOAT` columns, the problems remain because inexactness is the basic nature of floating point numbers.

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 before MySQL 5.0.3 are done using floating-point operations.

The following example (for older MySQL version than 5.0.3) 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. (In all MySQL versions, you would have similar problems if you would replace the `DECIMAL` columns with `FLOAT`).

    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.

As of MySQL 5.0.3, you will get only the last row in the above result.

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 |
    +------+-------+-------+

## A.6. Cuestiones relacionadas con el optimizados

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:

- Use the `EXPLAIN` statement to get information about how MySQL processes 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 Sección 7.2.1, “Sintaxis de `EXPLAIN` (Obtener información acerca de un `SELECT`)”.

- Use `ANALYZE TABLE `tbl_name`` to update the key distributions for the scanned table. See Sección 13.5.2.1, “Sintaxis de `ANALYZE TABLE`”.

- Use `FORCE INDEX` for the scanned table to tell MySQL that table scans are very expensive compared to using the given index. See Sección 13.2.7, “Sintaxis de `SELECT`”.

      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.

- Global and table-level `STRAIGHT_JOIN`. See Sección 13.2.7, “Sintaxis de `SELECT`”.

- You can tune global or thread-specific system variables. For example, Start 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 causes more than 1,000 key seeks. See Sección 5.3.3, “Variables de sistema del servidor”.

## A.7. Cuestiones relacionadas con definiciones de tabla

### A.7.1. Problemas con `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:

- Create a new table named `A-`xxx`` with the requested structural changes.

- Copy all rows from the original table to `A-`xxx``.

- Rename the original table to `B-`xxx``.

- Rename `A-`xxx`` to your original table name.

- Delete `B-`xxx``.

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` unlocks 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.

### A.7.2. Cómo cambiar el orden de las columnas en una tabla

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:

1. Create a new table with the columns in the new order.

2. Execute this statement:

       mysql> INSERT INTO new_table
           -> SELECT columns-in-new-order FROM old_table;

3. Drop or rename `old_table`.

4. Rename the new table to the original name:

       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 does not remain the same if you add, move, or delete columns. A simple change to your table structure could cause your application to fail.

### A.7.3. Problemas con `TEMPORARY TABLE`

The following list indicates limitations on the use of `TEMPORARY` tables:

- A `TEMPORARY` table can only be of type `HEAP`, `ISAM`, `MyISAM`, `MERGE`, or `InnoDB`.

- You cannot refer to a `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'

- The `SHOW TABLES` statement does not list `TEMPORARY` tables.

- You cannot use `RENAME` to rename a `TEMPORARY` table. However, you can use `ALTER TABLE` instead:

      mysql> ALTER TABLE orig_name RENAME new_name;

## A.8. Problemas conocidos en MySQL

This section is a list of the known issues in recent versions of MySQL.

For information about platform-specific issues, see the installation and porting instructions in Sección 2.12, “Notas específicas sobre sistemas operativos” and Apéndice D, Portar a otros sistemas.

### A.8.1. Problemas de la versión 3.23 resueltos en una versión posterior de MySQL

The following known issues have not been fixed in MySQL 3.23 for various reasons, and are not classified as critical.

- Fixed in MySQL 4.0: Avoid using spaces at the end of column names because this can cause unexpected behavior. (Bug#4196)

- Fixed in MySQL 4.0.12: You can get a deadlock (hung thread) if you use `LOCK TABLE` to lock multiple tables and then in the same connection use `DROP TABLE` to drop one of them while another thread is trying to lock it. (To break the deadlock, you can use `KILL` to terminate any of the threads involved.)

- Fixed in MySQL 4.0.11: `SELECT MAX(key_column) FROM t1,t2,t3...` where one of the tables are empty doesn't return `NULL` but instead returns the maximum value for the column.

- `DELETE FROM heap_table` without a `WHERE` clause doesn't work on a locked `HEAP` table.

### A.8.2. Problemas de la versión 4.0 resueltos en una versión posterior de MySQL

The following known issues have not been fixed in MySQL 4.0 for various reasons, and are not classified as critical.

- Fixed in MySQL 4.1.10: Using `HAVING`, you can get a crash or wrong result if you use an alias to a `RAND()` function. This will not be fixed in 4.0 because the fix may break compatability with some applications.

- Fixed in MySQL 4.1.1: In a `UNION`, the first `SELECT` determines the type, `max_length`, and `NULL` properties for the resulting columns.

- Fixed in MySQL 4.1: In `DELETE` with many tables, you can't refer to tables to be deleted through an alias.

- Fixed in MySQL 4.1.2: You cannot mix `UNION ALL` and `UNION DISTINCT` in the same query. If you use `ALL` for one `UNION`, it is used for all of them.

- `FLUSH TABLES WITH READ LOCK` does not block `CREATE TABLE`, which may cause a problem with the binary log position when doing a full backup of tables and the binary log.

- Fixed in MySQL 4.1.8: `mysqldump --single-transaction --master-data` behaved like `mysqldump --master-data`, so the dump was a blocking one.

- When using the `RPAD()` function (or any function adding spaces to the right) in a query that had to be resolved by using a temporary table, all resulting strings had rightmost spaces removed (i.e. `RPAD()` did not work).

### A.8.3. Problemas de la versión 4.1 resueltos en una versión posterior de MySQL

The following known issues have not been fixed in MySQL 4.1 for various reasons, and are not classified as critical.

- Fixed in 5.0.3: `VARCHAR` and `VARBINARY` did not remember end space.

### A.8.4. Cuestiones abiertas en MySQL

The following problems are known and fixing them is a high priority:

- If you compare a `NULL` value to a subquery using `ALL/ANY/SOME` and the subquery returns an empty result, the comparison might evaluate to the non-standard result of `NULL` rather than to `TRUE` or `FALSE`. This will be fixed in MySQL 5.1.

- Subquery optimization for `IN` is not as effective as for `=`.

- Even if you use `lower_case_table_names=2` (which enables MySQL to remember the case used for databases and table names), MySQL does not remember the case used for database names for the function `DATABASE()` or within the various logs (on case-insensitive systems).

- Dropping a `FOREIGN KEY` constraint doesn't work in replication because the constraint may have another name on the slave.

- `REPLACE` (and `LOAD DATA` with the `REPLACE` option) does not trigger `ON DELETE CASCADE`.

- `DISTINCT` with `ORDER BY` doesn't work inside `GROUP_CONCAT()` if you don't use all and only those columns that are in the `DISTINCT` list.

- If one user has a long-running transaction and another user drops a table that is updated in the transaction, there is small chance that the binary log may contain the `DROP TABLE` command before the table is used in the transaction itself. We plan to fix this by having the `DROP TABLE` command wait until the table is not being used in any transaction.

- When inserting a big integer value (between 263 and 264–1) into a decimal or string column, it is inserted as a negative value because the number is evaluated in a signed integer context.

- `FLUSH TABLES WITH READ LOCK` does not block `COMMIT` if the server is running without binary logging, which may cause a problem (of consistency between tables) when doing a full backup.

- `ANALYZE TABLE` on a `BDB` table may in some cases make the table unusable until you restart mysqld. If this happens, look for errors of the following form in the MySQL error file:

      001207 22:07:56  bdb:  log_flush: LSN past current end-of-log

- Don't execute `ALTER TABLE` on a `BDB` table on which you are running multiple-statement transactions until all those transactions complete. (The transaction might be ignored.)

- `ANALYZE TABLE`, `OPTIMIZE TABLE`, and `REPAIR TABLE` may cause problems on tables for which you are using `INSERT DELAYED`.

- Performing `LOCK TABLE ...` and `FLUSH TABLES ...` doesn't guarantee that there isn't a half-finished transaction in progress on the table.

- `BDB` tables are relatively slow to open. If you have many `BDB` tables in a database, it takes a long time to use the mysql client on the database if you are not using the `-A` option or if you are using `rehash`. This is especially noticeable when you have a large table cache.

- Replication uses query-level logging: The master writes the executed queries to the binary log. This is a very fast, compact, and efficient logging method that works perfectly in most cases.

  It is possible for the data on the master and slave to become different if a query is designed in such a way that the data modification is non-deterministic (generally not a recommended practice, even outside of replication).

  For example:

  - `CREATE ... SELECT` or `INSERT ... SELECT` statements that insert zero or `NULL` values into an `AUTO_INCREMENT` column.

  - `DELETE` if you are deleting rows from a table that has foreign keys with `ON DELETE CASCADE` properties.

  - `REPLACE ... SELECT`, `INSERT IGNORE ... SELECT` if you have duplicate key values in the inserted data.

  If and only if the preceding queries have no `ORDER BY` clause guaranteeing a deterministic order.

  For example, for `INSERT ... SELECT` with no `ORDER BY`, the `SELECT` may return rows in a different order (which results in a row having different ranks, hence getting a different number in the `AUTO_INCREMENT` column), depending on the choices made by the optimizers on the master and slave.

  A query is optimized differently on the master and slave only if:

  - The files used by the two queries are not exactly the same; for example, `OPTIMIZE TABLE` was run on the master tables and not on the slave tables. (To fix this, `OPTIMIZE TABLE`, `ANALYZE TABLE`, and `REPAIR TABLE` are written to the binary log as of MySQL 4.1.1).

  - The table is stored using a different storage engine on the master than on the slave. (It is possible to use different storage engines on the master and slave. For example, you can use `InnoDB` on the master, but `MyISAM` on the slave if the slave has less available disk space.)

  - MySQL buffer sizes (`key_buffer_size`, and so on) are different on the master and slave.

  - The master and slave run different MySQL versions, and the optimizer code differs between these versions.

  This problem may also affect database restoration using mysqlbinlog|mysql.

  The easiest way to avoid this problem is to add an `ORDER BY` clause to the aforementioned non-deterministic queries to ensure that the rows are always stored or modified in the same order.

  In future MySQL versions, we will automatically add an `ORDER BY` clause when needed.

The following issues are known and will be fixed in due time:

- Log filenames are based on the server hostname (if you don't specify a filename with the startup option). You have to use options such as `--log-bin=`old_host_name`-bin` if you change your hostname to something else. Another option is to rename the old files to reflect your hostname change (if these are binary logs, you need to edit the binary log index file and fix the binlog names there as well). See Sección 5.3.1, “Opciones del comando mysqld”.

- mysqlbinlog does not delete temporary files left after a `LOAD DATA INFILE` command. See Sección 8.5, “La utilidad mysqlbinlog para registros binarios”.

- `RENAME` doesn't work with `TEMPORARY` tables or tables used in a `MERGE` table.

- Due to the way table definition files are stored, you cannot use character 255 (`CHAR(255)`) in table names, column names, or enumerations. This is scheduled to be fixed in version 5.1 when we implement new table definition format files.

- When using `SET CHARACTER SET`, you can't use translated characters in database, table, and column names.

- You can't use '`_`' or '`%`' with `ESCAPE` in `LIKE ... ESCAPE`.

- If you have a `DECIMAL` column in which the same number is stored in different formats (for example, `+01.00`, `1.00`, `01.00`), `GROUP BY` may regard each value as a different value.

- You cannot build the server in another directory when using MIT-pthreads. Because this requires changes to MIT-pthreads, we are not likely to fix this. See Sección 2.8.5, “Notas sobre MIT-pthreads”.

- `BLOB` and `TEXT` values can't “reliably” be used in `GROUP BY`, `ORDER BY` or `DISTINCT`. Only the first `max_sort_length` bytes are used when comparing `BLOB` values in these cases. The default value of `max_sort_length` value is 1024 and can be changed at server startup time. As of MySQL 4.0.3, it can be changed at runtime. For older versions, a workaround is to use a substring. For example:

      SELECT DISTINCT LEFT(blob_col,2048) FROM tbl_name;

- Numeric calculations are done with `BIGINT` or `DOUBLE` (both are normally 64 bits long). Which precision you get depends on the function. The general rule is that bit functions are performed with `BIGINT` precision, `IF` and `ELT()` with `BIGINT` or `DOUBLE` precision, and the rest with `DOUBLE` precision. You should try to avoid using unsigned long long values if they resolve to be larger than 63 bits (9223372036854775807) for anything other than bit fields. MySQL Server 4.0 has better `BIGINT` handling than 3.23.

- You can have up to 255 `ENUM` and `SET` columns in one table.

- In `MIN()`, `MAX()`, and other aggregate functions, MySQL currently compares `ENUM` and `SET` columns by their string value rather than by the string's relative position in the set.

- mysqld_safe redirects all messages from mysqld to the mysqld log. One problem with this is that if you execute mysqladmin refresh to close and reopen the log, `stdout` and `stderr` are still redirected to the old log. If you use `--log` extensively, you should edit mysqld_safe to log to ``host_name`.err` instead of ``host_name`.log` so that you can easily reclaim the space for the old log by deleting it and executing mysqladmin refresh.

- In an `UPDATE` statement, columns are updated from left to right. If you refer to an updated column, you get the updated value instead of the original value. For example, the following statement increments `KEY` by `2`, not `1`:

      mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;

- You can refer to multiple temporary tables in the same query, but you cannot refer to any given temporary table more than once. For example, the following doesn't work:

      mysql> SELECT * FROM temp_table, temp_table AS t2;
      ERROR 1137: Can't reopen table: 'temp_table'

- The optimizer may handle `DISTINCT` differently when you are using “hidden” columns in a join than when you are not. In a join, hidden columns are counted as part of the result (even if they are not shown), whereas in normal queries, hidden columns don't participate in the `DISTINCT` comparison. We will probably change this in the future to never compare the hidden columns when executing `DISTINCT`.

  An example of this is:

      SELECT DISTINCT mp3id FROM band_downloads
             WHERE userid = 9 ORDER BY id DESC;

  and

      SELECT DISTINCT band_downloads.mp3id
             FROM band_downloads,band_mp3
             WHERE band_downloads.userid = 9
             AND band_mp3.id = band_downloads.mp3id
             ORDER BY band_downloads.id DESC;

  In the second case, using MySQL Server 3.23.x, you may get two identical rows in the result set (because the values in the hidden `id` column may differ).

  Note that this happens only for queries where that do not have the `ORDER BY` columns in the result.

- If you execute a `PROCEDURE` on a query that returns an empty set, in some cases the `PROCEDURE` does not transform the columns.

- Creation of a table of type `MERGE` doesn't check whether the underlying tables are compatible types.

- If you use `ALTER TABLE` to add a `UNIQUE` index to a table used in a `MERGE` table and then add a normal index on the `MERGE` table, the key order is different for the tables if there was an old, non-`UNIQUE` key in the table. This is because `ALTER TABLE` puts `UNIQUE` indexes before normal indexes to be able to detect duplicate keys as early as possible.

Ésta es una traducción del manual de referencia de MySQL, que puede encontrarse en dev.mysql.com. El manual de referencia original de MySQL está escrito en inglés, y esta traducción no necesariamente está tan actualizada como la versión original. Para cualquier sugerencia sobre la traducción y para señalar errores de cualquier tipo, no dude en dirigirse a mysql-es@vespito.com.

Anterior |  | Siguiente
Capítulo 27. Extender MySQL | Inicio | Apéndice B. Credits