そのバックアップスクリプトはばかげているので、他のバージョンを作成することはできません。私は以前にそのスクリプトと同様の試みを見たことがあり、それらには多くの問題があります:
- バックティックでテーブル名を区切りません
- NULLを処理しません
- 文字セットを処理しません
- バイナリデータを処理しません
- ビューをバックアップしません
- トリガー、ストアドプロシージャ、またはストアド関数やイベントをバックアップしません
- 廃止されたmysql拡張機能を使用します(ただし、これがPDOバージョンが必要な理由ですよね?)
- 適切なMySQLエスケープ関数の代わりにaddslashes()を使用します。
- すべてを追加 すべてのデータ コンテンツ全体を出力する前に、テーブルを1つの非常に長い文字列に変換します。これは、データベース全体を1つの文字列に格納できる必要があることを意味します。これにより、PHPの最大メモリ制限がほぼ確実に失われます。
不幸なDavidWalshバックアップスクリプトに関する私の過去の回答も参照してください:
コメントを再確認してください:
リンクしたページのコメントを読んでください。多くの人々が問題を特定し、一部の人々は修正または少なくとも提案をしています。
このスクリプトがすべてを1つの文字列に追加するという事実は、大きな問題だと思いますが、スクリプトを変更して出力ファイルを最初に開くことは難しくありません。 、次にループ中に各行のデータを出力し、ループ後にファイルを閉じます。それは簡単なことです。スクリプトがそれを行わない理由はわかりません。しかし、スクリプトが十分にテストされていないことは明らかです。
しかしとにかく、私はこの車輪を再発明しようとはしませんでした。 Mysqldumpまたはmydumperはこの仕事をうまくやります。 FWIW、データベースが存在するのと同じサーバーでmysqldumpを実行する必要はありません。 Mysqldumpは、--host
のオプションをサポートしています したがって、ファイアウォールがクライアントの接続をブロックしない限り、どこでもmysqldumpを実行してリモートデータベースをバックアップできます。基本的に、あるクライアントホストからデータベースにPHPアプリを接続できる場合は、mysqldumpを接続できます。
それが本当に選択肢ではない場合は、phpmyadminのデータベースダンプ機能を使用します。これらは成熟しており、十分にテストされており、すべてを正しくダンプします。ダンプ機能の使用方法を説明する記事は次のとおりです。
[あなたの答えから私のコメントをコピーする:]
これはコードレビューに入っていますが、StackOverflowの目的ではありません。しかし簡単に:
- NULLの適切なサポートはありません(それらを''に変換します);
- テーブル名を一貫して区切るわけではありません。
- 文字列区切り文字として非ANSI二重引用符を使用します。
- 巨大なテーブルでバッファリングされたクエリを使用すると、PHPの最大メモリ制限が破られます。
- 巨大なテーブルにすべての行を追加すると、PHPの最大メモリ制限が破られます。
- PDO ::quote();の代わりにaddslashes()を使用します。
- 関数の最後でのみクエリエラーをチェックします。
- 失敗したファイルの作成をチェックしません。
- gzip拡張機能が読み込まれない場合があります
- また、おそらくまだUTF8データをサポートしていません。
はい、これは元のDavidWalshスクリプトよりも優れています。 :-)
NULLはSQLの''と同じではありません(Oracleを除きますが、この場合はSQL標準に準拠していません)。 MySQLを参照してください。NULLまたは空を挿入することをお勧めします。文字列?
メモリ制限の問題に関するコードを読み間違えました。各行の出力を書き込んでいるので、問題ありません(行に1GBのblobなどが含まれている場合を除く)。
ただし、コンマで区切られた行のセットを含む単一のINSERTステートメントを出力するだけではいけません。 mysqldump --extended-insert
でさえ 有限長のデータを出力してから、新しいINSERTステートメントを開始します。基準は、INSERTステートメントの長さが--net-buffer-length
のオプション引数内に収まるかどうかです。 。
ANSI SQLでは、一重引用符''は、文字列リテラルまたは日付リテラルを区切るために使用されます。二重引用符""は、テーブル名や列名などの識別子を区切るために使用されます。デフォルトでは、MySQLはそれらを同じように扱いますが、これは非標準です。 データベースごとに異なる名前の引用符が使用されていますか? 。 SET SQL_MODE=ANSI_QUOTES
があるMySQLサーバーにバックアップデータをインポートしようとした場合 、インポートは失敗します。
例:query('SELECT * FROM '.$table);
実際、クエリで$tableを使用する他の各ケース。スクリプトが出力するINSERTステートメントで、テーブルを1回だけ区切りました。
MySQLは常に、バックティックを識別子の区切り文字、および文字列/日付の単一引用符として認識します。ただし、二重引用符は、前述のSQL_MODEに応じて意味が変わります。復元先のMySQLインスタンスでどのSQL_MODEが有効であるかを推測できないため、識別子にはバックティックを使用し、文字列には一重引用符を使用するのが最適です。テーブルをクエリするときにそれらを区切る理由は、SQLの予約語であるか、特殊文字などを含むテーブル名がある可能性があるためです。
区切り文字なしですべての数値タイプを挿入できます。文字列と日付のみに区切り文字が必要です。 dev.mysql.com/doc/refman/5.6/en/literals.html
を参照してください