Suponiendo que se ha iniciado el cliente MySQL con el comando
mysql test
, para crear una tabla
InnoDB
se debe especificar la opción
ENGINE = InnoDB
o
TYPE = InnoDB
en la sentencia SQL de creación de tabla:
CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) ENGINE=InnoDB; CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) TYPE=InnoDB;
La sentencia SQL crea una tabla y un índice en la columna
a
en el espacio de tablas InnoDB
que
consiste en los ficheros de datos especificados en
my.cnf
. Adicionalmente, MySQL crea un fichero
customers.frm
en el directorio
test
debajo del directorio de bases de datos de
MySQL. Internamente, InnoDB
agrega a su propio
diccionario de datos una entrada para la tabla
'test/customers'
. Esto significa que puede crearse una
tabla con el mismo nombre customers
en otra base de
datos, y los nombres de las tablas no entrarán en conflicto dentro de
InnoDB
.
Se puede consultar la cantidad de espacio libre en el espacio de tablas
InnoDB
dirigiendo una sentencia SHOW
TABLE STATUS
para cualquier tabla InnoDB
. La
cantidad de espacio libre en el espacio de tablas aparece en la sección
Comment
en la salida de SHOW
TABLE STATUS
. Un ejemplo:
SHOW TABLE STATUS FROM test LIKE 'customers'
Nótese que las estadísticas que SHOW
muestra acerca de
las tablas InnoDB
son solamente aproximadas. Se
utilizan en la optimización SQL. No obstante, los tamaños en bytes
reservados para las tablas e índices son exactos.
En forma predeterminada, cada cliente se que conecta al servidor MySQL
comienza con el modo de autocommit habilitado, lo cual automáticamente
confirma (commit) cada sentencia SQL ejecutada. Para utilizar
transacciones de múltiples sentencias se puede deshabilitar el modo
autocommit con la sentencia SQL SET AUTOCOMMIT = 0
y
emplear COMMIT
y ROLLBACK
para
confirmar o cancelar la transacción. Si se desea dejar activado
autocommit, se pueden encerrar las transacciones entre las sentencias
START TRANSACTION
y
COMMIT
o ROLLBACK
. El siguiente
ejemplo muestra dos transacciones. La primera se confirma, la segunda se
cancela.
shell> mysql test Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5 to server version: 3.23.50-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> CREATE TABLE CUSTOMER (A INT, B CHAR (20), INDEX (A)) -> ENGINE=InnoDB; Query OK, 0 rows affected (0.00 sec) mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO CUSTOMER VALUES (10, 'Heikki'); Query OK, 1 row affected (0.00 sec) mysql> COMMIT; Query OK, 0 rows affected (0.00 sec) mysql> SET AUTOCOMMIT=0; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO CUSTOMER VALUES (15, 'John'); Query OK, 1 row affected (0.00 sec) mysql> ROLLBACK; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM CUSTOMER; +------+--------+ | A | B | +------+--------+ | 10 | Heikki | +------+--------+ 1 row in set (0.00 sec) mysql>
En APIs como PHP, Perl DBI/DBD, JDBC, ODBC, o la interface de llamadas C
estándar de MySQL, se pueden enviar sentencias de control de
transacciones como COMMIT
al servidor MySQL en forma
de cadenas, igual que otras sentencias SQL como
SELECT
o INSERT
. Algunas APIs
también ofrecen funciones o métodos especiales para confirmación y
cancelación de transacciones.
Importante: No se deben convertir las tablas del sistema en la base de
datos mysql
(por ejemplo, user
o
host
) al tipo InnoDB
. Las tablas
del sistema siempre deben ser del tipo MyISAM
.
Si se desea que todas las tablas que no sean de sistema se creen como
tablas InnoDB
, simplemente debe agregarse la línea
default-table-type=innodb
a la sección
[mysqld]
del fichero my.cnf
o my.ini
.
InnoDB
no posee una optimización especial para la
creación separada de índices en la misma forma que la tiene el motor de
almacenamiento MyISAM
. Por lo tanto, no hay beneficio
en exportar e importar la tabla y crear los índices posteriormente. La
manera más rápida de cambiar una tabla al motor
InnoDB
es hacer las inserciones directamente en una
tabla InnoDB
. Es decir, utilizar ALTER
TABLE ... ENGINE=INNODB
, o crear una tabla
InnoDB
vacía con idénticas definiciones e insertar
las filas con INSERT INTO ... SELECT * FROM
...
.
Si se tienen restricciones UNIQUE
sobre claves
secundarias, se puede acelerar la importación de una tabla desactivando
temporalmente la verificación de unicidad durante la sesión de
importación: SET UNIQUE_CHECKS=0;
. Para tablas
grandes, esto ahorra gran cantidad de operaciones de E/S en disco, debido
a que InnoDB
puede emplear su buffer de inserciones
para grabar registros de índices secundarios en lote.
Para obtener un mejor control sobre el proceso de inserción, podría ser mejor llenar la tablas grandes por partes:
INSERT INTO nuevatabla SELECT * FROM viejatabla WHERE clave > valor1 AND clave <= valor2;
Luego de que todos los registros se hayan insertado, se pueden renombrar las tablas.
Durante la conversión de tablas grandes, se puede reducir la cantidad de
operaciones de E/S en disco incrementando el tamaño del pool de buffer
de InnoDB
. No debe usarse más del 80% de la memoria
física. También pueden aumentarse los tamaños de los ficheros de
registro (log) de InnoDB
.
Hay que asegurarse de no llenar completamente el espacio de tablas: las
tablas InnoDB
necesitan mucho más espacio que las
tablas MyISAM
. Si una sentencia ALTER
TABLE
se queda sin espacio, realizará una cancelación
(rollback), y esto puede tomar horas si lo hace sobre el disco. Para
las inserciones, InnoDB
emplea el buffer de inserción
para combinar en lotes los registros secundarios de índices con los
índices. Esto ahorra gran cantidad de operaciones de E/S en disco.
Durante la cancelación no se emplea ese mecanismo, de modo que puede
llevar más de 30 veces el tiempo insumido por la inserción.
Si se produjera una de estas cancelaciones fuera de control, sino se tienen datos valiosos en la base de datos, puede ser preferible matar el proceso de la base de datos en lugar de esperar que se completen millones de operaciones de E/S en disco. Para el procedimiento completo, consulte Sección 15.8.1, “Forzar una recuperación”.
Si se especifica que una columna de una tabla es
AUTO_INCREMENT
, la entrada para la tabla
InnoDB
en el diccionario de datos contiene un
contador especial llamado "contador de auto incremento", que se utiliza
para asignar nuevos valores a la columna. El contador de auto incremento
se almacena sólo en la memoria principal, no en disco.
InnoDB
utiliza el siguiente algoritmo para
inicializar el contador de auto incremento para una tabla
T
que contiene una columna
AUTO_INCREMENT
llamada ai_col
:
Luego de iniciarse el servidor, cuando un usuario realiza por primera
vez una inserción en una tabla T
,
InnoDB
ejecuta el equivalente de esta sentencia:
SELECT MAX(ai_col) FROM T FOR UPDATE;
El valor retornado por la sentencia se incrementa en uno y se asigna a
la columna, y al contador de auto incremento de la tabla. Si la tabla
está vacía, se asigna el valor 1
. Si el contador aún
no se ha inicializado y se ejecuta una sentencia SHOW TABLE
STATUS
que muestre su salida para la tabla
T
, el contador se inicializa (pero no se incrementa)
y se almacena para usos posteriores. Nótese que en esta inicialización
se realiza una lectura normal con bloqueo exclusivo y el bloqueo
permanece hasta el final de la transacción.
InnoDB
sigue el mismo procedimiento para inicializar
el contador de auto incremento de una tabla recientemente creada.
Nótese que si durante un INSERT
el usuario especifica
un valor NULL
o 0
para una columna
AUTO_INCREMENT
, InnoDB
trata a la
columna como si no se hubiera especificado un valor y genera un nuevo
valor para ella.
Luego de que el contador de auto incremento ha sido inicializado, si un
usuario inserta una fila que explícitamente indica para la columna auto
incremental un valor mayor que el valor actual del contador, éste se
establece al valor actual de la columna. Si no se indica un valor,
InnoDB
incrementa el valor del contador en uno y lo
asigna a la columna.
Al acceder al contador de auto incremento, InnoDB
emplea un nivel de bloqueo de tabla especial
AUTO-INC
, que mantiene hasta el final de la sentencia
SQL actual y no hasta el final de la transacción. Esta estrategia de
bloqueo especial fue introducida para mejorar la concurrencia de
inserciones en una tabla que contiene una columna
AUTO_INCREMENT
. Dos transacciones no pueden tener el
bloqueo AUTO-INC
simultáneamente en la misma tabla.
Nótese que pueden observarse valores faltantes en la secuencia de
valores asignados a la columna AUTO_INCREMENT
si se
cancelan transacciones que ya han obtenido números desde el contador.
El comportamiento del mecanismo de auto incremento no se encuentra definido si un usuario asigna un valor negativo a la columna o si el valor se vuelve mayor que el entero más grande que puede almacenarse en el tipo de entero especificado.
A partir de MySQL 5.0.3, InnoDB
soporta la opción
AUTO_INCREMENT =
n
en
sentencias CREATE TABLE
y ALTER
TABLE
, para establecer inicialmente o modificar el valor
actual del contador. El efecto de esta acción es cancelado al reiniciar
el servidor, por las razones tratadas anteriormente en esta sección.
InnoDB
también soporta restricciones de claves
foráneas. La sintaxis para definir una restricción de clave foránea en
InnoDB
es así:
[CONSTRAINTsímbolo
] FOREIGN KEY [id
] (nombre_índice
, ...) REFERENCESnombre_de_tabla
(nombre_índice
, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
Las definiciones de claves foráneas están sujetas a las siguientes condiciones:
-
Ambas tablas deben ser
InnoDB
y no deben ser tablas temporales. -
En la tabla que hace referencia, debe haber un índice donde las columnas de clave extranjera estén listadas en primer lugar, en el mismo orden.
-
En la tabla referenciada, debe haber un índice donde las columnas referenciadas se listen en primer lugar, en el mismo orden. En MySQL/InnoDB 5.0, tal índice se creará automáticamente en la tabla referenciada si no existe aún.
-
No están soportados los índices prefijados en columnas de claves foráneas. Una consecuencia de esto es que las columnas
BLOB
yTEXT
no pueden incluirse en una clave foránea, porque los índices sobre dichas columnas siempre deben incluir una longitud prefijada. -
Si se proporciona un
CONSTRAINT
símbolo
, éste debe ser único en la base de datos. Si no se suministra,InnoDB
crea el nombre automáticamente.
InnoDB
rechaza cualquier operación
INSERT
o UPDATE
que intente crear
un valor de clave foránea en una tabla hija sin un valor de clave
candidata coincidente en la tabla padre. La acción que
InnoDB
lleva a cabo para cualquier operación
UPDATE
o DELETE
que intente
actualizar o borrar un valor de clave candidata en la tabla padre que
tenga filas coincidentes en la tabla hija depende de la
accion referencial especificada utilizando las
subcláusulas ON UPDATE
y ON
DETETE
en la cláusula FOREIGN
KEY
. Cuando el usuario intenta borrar o actualizar una fila de
una tabla padre, InnoDB
soporta cinco acciones
respecto a la acción a tomar:
-
CASCADE
: Borra o actualiza el registro en la tabla padre y automáticamente borra o actualiza los registros coincidentes en la tabla hija. TantoON DELETE CASCADE
comoON UPDATE CASCADE
están disponibles en MySQL 5.0. Entre dos tablas, no se deberían definir varias cláusulasON UPDATE CASCADE
que actúen en la misma columna en la tabla padre o hija. -
SET NULL
: Borra o actualiza el registro en la tabla padre y establece enNULL
la o las columnas de clave foránea en la tabla hija. Esto solamente es válido si las columnas de clave foránea no han sido definidas comoNOT NULL
. MySQL 5.0 soporta tantoON DELETE SET NULL
comoON UPDATE SET NULL
. -
NO ACTION
: En el estándarANSI SQL-92
,NO ACTION
significa ninguna acción en el sentido de que unintento de borrar o actualizar un valor de clave primaria no sera permitido si en la tabla referenciada hay una valor de clave foránea relacionado. (Gruber, Mastering SQL, 2000:181). En MySQL 5.0,InnoDB
rechaza la operación de eliminación o actualización en la tabla padre. -
RESTRICT
: Rechaza la operación de eliminación o actualización en la tabla padre.NO ACTION
yRESTRICT
son similares en tanto omiten la cláusulaON DELETE
uON UPDATE
. (Algunos sistemas de bases de datos tienen verificaciones diferidas o retrasadas, una de las cuales esNO ACTION
. En MySQL, las restricciones de claves foráneas se verifican inmediatamente, por eso,NO ACTION
yRESTRICT
son equivalentes.) -
SET DEFAULT
: Esta acción es reconocida por el procesador de sentencias (parser), peroInnoDB
rechaza definiciones de tablas que contenganON DELETE SET DEFAULT
uON UPDATE SET DEFAULT
.
InnoDB
soporta las mismas opciones cuando se
actualiza la clave candidata en la tabla padre. Con
CASCADE
, las columnas de clave foránea en la tabla
hija son establecidas a los nuevos valores de la clave candidata en la
tabla padre. Del mismo modo, las actualizaciones se producen en cascada
si las columnas actualizadas en la tabla hija hacen referencia a claves
foráneas en otra tabla.
Nótese que InnoDB
soporta referencias de clave
foránea dentro de una tabla, y, en estos casos, la tabla hija realmente
significa registros dependientes dentro de la tabla.
InnoDB
necesita que haya índices sobre las claves
foráneas y claves referenciadas, así las verificaciones de claves
foráneas pueden ser veloces y no necesitan recorrer la tabla. En MySQL
5.0, el índice en la clave foránea se crea automáticamente. Esto
contrasta con versiones más antiguas (anteriores a 4.1.8), donde los
índices debían crearse explícitamente o fallaba la creación de
restricciones de claves foráneas.
Las columnas involucradas en la clave foránea y en la clave referenciada
deben tener similares tipos de datos internos dentro de
InnoDB
, de modo que puedan compararse sin una
conversión de tipo. La longitud y la condición de
con o sin signo de los tipos enteros deben ser iguales. La
longitud de los tipos cadena no necesita ser la misma. Si se especifica
una acción SET NULL
, hay que asegurarse de que
las columnas en la tabla hija no se han declarado
como NOT NULL
.
Si MySQL informa que ocurrió un error número 1005 en una sentencia
CREATE TABLE
y la cadena con el mensaje de error se
refiere al errno (número de error) 150, significa que la creación de una
tabla falló debido a una restricción de clave foránea formulada
incorrectamente. Del mismo modo, si un ALTER TABLE
falla y hace referencia al número de error 150, significa que se ha
formulado incorrectamente una restricción de clave extranjera cuando se
alteró la tabla. En MySQL 5.0, puede emplearse SHOW INNODB
STATUS
para mostrar una explicación detallada del último error
de clave foránea sufrido por InnoDB
en el servidor.
Nota: InnoDB
no
verifica las restricciones de claves foráneas en las claves foráneas o
valores de claves referenciados que contengan una columna
NULL
.
Una desviación del estándar SQL: Si en
la tabla padre hay varios registros que contengan el mismo valor de
clave referenciada, entonces InnoDB
se comporta en
las verificaciones de claves extranjeras como si los demás registros con
el mismo valor de clave no existiesen. Por ejemplo, si se ha definido
una restricción del tipo RESTRICT
, y hay un registro
hijo con varias filas padre, InnoDB
no permite la
eliminación de ninguna de éstas.
InnoDB
lleva a cabo las operaciones en cascada a
través de un algoritmo de tipo depth-first, basado en los registros de
los indices correspondientes a las restricciones de claves foráneas.
Una desviación del estándar SQL: Si
ON UPDATE CASCADE
u ON UPDATE
SET NULL
vuelven a modificar la misma
tabla que se está actualizando en cascada, el comportamiento
es como en RESTRICT
. Esto significa que en una tabla
no se pueden ejecutar operaciones ON UPDATE CASCADE
u ON UPDATE SET NULL
que hagan referencia a ella
misma. De ese modo se previenen bucles infinitos resultantes de la
actualización en cascada. En cambio, una operación ON DELETE
SET NULL
, puede hacer referencia a la misma tabla donde se
encuentra, al igual que ON DELETE CASCADE
. En MySQL
5.0, las operaciones en cascada no pueden anidarse en más de 15 niveles
de profundidad.
Una desviación del estándar SQL: Como
sucede en MySQL en general, en una sentencia SQL que realice
inserciones, eliminaciones o actualizaciones en varias filas, InnoDB
verifica las restricciones UNIQUE
y FOREIGN
KEY
fila a fila. De acuerdo con el estándar SQL, el
comportamiento predeterminado debería ser que las restricciones se
verifiquen luego de que la sentencia SQL ha sido procesada por completo.
Note: Actualmente, los disparadores no son activados por acciones de claves foráneas en cascada.
Un ejemplo sencillo que relaciona tablas padre
e
hijo
a través de una clave foránea de una sola
columna:
CREATE TABLE parent( id INT NOT NULL, PRIMARY KEY (id) ) ENGINE=INNODB; CREATE TABLE child( id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ) ENGINE=INNODB;
Aquí, un ejemplo más complejo, en el cual una tabla
product_order
tiene claves foráneas hacia otras dos
tablas. Una de las claves foráneas hace referencia a un índice de dos
columnas en la tabla product
. La otra hace referencia
a un índice de una sola columna en la tabla customer
:
CREATE TABLE product ( category INT NOT NULL, id INT NOT NULL, price DECIMAL, PRIMARY KEY(category, id) ) ENGINE=INNODB; CREATE TABLE customer ( id INT NOT NULL, PRIMARY KEY (id) ) ENGINE=INNODB; CREATE TABLE product_order ( no INT NOT NULL AUTO_INCREMENT, product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, PRIMARY KEY(no), INDEX (product_category, product_id), FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT, INDEX (customer_id), FOREIGN KEY (customer_id) REFERENCES customer(id) ) ENGINE=INNODB;
InnoDB
permite agregar una nueva restricción de
clave foránea a una tabla empleando ALTER TABLE
:
ALTER TABLE yourtablename ADD [CONSTRAINTsymbol
] FOREIGN KEY [id
] (index_col_name
, ...) REFERENCEStbl_name
(index_col_name
, ...) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
Debe recordarse crear en primer lugar los índices
necesarios.. También se puede agregar una clave foránea
autoreferente a una tabla empleando ALTER TABLE
.
InnoDB
también soporta el uso de
ALTER TABLE
para borrar claves foráneas:
ALTER TABLEnombre_tabla
DROP FOREIGN KEYsímbolo_clave_foránea
;
Si la cláusula FOREIGN KEY
incluye un nombre de
CONSTRAINT
cuando se crea la clave foránea, se puede
utilizar ese nombre para eliminarla. En otro caso, el valor
símbolo_clave_foránea
es generado internamente por
InnoDB
cuando se crea la clave foránea. Para saber
cuál es este símbolo cuando se desee eliminar una clave foránea, se
emplea la sentencia SHOW CREATE TABLE
. Un ejemplo:
mysql> SHOW CREATE TABLE ibtest11c\G *************************** 1. row *************************** Table: ibtest11c Create Table: CREATE TABLE `ibtest11c` ( `A` int(11) NOT NULL auto_increment, `D` int(11) NOT NULL default '0', `B` varchar(200) NOT NULL default '', `C` varchar(175) default NULL, PRIMARY KEY (`A`,`D`,`B`), KEY `B` (`B`,`C`), KEY `C` (`C`), CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11a` (`A`, `D`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`) REFERENCES `ibtest11a` (`B`, `C`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=INNODB CHARSET=latin1 1 row in set (0.01 sec) mysql> ALTER TABLE ibtest11c DROP FOREIGN KEY 0_38775;
El procesador de sentencias (parser) de InnoDB
permite emplear acentos graves (ASCII 96) para encerrar los nombres de
tablas y columnas en una clásusula FOREIGN KEY ...
REFERENCES ...
. El parser de InnoDB
también
toma en cuenta lo establecido en la variable de sistema
lower_case_table_names
.
InnoDB
devuelve las definiciones de claves foráneas
de una tabla como parte de la salida de la sentencia SHOW CREATE
TABLE
:
SHOW CREATE TABLE tbl_name
;
A partir de esta versión, mysqldump también produce definiciones correctas de las tablas en el fichero generado, sin omitir las claves foráneas.
Se pueden mostrar las restricciones de claves foráneas de una tabla de este modo:
SHOW TABLE STATUS FROMnombre_bd
LIKE 'nombre_tabla
';
Las restricciones de claves foráneas se listan en la columna
Comment
de la salida producida.
Al llevar a cabo verificaciones de claves foráneas,
InnoDB
establece bloqueos compartidos a nivel de fila
en los registros de tablas hijas o padres en los cuales deba fijarse.
InnoDB
verifica las restricciones de claves foráneas
inmediatamente, la verificación no es demorada hasta la confirmación de
la transacción.
Para facilitar la recarga de ficheros de volcado de tablas que tengan
relaciones de claves foráneas, mysqldump incluye
automáticamente una sentencia en la salida del comando para establecer
FOREIGN_KEY_CHECKS
a 0. Esto evita problemas con
tablas que tengan que ser creadas en un orden particular cuando se
recarga el fichero de volcado. También es posible establecer el valor de
esta variable manualmente:
mysql> SET FOREIGN_KEY_CHECKS = 0;
mysql> SOURCE dump_file_name
;
mysql> SET FOREIGN_KEY_CHECKS = 1;
Esto permite importar las tablas en cualquier orden si el fichero de
volcado contiene tablas que no están ordenadas según lo requieran sus
claves foráneas. También acelera la operación de importación. Establecer
FOREIGN_KEY_CHECKS
a 0 también puede ser útil para
ignorar restricciones de claves foráneas durante operaciones LOAD
DATA
y ALTER TABLE
.
InnoDB
no permite eliminar una tabla que está
referenciada por una restricción FOREIGN KEY
, a menos
que se ejecute SET FOREIGN_KEY_CHECKS=0
. Cuando se
elimina una tabla, las restricciones que fueron definidas en su
sentencia de creación también son eliminadas.
Si se recrea una tabla que fue eliminada, debe ser definida de acuerdo a las restricciones de claves foráneas que están haciendo referencia a ella. Debe tener los tipos y nombres correctos de columnas, y debe tener índices sobre las tablas referenciadas, como se estableció anteriormente. Si estas condiciones no se cumplen, MySQL devuelve un error número 1005 y menciona el error número 150 en el mensaje de error.
La replicación en MySQL funciona para tablas InnoDB
del mismo modo que lo hace para tablas MyISAM
. Es
posible usar replicación en una forma en que el tipo de tabla en el
servidor esclavo no es igual a la tabla original en el servidor maestro.
Por ejemplo, se pueden replicar modificaciones de una tabla
InnoDB
en el servidor maestro sobre una tabla
MyISAM
en el servidor esclavo.
Para configurar un nuevo esclavo para un servidor maestro, se debe
realizar una copia del espacio de tablas InnoDB
y de
los ficheros de registro, así como de los ficheros
.frm
de las tablas InnoDB
, y
mover las copias al servidor esclavo. El procedimiento adecuado para
esto se encuenta en Sección 15.9, “Trasladar una base de datos InnoDB
a otra máquina”.
Si se puede detener el servidor maestro o un esclavo existente, se puede
tomar un backup en frío del espacio de tablas InnoDB
y de los ficheros de registro y utilizarlos para configurar un servidor
esclavo. Para crear un nuevo esclavo sin detener ningún servidor, se
puede utilizar la herramienta comercial
InnoDB
Hot Backup
tool.
Una limitación menor en la replicación InnoDB
es que
LOAD TABLE FROM MASTER
no funciona con tablas de tipo
InnoDB
. Hay dos posibles soluciones:
-
Hacer un volcado de la tabla en el maestro e importarlo dentro del esclavo.
-
Utilizar
ALTER TABLE
nombre_tabla
TYPE=MyISAM en el maestro antes de realizar la replicación conLOAD TABLE
nombre_tabla
FROM MASTER, y luego emplearALTER TABLE
para convertir la tabla en el maestro nuevamente aInnoDB
.
Las transacciones que fallen en el maestro no afectan en absoluto la replicación. La replicación en MySQL se basa en el registro (log) binario donde MySQL registra las sentencias SQL que modifican datos. Un esclavo lee el registro binario del maestro y ejecuta las mismas sentencias SQL. Sin embargo, las sentencias emitidas dentro de una transacción no se graban en el registro binario hasta que se confirma la transacción, en ese momento todas las sentencias son grabadas de una vez. Si una sentencia falla, por ejemplo por infringir una clave foránea, o si se cancela una transacción, ninguna sentencia se guarda en el registro binario y la transacción no se ejecuta en absoluto en el servidor esclavo.
En MySQL 5.0, se puede almacenar cada tabla InnoDB
y
sus índices en su propio fichero. Esta característica se llama
“multiple tablespaces” (espacios de tablas múltiples)
porque, en efecto, cada tabla tiene su propio espacio de tablas.
El uso de múltiples espacios de tablas puede ser beneficioso para usuarios que desean mover tablas específicas a discos físicos separados o quienes deseen restaurar respaldos de tablas sin interrumpir el uso de las demás tablas InnoDB.
Se pueden habilitar múltiples espacios de tablas agregando esta línea a
la sección [mysqld]
de my.cnf
:
[mysqld] innodb_file_per_table
Luego de reiniciar el servidor, InnoDB
almacenará
cada nueva tabla creada en su propio fichero
nombre_tabla
.ibd en el
directorio de la base de datos a la que pertenece la tabla. Esto es
similar a lo que hace el motor de almacenamiento
MyISAM
, pero MyISAM
divide la
tabla en un fichero de datos
tbl_name
.MYD y el
fichero de índice
tbl_name
.MYI. Para
InnoDB
, los datos y los índices se almacenan juntos
en el fichero .ibd
. El fichero
tbl_name
.frm se sigue
creando como es usual.
Si se quita la línea innodb_file_per_table
de
my.cnf
y se reinicia el servidor,
InnoDB
creará nuevamente las tablas dentro de los
ficheros del espacio de tablas compartido.
innodb_file_per_table
afecta solamente la creación de
tablas. Si se inicia el servidor con esta opción, las tablas nuevas se
crearán empleando ficheros .ibd
, pero aún se puede
acceder a las tablas existentes en el espacio de tablas compartido. Si se
remueve la opción, las nuevas tablas se crearán en el espacio
compartido, pero aún se podrá acceder a las tablas creadas en espacios
de tablas múltiples.
InnoDB
siempre necesita del espacio de tablas
compartido. Los ficheros .ibd
no son suficientes
para que funcione InnoDB
. El espacio de tablas
compartido consiste de los ya conocidos ficheros
ibdata
, donde InnoDB
coloca su
diccionario de datos interno y los registros para deshacer cambios (undo
logs).
No se puede mover libremente ficheros
.ibd
entre directorios de bases de datos
en la misma forma en que se hace con ficheros de tablas
MyISAM
. Esto se debe a que la definición de las
tablas se almacena en el espacio de tablas compartido de
InnoDB
, y también porque InnoDB
debe preservar la consistencia de los identificadores de transacciones y
los números de secuencia de registros (log).
Dentro de una determinada instalación MySQL, se puede mover un fichero
.ibd
y las tablas asociadas de una base de datos a
otra con la conocida sentencia RENAME
TABLE
:
RENAME TABLEnombre_bd_anterior.nombre_tabla
TOnombre_bd_nuevo.nombre_tabla
;
Si se tiene un respaldo “limpio” de un fichero
.ibd
, se lo puede restaurar dentro de la
instalación MySQL de donde proviene del siguiente modo:
-
Utilizando esta sentencia
ALTER TABLE
:ALTER TABLE
nombre_tabla
DISCARD TABLESPACE;Precaución: Esto eliminará el actual fichero
.ibd
. -
Colocando el fichero
.ibd
nuevamente en el directorio de la base de datos adecuada. -
Utilizando esta sentencia
ALTER TABLE
:ALTER TABLE
nombre_tabla
IMPORT TABLESPACE;
En este contexto, un respaldo “limpio”
de un fichero .ibd
significa:
-
ç El fichero
.ibd
no contiene modificaciones realizadas por transacciones sin confirmar. -
No quedan entradas sin combinar en el buffer de inserciones en el fichero
.ibd
. -
Se han quitado todos los registros de índice marcados para eliminación en el fichero
.ibd
. -
mysqld ha descargado todas las páginas modificadas del fichero
.ibd
desde el buffer pool hacia el fichero.
Se puede realizar un respaldo limpio del fichero
.ibd
con el siguiente método:
-
Detener toda actividad del servidor mysqld y confirmar todas las transacciones.
-
Esperar hasta que
SHOW INNODB STATUS
indique que no hay transacciones activas en la base de datos, y el estado del subproceso (trhead) principal deInnoDB
seaWaiting for server activity
(Esperando por actividad del servidor). Entonces, se puede hacer una copia del fichero.ibd
.
Otro método para hacer una copia limpia de un fichero
.ibd
es utilizar la herramienta comercial
InnoDB Hot Backup:
-
Utilizar InnoDB Hot Backup para respaldar la instalación
InnoDB
. -
Iniciar un segundo servidor mysqld sobre el respaldo y permitirle limpiar los ficheros
.ibd
del mismo.
Figura en la lista de pendientes (TODO) para permitir mover ficheros
.ibd
limpios a otra instalación MySQL. Esto
necesita que se inicialicen los IDs (identificadores) de transacciones y
los números de secuencia de registros (log) en el fichero
.ibd
.