6

私はmysql (5.0.32-Debian_7etch6-log)を使用しており、夜間に実行するバルク ロードphp (5.2.6)スクリプト( PDO 経由でZend_DB (1.5.1) を使用) を使用しています。これは次のことを行います。

  1. 4 つの「インポート」テーブルのセットを切り捨てる
  2. これら4つの「インポート」テーブルにデータを一括挿入します(以前にテーブルにあったIDも再利用しましたが、テーブル全体を切り捨てたので、問題にはなりませんよね?)
  3. すべてがうまくいけば、「ライブ」テーブルの名前を「一時」に変更し、「インポート」テーブルを「ライブ」に変更し、「一時」(古い「ライブ」) テーブルを「インポート」に変更します。

これは何週間もうまくいきました。現在、一括読み込みプロセス全体の途中で、時折これを取得しています。

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '911' for key 1

これは、既に切り捨てられる前にテーブルにあった最初の ID ではないことに注意してください。スクリプトを手動で再度開始すると、魅力的に機能します。

何か案は?残りのインデックス、おそらく名前の変更と関係がありますか?

さらに、後でID 911のエントリのテーブルを確認すると、そこにもありません。

4

6 に答える 6

2

このようなエラーは、MyISAM テーブルが破損したときに発生する可能性があります。通常、問題のテーブルで修復コマンドを実行するだけで、問題を修正できます。

> repair table mytablename;

より良い解決策は、データが常に変化しているテーブルに MyISAM を使用しないことです。InnoDB はより強力であり、Paul が正しく指摘しているように、InnoDB テーブルではトランザクションを使用できますが、MyISAM では使用できません。

ところで、その場でテーブルの名前を変更することは避けたいと思います - これは定期的に行うのはかなり厄介なことであり、名前の変更中にシステムに他のユーザーがいる場合、非常に予期しない結果を引き起こす可能性があります。次のようなことをしてみませんか:

> truncate table temptable;
> truncate table importtable;

> #bulk insert new data
> insert into importtable(col1,col2,col3) 
> values(1,2,3),(4,5,6),(7,8,9);

> #now archive the live data
> insert into temptable(col1,col2,col3)
> select col1,col2,col3 from livetable;

> #finally copy the new data to live
> truncate table livetable;
> insert into livetable(col1,col2,col3)
> select col1,col2,col3 from importtable;

もちろん、非常に多数の行を挿入している場合、挿入が完了するまですべてのライブデータを使用できないというリスクがありますが、全体として、このアプローチはインデックス、トリガー、またはその他のものに対してはるかに破壊的ではありません問題のテーブルにリンクされている可能性があります。

于 2008-10-22T02:04:51.657 に答える
1

どうやらロックの問題か何かがあったようで、影響を受けるテーブルと関連するテーブルに並列接続で「SELECT」ステートメントを送信することで、動作を再現できました。

今ではDELETE FROM代わりにステートメントを使用TRUNCATEして変更しRENAME TABLE(一度に3つの名前を変更しました)、単一のALTER TABLE xxx RENAME TO zzzステートメントの束に変更し、エラーを再現できなくなりました。

これは解決されるかもしれません。たぶん、他の誰かが、研究と多くの試行錯誤に費やした私の一日から利益を得ることができます.

于 2008-10-21T18:20:39.787 に答える
0

「id」フィールドが省略された (または NULL) 新しいレコードを作成していますが、以前に別のレコードを更新し、その「id」を「911」に変更しました。つまり、テーブルの AUTO_INCREMENT 値が使用されている場合、別のレコードを作成することはできません。

于 2009-10-16T16:25:22.797 に答える
0

インポート スクリプトの実行中に、他のスクリプトがデータベースに挿入されている可能性はありますか?

于 2008-10-21T10:41:43.143 に答える
0

本当に重複を挿入しているかどうかを確認するために、クエリ ログを有効にしてみましたか?

テスト環境で再現できますか?本番環境ではクエリ ログを有効にしないでください。

問題が本物である場合、テーブルが破損している可能性があります。これは多くの原因で発生する可能性がありますが、危険なハードウェアまたは電源障害が考えられます。

mysql ログをチェックして、最近または期間中に問題 (またはクラッシュ) があったかどうかを確認します。

繰り返しますが、私が提案できるのは、テスト環境で再現することだけです。非常に大量のテスト データのロードを作成し、それらを繰り返しロードします。

于 2008-10-21T10:44:57.473 に答える
0

トランザクションを使用していますか?特に、テーブルをロックするか、トランザクション分離モードをシリアライズ可能に設定できる場合は、トランザクションに関するこの種の問題の多くを排除できます。私は MySQL のことにはあまり詳しくありませんが、トランザクションは InnoDB テーブルでしか機能しないと思います (または、それは時代遅れの知識かもしれません)。

于 2008-10-21T20:40:41.563 に答える