1

CSV ファイルから大量のデータを定期的に MySQL データベースにアップロードする必要があります。以前は、bash スクリプトから LOAD DATA INFILE を実行するだけでこれを行っていました。ただし、データは複数のテーブルに分散され、関係は保持されます。そのような場合の一般的な戦略は何ですか?

最初は単純なタスクを想定しましょう: 1 対多の 2 つのテーブルの関係です。

私は次のようなものを考えます:

  1. テーブル 1 の最大識別子の取得
  2. CSV ファイルに識別子を手動で適用する
  3. 2 つのターゲット テーブルを念頭に置いてファイルを分割する
  4. 両方のテーブルを挿入する

それは最適解ですか?(たとえば、実際のケースでは、この方法で更新される多対多の関係がたくさんあります。)

プロセス全体の間、bash のレベルからテーブル 1 をロックできますか? それとも、perl や Python などの中間ツールを使用して、すべてを 1 つのセッションに保持する必要がありますか?

4

1 に答える 1

0

あなたの質問には、さまざまな相反する要件が示されています。この回答は、その「キープ ロック」の側面に集中しています。

操作全体でテーブル ロックを維持するには、SQL サーバーへの単一の接続を維持する必要があります。1 つの方法は、すべてを複数行のマルチコマンド入力として mysql コマンド ライン クライアントの 1 回の呼び出しに渡すことです。基本的には次のようになります。

{ echo "LOCK TABLES Table1 WRITE"
  for i in "${infiles[@]}"; do
    echo "LOAD DATA LOCAL INFILE '${i}'"
  done
} | mysql

ロックが保持されている間、データベースから質問することなく(最大識別子など)必要なすべてのステートメントを生成できる限り、それは機能します。

読み取り操作 (最大値の要求など) と書き込み操作 (一部のファイルのコンテンツの読み込みなど) を混在させるには、サーバーとの双方向通信が必要です。これを bash で実現するのは非常に難しいので、お勧めしません。質問する必要がない場合でも、bash パイプによって提供される一方向接続は危険の元です。mysql 側で何か問題が発生した場合、bash は気付かず、とにかく次のコマンドを発行します。一貫性のないデータをコミットしてしまう可能性があります。

これらの理由から、あなたが言及したPerlやPyhonオプションのように、mysqlバインディングが利用可能なスクリプト言語を提案したいと思います。これらの言語で CVS ファイルを読み取るのは簡単なので、次のすべてを 1 つのスクリプトで実行できます。

  1. ロックテーブル
  2. 取引開始
  3. 入力 csv ファイルを読み取る
  4. 最大IDのような質問をする
  5. テーブルのレイアウトに合わせて入力データを調整する
  6. テーブルにデータを挿入する
  7. エラーが発生しなかった場合は、トランザクションをコミットします
于 2012-06-24T21:08:08.353 に答える