sql >> Base de Datos >  >> RDS >> Mysql

¿Mysqldump maneja datos binarios de manera confiable?

No, no siempre es confiable cuando tiene blobs binarios. En ese caso, DEBE usar el "--hex-blob " marcar para obtener resultados correctos.

Advertencia del comentario a continuación:

Tengo un caso en el que fallan estas llamadas (importando en un servidor diferente pero ambos ejecutando Centos6/MariaDB 10):

mysqldump --single-transaction --routines --databases myalarm -uroot -p"PASSWORD" | gzip > /FILENAME.sql.gz
gunzip < FILENAME.sql.gz | mysql -p"PASSWORD" -uroot --comments

Produce un archivo que silenciosamente no se puede importar. Agregar "--skip-extended-insert" me da un archivo que es mucho más fácil de depurar, y encuentro que esta línea se genera pero no se puede leer (pero no se informa ningún error al exportar o importar):

INSERT INTO `panels` VALUES (1003,1,257126,141,6562,1,88891,'??\\\?ŖeV???,NULL);

Tenga en cuenta que en el original falta la comilla final de los datos binarios.

select hex(packet_key) from panels where id=1003;
--> DE77CF5C075CE002C596176556AAF9ED

La columna son datos binarios:

CREATE TABLE `panels` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `enabled` tinyint(1) NOT NULL DEFAULT '1',
  `serial_number` int(10) unsigned NOT NULL,
  `panel_types_id` int(11) NOT NULL,
  `all_panels_id` int(11) NOT NULL,
  `installers_id` int(11) DEFAULT NULL,
  `users_id` int(11) DEFAULT NULL,
  `packet_key` binary(16) NOT NULL,
  `user_deleted` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  ...

Así que no, no solo no necesariamente puede confiar en mysqldump, ni siquiera puede confiar en él para informar un error cuando ocurre.

Una solución fea que usé fue mysqldump excluyendo las dos tablas afectadas agregando opciones como esta al volcado:

--ignore-table=myalarm.panels 

Entonces este truco de script BASH. Básicamente, ejecute un SELECT que produzca valores INSERT donde se manejen las columnas NULL y la columna binaria se convierta en una llamada UNHEX() así:

(123,45678,UNHEX("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),"2014-03-17 00:00:00",NULL),

Pégalo en el editor de tu elección para jugar con él si lo necesitas.

echo "SET UNIQUE_CHECKS=0;SET FOREIGN_KEY_CHECKS=0;DELETE FROM panels;INSERT INTO panels VALUES " > all.sql
mysql -uroot -p"PASSWORD" databasename -e "SELECT CONCAT('(',id,',', enabled,',', serial_number,',', panel_types_id,',', all_panels_id,',', IFNULL(CONVERT(installers_id,CHAR(20)),'NULL'),',', IFNULL(CONVERT(users_id,CHAR(20)),'NULL'), ',UNHEX(\"',HEX(packet_key),'\"),', IF(ISNULL(user_deleted),'NULL',CONCAT('\"', user_deleted,'\"')),'),') FROM panels" >> all.sql
echo "SET UNIQUE_CHECKS=1;SET FOREIGN_KEY_CHECKS=1;" > all.sql

Eso me da un archivo llamado "all.sql" que necesita que la coma final en INSERT se convierta en un punto y coma, luego se puede ejecutar como se indica arriba. Necesitaba los ajustes de "búfer de importación grande" establecidos tanto en el shell mysql interactivo como en la línea de comando para procesar ese archivo porque es grande.

mysql ... --max_allowed_packet=1GB

Cuando informé el error, finalmente me señalaron el indicador "--hex-blob", que hace lo mismo que mi solución pero de una manera trivial desde mi lado. Agregue esa opción, los blobs se descargan como hexadecimales, el final.