web-dev-qa-db-ja.com

mysqldumpはバイナリデータを確実に処理しますか?

MySQL 5.6には、いくつかのフィールドに大きなバイナリデータを含むテーブルがいくつかあります。 mysqldumpによって作成されたダンプを信頼できるかどうかを知りたいのですが、FTPやSCPなどのシステムを介してダンプファイルを転送するときに、これらのバイナリフィールドが簡単に破損しないようにします。また、そのようなシステムに、ダンプファイルをASCIIではなくバイナリ転送として処理するように強制する必要がありますか?

コメントありがとうございます!

21

いいえ、バイナリブロブがある場合は常に信頼できるとは限りません。その場合、正しい結果を得るには、 "-hex-blob"フラグを使用する必要があります。

これらの呼び出しが失敗する場合があります(別のサーバーにインポートしますが、両方とも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

サイレントにインポートに失敗するファイルを生成します。 「--skip-extended-insert」を追加すると、デバッグがはるかに簡単なファイルが得られます。この行は生成されますが、読み取ることができません(ただし、エクスポートまたはインポートのいずれでもエラーは報告されません)。

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

バイナリデータの終了引用符が元のデータにないことに注意してください。

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

列はバイナリデータです。

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

つまり、mysqldumpを必ずしも信頼できるとは限らないだけでなく、エラーが発生したときにそれを信頼してエラーを報告することもできません。


私が使用した醜い回避策は、次のようなオプションをダンプに追加することにより、2つの問題のあるテーブルを除外するmysqldumpを実行することでした。

--ignore-table=myalarm.panels 

次に、このBASHスクリプトをハックします。基本的に、NULL列が処理され、バイナリ列が次のようにUNHEX()呼び出しに変換されるINSERT値を生成するSELECTを実行します。

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

必要に応じて、選択したエディターに貼り付けて試してみてください。

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

これにより、INSERTの最後のコンマをセミコロンに変換する必要がある「all.sql」というファイルが作成され、上記のように実行できます。ファイルが大きいため、そのファイルを処理するには、インタラクティブなmysqlシェルとコマンドラインの両方に設定された「大きなインポートバッファー」の調整が必要でした。

mysql ... --max_allowed_packet=1GB

バグを報告したとき、最終的に「--hex-blob」フラグが指摘されました。これは回避策と同じですが、私の側からは些細なことです。そのオプションを追加すると、blobは最後の16進数としてダンプされます。

39
Code Abominator

mysqldumpから生成されたダンプは信頼できます。

エンコーディングやバイナリ転送などの問題を回避するには、--hex-blobオプションを使用して、各バイトを16進数に変換します(たとえば、「abc」は0x616263になります)。ダンプが大きくなりますが、情報を取得するための最も互換性があり安全な方法になります(純粋なテキストであるため、テキストファイルのバイナリデータで生成された特別な記号による奇妙な誤解はありません)。

RarまたはZipファイルにパックするダンプファイルの整合性を確保(および転送を高速化)できます。そうすれば、転送で破損していないことを簡単に検出できます。

サーバーにロードしようとするときは、my.cnfサーバー構成ファイルに割り当てられていることを確認してください

[mysqld]
max_allowed_packet=600M

必要に応じてそれ以上。

ところで、今は移行を行ったところ、mysqldumpを使用して大量のバイナリデータをダンプしましたが、完全に機能しました。

9
Gusstavv Gil