Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

O mysqldump lida com dados binários de forma confiável?


Não, nem sempre é confiável quando você tem blobs binários. Nesse caso, você DEVE usar o "--hex-blob " sinalizador para obter resultados corretos.

Advertência do comentário abaixo:

Eu tenho um caso em que essas chamadas falham (importando em um servidor diferente, mas ambos executando 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

Ele produz um arquivo que falha silenciosamente na importação. Adicionar "--skip-extended-insert" me dá um arquivo que é muito mais fácil de depurar, e acho que essa linha é gerada, mas não pode ser lida (mas nenhum erro é relatado na exportação ou importação):
INSERT INTO `panels` VALUES (1003,1,257126,141,6562,1,88891,'??\\\?ŖeV???,NULL);

Observe que a cotação final nos dados binários está ausente no original.
select hex(packet_key) from panels where id=1003;
--> DE77CF5C075CE002C596176556AAF9ED

A coluna é dados binários:
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`),
  ...

Portanto, não, você não pode necessariamente confiar no mysqldump, você não pode nem confiar nele para relatar um erro quando ocorrer.

Uma solução feia que usei foi mysqldump excluindo as duas tabelas afetadas adicionando opções como esta ao despejo:
--ignore-table=myalarm.panels 

Então este hack de script BASH. Basicamente execute um SELECT que produz valores INSERT onde as colunas NULL são tratadas e a coluna binária é transformada em uma chamada UNHEX() assim:
(123,45678,UNHEX("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),"2014-03-17 00:00:00",NULL),

Cole-o no editor de sua escolha para brincar com ele, se necessário.
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

Isso me dá um arquivo chamado "all.sql" que precisa da vírgula final no INSERT transformado em ponto e vírgula, então ele pode ser executado como acima. Eu precisava dos ajustes "grande buffer de importação" definidos no shell mysql interativo e na linha de comando para processar esse arquivo porque é grande.
mysql ... --max_allowed_packet=1GB

Quando relatei o bug, acabei sendo apontado para o sinalizador "--hex-blob", que faz o mesmo que minha solução alternativa, mas de maneira trivial do meu lado. Adicione essa opção, os blobs são despejados como hexadecimal, final.