sql >> Databasteknik >  >> RDS >> Mysql

Hanterar mysqldump binär data på ett tillförlitligt sätt?

Nej, det är inte alltid tillförlitligt när du har binära blobbar. I så fall MÅSTE du använda "--hex-blobben flagga för att få korrekta resultat.

Varning från kommentaren nedan:

Jag har ett fall där dessa anrop misslyckas (importerar till en annan server men båda kör 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

Den producerar en fil som tyst misslyckas med att importera. Att lägga till "--skip-extended-insert" ger mig en fil som är mycket lättare att felsöka, och jag upptäcker att den här raden genereras men inte kan läsas (men inget fel rapporteras varken vid export eller import):

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

Observera att det avslutande citatet på binära data saknas i originalet.

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

Kolumnen är binär data:

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`),
  ...

Så nej, inte bara kan du inte nödvändigtvis lita på mysqldump, du kan inte ens lita på att den rapporterar ett fel när ett uppstår.

En ful lösning jag använde var att mysqldump exkludera de två drabbade tabellerna genom att lägga till sådana här alternativ till dumpen:

--ignore-table=myalarm.panels 

Sedan detta BASH script hack. Kör i princip en SELECT som producerar INSERT-värden där NULL-kolumnerna hanteras och den binära kolumnen förvandlas till ett UNHEX()-anrop så här:

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

Klistra in den i din redigerare för att spela med den om du behöver.

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

Det ger mig en fil som heter "all.sql" som behöver det sista kommatecken i INSERT förvandlas till ett semikolon, sedan kan den köras enligt ovan. Jag behövde justeringarna för "stor importbuffert" i både det interaktiva mysql-skalet och kommandoraden för att bearbeta den filen eftersom den är stor.

mysql ... --max_allowed_packet=1GB

När jag rapporterade felet blev jag så småningom pekad på "--hex-blob"-flaggan, som gör samma sak som min lösning men på ett trivialt sätt från min sida. Lägg till det alternativet, blobbar dumpas som hex, slutet.



  1. MySQL:infoga värden från en annan tabell i en kolumn

  2. Hur man aktiverar Pipe Concatenation Operator i MySQL

  3. Hur man installerar ODP.NET 2.111 och ODP.NET 4.112 i samma maskin sida vid sida medan båda pekar på samma databasserver

  4. Uppdaterar post UTAN att uppdatera tidsstämpel