2010-05-07 5 views
32

동료가 방금 아주 이상한 MySQL 동작을 알게했습니다.실패한 삽입시 MySQL 자동 증가가 증가하는 이유는 무엇입니까?

auto_increment 필드가있는 테이블과 고유 (예 : 사용자 이름 필드)로 설정된 다른 필드가 있다고 가정합니다. 이미 테이블에있는 사용자 이름과 함께 행을 삽입하려고하면 삽입이 실패합니다. 그러나 auto_increment 값은 몇 번의 실패한 시도 후에 유효한 새 항목을 삽입 할 때 볼 수 있듯이 증가합니다.

예를 들어

, 우리의 마지막 항목은 다음과 같습니다 때 ...

ID: 10 
Username: myname 

... 그리고 우리는 우리가 같은 새 행을 만든 것입니다 우리의 다음 삽입에 동일한 사용자 이름 값을 다섯 개 개의 새로운 항목을보십시오 그래서 :

ID: 16 
Username: mynewname 

이 실패한 삽입 요청으로 범람하여 테이블을 죽일 매우 어리석은 공격 벡터 것 같아 그 자체로 큰 문제는 MySQL을 참조 설명서 상태로, 아니지만 :

"[-] 값이 지정된 정수 유형에 저장할 수있는 최대 정수보다 커지면 자동 증가 메커니즘의 동작이 정의되지 않습니다."

이 예상되는 동작입니까?

+6

공격 벡터가 아닌 문제를 보인다 제대로 작동 않습니다. 실패한 삽입 요청으로 플러딩 할 수 있다면 실패하지 않은 요청으로 균등하게 플러드를 적용 할 수 없습니까? –

+0

수동으로 설명하는 대신 ** 코드 **를 재현 할 수 있습니까? –

+4

@martin smith : 그렇다고해서 새로운 사용자가 급격히 증가한 것은 auto_increment가 자동 증가하는 것보다 더 분명 할 것이라고 생각합니다. 확인하지 않으면 길가에 잘 빠질 수 있습니다. – Sorcy

답변

23

InnoDB은 트랜잭션 엔진입니다.

  1. Session A 삽입 기록 1
  2. Session B 삽입 기록을 다시 2
  3. Session A

갭의 가능성 중 하나가 :

이는 다음 시나리오에서 것을 의미한다 또는 session B은까지 잠글 것입니다.커밋되거나 롤백됩니다.

(대부분의 다른 트랜잭션 엔진 디자이너와 마찬가지로) 틈을 허용하기로 결정했습니다.documentation에서

:

자동 - 증가 카운터에 접속, InnoDB이 그렇지 않은 트랜잭션의 끝으로, 현재 SQL 문장의 끝으로 유지하는 특별한 테이블 수준 AUTO-INC 잠금을 사용 . 특수 잠금 해제 전략은

InnoDB는 서버가 실행되는만큼 메모리 내 자동 증가 카운터를 사용하여 ... AUTO_INCREMENT

을 포함하는 테이블에 삽입을위한 동시성을 개선하기 위해 도입되었다. 서버가 중지되었다가 다시 시작되면 InnoDB은 앞에서 설명한대로 테이블에 대한 첫 번째 INSERT의 각 테이블에 대한 카운터를 다시 초기화합니다. 당신이 주변 id 열 포장 두려워하는 경우

, 그것은 BIGINT (8 바이트 길이)합니다.

+1

답변으로 제 자신의 문제가 해결되었습니다. 고맙습니다. autoincrement와 관련하여 InnoDB의 이러한 동작을 피할 수있는 방법이 있습니까? – Aufwind

+0

Aufwind와 (과) 같은 질문입니다. –

+1

@Ankit : 다른 질문으로 게시하고 여기에 링크를 넣어주십시오. – Quassnoi

4

정확한 내부 구조를 알지 못한다면 자동 증가는 건너 뛴 값이 실패한 삽입을 허용해야한다고합니다. 당신이 은행 거래를하고 있다고 말하면서, 또는 전체 거래와 여러 기록들이 모두 또는 아무것도 아닌 곳으로 가도록 할 수 있습니다. 삽입을 시도하고 ID를받은 다음 해당 트랜잭션 ID로 모든 후속 세부 사항을 스탬프하고 세부 레코드를 삽입하면 자격을 갖춘 고유성을 보장해야합니다. 여러 사람이 데이터베이스를 슬래 밍하는 경우 거래가 커밋 될 때 자신의 트랜잭션 ID와 충돌하지 않도록 자신의 트랜잭션 ID를 확보해야합니다. 첫 번째 트랜잭션에서 무언가가 실패하면 아무런 해를 끼치 지 않고 다운 스트림 요소도 없습니다.

+0

자동 증가의 skkiping 자연의 사용하지만이 skkiping을 중지하는 방법이 무엇인지 알고 싶습니다 –

+2

@Ankit, 아니, 당신은 건너 뛸 중지 할 수 없습니다. 항상 할당 된 마지막 ID를 추적하는 파일 헤더가 증가합니다. 문제가 발생하고 10 명이 거래를 시작하고 3 번이 중단되면 중단 된 트랜잭션을 백업하여 ID 만 사용하면 안됩니다. – DRapp

+0

dout 지우기에 대한 고맙습니다 –

-1

이 문서는 오래된 문서이지만 올바른 답변을 찾지 못해서 실제로이 작업을 수행 할 수있는 방법을 찾았습니다. if 문 안에서 쿼리를 래핑해야합니다. 그것의 일반적으로 쿼리를 삽입하거나 삽입 중복 querys에 그 엉망 일반 인서트를 사용할 수 있도록 구성 자동 증가 순서 :

대신의 INSERT 및 ON DUPLICATE WHERE를 쿼리 UPDATE의 SET를 사용 QUERY 속으로 바꿀 또는 문이 문제가되지 않는 경우와 외부

+2

나는이 답변을 전혀 적용 할 수 없으므로 downvoting하겠습니다. 예, 삽입을 시도하기 전에 레코드가 있는지 확인할 수 있습니다.하지만 레코드가 완전히 지점 옆에 있습니다. – Mave

관련 문제