2016-07-13 10 views
3

現在、プライマリキーIDに問題があり、これはauto incrementに設定されています。それは増分を維持しますON DUPLICATE KEY。例についてはInnoDBの自動インクリメントが無効になるのを防ぐ

:上記の説明から

ID | field1  | field2 

1 | user  | value 

5 | secondUser | value 

86 | thirdUser | value 

、あなたは私がそのテーブルの3つの入力を持っていますが、原因各アップデートの自動インクリメントに、IDは、第三の入力のために86を持っていることに気づくでしょう。

これを避けるためにとにかくありますか?ここで

は私のMySQLのクエリは次のようになります。

INSERT INTO table (field1, field2) VALUES (:value1, :value2) 
      ON DUPLICATE KEY 
      UPDATE field1 = :value1, field2 = :value2 

そして、ここに私のテーブルは次のようになります。

CREATE TABLE IF NOT EXISTS `table` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `field1` varchar(200) NOT NULL, 
    `field2` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `field1` (`field1`), 
    KEY `id` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 
+1

唯一のユニークな逐次IDを持つことは決して重要ではありません。シーケンシャルが必要な場合は、デザインに何か問題があります –

+0

@ MarkBakerテーブルデザインの構造を含めるように投稿を編集しました – youngbobby

+1

テーブルに別の列を作成して、手動で整数を追加してから、 'sID'列をクリックしてMAX値を見つけて、その値に+1して最新の挿入物を見つけることができます。 (あなたはおそらく自動的にSQLクエリでこれを行うことができます) – Martin

答えて

3

はすべてINSERT文がAUTO_INCREMENTの列の連続した値を代入することを保証し、「伝統的な」自動インクリメントロックモード、用"0"からinnodb_autoinc_lock_mode設定オプションを設定することができます。

つまり、アプリケーション内で連続する自動インクリメントIDには依存しないでください。その目的は一意の識別子を提供することです。

+0

リンクをありがとう。私はこれがオプションだったのか分からなかった – BeetleJuice

+0

私は共有ホスティングにいます:( – youngbobby

1

私は現在 auto incrementに設定されている主キーIDに問題を抱えています。それは増分を続けますON DUPLICATE KEY

私たちの誰かが問題を誤解しているか、それを間違って伝えているに違いありません。 ON DUPLICATE KEY UPDATEは新しい行を作成しないので、増分することはできません。 the docsから:

あなたがDUPLICATE KEY UPDATE ON指定し、行は がUNIQUEインデックスまたはPRIMARY KEY内の重複値を引き起こすことに挿入されている場合は、MySQLの は古い行のUPDATEが実行されます。

今、それはおそらく、あなたが何重複キーが見つからない挿入し時に自動インクリメントが発生した場合です。私はこれが起こっていると仮定すると、私の質問は:それはなぜ問題なのでしょうか?

プライマリキーの値を絶対に制御したい場合は、auto-incrementフラグを削除するようにテーブル構造を変更しますが、必須ではないフィールドにしておきます。それはあなた自身が鍵を提供することを余儀なくさせるでしょうが、これはあなたにとって大きな頭痛になるでしょう。

私は本当に不思議です:なぜあなたはID値のすべての穴を塞ぐ必要がありますか?

+0

投稿を編集してテーブル構造を追加しました – youngbobby

+1

実際のシステムに穴を開けることはできません。ある時点で、行を削除するためです。そして、あなたはすべての子テーブル内のすべてのPKとFKを再シフトすることはできません(またはIDの少なくとも1つが新しい穴へのホット置換として)。まだ正気ではいられないということを意味することはできません。したがって、OCDのない人は単なる十分に良い状態になります。 – Drew

1

この動作は、innodb_autoinc_lock_mode = 1( "連続"ロックモード)のデフォルト設定で簡単に確認できます。詳細マニュアルページAUTO_INCREMENT Handling in InnoDBも参照してください。この値を変更すると、テーブルレベルのAUTO-INCロックを使用するため、 "Tranditional"ロックモードの場合、設定値= 0で同時実行性とパフォーマンスが低下します。

上記、下記の私はあなたにそれがギャップを作成することがいかに簡単であるかの例を示していることを約午前= 1

デフォルトの設定です。

例1:

create table x 
( id int auto_increment primary key, 
    someOtherUniqueKey varchar(50) not null, 
    touched int not null, 
    unique key(someOtherUniqueKey) 
); 
insert x(touched,someOtherUniqueKey) values (1,'dog') on duplicate key update touched=touched+1; 
insert x(touched,someOtherUniqueKey) values (1,'dog') on duplicate key update touched=touched+1; 
insert x(touched,someOtherUniqueKey) values (1,'cat') on duplicate key update touched=touched+1; 

select * from x; 
+----+--------------------+---------+ 
| id | someOtherUniqueKey | touched | 
+----+--------------------+---------+ 
| 1 | dog    |  2 | 
| 3 | cat    |  1 | 
+----+--------------------+---------+ 

ギャップが(ID = 2はスキップされる)による操作や癖やINNODBエンジンの神経痙攣の一握りの一つです。デフォルトの高性能同時実行性モードでは、送信されたさまざまなクエリに対して範囲ギャップ割り当てを実行します。この設定を変更するとよい理由は、パフォーマンスに影響を与えるためです。 MySQLのそれ以降のバージョンのものはあなたに届きます。ハイパーフォーカスのために、プリントアウトシート(および「なぜギャップがあるのですか」と言うボス)の隙間に消えます。

重複キー更新の挿入(IODKU)の場合、1つの新しい行があると想定し、そのためのスロットを割り当てます。並行性と同じ操作をしている同僚、おそらく数百を覚えておいてください。 IODKUがUpdateに変わると、あなたの接続や他の人には、id = 2の放置された、決して挿入されていない行が使用されます。

例2:

鉱山のThis Answerに見られるように同じInsert ... Select From中に起こります。その中で私は意図的にカウント、最小、最大のレポートのためにMyISAMを使用します。そうしないと、レンジギャップのクォークは割り当てられ、すべてを埋めることはありません。実際の数字を扱った答えが奇妙に見えます。だから古いエンジン(MyISAM)は、きつい非ギャップのためにうまくいきました。その答えでは、私は何かをすばやく安全にしようとしていたことに注意してください。テーブルはINNODBALTER TABLEに変換されます。最初にINNODBの例を実行していたのであれば、(デフォルトモードでは)十分なギャップがあったでしょう。 の理由は、回答が私がINNODBを使用していたことにギャップが生じました。カウントが不確実であったため、エンジンが安全(不確実な)範囲割り当てのために選択するメカニズムでした。 INNODBエンジンは、自然に操作を知っていて、AUTO_INCREMENTというIDの安全なプールを作成しなければならず、並行性(他のユーザーも考えている)があり、ギャップが溢れています。それは事実です。 INNODBエンジンで例2を試して、min、max、およびcountについて何が出てくるかを見てください。 Maxはカウントと等しくありません。

実施例3および4:

彼らはより多くのにつまずくと、それらを文書としてPerconaのウェブサイト上の文書INNODBギャップを引き起こす様々な状況があります。たとえば、これは1452 Error imageに見られるForeign Keyの制約のために挿入が失敗したときに発生します。または1062 Error imageの主キーエラーです。

覚えておいてください。INNODBは、システムパフォーマンスの副作用として、安全なエンジンとして存在します。厳密なID範囲のために、本当にターンオフしたいもの(パフォーマンス、高いユーザ統計、高い並行性、テーブルロックの不足)ですか?とにかく削除に穴がある範囲。私は私の実装ではないと提案し、パフォーマンスのデフォルトはうまくいきます。

関連する問題